Hey guys. I'm still a novice to arduino and I want to make a 4 pushbutton lock as my first project. All the buttons seem to be working all right independently, but after the first pushbutton is pressed the other pushbuttons don't cause the correctLedPin (refer to the program) to light up for one tenth of a second. There must be something wrong with the 'if' loop but I'm not able to figure out what it is.
int correctLedPin = 7;
int wrongLedPin = 6;
int b1 = 1; //the four buttons
int b2 = 2;
int b3 = 3;
int b4 = 4;
void setup()
{
pinMode(correctLedPin, OUTPUT);
pinMode(wrongLedPin, OUTPUT);
pinMode(b1, INPUT);
pinMode(b2, INPUT);
pinMode(b3, INPUT);
pinMode(b4, INPUT);
}
void loop()
{
int bs1 = digitalRead(b1);
int bs2 = digitalRead(b2);
int bs3 = digitalRead(b3);
int bs4 = digitalRead(b4);
if(bs1 == LOW)
{
digitalWrite(correctLedPin, HIGH);
delay(100);
digitalWrite(correctLedPin, LOW);
if(bs2 == LOW)
{
digitalWrite(correctLedPin, HIGH);
delay(100);
digitalWrite(correctLedPin, LOW);
if(bs3 == LOW)
{
digitalWrite(correctLedPin, HIGH);
delay(100);
digitalWrite(correctLedPin, LOW);
if(bs4 == LOW)
{
digitalWrite(correctLedPin, HIGH);
digitalWrite(wrongLedPin, LOW);
}
}
}
}
else
{
digitalWrite(wrongLedPin, HIGH);
}
What you are forgetting is that the loop goes very fast, it does not wait for you to finish pressing a button. So you have to write code that once it detects a push button it will wait until the button is unpushed. It then has to look for the next button and if it is not the correct button it has to reset the variable keeping track of what is the next correct button.
Look up what a state machine is all about.
Nowhere are you waiting for the button to become unpressed?
The variable button press will just race away to a very big number.
There is nothing in the code that specifies any order of buttons pressed.
There is nothing that resets that state variable if the wrong button is pressed.
In short you are not thinking about what you want to do.
Use some debug printing, that is print out the value of your variables or little messages saying this point reached to see what program flow you have, see if this matches what you think you have.
okay.. My next attempt.. I did put a serial print for button presses on pressing the first button, but it never seems to go into that if loop.. and the order of buttons is determined by the 'val' variable..
int correctLedPin = 7;
int wrongLedPin = 6;
int b1 = 1; //the four buttons
int b2 = 2;
int b3 = 3;
int b4 = 4;
void setup()
{
pinMode(correctLedPin, OUTPUT);
pinMode(wrongLedPin, OUTPUT);
pinMode(b1, INPUT);
pinMode(b2, INPUT);
pinMode(b3, INPUT);
pinMode(b4, INPUT);
Serial.begin(9600);
}
void loop()
{
int bs1 = digitalRead(b1);
int bs2 = digitalRead(b2);
int bs3 = digitalRead(b3);
int bs4 = digitalRead(b4);
int val = 0;
int buttonPresses;
int lastButtonState = LOW;
if(bs1 == LOW && val == 0)
{
delay(200)
if(bs1 != lastButtonState)
{
digitalWrite(correctLedPin, HIGH);
delay(100);
digitalWrite(correctLedPin, LOW);
val = 1;
buttonPresses++;
Serial.println(buttonPresses);
delay(1000);
}
else
{
delay(200);
}
}
else if(bs2 == LOW && val == 1)
{
delay(200);
if(lastButtonState != bs2)
{
digitalWrite(correctLedPin, HIGH);
delay(100);
digitalWrite(correctLedPin, LOW);
val = 2;
buttonPresses++;
}
else
{
delay(200);
}
}
else if(bs3 == LOW && val == 2)
{
delay(200)
if(lastButtonState != bs3)
{
digitalWrite(correctLedPin, HIGH);
delay(100);
digitalWrite(correctLedPin, LOW);
val = 3;
buttonPresses++;
delay(1000);
}
}
else if(bs4 == LOW && val == 3)
{
if(lastButtonState == bs4)
{
val = 4;
buttonPresses++;
}
}
else
{
val = 0;
buttonPresses = 0;
digitalWrite(wrongLedPin, HIGH);
}
if(val == 4 && buttonPresses == 4)
{
digitalWrite(correctLedPin, HIGH);
digitalWrite(wrongLedPin, LOW);
}
}
I agree that clarifying the state machine will help to solve this problem pretty quickly, so I have attached a sample state diagram. You must be logged in to see the attached GIF image. The boxes are states. The lines are transitions between states, caused by button press events. One thing that came to my mind while reading this forum thread is that you were not accounting for the fact that you do not want to show the person whether the entire set of 4 button presses is correct or incorrect until after all 4 buttons have been pressed. This is a standard way of preventing the person from learning the passcode just by pressing random buttons. So, you should not light any LEDs until all 4 buttons are pressed, represented by the "Correct" and "Incorrect" states in the diagram.
If you implement this diagram using a single variable to hold the state identifier, and always check for a button press in the loop, based on the current state, then there is no need to wait for anything. The delays are inherent. The only time a delay is needed is when lighting the LED for an amount of time, and of course, you can use the state variable and a clock time variable to know when to turn off the LED, so your code does not need any delay statements at all.
One thing I forgot to mention... the blue lines represent moving to the next state when the proper button is pressed. The red lines represent moving to the next state when the wrong button is pressed (blue-to-red state transition) or when ANY button is pressed (red-to-red state transition).
Have you got external pull up resistors as you are not enabling the internal ones.
Print out the values you read and check you if statements.
You are still it looking for a button not pressed state!!!
thanks cawhiteley... and grumpy_mike i do have external resistors and the buttons work just fine independently.. sorry but could please tell me the exact coding part of whats wrong and the right code.. coz i don't understand what you mean when you're saying im reading the button and not the state..
Doing this EVERY TIME through the loop will set the value to zero. Therefore this value NEVER changes.
Define the variable outside any function, or declaire it as a static int.
Wait untill the button is unpressed BEFORE you increment the button pressed variable
while( digitalRead(pin) == LOW) ) { } // do nothing
finally got it working!! Thanks all you guys!! I couldn't get the while loop to work but i managed something else... ignore the motor pins..
const int buttonPin1 = 1;
const int buttonPin4 = 4;
const int buttonPin3 = 3;
const int buttonPin2 = 2; // the pin that the pushbutton is attached to
const int correctLedPin = 7; // the pin that the LED is attached to
const int wrongLedPin = 6;
const int motorPin = 11;// the pin that the LED is attached to
// variables that are changed by the program
int buttonPushCounter = 0; // counter for the number of button presses
int val = 0;
int bS1 = 0; // current state of the button
int lBS1 = 0; // previous state of the button
int bS2 = 0; // current state of the button
int lBS2 = 0;
int bS3 = 0; // current state of the button
int lBS3 = 0;
int bS4 = 0; // current state of the button
int lBS4 = 0;
// configure the pins to the right mode
void setup() {
pinMode(buttonPin1, INPUT);
pinMode(buttonPin2, INPUT);
pinMode(buttonPin3, INPUT);
pinMode(buttonPin4, INPUT);
pinMode(correctLedPin, OUTPUT);
pinMode(wrongLedPin, OUTPUT);
pinMode(motorPin, OUTPUT);
Serial.begin(9600);
}
// the main loop will constantly check to see if the button has been pressed
// if it has, a counter is incremented, and then some action can be taken
void loop() {
// read the state of the button
static int buttonPushCounter = 0;
bS1 = digitalRead(buttonPin1);
bS2 = digitalRead(buttonPin2);
bS3 = digitalRead(buttonPin3);
bS4 = digitalRead(buttonPin4);
// check to see if it different than the last time we checked
if (bS1 != lBS1) {
// either the button was just pressed or just released
if (bS1 == HIGH) {
// it was just pressed
buttonPushCounter = buttonPushCounter + 1;
Serial.println(buttonPushCounter);
digitalWrite(correctLedPin, HIGH);
delay(100);
digitalWrite(correctLedPin, LOW);
if(val == 0)
{
val = 1;
}
}
}
lBS1 = bS1;
if (bS2 != lBS2) {
// either the button was just pressed or just released
if (bS2 == HIGH) {
// it was just pressed
buttonPushCounter = buttonPushCounter + 1;
Serial.println(buttonPushCounter);
digitalWrite(correctLedPin, HIGH);
delay(100);
digitalWrite(correctLedPin, LOW);
if(val == 1)
{
val = 2;
}
}
}
lBS2 = bS2;
if (bS3 != lBS3) {
// either the button was just pressed or just released
if (bS3 == HIGH) {
// it was just pressed
buttonPushCounter = buttonPushCounter + 1;
Serial.println(buttonPushCounter);
digitalWrite(correctLedPin, HIGH);
delay(100);
digitalWrite(correctLedPin, LOW);
if(val == 2)
{
val = 3;
}
}
}
lBS3 = bS3;
if (bS4 != lBS4) {
// either the button was just pressed or just released
if (bS4 == HIGH) {
// it was just pressed
buttonPushCounter = buttonPushCounter + 1;
Serial.println(buttonPushCounter);
digitalWrite(correctLedPin, HIGH);
delay(100);
digitalWrite(correctLedPin, LOW);
if(val == 3)
{
val = 4;
}
}
}
lBS4 = bS4;
if(val == 4 && buttonPushCounter == 4)
{
digitalWrite(correctLedPin, HIGH);
val = 0;
buttonPushCounter = 0;
analogWrite(motorPin
}
else if(val != 4 && buttonPushCounter == 4)
{
digitalWrite(wrongLedPin, HIGH);
delay(3000);
digitalWrite(wrongLedPin, LOW);
val = 0;
buttonPushCounter = 0;
}
}