May 13, 2011
by SpaceGhost
|
I've been working on what should be a simple piece of code for several days now, and it's really starting to drive me nuts!
This function of the code works -
When the pushbutton is pressed LEDs 1 & 2 turn on and stay on until the button is released. LED 3 is off for the duration of the button press also.
When the pushbutton is released, LED 1 turns off and LED 3 turns on. LED 2 stays on for a duration of 900 ms., then turns off too...
What isn't working, is that I need LED 3 to turn off when LED 2 turns off.
///////////////// rbeep03
#define F_CPU 14745600
#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>
#include "../libnerdkits/delay.h"
#include "../libnerdkits/lcd.h"
int main() {
// fire up the LCD
lcd_init();
FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);
lcd_home();
DDRC |= (1<<PC0); // Set pin 23 as LED 1
DDRB |= (1<<PB5); // Set pin 19 as LED 2
DDRB |= (1<<PB4); // Set pin 18 as LED 3
DDRC &= ~(1<<PC5); // set PC5 (pin 28) as TX button (sink input)
PORTC |= (1<<PC5); // turn on internal pull up resistor (pin 28)
// declare variable to represent pushbutton input
uint8_t a;
a = 0;
while(1) {
lcd_line_one();
fprintf_P(&lcd_stream, PSTR("%u "), a);
if (!(PINC & (1<<PC5))) { // pin goes low on push
PORTC |= (1<<PC0); // LED 1 on
PORTB |= (1<<PB5); // LED 2 on
a = 1;
}
else {
PORTC &= ~(1<<PC0); // LED 1 off
PORTB |= (1<<PB4); // LED 3 on
a = 0;
}
if (a == 0) {
delay_ms(900); // delay
PORTB &= ~(1<<PB4); // LED 3 off
PORTB &= ~(1<<PB5); // LED 2 off
}
}
return 0;
}
I've tried several ways to get this to happen - but that darned LED 3 always stays on! (though at least I get it to turn off when the button is pressed, which is what I want it to do too).
Could someone please explain to me why oh why do these lines -
if (a == 0) {
delay_ms(900); // delay
PORTB &= ~(1<<PB4); // LED 3 off
PORTB &= ~(1<<PB5); // LED 2 off
}
work to turn off LED 2, but does not turn off LED 3 at the same time???
Dave |
May 13, 2011
by bretm
|
LED 3 does go off. And then your loop starts over, and because the button is not pushed it turns LED on again and starts the 900ms delay again, etc. You need to do something like this:
while (1)
{
// do LCD stuff
while (button isn't pushed)
; // do nothing
// turn on 1 and 2
delay_ms(50); // for debouncing
while (button is pushed)
; // do nothing
// turn off 1
// turn on 3
delay_ms(900);
// turn off 2
// turn off 3
}
|
May 14, 2011
by SpaceGhost
|
On my way to work, I will try this out when I get home this afternoon...
I should have searched the forums for "do nothing", and I might have saved myself a few a hours!
Thanks bretm again, for the point in the right direction.
Dave |
May 14, 2011
by SpaceGhost
|
Hey, works great - problem solved.
This bit of knowledge will most definitely help me out in future projects. Once I put the while statements where they belonged, it actually made sense for me. Then I got rid of that silly "if (a == 0)" statement and tidied up the code a bit. Had to move the LCD instructions into the button state loops too, of course -
///////////////// rbeep03
#define F_CPU 14745600
#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>
#include "../libnerdkits/delay.h"
#include "../libnerdkits/lcd.h"
int main() {
// fire up the LCD
lcd_init();
FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);
lcd_home();
DDRC |= (1<<PC0); // Set pin 23 as LED 1
DDRB |= (1<<PB5); // Set pin 19 as LED 2
DDRB |= (1<<PB4); // Set pin 18 as LED 3
DDRC &= ~(1<<PC5); // set PC5 (pin 28) as TX button (sink input)
PORTC |= (1<<PC5); // turn on internal pull up resistor (pin 28)
// declare variable to represent pushbutton input
uint8_t a;
a = 0;
while(1) {
while ((PINC & (1<<PC5)));
if (!(PINC & (1<<PC5))) { // pin goes low on push
PORTC |= (1<<PC0); // LED 1 on
PORTB |= (1<<PB5); // LED 2 on
a = 1;
lcd_line_one();
fprintf_P(&lcd_stream, PSTR("%u "), a);
}
while (!(PINC & (1<<PC5)));
if ((PINC & (1<<PC5))) { // switch open
PORTC &= ~(1<<PC0); // LED 1 off
PORTB |= (1<<PB4); // LED 3 on
delay_ms(900); // delay
PORTB &= ~(1<<PB4); // LED 3 off
PORTB &= ~(1<<PB5); // LED 2 off
a = 0;
lcd_line_one();
fprintf_P(&lcd_stream, PSTR("%u "), a);
}
}
return 0;
}
This was a good lesson for me, hope that it can help someone else out too. Thanks bretm!
Dave |