NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.
Microcontroller Programming » Code for Momentary Switch to stay on or off
March 26, 2010 by EdsJunk |
I can not seem to figure out how to write some code that will allow for a momentary button (like the red one available in the kit) to toggle between on and off when pushed. also would like the MCU to remember if it was off or on when its powered off and back on. My idea right now is to replace a bunch of switches in my car with a LCD and just a couple momentary switches. so i can turn off accessories, and also being able to switch the "page" on the LCD to give the buttons other functions as well. Thanks again! |
---|---|
March 28, 2010 by EdsJunk |
anybody? I have NO CLUE what to do |
March 28, 2010 by hevans (NerdKits Staff) |
Hi EdsJunk, It sounds like you have yourself a neat project in the works I can't wait to see how it progresses. The easiest way to react to a button press is to hook up the button so that it pulls a pin low, and leaves it floating otherwise. We go into plenty of detail on this subject in our Digital Calipers DRO tutorial. Once you have the button wired up. Reading it is a matter of checking the right register. Say I had my button hooked up on PC0. I could do:
The statement PINC & (1<<PC0) checks whether the pin is a digital high or low. Since the pullup resistor keeps the pin high while the button is not pressed it is going to wait in the while loop. When the button is pressed PINC & (1<<PC0) will evaluate to 0 (or false) and the while loop will exit allowing the rest of your code to execute. There are a couple of problems with this approach. If the rest of your code runs very quickly you will loop back around before you can release the button and it might execute more than once per button press. This may or may not be ok. In our DRO example we did not have to worry about that because we were just zeroing our scale, we didn't care if it got zeroed a bunch of times in succession. This approach also freezes your main loop leaving you unable to do other tasks while waiting for a button push. A different approach would be to use a pin change interrupt on the pin with the button. The interrupt will fire when the button changes the digital state of the pin. See our Interrupts tutorial for more on how to do that. With this approach you will have to be careful of mechanical bouncing on the button when you press it, it might cause the interrupt to fire more than once. Hope that gets you started. Let us know if you run into any problems. Humberto |
March 28, 2010 by EdsJunk |
Well i have it setup right now to read the button presses.. what I want it to do is to remember when i press the button and not return to off. So for example.. if I push the button.. it stays on, if i push it again, it goes off.. right now it stays on if i hold down the button and when I let off it goes back off.. here is my code so far int main() { // start up the LCD lcd_init(); lcd_home(); lcd_line_one(); lcd_write_string(PSTR(" JeePuter 2.0 ")); lcd_line_three(); lcd_write_string(PSTR(" 1998 Jeep Wrangler")); lcd_line_four(); lcd_write_string(PSTR(" Eddie Zarick ")); delay_ms(5000); // Set the 6 pins to input mode - Two 3 bit numbers // turn on the internal resistors for the pins PORTC |= (1<<PC0); // turn on internal pull up resistor for PA0 PORTC |= (1<<PC1); // turn on internal pull up resistor for PA1 PORTC |= (1<<PC2); // turn on internal pull up resistor for PA2 PORTC |= (1<<PC3); // turn on internal pull up resistor for PA3 PORTC |= (1<<PC4); // turn on internal pull up resistor for PA4 PORTC |= (1<<PC5); // turn on internal pull up resistor for PA5 // declare the variables to represent each bit, of our two 3 bit numbers uint8_t a1; uint8_t a2; uint8_t a3; uint8_t b1; uint8_t b2; uint8_t b3; while(1) {
// print message to screen //PAGE 1 if(b3<1) { lcd_line_one();
lcd_write_string(PSTR("CB RADIO SCANNER"));
lcd_line_two();
if (a1<1) //Sets On or Off depending on pin A1
lcd_write_string(PSTR("ON "));
if (a1>0)
lcd_write_string(PSTR("OFF"));
lcd_write_string(PSTR(" "));
if (a2<1)
lcd_write_string(PSTR(" ON"));
if (a2>0)
lcd_write_string(PSTR("OFF"));
} if(b3>0) { lcd_line_one();
lcd_write_string(PSTR("SCENE L GARAGE DOOR"));
lcd_line_two();
if (a1<1)
lcd_write_string(PSTR("ON "));
if (a1>0)
lcd_write_string(PSTR("OFF"));
lcd_write_string(PSTR(" "));
if (a2<1)
lcd_write_string(PSTR(" ON"));
if (a2>0)
lcd_write_string(PSTR("OFF"));
} } return 0; } |
March 29, 2010 by hevans (NerdKits Staff) |
Hi EdsJunk, You are doing great so far. Just getting a reading from your button is certainly a huge step using buttons effectively as an input. In order to move ahead with what you want to do though you have to understand the structure of your code, and think of the type of structure you want to have. As your code currently stands, it is zooming through in the big while loop, reading the state of your PC5 pin (you are reading others but only taking this one into consideration) every time. If the pin is low, you do something, and if not you don't, and this loop keeps running over and over as fast as it can. Looking at it this way, its easy to see why your LCD reflects the current state of the button and doesn't "remember" a button press. This is actually a fairly deep concept, when you start talking about whether your programs merely reflect the current state of the world, or actually hold their own state, and will behave differently depending on what that internal state is. Since the outside circuit will be exactly the same from one button press to the next, but you want something different to happen every time you press the button, you need to hold some internal state to be able to do what you want. Luckily, this is as easy as just introducing a variable that holds information in your code. You could do something like:
Notice that I use the ! operator to flip button_state between a logical true and a logical false depending on whether the button is pressed or not. The code then acts on the state of the variable, not the current state of the pin. Now this has one major issue. If the while loop executes very quickly, you will have only a few milliseconds to press the button and let go, or else the button state will flip a whole bunch of times. That is the reason for the delay_ms(), this will give you half a second to release the button before the code continues. This is a very naive way of solving this problem, but it works. I hope all this makes sense, and gets you going in the right direction. Humberto |
January 22, 2011 by SpaceGhost |
I know this is an old topic, but I think it is pretty interesting. I did it like this:
Actually, I did it like this first to test and debug the program with the LCD:
It's a modified version of the counter that Rick had helped me with. This one-switch "push on - push off" program seems to work pretty good. Counter only counts in a 0-1 loop, and basically does something if the count equals 0, and something else if the count equals 1. The 200 ms. delay seems to work pretty good to debounce the switch. I tried it with and without. Big difference. I think it would be neat to incorporate something like this with a transistor switch on the output to turn on and off the LCD backlight of a final project... Or for other stuff not yet thought of. I have one question though - could the variable (uint8_t i) "i" be changed to something else like another letter? Is there another way I could declare that variable that would also work? |
January 23, 2011 by SpaceGhost |
Answering my own question - yes, I found that I can change the "i" variable to something else (I changed it to a j). I pretty much figured that I could, seems kinda like a dumb question now. I think something like this makes a dandy little switching "circuit"... By raising the count limit and adding extra if statements, I think it could make a nice one-button "selector switch"... Or could be used to turn on things in a sequence... Adding another switch for directional selection, and another switch for "enter" for a "menu selection" switch also comes to mind... Hmmm. This is just another reason that I like counter circuits so much - so much more that you can do with them besides count things! |
January 23, 2011 by SpaceGhost |
Actually, after looking at the code I posted, I think this way might be better -
Dave |
Please log in to post a reply.
Did you know that there are Power MOSFETs for switching big loads on and off? Learn more...
|