Hello all and thank you in advance for any help!
This is my first real arduino-project. I am building a little darts "game station" for my sisal dartboard. Currently it consists of four 7segment screens, seven LEDs, a matrix keyboard and three push-buttons.I tried to make everything as adaptable and "generalized" as possible, to be able to change the design and add functionalities later.
Everything is working fine so far, but I can't seem to debounce the buttons properly. They still behave very much undebounced. For whatever reason I didn't want to use a library for the buttons, because I wanted to do it by myself but here I am asking for help anyway
The button function is called butR. Any help would be appreciated, thank you!
#include <Arduino.h>
#include <TM1637Display.h>
#include <Keypad.h>
/////////////////////////////////////////////////////////////// 7 SEGMENT
const uint8_t clockPin = 48;
const uint8_t DIO [] = {10,11,12,13};
int currentNum [] = {301,301,301,301};
const uint8_t displayNum = 4;
TM1637Display displays[4]={TM1637Display (clockPin, DIO[0]), // define display objects
TM1637Display (clockPin, DIO[1]),
TM1637Display (clockPin, DIO[2]),
TM1637Display (clockPin, DIO[3])
} ;
unsigned long nowDisp []= {0,0,0,0};
unsigned long beforeDisp []= {0,0,0,0};
bool dispBlink [] = {false,false,false,false};
const int intervalDisp = 650;
/////////////////////////////////////////////////////////////// KEYBOARD
int inputString;
const byte ROWS = 4;
const byte COLS = 4;
byte rowPins[ROWS] = {5, 4, 3, 2};
byte colPins[COLS] = {9, 8, 7, 6};
char hexaKeys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
Keypad kpd = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
/////////////////////////////////////////////////////////////// LEDS
const uint8_t pLED[] = {40,42,44,46}; //40=1;42=2;44=3;46=4
const uint8_t gLED[] = {38,36}; // 38=301; 36=501
const uint8_t pLEDNum = 4;
const uint8_t gLEDNum = 2;
const int intervalLED = 650;
unsigned long nowGLED []= {0,0};
unsigned long beforeGLED []= {0,0};
unsigned long nowPLED []= {0,0,0,0};
unsigned long beforePLED []= {0,0,0,0};
int pLEDState [] = {LOW,LOW,LOW,LOW};
int gLEDState [] = {LOW,LOW};
/////////////////////////////////////////////////////////////// BUTTONS
const uint8_t button [] = {53,50,51};
const uint8_t buttonNum = 3;
const int buttonDelay = 40;
unsigned long lastDebounceTime []= {0,0,0};
int lastButtonState [] = {LOW,LOW,LOW};
int buttonState [] = {LOW,LOW,LOW};
/////////////////////////////////////////////////////////////// BUZZER
const uint8_t buzzerPin(25);
/////////////////////////////////////////////////////////////// GAME
uint8_t gStage = 0;
uint8_t gMode = 0; // 0 = 301; 1 = 501
int maxScore[] = {301,501};
uint8_t maxpNum = 4; // max Players
uint8_t pNum = 1; // 1 = 1, 2 = 2, 3 = 3
int pScore [] = { 301,301,301,301}; // initialise as 301
const uint8_t gNum = 2;
/////////////////////////////////////////////////////////////// SETUP
///////////////////////////////////////////////////////////////
void setup()
{
for (int i = 0;i < displayNum; i++){
displays[i].setBrightness(0x0f);
}
for (int i = 0;i < pLEDNum; i++){
pinMode(pLED[i],OUTPUT);
}
for (int i = 0;i < gLEDNum; i++){
pinMode(gLED[i],OUTPUT);
}
for (int i = 0;i<buttonNum; i++){
pinMode(button[i],INPUT_PULLUP);
}
pinMode(buzzerPin,OUTPUT);
initialise();
Serial.begin(9600);
}
/////////////////////////////////////////////////////////////// LOOP
///////////////////////////////////////////////////////////////
void loop()
{
gSelect();
reStart();
while (gStage == 1){
reStart();
if (gStage == 1){
// ADD DISPLAY BLINK HERE
}
if(butR(0)==1){
pNum++;
if (pNum > maxpNum){ // TOGGLE BETWEEN PLAYER NUM
pNum = 1;
dispsOff();
}
}
for (int i = 0; i < pNum; i++){
blinkDisp(i,0);
if(butR(1)== 1){
gStage = 2;
}
}
}
/////// REWRITE BLINK FOR LEDs and SCREENS: use only one timer for all blinking operations?
////// select more than one players, then restart --> one display stays on (hopefully debouncing issue);
}
/////////////////////////////////////////////////////////////// FUNCTIONS
///////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////// LEDs
void pLEDon (int x){ // player 1 = 1 ...
digitalWrite(pLED[x-1],HIGH);
}
void pLEDoff (int x){ // player 1 = 1 ...
digitalWrite(pLED[x-1],LOW);
}
void gLEDon (int x){ // 0 = 301, 1 = 501
digitalWrite(gLED[x],HIGH);
}
void gLEDoff (int x){ // 0 = 301, 1 = 501
digitalWrite(gLED[x],LOW);
}
void blinkGLED(int x, int y){ // x = 0 (301), 1(501); y = either 0 (standard blink), or custom timer
nowGLED[x] = millis(); // start blinking timer for LEDs#
int timer;
if ( y > 0){
timer = y;
} else{
timer = intervalLED;
}
if (nowGLED[x] - beforeGLED[x] > timer){
beforeGLED[x] = nowGLED[x];
if(gLEDState[x] == LOW){
gLEDState[x] = HIGH;
} else {
gLEDState[x] = LOW;
}
digitalWrite(gLED[x],gLEDState[x]);
}
}
void blinkPLED(int x, int y){ // x = 1-4; y = either 0 (standard blink), or custom timer
nowPLED[x] = millis(); // start blinking timer for LEDs#
int timer;
if ( y > 0){
timer = y;
} else{
timer = intervalLED;
}
if (nowPLED[x] - beforePLED[x] > timer){
beforePLED[x] = nowPLED[x];
if(pLEDState[x] == LOW){
pLEDState[x] = HIGH;
} else {
pLEDState[x] = LOW;
}
digitalWrite(pLED[x],pLEDState[x]);
}
}
/////////////////////////////////////////////////////////////// BUTTONS
uint8_t butR (int x){
uint8_t reading = digitalRead(button[x]);
uint8_t output = 0;
if (reading != lastButtonState[x]) {
lastDebounceTime[x] = millis();
}
if ((millis() - lastDebounceTime[x]) > buttonDelay) {
if (reading != buttonState[x]) {
buttonState[x] = reading;
if (buttonState[x] == HIGH){
return output;
}
// if (buttonState[x] == LOW){
// return buttonState[x];
// }
}
}
}
/////////////////////////////////////////////////////////////// DISPLAYS
void dispsOff (){
for (int i = 0; i < displayNum;i++){ // clear all 7segment displays
displays[i].clear();
}
}
void blinkDisp (int x, int y){
nowDisp[x] = millis(); // start blinking timer for 7SEGMENT
int timer;
if ( y > 0){
timer = y;
} else{
timer = intervalDisp;
}
if (nowDisp[x] - beforeDisp[x] > timer){
beforeDisp[x] = nowDisp[x];
dispBlink[x]=!dispBlink[x];
}
if (dispBlink[x]== true){
displays[x].showNumberDec(currentNum[x]);
}else{
displays[x].clear();
}
}
/////////////////////////////////////////////////////////////// GAME
void initialise(){
dispsOff(); // clear all 7segment displays
gMode = 0;
pNum = 1;
for (int i = 0; i < displayNum; i++){ // set currentNum to default (301)
currentNum[i] = 301;
}
for (int i = 0; i < maxpNum;i++){ // initialise as 301
pScore[i] = 301;
}
for (int i = 0; i < gNum; i++){ // turn off game LEDs
gLEDoff(i);
}
for (int i = 0; i < pNum; i++){ // turn off player LEDs
pLEDoff(i);
}
}
void gSelect(){ // SELECT GAME TYPE
while (gStage==0){ // GAME SELECTION PHASE
blinkGLED(gMode,400);
if(butR(0)==1){
gMode++;
if (gMode > gNum-1){ // TOGGLE BETWEEN GAMES
gMode = 0;
}
for (int i = 0; i < gNum; i++){
gLEDoff(i);
}
}
if(butR(1) == 1){ // PRESS CONFIRM TO CONFIRM GAME CHOICE
for (int i = 0; i < gNum; i++){
gLEDoff(i);
}
gLEDon(gMode);
for (int i = 0; i < maxpNum;i++){ // SET SCORE TO GAME TYPE
if (gMode == 0){
pScore[i] = 301;
}
if (gMode == 1){
pScore[i] = 501;
}
}
for (int i = 0; i < maxpNum; i++){
currentNum[i] = maxScore[gMode];
}
gStage = 1; // SELECTION PHASE ENDED
}
}
}
void reStart(){
if (butR(2) == 1){
gStage = 0;
initialise();
delay(100);
}
}
void pSelect(){
}