Question

I have a piece of code for getting same analog pwm output voltage from PB4 and PB5 using fast pwm in output compare mode. However the voltage from them is different. What could possibly be the reason for this ? Also the voltage from neither of the pins is close to 1.23 V which is what should be the output voltage should be.

Here is the code.

#include <`avr/io.h`>

#include <`avr/interrupt.h`>

ISR(TIMER0_COMP_vect)
{
    cli();
    PORTB &= ~(1<<PB5);
    sei();
}


ISR(TIMER0_OVF_vect)
{
    cli();
    PORTB |= (1<<PB5);
    sei();
}

void init(void)
{
    TCCR0 |= (0<<FOC0)|(1<<WGM01)|(1<<WGM00)|(1<<COM01)|(1<<COM00)|(1<<CS02)|(1<<CS01)|(1<<CS00);
    OCR0 = 63;
    TIMSK |= (1<<OCIE0)|(1<<TOIE0);
}


int main(void)
{
    DDRB = 0xFF;
    PORTB = 0xFF;
    init();
    sei();
    while(1);
}
Was it helpful?

Solution

Firstly, if you're using something like an ATMega328p, having all three CS bits set will enable an external clock source, rather than using the internal clock, and so the timer won't run (unless you do actually have an external timer clock source). Depending on what microcontroller you are using, make sure that those bits are enabling a particular prescaler value instead.

Secondly, you might also encounter problems due to your measurement method and the way PWM actually works. Though it is often listed as an analog output when dealing with Arduinos, pulse width modulation actually does exactly what it says - it rapidly switches a digital output between ground and VCC (likely 5V), with a varying duty cycle. If one of those output pins is viewed on an oscilloscope, it will probably show some form of square wave. enter image description here

When measured with a multimeter, the value you are seeing will be a combination of samples taken while the output is either high or low, and possibly an average of these randomly timed samples, hence the unexpected reading.

To get your desired result, you really need to smooth out the digital output. In short, this is often done with a low pass filter, composed of a resistor and capacitor attached to the output pin. enter image description here

This works by using the square wave to charge the capacitor through the resistor while it is high, and discharge it while it is low. By having more time high than low (a longer duty cycle), the capacitor stabilises at a higher voltage (and vice versa). The resistor limits the current drawn from the AVR output pin (as if the capacitor was at 0V and the output gets driven high, you're effectively shorting the output to ground momentarily).

For your case, a resistor somewhere around 4.7K and a capacitor around 2uf will probably suit. Increase the capacitance or the resistance to reduce ripple.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top