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.
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. )
#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);
}
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%.
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.