Pinball - "All Lanes Lit" Bonus score is not behaving as expected I'm trying to build a (very basic) pinball machine with an Arduino Uno. This part of the code will detect when a ball passes 3 lanes. When a lane is passed, it will activate the lane(laneState), reward a score(+10) and light up an LED.

The Expected Result:


When all 3 lanes are LIT, assign a score of the lane passage(+10), assign a bonus score(+100) and reset all laneStates to 0 and turn all leds to LOW.
110 points are being added in total


Actual Result:


the last lane passed lights back up as active (while I set all of them to inactive)
120 points are being added in total (instead of 110?)


Any hints on why I see this behaviour are very welcome!



The sketch and board can be found here: https://circuits.io/circuits/2739062-poc-lane-passage-001/
Turn on 'Code Editor' and enable the Serial Monitor to see the scores.



More info:
I looked into using interrupts, but that is not an option here (the Uno only has 2 pins for interrupts, I need 3)

Thanks!

EDIT: added the code here too:

// Scores
int totalScore = 0;
const int lanePassageScore = 10; // 10 points for passing a lane
const int allLaneActiveBonus = 100; // 100 points for activating ALL lanes

// Digital pins to detect the state of the buttons
const int laneButtonPin[] = {2,3,4};
const int laneStateLedPin[] = {10,11,12};

// all three lanes are 'inactive' at the start of the game
int laneButtonState[] = {0,0,0};
int lastLaneButtonState[] = {0,0,0};
int laneState[] = {0,0,0};


void setup() {
  Serial.begin(9600); // for debugging
}

void loop() {
  // detect if lanes 1 to 3 were activated
  detectLaneButtonPassage(0); // Lane 1
  checkAllLanesLit();
  detectLaneButtonPassage(1); // Lane 2
  checkAllLanesLit();
  detectLaneButtonPassage(2); // Lane 3
  checkAllLanesLit();

  Serial.println(totalScore); // for debugging

  delay(5);
}

void detectLaneButtonPassage(int laneId){
  // Check state of the button
  laneButtonState[laneId] = digitalRead(laneButtonPin[laneId]);
  if(laneButtonState[laneId] != lastLaneButtonState[laneId]){
    if(laneButtonState[laneId] == HIGH){
      // The lane button change to an ON position, toggle the lane state
      if(laneState[laneId] == 0){
        // lane was not yet active, it becomes active now
        laneState[laneId] = 1;
        digitalWrite(laneStateLedPin[laneId], HIGH);
        rewardScore(lanePassageScore);
      }else{
        // lane was already active, it becomes inactive now
        laneState[laneId] = 0;
        digitalWrite(laneStateLedPin[laneId], LOW);
        rewardScore(lanePassageScore/2);
      }
    }
  }
  lastLaneButtonState[laneId] = laneButtonState[laneId];
}

void rewardScore(int score){
  totalScore += score;
}

void checkAllLanesLit(){
  // Check if ALL lanes are activated
  if(laneState[0]==1 &amp;&amp; laneState[1]==1 &amp;&amp; laneState[2]==1){
    // reset all buttons and states
    for(int laneId=0; laneId&lt;=2; laneId++){
      laneButtonState[laneId] = 0;
      lastLaneButtonState[laneId] = 0;
      laneState[laneId] = 0;
      digitalWrite(laneStateLedPin[laneId], LOW); //Turn off led
    }
    rewardScore(allLaneActiveBonus);
  }
}
Looks like a timing issue.

Which ever order you hit the buttons in the last one always stays lit (and you get an extra 10 points added).

I set a breakpoint at:

rewardScore(allLaneActiveBonus);


...and just waited a sec and then continued and your code worked as expected.

So I think that you are setting all lines to LOW in checkAllLanesLit() and then only have a short delay (5mS) before looping round and checking again (at which point the button is still HIGH as you haven't taken your finger off it quickly enough) - resulting in the additional 10 points and that lane being lit again.