I'm trying to make a single momentary switch serve a dual function. I want it to turn a pin High while pressed then when released turn the first pin Low and turn a second pin High for 1 second before turning it Low as well.
I've tried dozens of times to use If statements and variables but I'm missing something and I don't know what. I'd post my example code but it doesn't work and I don't think I'm on the right track with it at all.
It's not that I can't post the code, it's that my code is useless. I've modified it and tried integrating so many examples that it's spaghetti now.
I'm hoping for a pointer or example code that I can build on to accomplish the task listed above starting from scratch.
There is two concepts you need to master to accomplish this task. The first is signal edge detection. Here is an example with an explanation:
/*
* Example for "Edge Detection"
* Edge detection refers to determining the point at which a digital signal moves
* from low to high or high to low. Low to high is refered to as the 'positive' or
* rising edge. High to low is the 'negative or falling' edge. This example uses a
* button to run a commands at each edge, identifying the edge. Edges occur on a
* a button when it is either pushed or released. If the input pin is pulled high,
* pushing the button down wil be the falling edge, while releasing it will be th
* rising edge. If the input pin is pulled high, the opposite will be true.
*
* NOTE: This example does not utilize a debounce, so it's entirely possible that
* you'll see multiple prints if using a device, such as a button, that bounces
* during signal change.
*/
// Pin used for our digital signal
const short inputPin = 5;
void setup() {
Serial.begin(57600);
Serial.println("[EdgeDetection]");
pinMode(inputPin, INPUT); // Set the pin as input
digitalWrite(inputPin, HIGH); // enable pull-up resistor. (Pulled high)
}
void loop() {
/* Keep track of the last state of the button. A static variable will
* only be initialized the first time and will hold it's value through
* each loop. */
static short lastState = HIGH;
// Get the current state of the pin
short currentState = digitalRead(inputPin);
// Check for the falling edge
if ( (currentState==HIGH) && (lastState==LOW) ) {
fallingEdge();
}
// Check for rising edge
if ( (currentState==LOW) && (lastState==HIGH) ) {
risingEdge();
}
lastState = currentState;
}
void fallingEdge() {
Serial.println("Falling edge");
}
void risingEdge() {
Serial.println("Rising Edge");
}
You also need to understand how to schedule a task (in your case, turn off an LED) without using the delay() command. Check out the Blink Without Delay example to see how to use millis() to keep track of a timer that will allow you to determine when it's been longer than 1 second and turn off the LED accordingly.
Thanks, I got the buttons to do what I needed. One last question though.
How can I make it so that there is a second button that must be pressed at the very start before the other button will do anything.
I tried this code and it turns on the LED for power but the second part of the code still executes regardless of the state of the power LED.
const short inputPin = 5;
const short button = 6;
int LED1 = 2;
int LED2 = 3;
int LED3 = 13;
void setup() {
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(LED3, OUTPUT);
pinMode(inputPin, INPUT); // Set the pin as input
digitalWrite(inputPin, HIGH); // enable pull-up resistor. (Pulled high)
pinMode(button, INPUT);
digitalWrite(button, HIGH);
}
void loop() {
/* Keep track of the last state of the button. A static variable will
* only be initialized the first time and will hold it's value through
* each loop. */
static short lastState = LOW;
static short lastState2 = LOW;
// Get the current state of the pin
short currentState = digitalRead(inputPin);
short currentState2 = digitalRead(button);
if ((currentState2==HIGH) && (lastState==LOW))
digitalWrite(LED3, HIGH); {
// Check for the falling edge
if ( (currentState==HIGH) && (lastState==LOW) ) {
fallingEdge();
}
// Check for rising edge
if ( (currentState==LOW) && (lastState==HIGH) ) {
risingEdge();
}
lastState = currentState;
lastState2 = currentState2;
}
}
void fallingEdge() {
digitalWrite(LED2, LOW);
delay(100);
digitalWrite(LED1, HIGH);
}
void risingEdge() {
digitalWrite(LED1, LOW);
delay(100);
digitalWrite(LED2, HIGH);
delay(1000);
digitalWrite(LED2, LOW);
}
KE5AFU:
Thanks, I got the buttons to do what I needed. One last question though.
How can I make it so that there is a second button that must be pressed at the very start before the other button will do anything.
I tried this code and it turns on the LED for power but the second part of the code still executes regardless of the state of the power LED.
That depends on what you mean by "pressed." Does that mean pressed down? Pressed down and released? Does the second button have to be pressed within a certain interval from the first button pressed?
This block of code has some issues:
if ((currentState2==HIGH) && (lastState==LOW))
digitalWrite(LED3, HIGH); {
// Check for the falling edge
if ( (currentState==HIGH) && (lastState==LOW) ) {
fallingEdge();
}
// Check for rising edge
if ( (currentState==LOW) && (lastState==HIGH) ) {
risingEdge();
}
}
Based on your declarations, I'm assuming that first line of code should be lastState2? I also imagine that the first '{' should be on the first line, or by itself on the second line, so that it can encompasses all of the code in that block. Assuming those weren't intentional, the logic in this block is also going to cause issues. Are you expecting both buttons' edges to occur at the exact same time? When your if is nested like that, you expect both conditions to occur at the same time, and those edges will occur only once (ideally) per button push. The likelihood they occur during the same loop iteration is fairly slim.
Sorry for not being clear, the first button pressed and released is my intent, the second button will be pressed and released many times after the first one has been pressed and released but timing is not critical at all on it.
The buttons will not be pressed and released at the same time, in fact after the first edge trigger on button one (to activate the second button) it will never be used again, just the second button.
I somewhat follow you on the brackets, where should I move them to? I wasn't sure if it was a bracket issue or bad code (e.g. better way to write what I want) issue.
KE5AFU:
Sorry for not being clear, the first button pressed and released is my intent, the second button will be pressed and released many times after the first one has been pressed and released but timing is not critical at all on it.
The buttons will not be pressed and released at the same time, in fact after the first edge trigger on button one (to activate the second button) it will never be used again, just the second button.
I somewhat follow you on the brackets, where should I move them to? I wasn't sure if it was a bracket issue or bad code (e.g. better way to write what I want) issue.
So you'll need a state variable. You won't need to worry about edge detection with the first button, once it gets pressed down, you can set the state variable accordingly. Then, whenever you check an edge on the second button, you should also make sure that the state is set properly before you perform an action.
I posted the code below. It all works the way I wanted it to, though I don't know if it is the proper way to code for this application or not.
Jack, Thanks for posting your library but I wanted to do it this way to get a better understanding of how the code works instead of a precompiled source.
const short inputPin = 5;
int button = 6;
int LED1 = 2;
int LED2 = 3;
int LED3 = 4;
int val;
int buttonState;
void setup() {
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(LED3, OUTPUT);
pinMode(inputPin, INPUT); // Set the pin as input
digitalWrite(inputPin, HIGH); // enable pull-up resistor. (Pulled high)
pinMode(button, INPUT);
val = LOW;
buttonState = digitalRead(button);
}
void loop() {
/* Keep track of the last state of the button. A static variable will
* only be initialized the first time and will hold it's value through
* each loop. */
static short lastState = LOW;
// Get the current state of the pin
short currentState = digitalRead(inputPin);
val = digitalRead(button);
if (val != buttonState){
digitalWrite(LED3, HIGH);
val = HIGH;
}
else {
digitalWrite(LED3, LOW);
val = LOW;
}
// Check for the falling edge
if ( (val == HIGH) && (currentState==HIGH) && (lastState==LOW) ) {
fallingEdge();
}
// Check for rising edge
if ( (val == HIGH) && (currentState==LOW) && (lastState==HIGH) ) {
risingEdge();
}
lastState = currentState;
buttonState = val;
}
void fallingEdge() {
digitalWrite(LED2, LOW);
delay(100);
digitalWrite(LED1, HIGH);
}
void risingEdge() {
digitalWrite(LED1, LOW);
delay(100);
digitalWrite(LED2, HIGH);
delay(1000);
digitalWrite(LED2, LOW);
}