Society of Robots - Robot Forum
Software => Software => Topic started by: newInRobotics on September 08, 2011, 02:44:47 PM
-
##################################################################################
Solved! ButtonRelease detection was changed by ButtonPressed detection. Works like a charm ;D
while(!(PIND & (1 << PIND2))){} // Button release detection
to
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:
#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);
}
-
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
-
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?
-
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:
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
-
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.
-
I understand what You say, however, the delay is NOT 2ms, it is 2s (2000ms).
My mistake, sorry.
Joe
-
Got it sorted :) Have a loot at the first post.