Recent

Author Topic: Help by coding a PWM_WRITE procedure  (Read 1355 times)

pascalbythree

  • Sr. Member
  • ****
  • Posts: 266
Help by coding a PWM_WRITE procedure
« on: September 02, 2023, 08:03:36 pm »
https://wiki.freepascal.org/AVR_Embedded_Tutorial_-_Analog_Write

Code: Pascal  [Select][+][-]
  1.   var
  2.    i : integer;  // Loop counter
  3.  begin
  4.    // Configure PD5 and PD6 as outputs
  5.    DDRD := %01100000;
  6.  
  7.    // Configure PD5 and PD6 in PWM mode
  8.    TCCR0A := (%10 shl COM0A) or (%10 shl COM0B) or (1 shl WGM0);
  9.  
  10.    // Enable timer 0, clock / 1024
  11.    TCCR0B := TCCR0B or %101;
  12.  
  13.    // Main loop that continuously makes the LEDs brighter and darker
  14.    repeat
  15.      for i := 0 to 255 do
  16.        begin
  17.          OCR0A := i;
  18.          OCR0B := 255 - i;
  19.          sleep;
  20.      end;
  21.  
  22.      for i := 0 to 255 do
  23.        begin
  24.          OCR0A := 255 - i;
  25.          OCR0B := i;
  26.          sleep;
  27.        end;
  28.    until False;
  29.  end.


Can somebody help me out with this procedure, i have to cat it over to this:

Code: Pascal  [Select][+][-]
  1. procedure SETPWM(Port:Char; PIN:byte; Value:integer);
  2. begin
  3.  // ???
  4. end;

I Want to use PB2 to PWM output. For the Attiny2313A. Great thanks...

Its to control the FAN Speed in this project. See Photo!





« Last Edit: September 02, 2023, 08:38:48 pm by pascalbythree »

ccrause

  • Hero Member
  • *****
  • Posts: 988
Re: Help by coding a PWM_WRITE procedure
« Reply #1 on: September 03, 2023, 08:08:40 am »
Can somebody help me out with this procedure, i have to cat it over to this:

Code: Pascal  [Select][+][-]
  1. procedure SETPWM(Port:Char; PIN:byte; Value:integer);
  2. begin
  3.  // ???
  4. end;

I Want to use PB2 to PWM output. For the Attiny2313A. Great thanks...
One way of doing this is to check for valid port & pin combinations, then configure the appropriate timer attached to that pin:
Code: Pascal  [Select][+][-]
  1. procedure SETPWM(Port: Char; pin: byte; value: uint16);
  2. begin
  3.   if (Port = 'B') and (pin = 2) then
  4.   begin
  5.   // configure timer 0, channel A
  6.     TCCR0A := TCCR0A or (%10 shl COM0A) or (1 shl WGM0);
  7.     TCCR0B := TCCR0B or %101;
  8.     OCR0A := byte(value);
  9.   end
  10.   else if (Port = 'A') and (pin = 5) then
  11.   begin
  12.   // configure timer 0, channel B
  13.   end
  14.   else if (Port = 'B') and (pin = 3) then
  15.   begin
  16.   // configure timer 1, channel A
  17.   end
  18.   else if (Port = 'B') and (pin = 4) then
  19.   begin
  20.   // configure timer 1, channel B
  21.   end
  22.   else
  23.     // Do nothing, or output some error
  24. end;
This is an outline of one possible method of coding the SETPWM function.  This is the bare minimum functionality, more code would be required to make this robust.

While a SETPWM procedure may seem helpful, it will always generate code to configure all four PWM pins, even if you only use a single PWM pin. Also note that you will end up with some repeated code in the different if branches.

Note that timer0 is 8 bit, while timer1 is 16 bit.  This means that this generic SETPWM function has to range check the value parameter depending on which timer is used.  Perhaps an unsigned type for value is more useful since the timer only works with positive or zero values.

While Arduino has made this kind of abstraction popular, it comes at the cost of larger code size and slower execution because of the extra code required for the mapping.  Just think about the complication of switching off PWM on a pin.  Do you just disable the OCn output to the pin, but keep the timer running? Or do you check if both OCnA and OCnB are disabled before disabling the timer?  All of this logic requires extra code, which is not required if you know you only use fixed PWM pins in your project.

A general recommendation on the AVRfreaks forum is that you typically use fixed pins in a project, so just configure those pins specifically and be done.

pascalbythree

  • Sr. Member
  • ****
  • Posts: 266
Re: Help by coding a PWM_WRITE procedure
« Reply #2 on: September 03, 2023, 04:46:59 pm »
Tank you very much! it already got to work ! Now i am going to work on the speeds...

What number to change for higher PWM speeds? It seems that i need a higher speed to PWM to my mosfet driver IC. You can hear it a little in the noise of the fan.

Wait got it already, no FASTPWM is needed  value: uint16 is not a byte :-) Woops  :P
« Last Edit: September 03, 2023, 05:10:34 pm by pascalbythree »

pascalbythree

  • Sr. Member
  • ****
  • Posts: 266
Re: Help by coding a PWM_WRITE procedure
« Reply #3 on: November 14, 2023, 12:16:39 pm »
Code: Pascal  [Select][+][-]
  1.   // configure timer 0, channel A
  2.     TCCR0A := TCCR0A or (%10 shl COM0A) or (1 shl WGM0);
  3.     TCCR0B := TCCR0B or %101;
  4.     OCR0A := byte(value);

Can anybody help me out changing this code for the PB1 pin on a Atmega328P ?

To: OC1A

Greets, PascalByThree

pascalbythree

  • Sr. Member
  • ****
  • Posts: 266
Re: Help by coding a PWM_WRITE procedure
« Reply #4 on: November 14, 2023, 12:31:50 pm »
Yay! It got to work already!


Code: Pascal  [Select][+][-]
  1.    // Configure PD5 and PD6 in PWM mode
  2.    TCCR1A := (%10 shl COM1A) or (%10 shl COM1B) or (1 shl WGM1);
  3.  
  4.    // Enable timer 0, clock / 1024
  5.    TCCR1B := TCCR1B or %101;
  6.  
  7.    OCR1A := 125;

Stil thank you...

 

TinyPortal © 2005-2018