Inputs seem to be remembered

#include <arduino-timer.h>
#include <DFRobotDFPlayerMini.h>
#include "Arduino.h"
#include "SoftwareSerial.h"
SoftwareSerial mySoftwareSerial(10, 11); // RX, TX
DFRobotDFPlayerMini myDFPlayer;
auto timer = timer_create_default();
int dontrun = 0;
int xsound;
int in_pressed;
int mute = 0;
int out1 = 0;
int out2 = 0;
int out3 = 0;
int out4 = 0;
int in1 = 0;
int in2 = 0;
int in3 = 0;
int in4 = 0;
int inold1 = 0;
int inold2 = 0;
int inold3 = 0;
int inold4 = 0;
int gamenumber = 9;
int gamen;
int gamenold;

void setup()
{
  mySoftwareSerial.begin(9600);
  Serial.begin(9600);

  Serial.println();
  Serial.println(F("DFRobot DFPlayer Mini Demo"));
  Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));

  if (!myDFPlayer.begin(mySoftwareSerial)) {  //Use softwareSerial to communicate with mp3.
    Serial.println(F("Unable to begin:"));
    Serial.println(F("1.Please recheck the connection!"));
    Serial.println(F("2.Please insert the SD card!"));
    while (true) {
      delay(0); // Code to compatible with ESP8266 watch dog.
    }
  }
  Serial.println(F("DFPlayer Mini online."));

  myDFPlayer.volume(30);  //Set volume value. From 0 to 30

  soundpicker();
  //setup pins
  pinMode(14, INPUT_PULLUP);
  pinMode(15, OUTPUT);
  pinMode(16, INPUT_PULLUP);
  pinMode(17, OUTPUT);
  pinMode(18, INPUT_PULLUP);
  pinMode(19, OUTPUT);
  pinMode(20, INPUT_PULLUP);
  pinMode(21, OUTPUT);

delay(1000);
}
void loop()
{
  timer.tick();

  if (dontrun == 0)
  {
    checkbuttonpress();//sets out variables "in" to 0 or 1 depending on button press
  }

  rungame();

  check_for_done();
  setouts();//sets outputs depending on variable outx
  mute = 1;

}
void check_for_done()
{

  switch (gamenumber)
  {
    case 6:
      break;
  }

}
void rungame()
{

  if (in1 == inold1)
  {
  }
  else
  {
    inold1 = in1;
    switch (gamenumber)
    case 9:
    dontrun = 1;
    myDFPlayer.play(1);
    delay(1000);
    dontrun = 0;
    beep();
  }
  

  if (in2 == inold2)
  {
  }
  else
  {
    inold2 = in2;
    switch (gamenumber)
    case 9:
    dontrun = 1;
    myDFPlayer.play(2);
    delay(2000);
    dontrun = 0;
    beep();
  }
  

  if (in3 == inold3)
  {
  }
  else
  {
    inold3 = in3;
    switch (gamenumber)
    case 9:
    dontrun = 1;
    myDFPlayer.play(3);
    delay(2000);
    dontrun = 0;
    beep();
  }
 

  if (in4 == inold4)
  {
  }
  else
  {
    inold4 = in4;
    switch (gamenumber)
    case 9:
    dontrun = 1;
    myDFPlayer.play(4);
    delay(1000);
    dontrun = 0;
     beep();

  }
 
}


void checkbuttonpress()
{
  if (digitalRead(53) == HIGH)
  {
    gamen = 0;
  }
  else
  {
    gamen = 1;
  }

  if (digitalRead(14) == HIGH)
  {
    in1 = 0;
  }
  else
  {
    in1 = 1;
  }
  if (digitalRead(16) == HIGH)
  {
    in2 = 0;
  }
  else
  {
    in2 = 1;
  }
  if (digitalRead(18) == HIGH)
  {
    in3 = 0;
  }
  else
  {
    in3 = 1;
  }
}
void setouts()
{
  if (out1 == 0)
  {
    digitalWrite(15, HIGH);
  }
  else
  {
    digitalWrite(15, LOW);
  }
  if (out2 == 0)
  {
    digitalWrite(17, HIGH);
  }
  else
  {
    digitalWrite(17, LOW);
  }
  if (out3 == 0)
  {
    digitalWrite(19, HIGH);
  }
  else
  {
    digitalWrite(19, LOW);
  }
  if (out4 == 0)
  {
    digitalWrite(21, HIGH);
  }
  else
  {
    digitalWrite(21, LOW);
  }
}
void  beep()
{
  if (mute == 1)
  {
    myDFPlayer.play(xsound);
    check_for_done();
  }

}
void allinszero()
{
  in1 = 0;
  in2 = 0;
  in3 = 0;
  in4 = 0;
}
void alllightsout()
{
  out1 = 0;
  out2 = 0;
  out3 = 0;
  out4 = 0;
  setouts();
}

void soundpicker()
{
  //generate 14 random numbers and put in soundx
  randomSeed(analogRead(0));
  xsound = random(1, 14);
  xsound += 19;
  delay(5);
}

OK here it is. I have removed as much of the code as I can whilst still keeping the fault. There is a lot of redundant code and a lot of doing things the lpng way around, this is becasue of the code that is missing, if that makes sense.
So here is what happens:
I have 4 inputs connected to switches. I have 4 outputs connected to lights. (not used in this example). When I press buton 1 I get sound 1, when I press button 2 I get sound 2, etc. This is ok and works fine.
Now the fault. If I press 1 then 2 then 3 quickly. I get sound 1 then sound 2 then sound 3. But this should not happen, I should get only sound 1 once.

How quick is “quick” when you’re pressing the buttons?

rungame() sequentially processes the inputs as they are at the point the code enters rungame(). So IOW if you enter rungame() with in1 and in2 equal to 1; and inold1 and inold2 equal to 0; then rungame() will play sound 1 followed by sound 2.

A couple of observations which may or may not be pertinent:

  • The code isn’t debouncing the switches, so there’s a possibility to capture transient state. Maybe not with the delay() statements being used currently in rungame(), but worth bearing in mind.
  • dontrun is currently not doing anything especially useful since rungame sets it, calls delay(), and then unsets it before returning to loop(). IOW, loop() will never execute with dontrun set. Again, this probably doesn’t matter currently, but it’s IMO its potentially misleading since it’s telling a story about the code execution which doesn’t reflect the reality of how it will run.
    inold4 = in4;
    switch (gamenumber)
    case 9:
    dontrun = 1;
    myDFPlayer.play(4);
    delay(1000);
    dontrun = 0;
    beep();

I’m astonished that this ‘switch/case’ statement is syntactically valid, let alone doing something meaningful. Is this intended to mean:

    inold4 = in4;
    if (gamenumber == 9)
    {
      dontrun = 1;
      myDFPlayer.play(4);
      delay(1000);
      dontrun = 0;
      beep();
    }

This valid syntax

    switch (gamenumber)
    case 9:
    downturn = 1;

is a complete switch statement and the equivalent of

    if (gamenumber == 9)
        downturn = 1;

Something to keep in mind if your goal is to write code that will confuse people.

a7

I would suggest that your code would be easier to debug if you checked for a button in a more concise way. For example, your checkbuttonpress() function checks the STATE of the buttons rather than whether they have BEEN pressed. I realize rungame() checks for the transition (not pressed->pressed). However, this makes the code harder to read and debug.

For button presses most people (including me, every time) use the tried and true method in the following tutorial:

StateChangeDetection

It accounts for debounce also. This way if there is a problem with button detection it is all in one function.

Also you want to avoid using delay(). These tutorials can help with that:

BlinkWithoutDelay

Arduino Multiple Things

Several Things at a Time

Lastly, a state machine is perfect for most applications:

State Machine

Uknod:
it must be something on the hardware of the inputs that is storring it, not sure how. Its basically 19 touch sensitive switchs.

What kind of "touch-sensitive switch" are you using and how are they wired?

Here is a little sketch for testing you buttons. It will let you know if any button is reading as pressed (LOW) when it is released. Using it you can track down any problems in your button hardware.

const byte PinCount = 4;
const byte InputPins[PinCount] = {14, 16, 18, 20};
const byte OutputPins[PinCount] = {15, 17, 19, 21};


void setup()
{
  for (int i = 0; i < PinCount; i++)
  {
    pinMode(InputPins[i], INPUT_PULLUP);
    pinMode(OutputPins[i], OUTPUT);
  }
}


void loop()
{
  for (int i = 0; i < PinCount; i++)
  {
    digitalWrite(OutputPins[i], !digitalRead(InputPins[i]));
  }


  // After you have determined that the output LEDs track the input buttons very closely,
  // turning on when the button is pressed and turning off when the button is released,
  // add a delay(1000); here and try again.  The LEDs should only change once per second
  // and only light up for buttons that are still pressed, not buttons that were pressed
  // and released during the delay.
}

johnwasser:
Here is a little sketch for testing you buttons. It will let you know if any button is reading as pressed (LOW) when it is released. Using it you can track down any problems in your button hardware.

const byte PinCount = 4;

const byte InputPins[PinCount] = {14, 16, 18, 20};
const byte OutputPins[PinCount] = {15, 17, 19, 21};

void setup()
{
  for (int i = 0; i < PinCount; i++)
  {
    pinMode(InputPins[i], INPUT_PULLUP);
    pinMode(OutputPins[i], OUTPUT);
  }
}

void loop()
{
  for (int i = 0; i < PinCount; i++)
  {
    digitalWrite(OutputPins[i], !digitalRead(InputPins[i]));
  }

// After you have determined that the output LEDs track the input buttons very closely,
  // turning on when the button is pressed and turning off when the button is released,
  // add a delay(1000); here and try again.  The LEDs should only change once per second
  // and only light up for buttons that are still pressed, not buttons that were pressed
  // and released during the delay.
}

Thanks for the test programme, good idea, yes it still happens with it. So I guess that means its a hardware issue with my switches. Although, strange as it seems, why does it not do it before the dalay is put in. I can switch the lights very quick, surely if there was a memory problem I would have problems?

Thanks for your input and test programme, I have found the problem, and I was correct, it was hardware, but foolishly I knew the problem all along just forgot - old age - the problem, which isn;t realy a problem at all, is my complex electronic touch switches. They are toggles. AAAAAH.
I am amazed that with 6 different games so far, this has not come to light earlier, I guess I was making programme changes that worked for the user, but not in the 7th game. I think it is becasue I have put in a sound bite which re assures the user that they have pressed the button, so if it does make the noise, they just press again, this effectively turnd toggle back into a momentary switch.
As I need momentary switches for this game I now need to write some code to convert, shouldn;t be too difficult, just another variable to show the previous state.
Thanks for all your help, now I know you are here I am sure you will be seeing me again as I write a lot of arduino stuff for my escape rooms.
johnwasser
If you find yourself in Margate England, then I owe you an escape game.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.