I'm working on the debounce its been a lot to digest so im getting other basic functions working in-between.
//LOOP==============================================
void loop() {
//LCD TOP ROW: SCORE / GAME OVER
lcd.setCursor(0, 0);
if (ballnumber < 1)
{
lcd.clear();
lcd.print("GAME OVER ");
}
else
{
lcd.print("SCORE: BALL:");
lcd.print(ballnumber);
}
This causes a rapid pulsing "GAME OVER" message because its constantly looping the clear. It also clears your numeric score under it, which I do not want. I'd want the player to be able to see their score at the end of the game.
//position your cursor on the first location in the zone you want to clear
//then print spaces to the last position in the zone
lcd.setCursor(0,8 );
// 00111
// 89012
lcd.print(" ");
As for displaying the score: it may be time to introduce sprintf().
If I were doing this, I would use lines like these in my code:
// declare a buffer for characters
char buf[21] = "\0"; // max 20 characters plus marker at end of string
// we really only need 16 characters, but I want to be on the safe side
// write the score and ball number to the character buffer
sprintf(buf, "%05d %d ", score, ballnumber);
// display what is in the character buffer
lcd.print(buf);
ok, So I think I am beginning to wrap my head around debouncing, but ran into a road block.
I'm following this tutorial's code:
and I applied it to my (GREEN) 100pt button, and eventually got it working. I even tested the button in rapid succession and found that it worked exactly as it should, not allowing the points to be counted if the button was pushed within (50).
when I tried to apply this same code the 'Ball Lost' Button, I got an error:
debounce_tutorial:77: error: redeclaration of 'int reading'
int reading = analogRead(A1);
^
debounce_tutorial:59: error: 'int reading' previously declared here
int reading = analogRead(A0);
The error seems to say I cant use (analogRead) for two different functions in the loop?
Here is my code, and an image of my wiring:
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
boolean lastReadButton1;
boolean lastReadButton2;
boolean lastReadButton3;
boolean lastReadButton4;
int buttonState; // the current reading from the input pin
int lastButtonState = LOW; // the previous reading from the input pin
long lastDebounceTime = 0; // the last time the output pin was toggled
long debounceDelay = 50; // the debounce time; increase if the output flickers
unsigned int score = 0;
int ballnumber = 5;
int a = 100;
int b = 500;
int c = 1000;
// SETUP===========================================
void setup() {
//input pins for scoring triggers
pinMode(A0, INPUT);
pinMode(A1, INPUT);
// set up the LCD:
lcd.begin(16, 2);
lcd.clear();
}
//LOOP==============================================
void loop() {
//LCD TOP ROW: SCORE / GAME OVER
lcd.setCursor(0, 0);
if (ballnumber < 1)
{
lcd.print("GAME OVER ");
}
else
{
lcd.print("SCORE: BALL:");
lcd.print(ballnumber);
}
//LCD BOTTOM ROW: NUMERIC SCORE
lcd.setCursor(0, 1);
lcd.print(score);
///LOST BALL///BLACK///////////////////////////////////
int reading = analogRead(A0);
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonState) {
buttonState = reading;
if (buttonState == HIGH) {
ballnumber = ballnumber - 1;
}
}
}
lastButtonState = reading;
///SCORE a 100 PTS///GREEN////////////////
int reading = analogRead(A1);
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonState) {
buttonState = reading;
if (buttonState == HIGH) {
score = score + a;
}
}
}
lastButtonState = reading;
///SCORE B 500 PTS///YELLOW////////////////
boolean readButton3 = digitalRead(A2);
if (readButton3 == LOW and lastReadButton3 == HIGH)
{
score = score + b;
}
lastReadButton3 = readButton3;
///SCORE C 1000 PTS///RED////////////////
boolean readButton4 = digitalRead(A3);
if (readButton4 == LOW and lastReadButton4 == HIGH)
{
score = score + c;
}
lastReadButton4 = readButton4;
}
Thank you that did get rid of the error, however both buttons stopped working.
When I reverted back to the old the GREEN (A1) code, the (A0) code started working again.
So they are still combating each other?
Currently works (but no debounce on green)
///LOST BALL///BLACK///////////////////////////////////
int reading = analogRead(A0);
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonState) {
buttonState = reading;
if (buttonState == HIGH) {
ballnumber = ballnumber - 1;
}
}
}
lastButtonState = reading;
///SCORE a 100 PTS///GREEN////////////////
boolean readButton2 = digitalRead(A1);
if (readButton2 == LOW and lastReadButton2 == HIGH)
{
score = score + a;
}
lastReadButton2 = readButton2;
lastButtonState = reading;
Currently neither button works when I leave it like this:
///LOST BALL///BLACK///////////////////////////////////
int reading = analogRead(A0);
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonState) {
buttonState = reading;
if (buttonState == HIGH) {
ballnumber = ballnumber - 1;
}
}
}
lastButtonState = reading;
///SCORE a 100 PTS///GREEN////////////////
reading = analogRead(A1);
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonState) {
buttonState = reading;
if (buttonState == HIGH) {
score = score + a;
}
}
}
You have 2 buttons, you need to store the state for each button independently. You can only reuse a variable in this case if it is a temporary variable.
Something like this:
///LOST BALL///BLACK///////////////////////////////////
int reading = analogRead(A0);
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonState) {
buttonState = reading;
if (buttonState == HIGH) {
ballnumber = ballnumber - 1;
}
}
}
lastButtonState = reading;
///SCORE a 100 PTS///GREEN////////////////
reading = analogRead(A1);
if (reading != lastButton2State) {
lastDebounce2Time = millis();
}
if ((millis() - lastDebounce2Time) > debounceDelay) {
if (reading != button2State) {
button2State = reading;
if (button2State == HIGH) {
score = score + a;
}
}
}
well I tried making a unique naming convention for each copy of the button code as suggested, but that currently isnt working. I get no errors but neither button does anything at the moment:
Going to keep trying things. If anyone has other ideas let me know.
Code:
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
boolean lastReadButton1;
boolean lastReadButton2;
boolean lastReadButton3;
boolean lastReadButton4;
int button_0State; // the current reading from the input pin
int button_aState;
int lastButton_0State = LOW; // the previous reading from the input pin
int lastButton_aState = LOW;
long lastDebounce_0Time = 0; // the last time the output pin was toggled
long lastDebounce_aTime = 0;
long debounceDelay = 50; // the debounce time; increase if the output flickers
unsigned int score = 0;
int ballnumber = 5;
int a = 100;
int b = 500;
int c = 1000;
// SETUP===========================================
void setup() {
//input pins for scoring triggers
pinMode(A0, INPUT);
pinMode(A1, INPUT);
// set up the LCD:
lcd.begin(16, 2);
lcd.clear();
}
//LOOP==============================================
void loop() {
//LCD TOP ROW: SCORE / GAME OVER
lcd.setCursor(0, 0);
if (ballnumber < 1)
{
lcd.print("GAME OVER ");
}
else
{
lcd.print("SCORE: BALL:");
lcd.print(ballnumber);
}
//LCD BOTTOM ROW: NUMERIC SCORE
lcd.setCursor(0, 1);
lcd.print(score);
///LOST BALL///BLACK///////////////////////////////////
int reading = analogRead(A0);
if (reading != lastButton_0State) {
lastDebounce_0Time = millis();
}
if ((millis() - lastDebounce_0Time) > debounceDelay) {
if (reading != button_0State) {
button_0State = reading;
if (button_0State == HIGH) {
ballnumber = ballnumber - 1;
}
}
}
lastButton_0State = reading;
///SCORE a 100 PTS///GREEN////////////////
analogRead(A1);
if (reading != lastButton_aState) {
lastDebounce_aTime = millis();
}
if ((millis() - lastDebounce_aTime) > debounceDelay) {
if (reading != button_aState) {
button_aState = reading;
if (button_aState == HIGH) {
score = score + a;
}
}
}
lastButton_aState = reading;
///SCORE B 500 PTS///YELLOW////////////////
boolean readButton3 = digitalRead(A2);
if (readButton3 == LOW and lastReadButton3 == HIGH)
{
score = score + b;
}
lastReadButton3 = readButton3;
///SCORE C 1000 PTS///RED////////////////
boolean readButton4 = digitalRead(A3);
if (readButton4 == LOW and lastReadButton4 == HIGH)
{
score = score + c;
}
lastReadButton4 = readButton4;
}
int reading = analogRead(A0);
if (reading != lastButton_0State) {
lastDebounce_0Time = millis();
}
if ((millis() - lastDebounce_0Time) > debounceDelay) {
if (reading != button_0State) {
button_0State = reading;
if (button_0State == HIGH) {
ballnumber = ballnumber - 1;
}
}
}
lastButton_0State = reading;
basically,
if ((millis() - lastDebounce_0Time) > debounceDelay) {
can only be true if "reading" has been the same as the "lastButton_0State" for greater than the debounce time (otherwise the debounce timer would reset again), but then inside this "if", you do a check of:
I do not follow. Sorry, I have no programming experience as of a week ago so I'm really trying hard to learn and understand this.
I have eliminated everything from the code except the ball loss button. I have added comments into the debounce code as to my understanding of how this works... if you could correct me where I'm going wrong or let me know where the logic falls apart I'd appreciate it.
P.S. the button does not currently work. not sure why.
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int buttonState; // the current reading from the input pin
int lastButtonState = LOW; // the previous reading from the input pin
long lastDebounceTime = 0; // the last time the output pin was toggled
long debounceDelay = 50; // the debounce time; increase if the output flickers
unsigned int score = 0;
int ballnumber = 5;
// SETUP===========================================
void setup() {
//input pins for scoring triggers
pinMode(A0, INPUT);
// set up the LCD:
lcd.begin(16, 2);
lcd.clear();
}
//LOOP==============================================
void loop() {
//LCD TOP ROW: SCORE / GAME OVER
lcd.setCursor(0, 0);
if (ballnumber < 1)
{
lcd.print("GAME OVER ");
}
else
{
lcd.print("SCORE: BALL:");
lcd.print(ballnumber);
}
//LCD BOTTOM ROW: NUMERIC SCORE
lcd.setCursor(0, 1);
lcd.print(score);
///LOST BALL///BLACK///////////////////////////////////
int reading = analogRead(A0); //////Listen to what A0 is saying
if (reading != lastButtonState) {///////If what you hear is not the same....
lastDebounceTime = millis();/////...from the last reading 0 milliseconds ago.
}
if ((millis() - lastDebounceTime) > debounceDelay) {///...and if your last change was longer than 50 milliseconds ago...
if (reading != buttonState) {///if the signal is not high
buttonState = reading; ///then continue just reading
if (buttonState == HIGH) { ////if it IS high
ballnumber = ballnumber - 1;/////Then take away 1 ball from the ballnumber
}
}
}
lastButtonState = reading; /////....Refering to the first "if" statement?
}
analogRead(A0);
I believe you wanted
digitalRead(A0);
in fact I would use
digitalRead(14); //reminds you you are using a digital input rather than analog.
I have made some edits to your code which should now work. A big problem was that in your above post there was a closing brace (}) in the wrong spot (look at "if (reading != buttonState)"). Also another issue was your buttonState variable was only being set when reading != buttonState which since buttonState was never initialized it could be inconsistent.
The code below is quite a bit different so please compare it/read over it to and let me know if you have any questions.
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int lastButtonState = LOW; // the previous reading from the input pin
long lastDebounceTime = 0; // the last time the output pin was toggled
long debounceDelay = 50; // the debounce time; increase if the output flickers
unsigned int score = 0;
int ballnumber = 5;
// SETUP===========================================
void setup() {
//input pins for scoring triggers
pinMode(A0, INPUT);
// set up the LCD:
lcd.begin(16, 2);
lcd.clear();
}
//LOOP==============================================
void loop() {
//LCD TOP ROW: SCORE / GAME OVER
lcd.setCursor(0, 0);
if (ballnumber < 1)
{
lcd.print("GAME OVER ");
}
else
{
lcd.print("SCORE: BALL:");
lcd.print(ballnumber);
}
//LCD BOTTOM ROW: NUMERIC SCORE
lcd.setCursor(0, 1);
lcd.print(score);
///LOST BALL///BLACK///////////////////////////////////
int reading = analogRead(A0); //////Listen to what A0 is saying
//Turn off timer when button is released
if (reading == LOW)
{
lastDebounceTime = 0;
}
if (lastDebounceTime == 0)
{
if (reading == HIGH)
{///////If what you hear is not the same....
//Added -debounceDelay to offset timer so the first ball is removed right away
lastDebounceTime = millis() - debounceDelay;/////...from the last reading 0 milliseconds ago.
}
}
else
{
if ((millis() - lastDebounceTime) > debounceDelay)
{///...and if your last change was longer than 50 milliseconds ago...
ballnumber = ballnumber - 1;/////Then take away 1 ball from the ballnumber
lastDebounceTime = millis(); //Restart Timer
}
}
}
50 milliseconds is pretty fast, see what happens if you change "debounceDelay=2000" do they still all disappear really fast or is there now a 2 second delay?
Isn't this how you wanted it to work? Or did you just want it to take a ball away every time you press and wait until the next press to take the next one?