Help With First Project

@grimsightings - one trick you might be able to use is to preset the game variabkes so you start already with a sequence, like three or four you just stuff into your array along with making the length correct. Then at least you'll see that you do play the sequence and go on to gather input.

@xfpd got further than I did.

Add copious printing. At each section, at key points. Print "now I play the sequence"… "now I got some input"... along with the values of variabkes that may show you the code is doing what you wrote, not what you thought.

I found pressing a button just sees the button dozens of time. The button never compares favorably with where you think the user is in the sequence.

You need to handle the buttons differently! I don't know if using a button library would make your work harder and be a distraction of project-sized proportions all by itself, but somehow you have to use the presses, not the states, of the buttons.

With 22 edits to the first post, you've managed to make trash of this thread. What I am sober better able, I will try to read your first post with fresh eyes. Stop editing it! If you write new code post it. If you find new issues, post about them. New posts.

a7

In my online model, I have had 0 problems with unwanted or random button inputs, it works cleanly. Currently I am focusing on the problem with the code rather than the button inputs.

The game sequence should run like this :
Lights flash in order, waiting until any button is pressed,
Once a button is pressed (Only registers if button is being pressed as flashing sequence ends, a problem but I dont have the time to deal with it since it still works) all the lights go dark, then 1 light will flash,
Once a button is hit, if it matches the flashed color it shoud restart the sequence from the second step, but have 2 lights flash, and it waits for 2 inputs. If it receives the wrong button being pressed, it restarts as if it was just turned on.
The problem is that it registers every input as a correct input, and then plays the entire loop regardless of how many button presses are needed, causing it to simply go through the entire sequence again and again nonsensically with each input received. Am I changingone of the variables by accident?

In my model of it, I havent had the issue of it seeing the button input as if it was inputed dozens of times. I hadnt thought of using the print function like that, but I will try it! I am unable to put plain text in the print functions, how would I go about doing that?

Serial.print("Plain text"); // text
Serial.println("Plain text"); // text + linefeed

This is because your simulator "debounces" buttons... your sim is not being nice. Try using WOKWI.COM simulator. It will show you non-debounced buttons.

The moment I ran my code in WOKWI it just started fritzing through the serial monitor. I think I figured out the problem with the code, its not registering the variable changes of "startInput" or "phase", causing it to just run through the loop unwarrented. Although I now have to fix the button states too.

Try to be more descriptive, even when you and I understand this.

This is a combination of how the buttons are wired and debouncing.

See Post #47 for wokwi simulation of debouncing a wired button (pin -- button -- gnd).

What would be the best way to "adapting" my code into debouncing the button inputs? And is there something obvious im missing with why its skipping past while checks, or just not touching the variables associated with while checks?

 }
   Serial.print("Gonna check whether wrong");
 if(orderArray[arrayDigit] != pressInput){
    Serial.print("is wrong");
 //END SEQUENCE
   phase = 0;
   pressInput = 0;
   startInput = 0;
 //while(orderArray[arrayDigit] > 0){
 //arrayDigit++;
 //}

is at the bottom of the code, and

void loop(){
//ButtonState Qualifiers
  Serial.print(" Begin");
  Serial.print(startInput);
buttonStateRed = digitalRead(buttonRedPin);
buttonStateGrn = digitalRead(buttonGrnPin);
buttonStateYel = digitalRead(buttonYelPin);
buttonStateBlu = digitalRead(buttonBluPin);
//Transient Mode Screen
  delay(200);
if(startInput == 0){ 
if(buttonStateRed == 0 || buttonStateGrn == 0 || buttonStateYel == 0 || buttonStateBlu == 0) {
startInput = 1 ;

is at the top. "startInput" should not be registering as 0 then 1 if no buttons are being interacted with (In the debounce program)

Your drawings indicate pullup resistors, and they seem to be working for your hardware simulation.

AS you press a button, before contact is made, a small charge jumps back and forth inside the button, between the two contacts, called "ringing."

"Debouncing" follows steps to ensure the "press" is intentional and not ringing.

  1. compares the state: "if your button was high, and is low, a change occurred"
  2. times change of state duration: "if change of states occurred sooner than XXms, it was ringing, and not a button"
  3. if "LOW" means pressed, is the button now "HIGH" (button released) or still LOW (still pressed).

You can follow how this is done in the simulation in Post #47.

That's a simple way to debounce BUT the delay(200) blocks key-presses (and everything else) for 1/5 of a second. It works less often than it fails.

So basically, I need to make a function that does this for each button, that I then just call up whenever I need to check if a button is pressed or not?

Feel free to copy mine. (readButton2())

One function only. Send "which button" to the debounce function.

I put that delay there because I thought the button press triggering the reset was being registered by the if statement below that, but the problem appears to be the "startInput" variable just changes back to 1 on its own somewhere. Il remove that delay since its no longer needed

So a function that checks each button, or a function that checks a variable to see which button needs to be pressed?

Yes... checks for "valid button press and release" versus a ringing noise surrounding the button press. This link describes, ringing, with pictures... Arduino - Button - Debounce | Arduino Tutorial

ok, thank you, im going to get to work on implementing it, but checking my code I cant figure out why the "startInput" function changes to 1 without the if statement passing, or why the same is happening with my "phase" variable

(Also, would I have to change all of my If statements if i made my button states booleans instead of variables?)

I believe sees "false" button presses (random electrical noise).

A bool is 0 or 1, an int is 0, 1, ... forever... so you do not need to change to boolean.

If it was random electrical noise, why is it always the second loop run through that triggers it, and it doesnt play the else statement code? What im seeing is that the loop just seemingly... skips over code. It doesnt resolve the "phase" variable correctly, at all, seemingly ignoring the while statement it dictates. I feel like im missing something with my variables thats causing the variables in the while statements to just, not work

Im not gonna be able to access the forum for a bit, but I will be able to after 4-5 ish, if you able to spare some time later to help. I do appreciate all the help!

I can not duplicate your setup. I can only share advice on what I see.

You can't imagine that code does magic. The code does EXACTLY what it is told.

Well... beside all the advice you were given... maybe you should make a ONE BUTTON sketch to discover part of what is needed for a four-button sketch.

1 Like

Print the values of key variables, viz:

Serial.print("press input "); Serial.print(pressInput);
Serial.print(" arrayDigit is  "); Serial.print(arrayDigit);
Serial.print(" orderArray[arrayDigit] is "); Serial.print(orderArray[arrayDigit]);
Serial.println("");

     if (orderArray[arrayDigit] == pressInput) {
Serial.println("                          sequence == input");
       if (arrayDigit > 0) {
         arrayDigit--;

Does this have to work IRL? Or is getting your model working sufficient?

As @xfpd notes, the model you are using is not very faithful. You have seen what the wokwi does - its switches will bounce if you don't tell them not to - by default they act enough like real ones to be useful in finding a class of errors.

This

    while (orderArray[arrayDigit] > 0) {
      arrayDigit++;
    }
    orderArray[arrayDigit] = random(1, 5);
    while (arrayDigit > 0) {
      digitalWrite((orderArray[arrayDigit]) + 9, HIGH);
      delay(300);
      digitalWrite((orderArray[arrayDigit]) + 9, LOW);
      arrayDigit--;
    }
    digitalWrite((orderArray[arrayDigit]) + 9, HIGH);
    delay(300);
    digitalWrite((orderArray[arrayDigit]) + 9, LOW);
    while (orderArray[arrayDigit] > 0) {
      arrayDigit++;
    }
    arrayDigit--;

is asking for trouble of the kind you are experiencing. A delicate balancing act of increments and decrements…

Add that variabke I mentioned:

 // grow the sequence
    orderArray[sequenceLength] = random(1, 5);
    sequenceLength++; 

// play it for the player
   for (byte ii = 0; ii < sequenceLength; ii++) {
      digitalWrite((orderArray[ii]) + 9, HIGH);
      delay(300);
      digitalWrite((orderArray[ii]) + 9, LOW);
      delay(77);
    }

An index skittering through the sequence as an index shoukd only be locally needed. Another variable, here sequenceLength is always the current number of valid entries in the array.

If you manage to get to the end of one game and want to start a new one, you can initialise the game state by

  sequenceLength = 0;

a7