Montréal, Qc
Offline
Full Member
Karma: 0
Posts: 185
Practice safe hex!
|
 |
« on: December 06, 2006, 02:08:44 pm » |
I'm sorry if this is a little stupid, I'm totally new to this (I got the board yesterday ;D ) I'm trying to code a "soft button". Press once the circuit turns on (a LED in this case) press another time and it turns off... It actually works, but only partially. Most of the times when I hit the button the LED will light up until I release the button. If I press many times in a row it will however produce the desired effect and turn on or off the LED. int flashLED = 11; int statusLED = 13; int actionBTN = 12; int btnValue = 0; int softValue = 0; void setup(void) { // initialize inputs/outputs pinMode(flashLED, OUTPUT); pinMode(statusLED, OUTPUT); pinMode(actionBTN, INPUT); digitalWrite(statusLED, HIGH); // I just want to know when the AVR is done booting } void loop(void) { btnValue = digitalRead(actionBTN);
if (btnValue == LOW) { if (softValue == 0) { softValue = 1; } else { softValue = 0; } } if (softValue == 1) { digitalWrite(flashLED, HIGH); } else { digitalWrite(flashLED, LOW); } }
|
|
|
|
|
Logged
|
"Pilots believe in a clean living... they never drink wisky from a dirty glass."
|
|
|
|
Montréal, Qc
Offline
Full Member
Karma: 0
Posts: 185
Practice safe hex!
|
 |
« Reply #1 on: December 06, 2006, 02:28:49 pm » |
Well, adding a bit of delay at the bottom of the (btnValue == LOW) statement seems to help. It works nicely with a "static" LED. If I use a flashing LED though, it will turn it on, but the problem is the same when trying to turn it off.
|
|
|
|
|
Logged
|
"Pilots believe in a clean living... they never drink wisky from a dirty glass."
|
|
|
|
Florida, USA
Offline
Full Member
Karma: 0
Posts: 146
meow!
|
 |
« Reply #2 on: December 08, 2006, 03:37:43 pm » |
When I read your code literally, it looks like you are looping as fast as possible, polling digital input pin 12. If that pin is LOW, you are rapidly toggling the output pin 11 HIGH/LOW. In fact, it is probably so rapid that it appears to be on all the time. Two things occur to me: 1. Instead of toggling every time you see pin 12 low, you probably want to toggle only when it goes from high to low. 2. Even that probably won't work right, because real mechanical switches have a tendency to produce noise for a millisecond or so while they are transitioning between open and closed, or closed and open. So you may want to add a delay(1) on each loop, notice when you are transitioning from input pin 12 being high to low, and then start a countdown of maybe 50 loops (or 0.05 seconds). Only when pin 12 has been low for 0.05 seconds, immediately after having just been high, should you toggle the output state.
Oh, and instead of doing this:
if (softValue == 0) { softValue = 1; } else { softValue = 0; }
you can do this, which will do the same thing:
softvalue = !softvalue;
Likewise, because HIGH==1 and LOW==0 (see lib\targets\arduino\wiring.h), you can replace:
if (softValue == 1) { digitalWrite(flashLED, HIGH); } else { digitalWrite(flashLED, LOW); }
with:
digitalWrite (flashLed, softValue);
I'm not sure if my earlier suggestion is phrased in an understandable way. Feel free to post again with questions and I'll do my best to help!
- Don
|
|
|
|
|
Logged
|
|
|
|
|
Montréal, Qc
Offline
Full Member
Karma: 0
Posts: 185
Practice safe hex!
|
 |
« Reply #3 on: December 09, 2006, 01:56:09 am » |
Thanks for the pointers! I've been able to make this work. The code was refined. I did not have to take the noise into account with the switch and code I'm using (the switch is the one included on the SparkFun protoshield). The only thing that could still be integrated (noise excluded) is soft debounce, as it's now tracking changes of LOW to HIGH state. I'll have to look into it, but I don't think it would be so hard to do. I'll post an update when I do. Here is what I came up with. int statusLED = 13; int flashLED = 11; int actionBtn = 12; int btnVal = 0; int softVal = 0; int lastBtnVal = HIGH;
void setup () { pinMode(statusLED, OUTPUT); digitalWrite(statusLED, HIGH); pinMode(flashLED, OUTPUT); pinMode(actionBtn, INPUT); beginSerial(9600); // Connect to the serial port, used for debugging }
void loop() { btnVal = digitalRead(actionBtn); if (btnVal == LOW && lastBtnVal == HIGH) { lastBtnVal = LOW; Serial.println("Going low"); } if (btnVal == HIGH && lastBtnVal == LOW) { softVal = !softVal; lastBtnVal = HIGH; Serial.println("Going high"); } digitalWrite(flashLED, softVal); }
Hopefully this will help others too 
|
|
|
|
|
Logged
|
"Pilots believe in a clean living... they never drink wisky from a dirty glass."
|
|
|
|
Montréal, Qc
Offline
Full Member
Karma: 0
Posts: 185
Practice safe hex!
|
 |
« Reply #4 on: December 09, 2006, 03:42:50 pm » |
I got around implementing soft debounce and figured I could post the code, maybe others will find it useful, maybe others will be able to tell me if I did anything wrong. It works very nicely as far as I can see. int statusLED = 13; int flashLED = 11; int actionBtn = 12; int btnVal = 0; int softVal = 0; int bounceTime = 0; int lastBtnVal = HIGH;
void setup () { pinMode(statusLED, OUTPUT); digitalWrite(statusLED, HIGH); pinMode(flashLED, OUTPUT); pinMode(actionBtn, INPUT); Serial.begin(9600); // connect to the serial port Serial.println("Initialized"); }
void loop() { btnVal = digitalRead(actionBtn); if (btnVal == LOW && lastBtnVal == HIGH && bounceTime != -1) { lastBtnVal = LOW; Serial.println("Going low"); } if (bounceTime == -1 && btnVal == HIGH) { bounceTime = 0; } if (btnVal == LOW && lastBtnVal == LOW) { bounceTime++; if (bounceTime >= 50) { bounceTime = -1; btnVal = HIGH; Serial.println("Action button debounced!"); } } if (btnVal == HIGH && lastBtnVal == LOW) { softVal = !softVal; lastBtnVal = HIGH; Serial.print("Going high with softVal to: "); Serial.println(softVal); } digitalWrite(flashLED, softVal); }
|
|
|
|
« Last Edit: December 09, 2006, 04:09:54 pm by xSmurf »
|
Logged
|
"Pilots believe in a clean living... they never drink wisky from a dirty glass."
|
|
|
|
Montréal, Qc
Offline
Full Member
Karma: 0
Posts: 185
Practice safe hex!
|
 |
« Reply #5 on: December 10, 2006, 11:21:03 pm » |
Here's a little video of the result, including a pulsating LED without using delay() http://www.youtube.com/v/krln7ZwSt8E/* Software Pulsating LED using PWM * -------------------------------- * * This example does not use delay() as to not block the cpu from processing other stuff * the down side is it might jerk off when stuff interrupts the cpu. * * (cleft) 2005 by Matthieu Lalonde * <http://smurfturf.net> * <mailto:mlalonde(at)smurfturf(dot)net> * */ // Pins definition #define statusLED 13 #define actionBtn 12 // The input button #define protoLED 11 // The output led
/* ** Program variables ** */ // Button variables int btnVal = 0; // Used to store the button's value on cycle int softVal = 0; // The software value of the button int bounceInterval = 50; // bounce interval in cycles int bounceTime = 0; // Bounce cycle counts int lastBtnVal = HIGH; // Last cycle's button value // Pulsation variables long previousMillis = 0; // Will store last time LED was updated int interval = 10; // interval at which to blink (milliseconds) int i = 0; // Cycle counter for the pulsating effect int valLED = 0; // Stores the current PWM value for the LED int stopNextRun = 0; /* *********************** */
void setup () { pinMode(protoLED, OUTPUT); pinMode(actionBtn, INPUT);
Serial.begin(9600); reportAVRState(3, 1); }
void loop() { btnVal = digitalRead(actionBtn);
if (btnVal) { readRemoteSoftVal(); }
if (btnVal == LOW && lastBtnVal == HIGH && bounceTime != -1) { lastBtnVal = LOW; Serial.println("Going low"); }
if (bounceTime == -1 && btnVal == HIGH) { bounceTime = 0; }
if (btnVal == LOW && lastBtnVal == LOW) { bounceTime++; if (bounceTime >= bounceInterval) { bounceTime = -1; btnVal = HIGH; Serial.println("Action button debounced!"); } }
if (btnVal == HIGH && lastBtnVal == LOW) { softVal = !softVal; lastBtnVal = HIGH; Serial.print("Going high with softVal to: "); Serial.println(softVal); }
// We want the LED to be off! if (!softVal) { digitalWrite(protoLED, softVal); previousMillis = 0; valLED = 0; i = 0; } // Pulsate that shiny thing! else { // check to see if it's time to blink the LED; that is, is the difference // between the current time and last time we blinked the LED bigger than // the interval at which we want to blink the LED. if (millis() - previousMillis > interval) { previousMillis = millis(); // remember the last time we blinked the LED
i++; // Pulsating up if (i < 175) { interval = 15; valLED = i; } // Let's light it up for a bit more time in the middle else if (i == 175) { valLED = 175; interval = 20; } // Pulsating down else if (i < 350) { interval = 10; valLED = (175 - (i - 175)); } // The led is off, the loop restarts else { i = 0; valLED = 0; interval = 20; }
analogWrite(protoLED, valLED); } } }
void readRemoteSoftVal( void ) { int incomingByte = 0;
// send data only when you receive data: if (Serial.available() > 0) { // read the incoming byte: incomingByte = Serial.read();
if (incomingByte == 49) { btnVal&= LOW; } }
btnVal&= HIGH; }
// Reports the state of the controller via pin 13's led and serial void reportAVRState(int howManyTimes, int leaveOn) { int i;
pinMode(statusLED, OUTPUT);
for (i=0; i< howManyTimes; i++) { digitalWrite(statusLED, HIGH); delay(200); digitalWrite(statusLED, LOW); delay(200); }
if (leaveOn) { digitalWrite(statusLED, HIGH); }
Serial.println("AVR Initialized"); }
|
|
|
|
|
Logged
|
"Pilots believe in a clean living... they never drink wisky from a dirty glass."
|
|
|
|
|