SpenceKonde / ATTinyCore

Arduino core for ATtiny 1634, 828, x313, x4, x41, x5, x61, x7 and x8
Other
1.53k stars 302 forks source link

Attiny84(a): Phase Correct PWM on Timer 0 issue? #736

Closed NaokiS28 closed 1 year ago

NaokiS28 commented 1 year ago

Hi there. I've been trying for about 4 hours now to generate a PWM signal from an ATTiny84 using the internal 8Mhz internal oscillator. I've set the options to use optiboot, don't use millis/micros() and burnt the bootloader but I cannot get a proper PWM output. I'm uploading using the USBasp programmer.

I've been using code from an example to try generate a 140Hz PWM with 20% duty cycle: ` void setup() { pinMode(8, OUTPUT);

//DDRB = (1 << PB2); TCCR0A = (1<<COM0A1) | (1<<WGM00); TCCR0B = ((1<<WGM02) | 0x04);

OCR0A = 223;

OCR0B = 44; }

void loop() { } `

But at least with my setup, it just does not generate the expected PWM signal. Timer 1 also does not work at all how I expect it to either no matter the options. Using any of the bootloaders or not changes the behavoir but doesn't make it work.

Finally, I tested the same code on an arduino uno and it works perfectly fine. Is this just a problem with the library or am I missing something?

Thanks

hmeijdam commented 1 year ago

You are setting for optiboot, but then you are using an USBASP instead of using optiboot as method for uploading? That looks wrong to me.

NaokiS28 commented 1 year ago

It doesnt work even with the no bootloader option.

SpenceKonde commented 1 year ago

Require specific examples that demonstrate issue to proceed

NaokiS28 commented 1 year ago

The code in my comment is the exact code I'm currently using and it just results in a low output on pin 8/PB2

NaokiS28 commented 1 year ago

I've changed the code to now use Timer 1 but unless I'm missing something painfully obvious, this still just does not work.

Code: `void setup() { // put your setup code here, to run once: DDRA = (1 << PA6); TCCR1A = ((1<<COM1A1) | (1<<COM1A0) | (1 << WGM11) | (1<<WGM10)); // PWM, Phase correct - change at OCR2A, inverted TCCR1B = ((1<<WGM13) | 0b100); // prescaling by 256 the system clock OCR1A = 223; // 140hz for jaguar fan OCR1B = 6; // 5% PWM }

void loop() { // put your main code here, to run repeatedly:

} `

EDIT: I found that using PA5 will work as expected, using Timer 1. Timer 0 just never works regardless whether I use OCR0 A or B. Timer 1 will not work on OCR1 A using the code above. Not sure if the millis() stuff is overriding my code in the initial example?

SpenceKonde commented 1 year ago

TCA0 phase correct PWM should break millis timekeeping, not the other way around (phase correct / "dual slope" pwm always breaksd millis, because you can't efficiently tell if the timer is counting up or down at t the moment.

SpenceKonde commented 1 year ago

It sounds to me like this issue has been resolved as best it can be - phase correct PWM mode cannot be used on timer0 if millis() is enabled. This is the case everywhere - if millis tried to use it it couldn't determine if it was in the first or second half of a cycle, and thus could not calculate micros, (thus breaking delay() as well) Use Timer1 if phase correct PWM is required, or if you need 2 phase correct timers, use the pin compatible tiny841 which has an extra timer (with remappable output pins!).