I am making an alarm system using an ultrasonic distance sensor. It can be armed and disarmed using a remote, and I want a green led to be on when it is disarmed, and a red led to be on when it is armed. The red led works fine, but the green one stays on.
I have tried commenting out the line that turns on the green led, but it seems to be on by default, so when I start the program, it is already on and won't turn off. The code in question is near the bottom, marked by a comment that says //HERE
#include "IRremote.h"
#include "SR04.h"
#define TRIG_PIN 12
#define ECHO_PIN 11
SR04 sr04 = SR04(ECHO_PIN,TRIG_PIN);
long distance;
int receiver = 10;
IRrecv irrecv(receiver); // create instance of 'irrecv'
decode_results results; // create instance of 'decode_results'
int buzzer = 3;
int red_led = 2;
int green_led = 0;
bool can_sense = false;
bool release_pressed = false;
bool alarm_off = false;
/*-----( Function )-----*/
void translateIR() // takes action based on IR code received
// describing Remote IR codes
{
switch(results.value)
{
case 0xFFA25D: Serial.println("POWER"); alarm_off = true; break;
case 0xFFE21D: Serial.println("FUNC/STOP"); break;
case 0xFF629D: Serial.println("VOL+"); break;
case 0xFF22DD: Serial.println("FAST BACK"); break;
case 0xFF02FD: Serial.println("PAUSE"); release_pressed = true; break;
case 0xFFC23D: Serial.println("FAST FORWARD"); break;
case 0xFFE01F: Serial.println("DOWN"); break;
case 0xFFA857: Serial.println("VOL-"); break;
case 0xFF906F: Serial.println("UP"); break;
case 0xFF9867: Serial.println("EQ");release_pressed = false; break;
case 0xFFB04F: Serial.println("ST/REPT"); break;
case 0xFF6897: Serial.println("0"); break;
case 0xFF30CF: Serial.println("1"); break;
case 0xFF18E7: Serial.println("2"); break;
case 0xFF7A85: Serial.println("3"); break;
case 0xFF10EF: Serial.println("4"); break;
case 0xFF38C7: Serial.println("5"); break;
case 0xFF5AA5: Serial.println("6"); break;
case 0xFF42BD: Serial.println("7"); break;
case 0xFF4AB5: Serial.println("8"); break;
case 0xFF52AD: Serial.println("9"); break;
case 0xFFFFFFFF: Serial.println(" REPEAT");break;
default:
Serial.println(" other button ");
}// End Case
delay(100);
}
void setup() {
Serial.begin(9600);
pinMode(buzzer,OUTPUT);
pinMode(red_led,OUTPUT);
pinMode(green_led,OUTPUT);
irrecv.enableIRIn();
}
void loop() {
if (irrecv.decode(&results)) // have we received an IR signal?
{
translateIR();
irrecv.resume(); // receive the next value
}
distance = sr04.Distance();
if (distance < 70)
{
can_sense = true;
}
if (can_sense==true and release_pressed==false)
{
while (alarm_off==false)
{
digitalWrite(buzzer,HIGH);
digitalWrite(red_led,HIGH);
delay(500);
digitalWrite(buzzer,LOW);
digitalWrite(red_led,LOW);
delay(250);
if (irrecv.decode(&results)) // have we received an IR signal?
{
translateIR();
irrecv.resume(); // receive the next value
}
}
}
if (release_pressed==false) //HERE
{
digitalWrite(red_led,HIGH);
digitalWrite(green_led,LOW); // This should turn off the green led, but it doesn't
}
if (release_pressed==true)
{
digitalWrite(red_led,LOW);
digitalWrite(green_led,HIGH);
}
alarm_off = false;
can_sense = false;
}
Thanks for any help :)
Pins 0 and 1 on an Uno are used for serial communication.
As soon as you did Serial.begin(9600);, you enabled those pins for serial comms, so you can't also use them as standard digital pins.
Simply use another pin for your green LED.
Related
I am using an RGB LED with a keypad. Pressing '1' turns on a light while pressing '2' turns off the light. After I press '3' I want the LED to loop through colors and only if a different button is pressed is when the code leaves the loop. My problem is while looping the keypads state of HIGH or LOW is not changed therefore the key that is saved as pressed cannot change. I need some way to get out of this loop without stopping the loop.
#include <Keypad.h>
const int GreenLED=9;
const int BlueLED=10;
const int RedLED=11;
const byte numRows=4;
const byte numCols=4;
char keymap[numRows][numCols] =
{
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
};
byte rowPins[numRows] = {5,4,3,2};
byte colPins[numCols] = {13,8,7,6};
char keypressed;
boolean ledPin_stateGreen;
boolean ledPin_stateRed;
boolean ledPin_stateBlue;
Keypad myKeypad = Keypad(makeKeymap(keymap), rowPins, colPins, numRows,
numCols);
void setup() {
pinMode(GreenLED, OUTPUT);
pinMode(BlueLED, OUTPUT);
pinMode(RedLED, OUTPUT);
ledPin_stateGreen = digitalRead(GreenLED);
ledPin_stateRed = digitalRead(RedLED);
ledPin_stateBlue = digitalRead(BlueLED);
Serial.begin(9600);
}
void loop() {
char key = myKeypad.getKey();
if(key != NO_KEY)
{
Serial.println(key);
}
//Serial.println(myKeypad.getState());
keypadEvent(key);
}
void setColor(int red, int green, int blue)
{
#ifdef COMMON_ANODE
red = 255 - red;
green = 255 - green;
blue = 255 - blue;
#endif
analogWrite(RedLED, red);
analogWrite(GreenLED, green);
analogWrite(BlueLED, blue);
}
void keypadEvent (KeypadEvent key)
{
switch (myKeypad.getState())
{
case PRESSED:
if (key == '1')
{
digitalWrite(GreenLED, HIGH);
digitalWrite(BlueLED, HIGH);
digitalWrite(RedLED, HIGH);
}
if (key == '2')
{
digitalWrite(GreenLED, LOW);
digitalWrite(BlueLED, LOW);
digitalWrite(RedLED, LOW);
}
if (key == '3')
{
int previousState= myKeypad.getState();
while(key == '3')
{
key = myKeypad.getKey();
setColor(255, 0, 0); // red
delay(200);
Serial.println(myKeypad.getState());
setColor (50,50,50); //white
delay (200);
setColor (255,40,0);
delay(200);
setColor(0, 255, 0); // green
delay(200);
setColor(0, 0, 255); // blue
delay(200);
setColor(255, 255, 0); // yellow
delay(200);
setColor(80, 0, 80); // purple
delay(200);
setColor(0, 255, 255); // aqua
delay(200);
Serial.println(myKeypad.getState());
}
}
}
}
In your setup, you have GreenLED, BlueLED, RedLED set to OUTPUT, but then you try to digitalRead() from them...
void setup() {
pinMode(GreenLED, OUTPUT);
pinMode(BlueLED, OUTPUT);
pinMode(RedLED, OUTPUT);
ledPin_stateGreen = digitalRead(GreenLED);
ledPin_stateRed = digitalRead(RedLED);
ledPin_stateBlue = digitalRead(BlueLED);
Serial.begin(9600);
}
Your loop is preventing the keypad from being read for about 1.6 seconds. Then you have a very very small window to have the key pressed to pickup the key. Also, as you have stated, once you are in the loop you can't exit out of it due to the fact that you don't check for key presses. The tutorial on Arduino Playground states:
Consider, though, when you are writing your code that every delay()
you use will take processing time away from the keypad. Something as
short as delay(250) can make the keypad seem very unresponsive. And
the same thing will happen if you sprinkle a bunch of delay(10)'s all
through your code.
One way to solve this problem is to remove the delays from your loop and turn your program into a state machine which continuously polls the keypad for key presses. Now there are many ways to do this, of which I have chosen only one, and actually I really have turned it into 2 state machines. The top level one is the overall state of your program (i.e. what is our state based on the key pressed). The second one is a state machine to represent your loop which changes the colors of your LEDs. You can learn more about state machines here.
Here is your program turned into the above state machines:
#include <Keypad.h>
const int GreenLED=9;
const int BlueLED=10;
const int RedLED=11;
const byte numRows=4;
const byte numCols=4;
char keymap[numRows][numCols] =
{
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
};
byte rowPins[numRows] = {5,4,3,2};
byte colPins[numCols] = {13,8,7,6};
char keypressed;
boolean ledPin_stateGreen;
boolean ledPin_stateRed;
boolean ledPin_stateBlue;
enum MyState {
LIGHT_ON,
LIGHT_OFF,
LIGHT_LOOPING
};
enum LightState {
COLOR_1,
COLOR_2,
COLOR_3,
COLOR_4,
COLOR_5,
COLOR_6,
COLOR_7,
COLOR_8
};
//Our current state for lights
MyState currentState = LIGHT_LOOPING;
LightState currentLightState = COLOR_1;
//The previous time in milliseconds
unsigned long prevTimeMS = 0;
Keypad myKeypad = Keypad(makeKeymap(keymap), rowPins, colPins, numRows,
numCols);
void setup() {
pinMode(GreenLED, OUTPUT);
pinMode(BlueLED, OUTPUT);
pinMode(RedLED, OUTPUT);
ledPin_stateGreen = digitalRead(GreenLED);
ledPin_stateRed = digitalRead(RedLED);
ledPin_stateBlue = digitalRead(BlueLED);
Serial.begin(9600);
prevTimeMS = millis();
}
void loop() {
char key = myKeypad.getKey();
if(key != NO_KEY)
{
Serial.println(key);
}
//Serial.println(myKeypad.getState());
//This function is really checking to see if we need to perform a state
//transition or not for the currentState
keypadEvent(key);
//Do stuff based on the state We are in
unsigned long currentTimeMS = millis();
switch(currentState)
{
case LIGHT_ON:
//Don't really need to do anything since we perform
//the work on the state transition
break;
case LIGHT_OFF:
//Don't really need to do anything since we perform
//the work on the state transition
break;
case LIGHT_LOOPING:
//Now switch based on the current color state to see if we
//need to change to the next state
switch(currentLightState)
{
case COLOR_1:
if(checkDelay(currentTimeMS,prevTimeMS,200))
{
//We need to transition to the next state
transitionLightState(COLOR_2);
}
break;
case COLOR_2:
if(checkDelay(currentTimeMS,prevTimeMS,200))
{
//We need to transition to the next state
transitionLightState(COLOR_3);
}
break;
case COLOR_3:
if(checkDelay(currentTimeMS,prevTimeMS,200))
{
//We need to transition to the next state
transitionLightState(COLOR_4);
}
break;
case COLOR_4:
if(checkDelay(currentTimeMS,prevTimeMS,200))
{
//We need to transition to the next state
transitionLightState(COLOR_5);
}
break;
case COLOR_5:
if(checkDelay(currentTimeMS,prevTimeMS,200))
{
//We need to transition to the next state
transitionLightState(COLOR_6);
}
break;
case COLOR_6:
if(checkDelay(currentTimeMS,prevTimeMS,200))
{
//We need to transition to the next state
transitionLightState(COLOR_7);
}
break;
case COLOR_7:
if(checkDelay(currentTimeMS,prevTimeMS,200))
{
//We need to transition to the next state
transitionLightState(COLOR_8);
}
break;
case COLOR_8:
if(checkDelay(currentTimeMS,prevTimeMS,200))
{
//We need to transition to the next state
//which is back to the first state so we loop
transitionLightState(COLOR_1);
}
break;
}
break;
}
}
//This will return true if the correct amount of time has passed
boolean checkDelay(unsigned long currentMS, unsigned long prevMS, unsigned long delayMS)
{
if((currentMS - prevMS) >= delayMS)
{
return true;
}
return false;
}
void transitionMyState(MyState newState)
{
switch(newState)
{
case LIGHT_ON:
digitalWrite(GreenLED, HIGH);
digitalWrite(BlueLED, HIGH);
digitalWrite(RedLED, HIGH);
break;
case LIGHT_OFF:
digitalWrite(GreenLED, LOW);
digitalWrite(BlueLED, LOW);
digitalWrite(RedLED, LOW);
break;
case LIGHT_LOOPING:
//We want to transition to the COLOR_1 state here
transitionLightState(COLOR_1);
break;
}
currentState = newState;
//need to save off a new prevTimeMS
prevTimeMS = millis();
}
void transitionLightState(LightState newState)
{
//perform the action for the state transition
switch(newState)
{
case COLOR_1:
setColor(255, 0, 0); // red
break;
case COLOR_2:
setColor (50,50,50); //white
break;
case COLOR_3:
setColor (255,40,0);
break;
case COLOR_4:
setColor(0, 255, 0); // green
break;
case COLOR_5:
setColor(0, 0, 255); // blue
break;
case COLOR_6:
setColor(255, 255, 0); // yellow
break;
case COLOR_7:
setColor(80, 0, 80); // purple
break;
case COLOR_8:
setColor(0, 255, 255); // aqua
break;
}
currentLightState = newState;
//need to save off a new prevTimeMS
prevTimeMS = millis();
}
void setColor(int red, int green, int blue)
{
#ifdef COMMON_ANODE
red = 255 - red;
green = 255 - green;
blue = 255 - blue;
#endif
analogWrite(RedLED, red);
analogWrite(GreenLED, green);
analogWrite(BlueLED, blue);
}
void keypadEvent (KeypadEvent key)
{
switch (myKeypad.getState())
{
case PRESSED:
if (key == '1')
{
transitionMyState(LIGHT_ON);
}
if (key == '2')
{
transitionMyState(LIGHT_OFF);
}
if (key == '3')
{
transitionMyState(LIGHT_LOOPING);
}
}
}
The implementation is more for readability then minimizing code by the way. I added 2 state variables which hold what state we are in for the key handler state machine and the looping state machine. The important thing to note about this implementation is that key presses are checked every iteration of the loop and there are no delays implemented. This allows for us to break out of the looping color state machine at anytime. You could also say that the looping of colors changed into a poll of "Do I need to change my color now?"
The other important thing to note is that now the time needs to be tracked so the looping state machine can determine when the right amount of time has passed in order to know when to change states. When a state transition happens then the current time is saved off. Note: The rollover of the millis counter is not taken into account in this example. This happens roughly every 50 days according to the Arduino docs. So every 50 days you will get a glitch if you are in the LIGHT_LOOPING state.
Here is the code I'm trying to run on my Arduino.
#include "IRremote.h"
int receiver = 11; // Signal Pin of IR receiver to Arduino Digital Pin 11
/*-----( Declare objects )-----*/
IRrecv irrecv(receiver); // create instance of 'irrecv'
decode_results results; // create instance of 'decode_results'
void setup() /*----( SETUP: RUNS ONCE )----*/
{
Serial.begin(9600);
Serial.println("IR Receiver Button Decode");
irrecv.enableIRIn(); // Start the receiver
}/*--(end setup )---*/
void loop() /*----( LOOP: RUNS CONSTANTLY )----*/
{
if (irrecv.decode(&results)) // have we received an IR signal?
{
translateIR();
irrecv.resume(); // receive the next value
}
}/* --(end main loop )-- */
/*-----( Function )-----*/
void translateIR() // takes action based on IR code received
// describing Remote IR codes
{
switch(results.value)
{
case 0xFF629D: Serial.println(" FORWARD"); break;
case 0xFF22DD: Serial.println(" LEFT"); break;
case 0xFF02FD: Serial.println(" -OK-"); break;
case 0xFFC23D: Serial.println(" RIGHT"); break;
case 0xFFA857: Serial.println(" REVERSE"); break;
case 0xFF6897: Serial.println(" 1"); break;
case 0xFF9867: Serial.println(" 2"); break;
case 0xFFB04F: Serial.println(" 3"); break;
case 0xFF30CF: Serial.println(" 4"); break;
case 0xFF18E7: Serial.println(" 5"); break;
case 0xFF7A85: Serial.println(" 6"); break;
case 0xFF10EF: Serial.println(" 7"); break;
case 0xFF38C7: Serial.println(" 8"); break;
case 0xFF5AA5: Serial.println(" 9"); break;
case 0xFF42BD: Serial.println(" *"); break;
case 0xFF4AB5: Serial.println(" 0"); break;
case 0xFF52AD: Serial.println(" #"); break;
case 0xFFFFFFFF: Serial.println(" REPEAT");break;
default:
Serial.println(" other button ");
}// End Case
delay(500); // Do not get immediate repeat
}
Here is my error message. (I think I fixed first one.)
Arduino: 1.8.0 (Windows 8.1), Board: "Arduino/Genuino Uno"
C:\(my folers)
arduino\arduino\libraries\RobotIRremote\src\IRremoteTools.cpp:5:16: error: 'TKD2' was not declared in this scope
int RECV_PIN = TKD2; // the pin the IR receiver is connected to
^
Multiple libraries were found for "IRremote.h"
Used: C:\Users\Mike\Desktop\Games\Zach arduino\arduino\libraries\RobotIRremote
Not used: C:\Users\Mike\Documents\Arduino\libraries\Arduino-IRremote-master
exit status 1
Error compiling for board Arduino/Genuino Uno.
This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.
The error is pretty self-explanatory:
"Multiple libraries were found for 'IRremote.h'"
It looks like you have the same library file in two locations. Delete one and the compiler will know which one to use.
So I run into a problem when I am trying to disarm the system. When I upload the code to the arduino it asks me to enter a pin and then it activates the system right away. But then when I try to deactivate the system it takes the pin and just clears the screen and execute the mainScreen function that i have set.
The code is provided below:
#include "Keypad.h"
#include "LiquidCrystal.h"
#include "Password.h"
LiquidCrystal lcd(0,1,10,11,12,13);
char newPasswordString; //hold the new password
char newPassword[4]; //charater string of newPasswordString
//initialize password to 1234
//you can use password.set(newPassword) to overwrite it
Password password = Password("1234");
byte maxPasswordLength = 4;
byte currentPasswordLength = 4;
// keypad type definition
const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {9,8,7,6}; //Rows 0 to 3
byte colPins[COLS]= {5,4,3,2}; //Columns 0 to 3
int count=0;
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
void setup()
{
lcd.begin(16, 2);
mainScreen();
}
void loop(){
char key = keypad.getKey();
if (key != NO_KEY){
delay(60);
switch (key){
case 'A': activate(); break;
case 'B': break;
case 'C': break;
case 'D': deactivate(); break;
case '#': break;
case '*': break;
default: processNumberKey(key);
}
}
}
void processNumberKey(char key) {
lcd.print(key);
currentPasswordLength++;
password.append(key);
if(password.evaluate()){
activate();
}
}
void activate() {
if (password.evaluate()){
lcd.clear();
lcd.print("Activated.");
delay(1000);
mainScreen();
} else {
lcd.clear();
lcd.print("Wrong Password!");
mainScreen();
}
}
void deactivate(){
if (password.evaluate()){
lcd.clear();
lcd.print("Deactivated.");
delay(1000);
} else {
lcd.clear();
lcd.print("Wrong Password!");
mainScreen();
}
}
void mainScreen(){
lcd.clear();
lcd.print("Enter Pin:");
keypad.getKey();
}
As noted in Arduino keypad 4x4 to LCD activate/deactivate you have to keep current state and you have to CLEAR the password and currenPasswordLength. See the WORKING example in the answer.
It won't help that you set byte currenPasswordLength = 4. If you press first key, it will be incremented to 5, next key increments it to the 6 and so on.
You'll get 4 again after the 256 key-presses!!!!!!! And as you don't clear previously checked password, you'll get "wrong password" result (and eventually stack overflow).
I am creating an Arduino project that plays Rock Paper Scissors.
I have a part of the code reading the value of the button and whenever I click only one button, it outputs three times (View code and images of serial monitor to understand what I mean, I can't really explain it)
Here is my code:
// constants won't change. They're used here to
// set pin numbers:
const int buttonPin1 = A0; // the number of the pushbutton pin
const int buttonPin2 = A1;
const int buttonPin3 = A2;
const int ledPin = 12; // the number of the LED pin
// variables will change:
int buttonState1 = 0; // variable for reading the pushbutton status
int buttonState2 = 0;
int buttonState3 = 0;
char * choices[3] = {"Rock", "Paper", "Scissors"};
char * finalResult[3] = {"You Lost", "You Won!", "It's a Tie"};
byte Human = 0, Computer = 0, FR = 0;
char result[25];
void setup() {
// initialize the LED pin as an output:
pinMode(ledPin, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(buttonPin1, INPUT);
pinMode(buttonPin2, INPUT);
pinMode(buttonPin3, INPUT);
digitalWrite(ledPin,LOW);
Serial.begin(9600);
unsigned long R;
randomSeed(R);
}
void loop(){
int choice = random(1,4);
int pick;
// read the state of the pushbutton value:
// check if the pushbutton is pressed.
// if it is, the buttonState is HIGH:
Serial.println("Entering Reading Loop...");
while(true)
{
buttonState1 = digitalRead(buttonPin1);
buttonState2 = digitalRead(buttonPin2);
buttonState3 = digitalRead(buttonPin3);
if (buttonState1 == HIGH && buttonState2 == LOW && buttonState3 == LOW) {
// turn LED on:
Throw('1');
} else if (buttonState1 == LOW && buttonState2 == HIGH && buttonState3 == LOW) {
// turn LED on:
pick = 2; //Paper
Throw('2');
}else if (buttonState1 == LOW && buttonState2 == LOW && buttonState3 == HIGH) {
// turn LED on:
pick = 3; //Scissor
Throw('3');
}
}
}
void Throw(char H)
{
bool thrown = false;
H -= '0'; //convert ascii to decimal
H -= 1; // instead of 1,2,3, H is now 0,1,2
byte C = random(0, 3);
sprintf(result, "The Computer chose: %s, You chose: %s", choices[C], choices[H]);
Serial.println(result);
if ( C == H)
Serial.println(F("Its a TIE"));
else
{
switch (C)
{
case 0:
switch (H)
{
case 1:
Serial.println(F("Paper wraps Rock, You WIN!"));
Human++;
break;
case 2:
Serial.println(F("Rock crushes Scissors, You LOSE!"));
Computer++;
break;
}
break;
case 1:
switch (H)
{
case 0:
Serial.println(F("Paper wraps Rock, You LOSE!"));
Computer++;
break;
case 2:
Serial.println(F("Scissors cuts Paper, You WIN!"));
Human++;
break;
}
break;
case 2:
switch (H)
{
case 0:
Serial.println(F("Rock crushes Scissors, You WIN!"));
Human++;
break;
case 1:
Serial.println(F("Scissors cuts Paper, You LOSE!"));
Computer++;
break;
}
break;
}
}
}
This is what I'm getting on the serial monitor when I click only ONE button(the rock button)
http://gyazo.com/ceb5c8329993339368cf5d52181ed4d7
As you can see, it chooses the right option for the button but it calls the throw function 3 times.
http://playground.arduino.cc/Main/RockPaperScissors)
From the Arduino docs they recommend using a Debounce strategy for handling inputs.
Without debouncing, pressing the button once can appear to the code as
multiple presses.
http://www.arduino.cc/en/Tutorial/Debounce
Here is another example illustrating the Debounce technique:
http://danthompsonsblog.blogspot.com/2011/12/arduino-push-button-onoff-example.html
There are pull-up resistors built in to the arduino that will allow you to filter out the erratic electrical signal you get when pressing a button. See the section on INPUT_PULLUP here.
I don't what the exact issue was but, I added a delay in my throw function and it stopped outputting the serial print statement 3 times!
Here is my updated function:
void Throw(char H)
{
bool thrown = false;
H -= '0'; //convert ascii to decimal
H -= 1; // instead of 1,2,3, H is now 0,1,2
byte C = random(0, 3);
sprintf(result, "The Computer chose: %s, You chose: %s", choices[C], choices[H]);
Serial.println(result);
delay(500);
if ( C == H)
Serial.println(F("Its a TIE"));
else
{
switch (C)
{
case 0:
switch (H)
{
case 1:
Serial.println(F("Paper wraps Rock, You WIN!"));
Human++;
break;
return;
case 2:
Serial.println(F("Rock crushes Scissors, You LOSE!"));
Computer++;
break;
}
break;
case 1:
switch (H)
{
case 0:
Serial.println(F("Paper wraps Rock, You LOSE!"));
Computer++;
break;
case 2:
Serial.println(F("Scissors cuts Paper, You WIN!"));
Human++;
break;
}
break;
case 2:
switch (H)
{
case 0:
Serial.println(F("Rock crushes Scissors, You WIN!"));
Human++;
break;
case 1:
Serial.println(F("Scissors cuts Paper, You LOSE!"));
Computer++;
break;
}
break;
}
}
}
StackOverflow! I am a teenager fairly new to Arduino coding, and am investigating a problem. I am running Linux Ubuntu 10.10 if that makes a difference. I have a setup going with a homemade board consisting of five buttons, one for each left, right, up, and down, and one center button, and a Hitachi 2x16 character LCD screen, using the Arduino Uno board.. My programs purpose is to play my splash screen, issue a countdown from three on-screen, display a helpful message, and then go into the program, which simply opens up a list of items, showing one at a time, and allows you to scroll through them using the up and down buttons, and exit the program by clicking the center button. So, here's the problem: the rest of the program works just fine, but when it comes to the menu, it correctly displays the first item, but the buttons do not serve their purpose. I checked using the serial monitor, and the state of the button doesn't change when pressed. But here's the kicker. I used a volt meter to check if the buttons were correctly using power, and they are. They just don't seem to be working digitally. I have checked my wiring, and it is all correct. I think the problem may be in the code, so I leave it to your more experienced hands:
// include the library code:
#include <LiquidCrystal.h>
int itemNum = 0;
// Declare variables for on and off states, for efficiency!
int on = LOW;
int off = HIGH;
// Declare the buttons' digital pins and states respectively
const int upbtnpin = 8;
const int dwnbtnpin = 9;
const int cntrbtnpin = 10;
int upbtnstate = off;
int dwnbtnstate = off;
int cntrbtnstate = off;
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
void setup() {
// Activate Serial Monitor
Serial.begin(9600);
// Declare buttons to be INPUT
pinMode(upbtnpin, INPUT);
pinMode(dwnbtnpin, INPUT);
pinMode(cntrbtnpin, INPUT);
// Activate Pullups
digitalWrite(upbtnpin, HIGH);
digitalWrite(dwnbtnpin, HIGH);
digitalWrite(cntrbtnpin, HIGH);
// Begin LCD
lcd.begin(16, 2);
// Splash Screen
lcd.setCursor(0, 0);
lcd.print(" _# Paradigm #_");
lcd.setCursor(0,1);
lcd.print("<-> Robotics <->");
delay(3000);
lcd.clear();
// Display Message and countdown
cntrbtnstate = digitalRead(cntrbtnpin);
lcd.setCursor(0, 0);
lcd.print("Menu Program 1.0");
lcd.setCursor(0, 1);
int i = 3;
while (i > 0) {
if (i == 3) {
lcd.setCursor(0, 1);
lcd.print("Wait 3 second(s)");
delay(1000);
i--;
}
else if (i == 2) {
lcd.setCursor(0, 1);
lcd.print("Wait 2 second(s)");
delay(1000);
i--;
}
else if (i == 1) {
lcd.setCursor(0, 1);
lcd.print("Wait 1 second(s)");
delay(1000);
i--;
}
}
lcd.clear();
delay(500);
lcd.setCursor(0, 0);
lcd.print("Press enter any");
lcd.setCursor(0, 1);
lcd.print(" time to exit. ");
delay(1200);
lcd.clear();
}
// ...And finally, to the actual program!
void loop() {
upbtnstate = digitalRead(upbtnpin);
dwnbtnstate = digitalRead(dwnbtnpin);
cntrbtnstate = digitalRead(cntrbtnpin);
while (cntrbtnstate != on) {
if (upbtnstate == on) {
delay(250);
itemNum++;
}
else if (dwnbtnstate == on) {
delay(250);
itemNum--;
}
// OPTIONAL for debugging
delay(150);
Serial.print(" ! ");
delay(150);
Serial.print(int(upbtnstate));
Serial.print(" ");
delay(150);
Serial.print(int(dwnbtnstate));
Serial.print(" ");
delay(150);
Serial.print(int(cntrbtnstate));
String item = "";
int itemNum = 0;
switch(itemNum) {
case 0:
lcd.setCursor(0, 1);
lcd.print("END OF LIST");
break;
case 1:
lcd.setCursor(0, 1);
lcd.print("Water Bottle");
break;
case 2:
lcd.setCursor(0, 1);
lcd.print("Biker Jacket");
break;
case 3:
lcd.setCursor(0, 1);
lcd.print(".44 Magnum");
break;
case 4:
lcd.setCursor(0, 1);
lcd.print(".44 Rounds (x14)");
break;
case 5:
lcd.setCursor(0, 1);
lcd.print("Machete");
break;
case 6:
lcd.setCursor(0, 1);
lcd.print("END OF LIST");
break;
default:
lcd.setCursor(0, 0);
lcd.print(" An error has ");
lcd.setCursor(0, 1);
lcd.print(" occoured ");
}
if (itemNum > 6) {
itemNum == 6;
}
else if (itemNum < 0) {
itemNum == 0;
}
lcd.setCursor(0, 1);
lcd.print(item);
}
lcd.clear();
lcd.setCursor(0, 1);
lcd.print(" Goodbye! ");
}
First, you need to de-bounce the buttons.
http://arduino.cc/it/Tutorial/Debounce
Second, immediately before your case statement, you set the itemNum to 0. That should probably be moved to the setup section, otherwise it will reset the itemNum each iteration of the loop, and you will always be stuck on "END OF LIST".
Likewise with String item = ""; You are blanking out the string each iteration of the loop, and it runs faster than you can press the buttons.
Also, I don't see any code that ever sets the String item to anything except "". Since you print the item name in the case statement, perhaps you can just remove "String item" and all references.
Finally, you can shorten the delay loop section to :
int i = 3;
while (i > 0) {
lcd.setCursor(0, 1);
lcd.print("Wait " + i + " second(s)");
delay(1000);
i--;
}