I have a website mainly consisting of vertical pages with photos. I want visitors to be able to use the arrow keys (up & down, left & right) on their keyboards to move upwards and downwards.
I tried a code shared here at overflow, but I can only make it work upwards with the up-arrow on my keyboard. When I press the other arrows nothing happens. I've tested in Chrome and Firefox in OS X on my MacBook Pro. View my test-page.
Are there any code modifications I can do to make it work?
This is the code I tried:
var handler = function(e) {
e = e || window.event;
var k = e.keyCode || e.which;
switch(k) {
case 37:
document.body.scrollLeft -= 1000;
document.documentElement.scrollLeft -= 1000;
break;
case 38:
document.body.scrollTop-= 1000;
document.documentElement.scrollTop-= 1000;
break;
case 39:
document.body.scrollLeft += 1000;
document.documentElement.scrollLeft += 1000;
break;
case 40:
document.body.scrollLeft += 1000;
document.documentElement.scrollLeft += 1000;
break;
default: return true;
}
if( e.preventDefault) e.preventDefault();
return false;
};
if( window.attachEvent) window.addEvent("onkeydown",handler,false);
else window.addEventListener("keydown",handler,false);
Scroll left and right wont work if the page is not wider than the screen. You have assigned scrollLeft to the key 40 (down) so nothing will happen. The following code is corrected and works for up and down:
var handler = function(e) {
e = e || window.event;
var k = e.keyCode || e.which;
switch(k) {
case 37:
console.log("37 pressed");
document.body.scrollLeft -= 1000;
document.documentElement.scrollLeft -= 1000;
break;
case 38:
console.log("38 pressed");
document.body.scrollTop-= 1000;
document.documentElement.scrollTop-= 1000;
break;
case 39:
console.log("39 pressed");
document.body.scrollLeft += 1000;
document.documentElement.scrollLeft += 1000;
break;
case 40:
console.log("40 pressed");
document.body.scrollTop += 1000;
document.documentElement.scrollTop += 1000;
break;
default: return true;
}
if( e.preventDefault) e.preventDefault();
return false;
};
if( window.attachEvent) window.addEvent("onkeydown",handler,false);
else window.addEventListener("keydown",handler,false);
Related
This is the code from someone for a water pump, I changed it to make a basic menu with the help of a YouTube video. Everything works fine, a lot fine, however, there is one problem.
To explain my problem, for example, when opening there is no problem, menu will be like
-Menu1
Menu2
and when I press once to down, menu will be
Menu1
-Menu2
Down again
Menu2
-Menu3
Until here everything is fine, when I click the up button it works well and go back like
-Menu2
Menu3
Then
-Menu1
Menu2
However if I press down at Menu3 and go for Menu4, I cannot go up again, I mean I can but Menu names not change, it always Menu3 and Menu 4, functions are work for 1 and 2 when I click but the menu always be like
Menu3
-Menu4
So that's the my problem, the code is below, so if you can help me, I would be really happy. This is my 1st week on my new work so I don't wanna be screw up :(
String menuItems[] = {"Menu1", "Menu2", "Menu3", "Menu4"};
// Navigation button variables
int readKey;
int button;
// Main Menu control variables:
int menuPage = 0;
int maxMenuPages = round(((sizeof(menuItems) / sizeof(String)) / 2) + .2);
int cursorPosition = 0;
int a;
int b;
// Creates 3 custom characters for the menu display
byte downArrow[8] = {
0b00100, // *
0b00100, // *
0b00100, // *
0b00100, // *
0b00100, // *
0b10101, // * * *
0b01110, // ***
0b00100 // *
};
byte upArrow[8] = {
0b00100, // *
0b01110, // ***
0b10101, // * * *
0b00100, // *
0b00100, // *
0b00100, // *
0b00100, // *
0b00100 // *
};
byte menuCursor[8] = {
B01000, // *
B00100, // *
B00010, // *
B00001, // *
B00010, // *
B00100, // *
B01000, // *
B00000 //
};
#include <Wire.h>
#include <LiquidCrystal.h>
// Setting the LCD shields pins
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
void setup() {
// Initializes serial communication
Serial.begin(9600);
// Initializes and clears the LCD screen
lcd.begin(16, 2);
lcd.clear();
// Creates the byte for the 3 custom characters
lcd.createChar(0, menuCursor);
lcd.createChar(1, upArrow);
lcd.createChar(2, downArrow);
}
void loop() {
mainMenuDraw();
drawCursor();
operateMainMenu();
}
// This function, for the MAIN menu, will generate the 2 menu items that can fit on the screen.
//They will change as you scroll through your menu.
//Up and down arrows will indicate your current menu position.
void mainMenuDraw() {
lcd.clear();
lcd.setCursor(1, 0);
lcd.print(menuItems[menuPage]);
lcd.setCursor(1,1);
lcd.print(menuItems[menuPage + 1]);
UpDnArrowDraw(menuPage, maxMenuPages);
}
void drawCursor() {
for (int x = 0; x < 2; x++) {
lcd.setCursor(0, x);
lcd.print(" ");
}
if (menuPage % 2 == 0) {
if (cursorPosition % 2 == 0) {
lcd.setCursor(0, 0);
lcd.write(byte(0));
}
if (cursorPosition % 2 != 0) {
lcd.setCursor(0, 1);
lcd.write(byte(0));
}
}
if (menuPage % 2 != 0) {
if (cursorPosition % 2 == 0) {
lcd.setCursor(0, 1);
lcd.write(byte(0));
}
if (cursorPosition % 2 != 0) {
lcd.setCursor(0, 0);
lcd.write(byte(0));
}
}
}
void operateMainMenu() {
int activeButton = 0;
while (activeButton == 0) {
int button;
readKey = analogRead(0);
if (readKey > 790) { // Wait here if no buttons pushed; read value should be max (~1023)
delay(50);
readKey = analogRead(0);
}
button = evaluateButton(readKey);
switch (button) {
case 0: // NO button returns as 0 there is no action taken
break;
case 1:
button = 0;
switch (cursorPosition) {
case 0:
menuItem1();
break;
case 1:
menuItem2();
break;
case 2:
menuItem3();
break;
case 3:
menuItem4();
break;
}
activeButton = 1;
mainMenuDraw();
drawCursor();
break;
case 2:
button = 0;
if (menuPage == 0) {
cursorPosition = cursorPosition - 1;
cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));
}
if (menuPage % 2 != 0 and cursorPosition % 2 == 0) {
menuPage = menuPage - 1;
menuPage = constrain(menuPage, 0, maxMenuPages);
}
if (menuPage % 2 != 0 and cursorPosition % 2 != 0) {
menuPage = menuPage - 1;
menuPage = constrain(menuPage, 0, maxMenuPages);
}
cursorPosition = cursorPosition - 1;
cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));
mainMenuDraw();
drawCursor();
activeButton = 1;
break;
case 3:
button = 0;
if (menuPage % 2 == 0 and cursorPosition % 2 != 0) {
menuPage = menuPage + 1;
menuPage = constrain(menuPage, 0, maxMenuPages);
}
if (menuPage % 2 != 0 and cursorPosition % 2 == 0) {
menuPage = menuPage + 1;
menuPage = constrain(menuPage, 0, maxMenuPages);
}
cursorPosition = cursorPosition + 1;
cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));
mainMenuDraw();
drawCursor();
activeButton = 1;
break;
}
}
}
// This function is called whenever a button is pressed and determines which of the 5 buttons was pressed,
//based on the voltage drop across the buttons all hooked up to A0.
int evaluateButton(int x) {
int result = 0;
x = analogRead(0);
if (x < 800) {
delay(100);
x = analogRead(0); // Performs glitch filtering
}
if (x < 50) {
result = 1; // right button
} else if (x < 200) {
result = 2; // up button
} else if (x < 400) {
result = 3; // down button
} else if (x < 600) {
result = 4; // Left button
} else if (x < 800) {
result = 5; // Select button
}
return result;
}
void menuItem1() { // Function executes when you select the 1st item from main menu
int activeButton = 0;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("SubMenu1");
while (activeButton == 0) {
int button; // Debounce
readKey = analogRead(0);
while (readKey > 790) { // Wait here if no buttons pushed; read value should be max (~1023)
delay(10);
readKey = analogRead(0);
}
button = evaluateButton(readKey);
switch (button) {
case 4: // This case will execute if the "back" button (e.g. LEFT) is pressed to go back to the Main menu
button = 0;
activeButton = 1;
break;
}
}
}
void menuItem2() { // Function executes when you select the 1st item from main menu
int activeButton = 0;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("SubMenu2");
while (activeButton == 0) {
int button; // Debounce
readKey = analogRead(0);
while (readKey > 790) { // Wait here if no buttons pushed; read value should be max (~1023)
delay(10);
readKey = analogRead(0);
}
button = evaluateButton(readKey);
switch (button) {
case 4: // This case will execute if the "back" button (e.g. LEFT) is pressed to go back to the Main menu
button = 0;
activeButton = 1;
break;
}
}
}
void menuItem3() { // Function executes when you select the 1st item from main menu
int activeButton = 0;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("SubMenu3");
while (activeButton == 0) {
int button; // Debounce
readKey = analogRead(0);
while (readKey > 790) { // Wait here if no buttons pushed; read value should be max (~1023)
delay(10);
readKey = analogRead(0);
}
button = evaluateButton(readKey);
switch (button) {
case 4: // This case will execute if the "back" button (e.g. LEFT) is pressed to go back to the Main menu
button = 0;
activeButton = 1;
break;
}
}
}
void menuItem4() { // Function executes when you select the 1st item from main menu
int activeButton = 0;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("lak lak lak");
while (activeButton == 0) {
int button; // Debounce
readKey = analogRead(0);
while (readKey > 790) { // Wait here if no buttons pushed; read value should be max (~1023)
delay(10);
readKey = analogRead(0);
}
button = evaluateButton(readKey);
switch (button) {
case 4: // This case will execute if the "back" button (e.g. LEFT) is pressed to go back to the Main menu
button = 0;
activeButton = 1;
break;
}
}
}
// This function will generate the arrows that indicate which UP/DN buttons to press.
int UpDnArrowDraw(int a,int b) {
if (a == 0) { // IF for Up/Dn arrows
lcd.setCursor(15, 1);
lcd.write(byte(2)); // Display DN arrow only ( BYTE 1 is UP arrow; BYTE 2 is DN arrow)
lcd.setCursor(15, 0);
lcd.print(" ");
}
else if (a > 0 and a < b ) {
lcd.setCursor(15, 1);
lcd.write(byte(2));
lcd.setCursor(15, 0);
lcd.write(byte(1)); // Display both UP and DN arrow
}
else if (a == b) {
lcd.setCursor(15, 0);
lcd.write(byte(1)); // Display UP arrow only
lcd.setCursor(15, 1);
lcd.print(" ");
}
}
Well, changing the operateMainMenu part to this, miraculously solved everything lol, I'm gonna post it for who will use this code in future and dealing with this problem
void operateMainMenu() {
int activeButton = 0;
while (activeButton == 0) {
int button;
readKey = analogRead(0);
if (readKey > 790) { // Wait here if no buttons pushed; read value should be max (~1023)
delay(50);
readKey = analogRead(0);
}
button = evaluateButton(readKey);
switch (button) {
case 0: // NO button returns as 0 there is no action taken
break;
case 1:
button = 0;
switch (cursorPosition) {
case 0:
menuItem1();
break;
case 1:
menuItem2();
break;
case 2:
menuItem3();
break;
case 3:
menuItem4();
break;
}
activeButton = 1;
mainMenuDraw();
drawCursor();
break;
case 2:
button = 0;
cursorPosition = cursorPosition - 1;
cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));
menuPage = menuPage - 1;
menuPage = constrain(menuPage, 0, maxMenuPages);
mainMenuDraw();
drawCursor();
activeButton = 1;
break;
case 3:
button = 0;
cursorPosition = cursorPosition + 1;
cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));
menuPage = menuPage + 1;
menuPage = constrain(menuPage, 0, maxMenuPages);
mainMenuDraw();
drawCursor();
activeButton = 1;
break;
}
}
}
Well I know it sounds pretty weird, but I made code in Arduino which works find when i just use an if statement for every different option. But that's what switch cases are for, so I tried it and for some weird reason it goes into and executes the code for standbyStatus==0 and for standbyStatus==1, but for standbyStatus==2 or in default, nothing is executed whatsoever. Note that the variable standbyStatus is set to 2 by the code for status 1. I can check that over the serial monitor, but the test Serial.print("case 2.1"); in the 2 -code doesn't appear. Only END of standbymanager. Again, when I use if, everything works as it should. Here is first the code with if and then the same code just as a switch case:
Also, that method is called over and over again. This is my loop.
void loop()
{
t= millis();
newAudio();
calcAudioScale();
if(standbyStatus==0){changeLEDs();}
standbymanager();
}
That method is basicly checking if there is some sound for like 40ms or sth, and if there is not, it'll change to standbyStatus One, which is a smooth dim up of the LEDs, which will be interrupted if there is sound, but if there isn't, it'll change to standbyStatus Two, which is just a solid light and checking just every second if there is sound. If so, it'll change back to stabdbyStatus zero.
Code #1 'IF':
void standbymanager()
{
if(standbyStatus==0)
{
Serial.print(" ");
Serial.print("case0");
if(audio[standbyTrigger]<0)
{
idleCounter++;
}
if(idleCounter>40)
{
standbyStatus = 1;
}
}
if(standbyStatus==1)
{
Serial.print(" ");
Serial.print("case1");
idleCounter = 0;
float power = 0;
for(int i=0; i<100; i++)
{
if(audio[standbyTrigger]>0)
{
standbyStatus = 0;
return;
}
power = i/100;
analogWrite(red, 255 - r*power);
analogWrite(green, 255 - g*power);
analogWrite(blue, 255 - b*power);
delay(20);
}
standbyStatus = 2;
return;
}
if(standbyStatus==2)
{
Serial.print(" ");
Serial.print("case 2.1");
if(audio[standbyTrigger]>10)
{
standbyStatus = 0;
return;
}
analogWrite(red, 255 - r);
analogWrite(green, 255 - g);
analogWrite(blue, 255 - b);
Serial.print(" ");
Serial.print("case2.2");
delay(1000);
return;
}
Serial.print(" ");
Serial.print("END of StandbyManager");
}
Code #2 'Switch Case'
void standbymanager()
{
switch(standbyStatus)
{
case 0:
Serial.print(" ");
Serial.print("case0");
if(audio[standbyTrigger]<0)
{
idleCounter++;
}
if(idleCounter>40)
{
standbyStatus = 1;
}
break;
case 1:
Serial.print(" ");
Serial.print("case1");
idleCounter = 0;
float power = 0;
for(int i=0; i<100; i++)
{
if(audio[standbyTrigger]>0)
{
standbyStatus = 0;
break;
}
power = i/100;
analogWrite(red, 255 - r*power);
analogWrite(green, 255 - g*power);
analogWrite(blue, 255 - b*power);
delay(20);
}
standbyStatus = 2;
break;
case 2:
Serial.print(" ");
Serial.print("case 2.1");
if(audio[standbyTrigger]>0)
{
standbyStatus = 0;
break;
}
analogWrite(red, 255 - r);
analogWrite(green, 255 - g);
analogWrite(blue, 255 - b);
Serial.print(" ");
Serial.print("case2.2");
delay(1000);
break;
default:
standbyStatus=0;
Serial.print(" ");
Serial.print("default");
delay(1000);
break;
}
Serial.print(" ");
Serial.print("END of StandbyManager");
}
I guess the errors come from case 1:
variables can't be declared inside a case statement
the break inside the for doesn't break from the switch statement
You can refactor it to:
case 1:
{
Serial.print(" ");
Serial.print("case1");
idleCounter = 0;
float power = 0;
bool flag = false;
for(int i=0; i<100; i++)
{
if(audio[standbyTrigger]>0)
{
standbyStatus = 0;
flag = true;
break;
}
power = i/100;
analogWrite(red, 255 - r*power);
analogWrite(green, 255 - g*power);
analogWrite(blue, 255 - b*power);
delay(20);
}
if (flag == false) {
standbyStatus = 2;
}
break;
}
You're probably changing standbyStatus 0 to 1 here:
if(standbyStatus==0)
{
Serial.print(" ");
Serial.print("case0");
if(audio[standbyTrigger]<0)
{
idleCounter++;
}
if(idleCounter>40)
{
standbyStatus = 1;
}
}
then it's normal to enter this if statement:
if(standbyStatus==1)
{
Serial.print(" ");
Serial.print("case1");
idleCounter = 0;
float power = 0;
for(int i=0; i<100; i++)
{
if(audio[standbyTrigger]>0)
{
standbyStatus = 0;
return;
}
power = i/100;
analogWrite(red, 255 - r*power);
analogWrite(green, 255 - g*power);
analogWrite(blue, 255 - b*power);
delay(20);
}
standbyStatus = 2;
return;
}
and second version of your code you use switch case, as the name suggest you only select one. Therefore standbyStatus will be updated but not going to enter other cases.
Edit:
Be aware that two codes are doing different things, code 1 can change standbyStatus and enter other if statements, and it returns after setting standbyStatus. Code 2 doesn't return in cases it only breaks the loop not entire case. Also Code 2 is not going to enter different blocks like in Code 1 (for single function call).
I'm using a SG-90 servo and sweeping left and right between two values.
My problem is that there is a distinct delay of about 500ms between direction changes. I would like the position of the servo to be predictable, but due to this at direction changes it is not.
bool servoDir = true;
int servoCnt = 90;
int servoInc = 1;
int servoMin = servoCnt - 5;
int servoMax = servoCnt + 5;
void loop() {
if (servoDir) {
dx = servoInc;
if (servoCnt > servoMax) {
servoDir = false;
}
} else {
dx = -servoInc;
if (servoCnt < servoMin) {
servoDir = true;
}
}
servoCnt += dx;
servo.write(servoCnt);
// delay or other code here (mine is 40ms)
}
I've tried both the Arduino Servo library and the VarspeedServo library. They both show the same thing.
What is the cause of this and what can I do about it?
Update
So if I up the speed at direction change, like so:
int extra = 5;
void loop() {
if (servoDir) {
dx = servoInc;
if (servoCnt > servoMax) {
dx -= extra;
servoDir = false;
}
} else {
dx = -servoInc;
if (servoCnt < servoMin) {
dx += extra;
servoDir = true;
}
}
servoCnt += dx;
servo.write(servoCnt);
// delay or other code here (mine is 40ms)
}
the delay disappears, but the servo position does become a lot less predictable.
You would experience exactly these symptoms if servoMin and servoMax were out of the servo range.... Which they are.
More seriously, these servos are not very precise. Incrementing by 1 at a time is probably the issue. You are experiencing some form of backlash.
You should check and clamp the count against the range AFTER incrementing/decrementing. That's one of the basic rules of embedded programming. Lives may be at stake, or equipment destroyed when sending out out of range values.
bool servoDir = true;
int servoCnt = 90;
int servoInc = 1; // <-- exclusively use this to control speed.
int servoMin = servoCnt - 5; // <-- this range is a bit short for testing
int servoMax = servoCnt + 5;
void loop() {
// 'jog' the servo.
servoCnt += (servoDir) ? servoInc : -servoInc;
// past this point, all position jogging is final
if (servoCnt > servoMax)
{
servoCnt = servoMax;
servoDir = false;
}
else if (servoCnt < servoMin)
{
servoCnt = servoMin;
servoDir = true;
}
servo.write(servoCnt);
// 40ms sounds a bit short for tests.
// 100 ms should give you a 2 seconds (0.5Hz) oscillation
delay(100);
}
Suppose I have an array:
int rgbcolors = {{R1,G1,B1},{R2,G2,B2},{R3,G3,B3},{Rn,Gn,Bn}}
How do I cycle through the values of this array by pressing 1 button on the remote?
So pressing once, gives the first {R1,G1,B1}, pressing twice, gives {R2,G2,B2} etc...
My current void loop for predefined colors:
if (irrecv.decode(&results))
{
int i = 0;
int j = 0;
int k = 0;
unsigned int val = results.value;
irrecv.resume();
switch(val) {
case button1: //RED
analogWrite(RedPin,255);
analogWrite(GreenPin,0);
analogWrite(BluePin,0);
break;
case button2: //GREEN
analogWrite(RedPin,0);
analogWrite(GreenPin,255);
analogWrite(BluePin,0);
break;
case button3: //BLUE
analogWrite(RedPin,0);
analogWrite(GreenPin,0);
analogWrite(BluePin,255);
break;
case button4: //YEL0
analogWrite(RedPin,255);
analogWrite(GreenPin,255);
analogWrite(BluePin,0);
break;
case button5: //PURPLE
analogWrite(RedPin,255);
analogWrite(GreenPin,0);
analogWrite(BluePin,255);
break;
case button6: //TURQUOISE
analogWrite(RedPin,0);
analogWrite(GreenPin,255);
analogWrite(BluePin,255);
break;
case button7: //ORANGE
analogWrite(RedPin,255);
analogWrite(GreenPin,140);
analogWrite(BluePin,0);
break;
case button8: //LIME !!! DON'T USE // CRASHES
analogWrite(RedPin,133);
analogWrite(GreenPin,255);
analogWrite(BluePin,140);
break;
case button9: //PINK
analogWrite(RedPin,50);
analogWrite(GreenPin,50);
analogWrite(BluePin,50);
break;
case buttonOn:
analogWrite(RedPin,255);
analogWrite(GreenPin,255);
analogWrite(BluePin,255);
break;
case buttonOff:
analogWrite(RedPin,0);
analogWrite(GreenPin,0);
analogWrite(BluePin,0);
break;
}
}
I unfortunately cannot help you with your "IR receiver value suddenly changed" issue, but I think I can help with your "cycle through the values of this array by pressing 1 button on the remote" question. The following is a code sample that does what I think you want to do:
const int NumberOfModes = 4;
int CurrentMode = -1;
void loop() {
int rgbcolors[NumberOfModes][3] = {
{ 255,0,0 }, // RED
{ 0,255,0 }, // GREEN
{ 0,0,255 }, // BLUE
{ 255,255,0 } // YELLOW
};
if (irrecv.decode(&results))
{
unsigned int val = results.value;
irrecv.resume();
if (val == button1) {
// Switch to new mode
CurrentMode++;
if (CurrentMode >= NumberOfModes)
{
CurrentMode = 0;
}
// Set output values
analogWrite(RedPin, rgbcolors[CurrentMode][0]);
analogWrite(GreenPin, rgbcolors[CurrentMode][1]);
analogWrite(BluePin, rgbcolors[CurrentMode][2]);
}
}
}
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;
}
}
}