I planned to add a time setting mode to the alarm clock later, as gravy-- thought I wouldn't need one since the clock chip keeps time-- but with the board not yet built, I keep accidentally disconnecting the DS1307's battery and needing to reset it with a special sketch.
That's a pain, so I'm adding it to the PPAC program next, and to keep the interface simple-- jog/shuttle and a button-- a press and hold event seems appropriate for switching into an otherwise hidden mode, like shutting down a MacBook by holding down the button instead of just clicking it.
Despite a few posted examples on debouncing a button press (explicitly or with a library), I couldn't find any press+hold examples, so I took a stab at it and got a test sketch working pretty quickly with a button and two indicator LEDs. The code is posted below, as a comment.
Subscribe to:
Post Comments (Atom)

/* Click and Press+Hold Test Sketch
ReplyDeleteBy Jeff Saltzman
To keep input interfaces simple, I want to use a single button to:
1) click (fast press and release) for regular button use, and
2) press and hold to enter a configuration mode.
*/
#define buttonPin 19 // analog input pin to use as a digital input
#define ledPin1 9 // digital output pin for LED 1 indicator
#define ledPin2 8 // digital output pin for LED 2 indicator
#define debounce 20 // ms debounce period to prevent flickering when pressing or releasing the button
#define holdTime 2000 // ms hold period: how long to wait for press+hold event
// Button variables
int buttonVal = 0; // value read from button
int buttonLast = 0; // buffered value of the button's previous state
long btnDnTime; // time the button was pressed down
long btnUpTime; // time the button was released
boolean ignoreUp = false; // whether to ignore the button release because the click+hold was triggered
// LED variables
boolean ledVal1 = false; // state of LED 1
boolean ledVal2 = false; // state of LED 2
//=================================================
void setup()
{
// Set button input pin
pinMode(buttonPin, INPUT);
digitalWrite(buttonPin, HIGH );
// Set LED output pins
pinMode(ledPin1, OUTPUT);
digitalWrite(ledPin1, ledVal1);
pinMode(ledPin2, OUTPUT);
digitalWrite(ledPin2, ledVal2);
}
//=================================================
void loop()
{
// Read the state of the button
buttonVal = digitalRead(buttonPin);
// Test for button pressed and store the down time
if (buttonVal == LOW && buttonLast == HIGH && (millis() - btnUpTime) > long(debounce))
{
btnDnTime = millis();
}
// Test for button release and store the up time
if (buttonVal == HIGH && buttonLast == LOW && (millis() - btnDnTime) > long(debounce))
{
if (ignoreUp == false) event1();
else ignoreUp = false;
btnUpTime = millis();
}
// Test for button held down for longer than the hold time
if (buttonVal == LOW && (millis() - btnDnTime) > long(holdTime))
{
event2();
ignoreUp = true;
btnDnTime = millis();
}
buttonLast = buttonVal;
}
//=================================================
// Events to trigger by click and press+hold
void event1()
{
ledVal1 = !ledVal1;
digitalWrite(ledPin1, ledVal1);
}
void event2()
{
ledVal2 = !ledVal2;
digitalWrite(ledPin2, ledVal2);
}
how do you have it wired. i tried on my arduino uno and i get nothing.
Deletevery, very nice! I think a lot of 'duino with LCD's just got nested menus because of you!
ReplyDeleteGotta say that's a great idea. Seems so simply obvious to do that now that you've stated it. :-)
ReplyDeleteI think that's begging to become a compliment to AlphaBeta's Button abstraction layer: http://www.arduino.cc/playground/Code/Button.
We could start coding all that in two lines like this, and get down to the fun stuff:
Button pressMe = button(2, PULLUP);
if (pressMe.held(1000)) someFunction();
I used something like this in a project I was working on. Though I think this could be compacted further. If you use a simple counter 'while' or 'for' loop, you can have the led turn on, or the function occur right when the threshold between a 'press' and a 'hold' is crossed.
ReplyDeleteAttach this function to an interrupt pin
int ButtonCheck(){
count = 0;
while(digitalRead(But)==HIGH){
delay(10);
count++;
}
if (count > 100){ /button held
return 2; /button held
else if count > 0
return 1; /button pressed
}
}
What about a double press?
ReplyDeleteI'm working on a similar code but with a sensor instead. I've been trying for days to convert the code but no luck.
ReplyDeleteHere's the code I have for the sensor to turn off a single led.
void loop() {
val = analogRead(LDR);
if (val2 < 28)
{digitalWrite(ledPin, HIGH);
//delay(3000);
} else {
digitalWrite(ledPin, LOW); // turn the ledPin off
}
//delay(1000);
}
Thanks, 12 year old from Toronto