0

I got the following code from Github, and have been playing with it for the last couple months. The loop ALWAYS begins with the same LED as long as you do a complete reset to the board or power it up. If I press the start button (I added) after running the loop previously, a different LED typically will fire. I want to have the same led to start every loop, ALL the time (reset, power up, AND start button).

My current breadboard setup is an Arduino Mega, using a 4x4 matrix for the buttons and the LEDS to some digital outs. I currently am using 6 LEDS but plan to expand to several more when I get everything working where I want it.

A quick rundown of how this functions... At power up the LCD read out says Kyndras reaction timer. If the start button is pressed a countdown begins and the first led lights up (LED 2), when the corresponding button is pressed another led lights until that corresponding button is pressed, etc. The game runs for 30 seconds, at the end of the game your score is shown. At that point you can simply press start to do it again. My current issue is, I want LED "2" to be the first one to fire when the next game starts. I know there is something retaining memory, because when you watch the last light power on a second before the timer ends, it lights the same light for a fraction of a second on the next game.

I suspect (old_butn = 0;) is my issue. I have tried moving it all over the sketch and tried changing the digit after it, but I haven't had much luck.

I'm hoping someone can point me in the right direction.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <Utility.h>
#include "tones.h" // file music, lies in the folder firmware

#define GAMETIME 30000
#define LAMP 6
#define RES_KEY 15
#define BUZZER_PIN 19
#define BLINK 40

LiquidCrystal_I2C lcd(0x3F, 20, 4);

const byte ROWS = 4;
const byte COLS = 4;
char hexaKeys[ROWS][COLS] = {
  {'<', '8', '4', '0'},
  {'=', '9', '5', '1'},
  {'>', ':', '6', '2'},
  {'?', ';', '7', '3'}
};

byte colPins[ROWS] = {39, 37, 35, 33};
byte rowPins[COLS] = {41, 43, 45, 47};
boolean lamp_on[6];
boolean steps = true, go_game = true;
int lamp_pin[15] = {2, 3, 4, 5, 6, 7};
unsigned long startTime [12] = { 0, 0, 0, 0 };
unsigned long duration [12] ;
const int buttonPin = 14;
const int startPin = 8;
long last_pressed = 0;
long nowMillis = 0;
long toSec = 0;
long gameStart = 0;
long toBlink = 0;
int score = 0;
int dlay = 1000;
int butn = 0;
int old_butn = 100;
char customKey;

int melody[] = { NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C4 };
int noteDurations[] = { 4, 8, 8, 4, 4, 4, 4, 4 };

Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
//=====================================
void(* resetFunc) (void) = 0;
//=====================================
void setup()
{
  randomSeed(analogRead(0));
  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(startPin, OUTPUT);
  tone(BUZZER_PIN, 5000, 500);
  foreach (lamp_pin, LAMP, pinMode, OUTPUT);
  foreach (lamp_pin, LAMP, digitalWrite, HIGH);
  foreach (lamp_pin, LAMP, digitalWrite, LOW);
  delay(500);
  lcd.init();
  lcd.backlight();
  lcd.setCursor(4, 0);
  lcd.print("ver 3.5");
  lcd.setCursor(0, 2);
  lcd.print("KYNDRAS REACTION");
  lcd.setCursor(6, 3);
  lcd.print("GAME");
}
//=====================================
void loop()
{
  //******* allows a reset at anytime within the loop
  customKey = customKeypad.getKey();
  if (customKey - 48 == RES_KEY) {
    go_game = true;
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("RESTART!");
    delay(500);
    resetFunc();
  }
  //******* shit gets real
  if (digitalRead(startPin) == HIGH)
  {
    foreach (lamp_pin, LAMP, digitalWrite, LOW);//makes all leds go LOW after randomBlink

    countDown();
    //-------
    gameStart = millis();
    nowMillis = gameStart;
    score = 0;
    steps = true;
    go_game = true; //this line allows you to start w/o reset
    while ((nowMillis - gameStart < GAMETIME) and (go_game)) {
      nowMillis = millis();
      //**********
      if (nowMillis - toSec > 1000) {
        lcd_print();
        toSec = nowMillis;
      }
      //**********
      if (nowMillis - toBlink > BLINK) {
        if (lamp_on[old_butn]) {
          sw_led_off(old_butn);
        }
        else {
          sw_led_on(old_butn);
        }
        toBlink = nowMillis;
      }
      //**********
      if (steps) {
        while (old_butn == butn) {
          butn = random(LAMP);
        }
        sw_led_off(old_butn);
        old_butn = butn;
        sw_led_on(butn);
        steps = false;
      }
      //**********
      customKey = customKeypad.getKey();
      if (customKey) Serial.println((int)customKey);
      if (customKey - 48 == butn) {
        sw_led_off(customKey - 48);
        score++;
        steps = true;
        lcd_print();
      } else if (customKey - 48 == RES_KEY) {
        gameStart = millis();
        foreach (lamp_pin, LAMP, digitalWrite, LOW);
        score = 0;
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("RESTART!");
        delay(500);
        resetFunc();
      }
    }
    if (go_game) game_over(); // the game is over
    go_game = false;
      }
  //******** random blink

  for (int i = 0; i < 6; i++)
  {
    randomBlink(i);
  }
}

//=====================================
void lcd_print() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("TIME:");
  int time = GAMETIME / 1000 - (nowMillis - gameStart) / 1000;
  lcd.print(time);
  if (time < 11) {
    tone(BUZZER_PIN, 3500 + time * 300, 150);
  }
  lcd.setCursor(11, 0);
  lcd.print("BTN:");
  lcd.print(customKey);
  lcd.setCursor(0, 2);
  lcd.print("SCORE:");
  lcd.print(score);
}
//=====================================
void game_over() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("   END");
  lcd.setCursor(0, 2);
  lcd.print("     SCORE: ");
  lcd.print(score);
  foreach (lamp_pin, LAMP, digitalWrite, HIGH);//all lamps light for 2sec at end of game
  delay (2000);
  for (int thisNote = 0; thisNote < 8; thisNote++) {
    int noteDuration = 1000 / noteDurations[thisNote];
    tone(BUZZER_PIN, melody[thisNote], noteDuration);
    int pauseBetweenNotes = noteDuration * 1.30;
    delay(pauseBetweenNotes);
    noTone(BUZZER_PIN);
  }
}
//=====================================
void sw_led_on(int num) {
  digitalWrite(lamp_pin[num], 1);
  lamp_on[num] = 1;
}
//=====================================
void sw_led_off(int num) {
  digitalWrite(lamp_pin[num], 0);
  lamp_on[num] = 0;
}
//=====================================
void randomBlink(int pin)
{
  if (millis() - startTime[pin] >= duration[pin])
  {
    digitalWrite(lamp_pin[pin], !digitalRead(lamp_pin[pin]));
    duration[pin] = random(150, 1500);  //smallest and longest ON/OFF times.
    startTime[pin] = millis();
  }
}
//=======================================
void countDown() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("   GET READY");
  delay(500);
  lcd.setCursor(0, 2);
  lcd.print("   START IN 3...");
  tone(BUZZER_PIN, 4000, 200);
  delay(500);
  lcd.setCursor(0, 2);
  lcd.print("   START IN 2...");
  tone(BUZZER_PIN, 4500, 200);
  delay(500);
  lcd.setCursor(0, 2);
  lcd.print("   START IN 1...");
  tone(BUZZER_PIN, 5000, 200);
  delay(500);
  lcd.clear();
  lcd.setCursor(0, 1);
  lcd.print("  GO!");
  delay(250);
  for (int i = 0; i < 5; i++) {
    int frequency = 4000 + i * 300;
    tone(BUZZER_PIN, frequency, 150);
    delay(130);
  }
}
2
  • 1
    Can you give a link to where you found it on Github? What is <Utility.h>? Is that the game library? Is the function foreach in that library? I'm not sure what you want and I don't know if that is possible.
    – Jot
    Commented Sep 12, 2018 at 21:52
  • look at all the commands that have anything to do with random numbers ... one of them may be the cause
    – jsotola
    Commented Sep 13, 2018 at 5:30

1 Answer 1

0

The variables butn and old_butn are set to 0 and 100 before the game starts. It's not clear to me what these value represents. But re-assigning the variables back to 0 and 100 whenever the game restarts or resets should fix it.

Maybe at the end of the function game_over(). However it should probably also be done before the call to resetFunc() - whatever that does, its definition is not included.

1
  • Thankyou. I tried that with each one. You were right, both needed to be done.
    – Bender
    Commented Sep 13, 2018 at 22:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.