Society of Robots - Robot Forum

Software => Software => Topic started by: newInRobotics on September 08, 2011, 02:44:47 PM

Title: ATmega48 - falling edge interrupt regulated PWM - issue with code
Post by: newInRobotics on September 08, 2011, 02:44:47 PM
##################################################################################
Solved! ButtonRelease detection was changed by ButtonPressed detection. Works like a charm  ;D

Code: [Select]
while(!(PIND & (1 << PIND2))){} // Button release detectionto
Code: [Select]
while(PIND & (1 << PIND2)){} // Button pressed detection##################################################################################

Hi everyone

I've recently started learning uC programming. My first small project is PWM driven LED torch with 3 brightness settings and off mode (duty cycle = 0%).

My problem is that with a single button press, PWM compare value is changed twice (incremented twice) instead of single increment. In other words:
LEDOff --> BtnPressRelease --> LEDBrightnessLevel1 --> Delay(2sec) --> LEDBrightnessLevel2
then
LEDBrightnessLevel2 --> BtnPressRelease --> LEDBrightnessLevel3 --> Delay(2sec) --> LEDOff.

I do not understand why that happens. Code is below:

Code: [Select]
#define F_CPU 1000000UL

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

int main(void)
{
PORTD |= 1 << PORTD2; // Set PD2 (INT0) high (pull - up)

TCCR1A |= 1 << COM1A1; // Set OC1A on Compare Match when upcounting, clear - when downcounting
TCCR1A |= 1 << WGM11; // PWM, phase and frequency correct

TCCR1B |= 1 << WGM13; // PWM, phase and frequency correct
TCCR1B |= 1 << CS10; // No timer prescaling

ICR1 = 3; // PWM top value

OCR1A = 0; // PWM compare value;

EICRA |= 1 << ISC01; // The falling edge of INT0 (PD2) generates an interrupt request

EIMSK |= 1 << INT0; // Enable INT0 external interrupt

SREG |= 1 << 7; // Enable global interrupt

DDRB |= 1 << DDB1; // Set PB1 (OSC1A) as output

while(1)
{}
}

ISR(INT0_vect) // Routine when interrupt occours
{
while(!(PIND & (1 << PIND2))){} // Button release detection

if(OCR1A < 3) // If(DutyCycle < 100%)
{
OCR1A++; // Increase PWM compare value by 1 (increase duty cycle)
}

else
{
OCR1A = 0; // Set PWM compare value to 0 (set duty cycle to 0%)
}

_delay_ms(2000);
}
Title: Re: ATmega48 - falling edge interrupt regulated PWM - issue with code
Post by: joe61 on September 08, 2011, 03:12:45 PM
The problem is mechanical switches bounce when pushed, and things happen fast enough in a microcontroller that you can get more than one reading while it's bouncing. You could try reading it, waiting some period of time, then checking to see if the value changed. Do that until you get the same value.

I'm not a good one to explain this, I don't understand the details well enough. There are some interesting threads about this on the avrfreaks web site, and this has probably more information than you want: http://www.ganssle.com/debouncing.pdf (http://www.ganssle.com/debouncing.pdf)

Joe
Title: Re: ATmega48 - falling edge interrupt regulated PWM - issue with code
Post by: newInRobotics on September 09, 2011, 12:47:39 AM
I would expect my code to deal with debounce as interrupt event is triggered by buttonDown action, however it has to wait for button to be released to carry on executing interrupt routine, and then at the end it does nothing for ~2s (delay). So if first interrupt is triggered by first falling edge detected on input pin, how come the second event occurs after 2 second delay?
Title: Re: ATmega48 - falling edge interrupt regulated PWM - issue with code
Post by: joe61 on September 09, 2011, 06:31:19 AM
Well, I think you'll get more than one "button down" interrupt because of the bounce. Someone else here may correct me  but that's my understanding.

So here's what I would expect:


Code: [Select]
ISR(INT0_vect) // Routine when interrupt occours
{
    while(!(PIND & (1 << PIND2))){} // Button release detection

    [ ...]

}

When the switch bounces up, this loop will end and the following code will execute. Then the ISR will be called again when the switch bounces down. I would think the 2ms delay at the end of the isr would deal with that, but I've heard of switches that take longer to stop bouncing.

I don't know that this is the case, but there are a lot of people who put a lot of effort into debouncing because it's tricky.

Joe
Title: Re: ATmega48 - falling edge interrupt regulated PWM - issue with code
Post by: newInRobotics on September 09, 2011, 08:19:07 AM
Hi joe61

When the switch bounces up, this loop will end and the following code will execute. Then the ISR will be called again when the switch bounces down. I would think the 2ms delay at the end of the isr would deal with that, but I've heard of switches that take longer to stop bouncing.
I understand what You say, however, the delay is NOT 2ms, it is 2s (2000ms). You can set my hair on fire and call me a princess, but bouncing does not last for 2 seconds. Also, after first interrupt trigger, that interrupt becomes disabled as long as it's function is running.

I'll try to use RC de-bouncer to see if it really is related to bouncing button.
Title: Re: ATmega48 - falling edge interrupt regulated PWM - issue with code
Post by: joe61 on September 09, 2011, 11:03:57 AM
I understand what You say, however, the delay is NOT 2ms, it is 2s (2000ms).

My mistake, sorry.

Joe
Title: Re: ATmega48 - falling edge interrupt regulated PWM - issue with code
Post by: newInRobotics on September 09, 2011, 11:42:44 AM
Got it sorted :) Have a loot at the first post.