PMW on pin 9 using registers

Hey all, so I've been digging around the atmega328p data sheet for a while now trying to figure out fastpmw on pin 9 using registers. The code I have so far seems to have all the registers set correctly, but I'm not getting a PMW output.

Here is the code.

#include <Arduino.h>
byte standardPMW = 3;


void setup() {
  pinMode(standardPMW, OUTPUT);
//Removes any defulat timer values
  TCCR1A = 0; 
  TCCR1B = 0;

  Serial.begin(115600); 
//Sets pin 9 to output
//Uses Timer1 on pin 9 @ 16bit resolution. 
  DDRB |= (1<<DDB1);
//Should set duty cycle of pin 9 at 16bit
  OCR1A = 0x3FFF; // Should be 25% duty cycle
  


  TCCR1A = (1<<COM1A1) | (1<<WGM11) | (1<<WGM10); //Sets to compare at bottom
  
  TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS10); //Sets presclaller to 1
  //WGM10, 11, 12, 13 set to 1111 for TOP = OCR1A
  
  
}

void loop() {
  analogWrite(standardPMW, 64);
  

}

I'm not sure what I'm missing, I have it set to Fastpmw using ORCA1 as a top, with a roughly 25% duty cycle however I'm still gating 5volts out on a meter and the output on my scope is pretty much just a regular dc wave still.

Don't know as it'll help but, you could tinker with Arduino Web Timers 'til you get something satisfactory then transfer it to the processor.

You can have a look at the FastPwmPin library that I wrote. You can find it here on Github. Note that fast pwm mode is toggle-only on pin 9. See the readme for more info.

I had an earlier answer, but I think this is closer to what you were attempting. It uses ICR1 to set TOP and then OCR1A for the compare. With ICR1 set to 0xFFFF and OCR1A set to 0x3FFF as in your original, you get an approx. 25% duty cycle output on pin 9.

(And as it's still not really in my wheelhouse, I won't be surprised if someone who actually knows about this stuff corrects me. :slight_smile: )

#include <Arduino.h>
byte standardPMW = 3;


void setup() {
  pinMode(standardPMW, OUTPUT);
//Removes any defulat timer values
  TCCR1A = 0; 
  TCCR1B = 0;

  Serial.begin(115600); 
//Sets pin 9 to output
//Uses Timer1 on pin 9 @ 16bit resolution. 
  DDRB |= (1<<DDB1);
//Should set duty cycle of pin 9 at 16bit
  OCR1A = 0x3FFF; // Should be 25% duty cycle
  ICR1 = 0xFFFF;


  TCCR1A = (1<<COM1A1) | (1<<WGM11); //Sets to compare at bottom
  
  TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS10); //Sets presclaller to 1
  //WGM10, 11, 12, 13 set to 0111 for TOP = ICR1
  
  
}

void loop() {
  analogWrite(standardPMW, 64);
  

}

If you are using Windows, another handy tool is RTM Timer Calculator Arduino PWM Calculator is WYSIWYG code generator

I used the website to generate the code, however upon uploading It does not work and my scope still shows a straight dc line coming out of pin 9 and my meter still reads 5v. Is my board possibly bunk?

While using OCR1A as TOP, there isn't a good way to simultaneously use OCR1A for setting the duty cycle for output pin OC1A (pin9), so it stays at 100%.

Oh, and since:

you're not setting PWM duty cycle on pin 9, you are setting the pin3 duty cycle by using analogWrite() to set OCR2B

I think you're missing OCR1B. Anyway, here's my code demonstrating PWM on D10. Last I checked, it worked:

//This demonstrates PWM output on D10.  The key to making it work
//is the order of register settings, turning on the clock at the
//very end.

void setup () {
  // Pin 10(OC1B) is output
  pinMode(10, OUTPUT);
  TCCR1A = 0;
  TCCR1B = 0;

  //Load 1000 into OCR1A for 15.98KHz
  OCR1A = 1000;

  //Load 200 into OCR1B for 20% duty cycle
  OCR1B = 200;

  // non-inverted fast PWM on OC1B with prescalar of 1 for 15.98KHz fast PWM
  TCCR1A = (1 << COM1B1) | (1 << WGM11) | (1 << WGM10);
  TCCR1B = (1 << WGM13) | (1 << WGM12) | (0b001 << CS10);
}

void loop() {
}

There must be a class assignment going around. I just ran into virtually the same question on the Arduino sub reddit. Same misspellings and everything.

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