Fast high-resolution PWM

I wanted to generate a high-resolution PWM (15-bit) output on the Port#9 of an UNO Arduino board. I used the following code, but it gives me a couple of warnings an no pulse train on the port:


Here is the code:

// Arduino UNO PWM Frequency and Resolution Adjustment (Port 9)

const int pwmPin = 9;

void setup() {
  pinMode(pwmPin, OUTPUT);
  // Configure Timer1 for PWM on pins 9 and 10.
  // We'll focus on pin 9.

  // 1. Disable interrupts during configuration.
  cli();

  // 2. Set Timer1 Control Registers (TCCR1A and TCCR1B).
  // WGM13, WGM12, WGM11, WGM10 bits control the Waveform Generation Mode.
  // We'll use mode 14 (Fast PWM, ICR1 top).
  // COM1A1, COM1A0 bits control the Output Compare mode for pin 9 (OC1A).
  // COM1B1, COM1B0 bits control the Output Compare mode for pin 10 (OC1B).
  // CS12, CS11, CS10 bits control the Clock Select bits for the prescaler.

  // Set WGM13 and WGM12 to 1, WGM11 and WGM10 to 1 for mode 14 (Fast PWM, ICR1 top).
  // Set COM1A1 to 1, COM1A0 to 0 for non-inverting PWM on pin 9.
  // Set COM1B1 and COM1B0 to 0 for normal port operation on pin 10.
  TCCR1A = _BV(COM1A1) | _BV(WGM11) | _BV(WGM10);

  // Set WGM13 to 1, WGM12 to 1 for mode 14 (Fast PWM, ICR1 top).
  // Set CS10 to 1 for no prescaling.
  TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10);

  // 3. Set the Top value for Timer1 (ICR1).
  // Frequency = Clock / (Prescaler * (1 + ICR1))
  // 1000 Hz = 16,000,000 Hz / (1 * (1 + ICR1))
  // ICR1 = (16,000,000 / 1000) - 1
  // ICR1 = 15999
  ICR1 = 15999; // Set the top value for 1000 Hz.

  // 4. Set the Output Compare Register A (OCR1A) for the duty cycle.
  // 16-bit resolution means values from 0 to 65535. However, since we set ICR1 to 15999,
  // the max value should be 15999.
  // Example for 50% duty cycle:
  OCR1A = 7999; // 50% duty cycle (15999 / 2)

  // 5. Re-enable interrupts.
  sei();
}

void loop() {
  // You can change the duty cycle here if needed.
  // Example for 25% duty cycle:
  //OCR1A = 3999;
 // delay(1000); // Change duty cycle once per second for testing.
}

How does WGM mode 0b1111 equal WGM mode 14?

1 Like

I didn't have this table. Should I use 0b1110?

Topic moved. Please do not post in "Uncategorized"; see the sticky topics in Uncategorized - Arduino Forum.

Hi @hcalgary2.

The "Spurious .github folder in ..." warnings shown in your screenshot are completely innocuous and are not in any way related to the "no pulse train" problem you are experiencing. So please don't get distracted by those. You can safely ignore them as these "spurious" folders don't cause any problems at all.

I think the reason why the Arduino IDE developers added these warnings was to encourage the library developers to avoid cluttering up their libraries with folders that aren't used by Arduino IDE. Since the warnings more often only annoyed the users, they have been removed in modern 2.x versions of Arduino IDE (I guess you are using one of the 1.x versions).

1 Like

Yes, I'm using 1.6.5 version

1 Like

I changed
" TCCR1A = _BV(COM1A1) | _BV(WGM11) | _BV(WGM10);"
to
" TCCR1A = _BV(COM1A1) | _BV(WGM11);// | _BV(WGM10);"
and it worked.
Thanks

1 Like

Its in the datasheet:

Yes, if you want fast PWM with ICR1 as TOP, you need mode 14.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.