0
\$\begingroup\$

I've recently been moving from Arduino environments to AVR, and I'm programming a Tiny84 with the Sparkfun USBTiny programmer and Atmel Studio 7. For the life of me, I cannot figure out why I can't output a PWM signal.

I've tried so many different example codes, scoured the datasheet and set my own TCCR0A and TCCR0B bits to set the modes, but every program so far has either a) not lit the LED at all or b) lit the LED at full brightness, ie does not correlate to OCR0A at all. The LED MOSFET is on PB2 (OCR0A, right?) and works fine with a simple blink function. The code I'm trying currently: (this one outputs full brightness all the time. I've even tested with a normal 5V led on the output to make sure it wasn't the MOSFET having an extremely slow recovery time)

#ifndef F_CPU
#define F_CPU 8000000UL // 8 MHz clock speed
#endif

#include <avr/io.h>
//#include <avr/interrupt.h>
#include <util/delay.h>


int main(void)
{   
    DDRB |= 1 << PB2;
    TCCR0A |= (1<<WGM00)|(1<<COM0A1);
    TCCR0B |= (1<<WGM02)|(1<<CS00);

    while(1){
        for (uint8_t i = 0; i < 255; i++) {
            OCR0A = i;
            _delay_ms(4);
        }

        for (uint8_t i = 255; i >= 0; i--) {
            OCR0A = i;
            _delay_ms(4);
        }
    }
}

As I understand, this should be phase correct PWM, clear on OCR0A match, and no pre-scaler

And the (full) schematic: tiny84LEDdriver I'm attempting to put PWM on the White control MOSFET, which is driving a small section of 12V LED strip. MOSFETs are NVR4501NT1G n-channel

This is on a custom-made board which had the problem of a broken ground plane where I haphazardly placed mousebites, so I have two bodge wires to fix that issue.

Any help would be greatly appreciated; even just an example of what should work would let me know whether this is a software issue or another problem with my board.

\$\endgroup\$
3
\$\begingroup\$

I think your issue may be the choice of waveform generation mode.

Looking at the datasheet (extract from page 83): enter image description here

You have set bits WGM02 and WGM00 so you are using mode 5. You can see that in mode 5 the timer TOP is at OCRA, so the timer is counting from 0 up to the value you have written into the OCR0A register, but then resetting to zero before the pin output has a chance to go low, so you have 100% duty cycle PWM.

Using mode 1 should work as expected, as TOP is at 0xFF so the timer will count from 0 to 255 each time and give the 8-bit resolution fixed frequency PWM output you expect. Just don't set bit WGM02.

Also as an aside: I think you second for loop has an issue. The test condition is that i is >= 0 but this will always be true for an unsigned integer as it will wrap around from 0 to 255. Using a signed integer type like int16_t would work, or you could test for > 0 which will become false once i equals 0.

Hope that helps.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.