Author Topic: ATMega328 Timer issues for PWM generation  (Read 652 times)

0 Members and 1 Guest are viewing this topic.

Offline dvhTopic starter

  • Contributor
  • Posts: 18
  • Country: hu
ATMega328 Timer issues for PWM generation
« on: March 11, 2024, 12:49:17 pm »
Hello everyone!

I'd like to generate a PWM signal with a duty cycle of 30%. When the following code was flashed to an UNO board, pin 11 (PB3) remained high and never did the good old oscillation. I'm sure I screw something up, I just can't seem to figure out what.

Code: [Select]

void setup()

  Serial.begin(19200);

  /*  MY SETTINGS:
  ╔════════╦═══════╦═══════╦═══╦═══╦═══════╦══════╦══════╦══════╗
  ║        ║ FOC2A ║ FOC2B ║ - ║ - ║ WGM22 ║ CS22 ║ CS21 ║ CS20 ║
  ╠════════╬═══════╬═══════╬═══╬═══╬═══════╬══════╬══════╬══════╣
  ║ TCCR2B ║   0   ║   0   ║ - ║ - ║   1   ║  1   ║  0   ║  1   ║
  ╚════════╩═══════╩═══════╩═══╩═══╩═══════╩══════╩══════╩══════╝
  ╔════════╦════════╦════════╦════════╦════════╦═══╦═══╦═══════╦═══════╗
  ║        ║ COM2A1 ║ COM2A0 ║ COM2B1 ║ COM2B0 ║ - ║ - ║ WGM21 ║ WGM20 ║
  ╠════════╬════════╬════════╬════════╬════════╬═══╬═══╬═══════╬═══════╣
  ║ TCCR2A ║   1    ║   0    ║   0    ║   0    ║ - ║ - ║   1   ║   1   ║
  ╚════════╩════════╩════════╩════════╩════════╩═══╩═══╩═══════╩═══════╝

  Timer Mode: 7 (WGM2:0 = 7)
  Duty cycle: 30% 
  TOP: 102 
  */

  pinMode(LED_BUILTIN, OUTPUT);
  // set OC2A as OUTPUT
  DDRB |= (1 << PB3);; // OC2A pin - pin No.3
  // clear settings
  TCCR2A = 0;
  TCCR2B = 0;

  Serial.print("TCCR2A: ");
  Serial.println(TCCR2A, BIN);
  Serial.print("TCCR2B: ");
  Serial.println(TCCR2B, BIN);

  // set TOP to 102 -> generate 25KHz
  OCR2A = 102;
  // 30% duty cycle
  OCR2B = 34;

  // set Timer mode 7: goes from BOTTOM to TOP
  // WARNING: WGM22 is part of TCCR2B
  TCCR2A |= (1 << WGM21) | (1 << WGM20);
  // clear OC2A on compare match, set OC2A at BOTTOM
  // non-inverting FAST PWM mode
  TCCR2A |= (1 << COM2A1);

  Serial.print("TCCR2A: ");
  Serial.println(TCCR2A, BIN); // prints 10000011

  // set prescaler to 0 -> running at 16MHz - start timer
  TCCR2B = (1 << CS22) | (0 << CS21) | (1 << CS20);
  // WGM2:0 define mode 7
  TCCR2B |= (1 << WGM22);
  Serial.print("TCCR2B: ");
  Serial.println(TCCR2B, BIN); //prints 00001101
}

So the question is: what am I missing to generate the PWM signal? Thank you in advance!
 

Offline ozcar

  • Frequent Contributor
  • **
  • Posts: 322
  • Country: au
Re: ATMega328 Timer issues for PWM generation
« Reply #1 on: March 11, 2024, 09:49:42 pm »
For mode = 7, TOP is the value in OCRA.  From the Fine Manual: "Setting the OCR2A equal to MAX will result in a constantly high or low output (depending on the polarity of the output set by the COM2A1:0 bits.)" This is what I think you are seeing.

What you put in OCR2B does not come into it- at least, not for output on OC1A. If you set DDRD for output on PD3 (OC2B), and turn on COM2B1 in TCCR2A you might see some action (not sure that the comment about frequency 25kHz is correct though).

If the output must be on OC1A. you could change to mode 3, with OCR2A = 77 you should get duty cycle 30%, but you won't have fine control of the frequency due to limited prescaler values.
« Last Edit: March 11, 2024, 09:51:31 pm by ozcar »
 
The following users thanked this post: dvh

Offline dvhTopic starter

  • Contributor
  • Posts: 18
  • Country: hu
Re: ATMega328 Timer issues for PWM generation
« Reply #2 on: March 12, 2024, 09:33:11 pm »
This is exactly what happened!

Indeed, when I started using OC2B pin to monitor the output, all was good (after setting it to output).

Thanks for taking the time to look up the relevant stuff in the datasheet! I missed it..
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf