Automating String Pinsetter for Half Scale Bowling Alley

Purpose (Part 1)

Convert a half scale bowling alley with manual pinsetter (currently uses an Arduino Uno in conjunction with a pc running scoring software) to arcade style bowling alley with automated string pinsetter. Part 1 to focus on how to utilize a separate Arduino Mega to monitor when ball is rolled and, after the bowling ball makes contents with the pins, how many pins remain standing.

Background

I recently built a half scale bowling alley in my home. It has a manual pinsetter which means a person needs to maintain the pin deck at all times. With a third-party computer software, called ScoreMore, it very much works like a commercial bowling alley (less the automatic pinsetter). An Arduino Uno works in conjunction with a typical PC which runs the ScoreMore software (ScoreMore - A bowling scoring system). The bowling lane works as follows. There is a laser sensor (software calls a “trigger”) that detects when a ball is rolled down the lane. A pc camera takes a picture of the remaining pins. The software updates the score which is displayed on a monitor. The Arduino Uno monitors the laser sensor and turns lights on/off for ball 1, ball 2, strike, and spare. It also has the ability to pass along the status of each bowling pin which I didn’t use before but would like to use now to automate the string pinsetter.

I have completed the conversion of the manual pinsetter to a string pinsetter. I have rebuilt and rewired my control panel to add an Arduino Mega to handle the additional inputs (note the Uno remains and operates as before). My initial thought was to have the Mega digitally read the Uno’s output pins associated with the status of the bowling pins. Additionally, I need to monitor the bowling ball “trigger” which initially I thought I would share the signal being sent from the trigger to the Uno. Note the author of ScoreMore states the trigger monitoring done by the Uno is very sensitive. As such I am inclined NOT to try to eliminate the Uno by transferring its functions to the Mega although I am open to a conversation about that once the string pinsetter is automated.

Priority 1 (Part 1)

I have several things I am seeking help on so I will prioritize in bite sized pieces starting with the highest priority. First and foremost, I need to figure out how best to monitor the “trigger” after which how best to determine how many pins are left standing.

The hyperlink for ScoreMore is above. The Arduino Sketch that is supplied by ScoreMore for the Uno is as follows. While I appreciate this code could be incorporated into the Mega, let’s assume for now I would like to keep the two processors and their sketches separate. (NOTE: this sketch references “Pin 2”, “Pin 3”, etc. and this refers to bowling pin 2, bowling pin 3, etc.)

// Uno sketch to work in conjunction with ScoreMore pc software

const int maxPins = 17;

// These are the pins used by ScoreMore. Do not edit these.
const int scoreMorePins[maxPins] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19};

// Edit these for your Arduino pins (Original positions shown)
const int arduinoPins[maxPins] = {
  2, //Pin 2
  3, //Pin 3
  4, //Pin 4
  5, //Pin 5
  6, //Trigger Sensor
  7, //Auto Reset Trigger
  8, //Ball Speed Sensor
  9, //Spare / Strike Light
  10, //Strike Light
  11, //1st Ball Light
  12, //2nd Ball Light
  A0, //Pin 1
  A1, //Pin 6
  A2, //Pin 7
  A3, //Pin 8
  A4, //Pin 9
  A5 //Pin 10
};

const int bowlingPins[] = {2, 3, 4, 5, 14, 15, 16, 17, 18, 19};
const int bowlingPinCount = sizeof(bowlingPins) / sizeof(bowlingPins[0]);

int inputPins[maxPins];     // Aktiva Arduino-pins
int pinStates[maxPins];     // Senaste lästa tillstånd
int inputCount = 0;

void setup() {
  Serial.begin(9600);
  delay(2000);
  Serial.println("READY");
}

void loop() {
  checkSerial();
  checkInputChanges();
}

void checkSerial() {
  static char buffer[100];
  static uint8_t index = 0;

  while (Serial.available()) {
    char c = Serial.read();

    if (c == '\n') {
      buffer[index] = '\0';  // terminate string
      String cmd = String(buffer);
      cmd.trim();
      if (cmd.length() > 0) handleCommand(cmd);

      index = 0;
      continue;
    }

    // Only store printable characters
    if (c >= 32 && c <= 126) {
      if (index < sizeof(buffer) - 1) {
        buffer[index++] = c;
      } else {
        // overflow protection
        index = 0;
      }
    }
  }
}

void handleCommand(String cmd) {
  Serial.print("Received command: ");
  Serial.println(cmd);
  cmd.trim();

  if (cmd.startsWith("SET_INPUT:")) {
    int scoreMorePin = cmd.substring(10).toInt();
    int pin = resolveArduinoPin(scoreMorePin);
    if (pin != -1 && !isTrackedInput(pin) && inputCount < maxPins) {
      if (isBowlingPin(scoreMorePin)) {
        pinMode(pin, INPUT_PULLUP);
      } else {
        pinMode(pin, INPUT);
      }
      inputPins[inputCount] = pin;
      pinStates[inputCount] = digitalRead(pin);
      inputCount++;
      Serial.print("ACK_SET_INPUT:");
      Serial.println(scoreMorePin);
    }

  } else if (cmd.startsWith("SET_OUTPUT:")) {
    int scoreMorePin = cmd.substring(11).toInt();
    int pin = resolveArduinoPin(scoreMorePin);
    if (pin != -1) {
      pinMode(pin, OUTPUT);
      removeInputPin(pin);
      Serial.print("ACK_SET_OUTPUT:");
      Serial.println(scoreMorePin);
    }

  } else if (cmd.startsWith("WRITE:")) {
    int firstColon = cmd.indexOf(':');
    int secondColon = cmd.indexOf(':', firstColon + 1);
    int scoreMorePin = cmd.substring(firstColon + 1, secondColon).toInt();
    int value = cmd.substring(secondColon + 1).toInt();
    int pin = resolveArduinoPin(scoreMorePin);
    if (pin != -1) {
      digitalWrite(pin, value);
      Serial.print("ACK_WRITE:");
      Serial.print(scoreMorePin);
      Serial.print(":");
      Serial.println(value);
    }

  } else if (cmd == "RESET") {
    digitalWrite(10, LOW);
    Serial.println("ACK_RESET");
  }
}

void checkInputChanges() {
  String changes = "";

  for (int i = 0; i < inputCount; i++) {
    int pin = inputPins[i];
    int scoreMorePin = getScoreMorePin(pin);
    int currentState;

    if (isBowlingPin(scoreMorePin)) {
      // Read twice for stability
      int first = digitalRead(pin);
      delayMicroseconds(500);
      int second = digitalRead(pin);
      if (first == second) {
        currentState = first;
      } else {
        currentState = pinStates[i];
      }
    } else {
      // Trigger sensor
      currentState = digitalRead(pin);
    }

    if (currentState != pinStates[i]) {
      pinStates[i] = currentState;
      if (scoreMorePin != -1) {
        if (changes.length() > 0) changes += ",";
        changes += String(scoreMorePin) + ":" + String(currentState);
      }
    }

    delayMicroseconds(200);
  }

  if (changes.length() > 0) {
    Serial.print("INPUT_CHANGE:");
    Serial.println(changes);
  }
}

bool isTrackedInput(int pin) {
  for (int i = 0; i < inputCount; i++) {
    if (inputPins[i] == pin) return true;
  }
  return false;
}

void removeInputPin(int pin) {
  for (int i = 0; i < inputCount; i++) {
    if (inputPins[i] == pin) {
      for (int j = i; j < inputCount - 1; j++) {
        inputPins[j] = inputPins[j + 1];
        pinStates[j] = pinStates[j + 1];
      }
      inputCount--;
      break;
    }
  }
}

int resolveArduinoPin(int scoreMorePin) {
  for (int i = 0; i < maxPins; i++) {
    if (scoreMorePins[i] == scoreMorePin) {
      return arduinoPins[i];
    }
  }
  return -1;
}

int getScoreMorePin(int arduinoPin) {
  for (int i = 0; i < maxPins; i++) {
    if (arduinoPins[i] == arduinoPin) {
      return scoreMorePins[i];
    }
  }
  return -1;
}

bool isBowlingPin(int scoreMorePin) {
  for (int i = 0; i < bowlingPinCount; i++) {
    if (bowlingPins[i] == scoreMorePin) {
      return true;
    }
  }
  return false;
}

So far, I have written the following sketch for the Mega. For Part 1 of this exercise I am looking for help for “Mode = 2” (lines 318-336). Could you pass along suggestions on how best to monitor the Uno pinouts for status of a ball rolling and the subsequent bowling pin status? I have attached a manual showing the various equipment being used and photos of the alley as well as my current wiring diagrams. ScoreMore documentation also added. Thanks in advance.

// //////////////////////////////////////////////////////////// //
//                                                              //
//                Arduino Sketch for Bowling Game               //
//                           Rev 1.0                            //
//                       December 26.2025                       //
//                         Deron Butler                         //
//                dbutler@josephdouglashomes.com                //
//                                                              //
// /////////////////////////////////////////////////////////// ///


// *********************************************************************** //
// Libraries
// *********************************************************************** //

// #include <FastLED.h> // Library for LED controls (future use)

// *********************************************************************** //
// Definitions for MP3 Players
// *********************************************************************** //

// (future use)

// *********************************************************************** //
// Constants/Variables for Set Up
// *********************************************************************** //

int Mode = 1;
const int solenoidExtend[14] = {0, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47}; // Defines pinout for extending solenoid
const int solenoidRetract[14] = {0, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48}; // Defines pinout for retracting solenoid
const int pinDesignation[11] = {0, 8, 2, 3, 4, 5, 9, 10, 11, 12, 13}; // Defines pinout for bowling pin status
// NOTE:  1st position of an index is intentionally not used in this sketch

unsigned long time = 0; // Assigns value of relative time in milliseconds
unsigned long time1 = 0; // Assigns value of relative time in milliseconds
unsigned long time2 = 0; // Assigns value of relative time in milliseconds
unsigned long time3 = 0; // Assigns value of relative time in milliseconds
unsigned long time4 = 0; // Assigns value of relative time in milliseconds
unsigned long time5 = 0; // Assigns value of relative time in milliseconds
unsigned long time6 = 0; // Assigns value of relative time in milliseconds
unsigned long time7 = 0; // Assigns value of relative time in milliseconds
unsigned long currentTime = 0; // Assigns value of relative time in milliseconds
bool bowlpinState[] = {LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW}; // LOW = pin standing; HIGH = pin has fallen
// NOTE:  1st position of an index is position 0 which is purposely chosen to be ignored in this sketch

int statusVar1 = 0; // Variable to toggle (0 = OFF, 1 = ON)
int statusVar2 = 0; // Variable to toggle (0 = OFF, 1 = ON)
int statusVar3 = 0; // Variable to toggle (0 = OFF, 1 = ON)
int statusVar4 = 0; // Variable to toggle (0 = OFF, 1 = ON)
int statusVar5 = 0; // Variable to toggle (0 = OFF, 1 = ON)
int statusVar6 = 0; // Variable to toggle (0 = OFF, 1 = ON)
int statusVar7 = 0; // Variable to toggle (0 = OFF, 1 = ON)

// *********************************************************************** //
// Variables for Ball Return
// *********************************************************************** //
int ballReturnState = LOW; // Current reading from the button
int lastBallReturnState = LOW; // Previous reading from the button
bool ballReturn = LOW;

unsigned long ballReturnStartTime  = 0; // Assigns value of relative time in milliseconds
unsigned long lastDebounceTime1 = 0; // Last time the button state changed
unsigned long debounceDelay1 = 500;   // Debounce time in milliseconds

// *********************************************************************** //
// Variables for Service Button
// *********************************************************************** //
bool serviceButtonPressed = false;
int serviceButtonState = LOW;     // Current reading from the button
unsigned long pressStartTime = 0;

// *********************************************************************** //
// Variables for Current Sensing
// *********************************************************************** //

float voltageOut[13] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
float current[13] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int currentMax = 2;
bool maxCurrentEvent[13] = {false,false,false,false,false,false,false,false,false,false,false,false,false};
unsigned long lastCurrentDebounceTime[13] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // Last time the current state changed
unsigned long currentDebounceDelay = 350;   // Debounce time in milliseconds

// *********************************************************************** //
// Variables for Modes
// *********************************************************************** //

unsigned long ballRolledTime = 0;
int ballRolledState = HIGH;
int lastBallRolledState = HIGH;

// ________________________________________________________________________ //
// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //
void setup() {
// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //
// ________________________________________________________________________ //

  // area reserved for future MP3 Player

  Serial.begin(9600); // Opens the serial port at 9600 bps
  
  // Mega Arduino Pin Assignments

    // pins 0-1 not used

    for (int ii = 2; ii < 14; ii++) { // Define pins 2-13
      pinMode(ii, INPUT_PULLUP);
    }

    // pins 14-21 not used

    pinMode(22, INPUT_PULLUP);
  
    for (int ii = 23; ii < 51; ii++) { // Define pins 23-50
      pinMode(ii, OUTPUT);
    }

    // pins 51-53 not used  

    pinMode (A0, INPUT); // Analog
    pinMode (A1, INPUT); // Analog
    pinMode (A2, INPUT); // Analog
    pinMode (A3, INPUT); // Analog
    pinMode (A4, INPUT); // Analog
    pinMode (A5, INPUT); // Analog
    pinMode (A6, INPUT); // Analog
    pinMode (A7, INPUT); // Analog
    pinMode (A8, INPUT); // Analog
    pinMode (A9, INPUT); // Analog
    pinMode (A10, INPUT_PULLUP); // Digital
    pinMode (A11, INPUT_PULLUP); // Digital
  
}


// ________________________________________________________________________ //
// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //
void loop() {
// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //
// ________________________________________________________________________ //
  
// currentTime = millis(); // future use

// ________________________________________________________________________
// Ball Return Idle // Note:  Elevator may run concurrently with any Mode
// ________________________________________________________________________
  
 if (ballReturn == false) { //Ball return is not in use = false
 int reading1 = digitalRead(A10);

   if (reading1 != lastBallReturnState) { // Check to see if ball is at ball return sensor
    lastDebounceTime1 = millis(); // Reset debounce timer
   }

  if ((millis() - lastDebounceTime1) > debounceDelay1) { // If enough time has passed, confirm the change
    if (reading1 != ballReturnState) {
      ballReturnState = reading1;

      if (ballReturnState == LOW) { // Only toggle when ball sensor actually detects the ball (LOW with INPUT_PULLUP)
        ballReturn = true; // Ball return now active
        ballReturnStartTime = millis();
        // Serial.print("Status variable changed to: ");
        // Serial.println(statusVar1);
      }
    }
  }

  lastBallReturnState = reading1;
 }
  
  // ________________________________________________________________________
  // Ball Return Operating
  // ________________________________________________________________________
    
    if (ballReturn = true) { // Ball elevator = true when operating
      time = millis() - ballReturnStartTime; // keeps track of how long ball elevator has been running

      if (time < 500) {
        resetActuators2(); // assures ball gate actuator not moving
        resetActuators3(); // assures ball elevator actuator not moving
      }
      
      if (time >= 500 && time < 3500) {
        openBallGate();
      }
          
      if (time >= 3500 && time < 20500) {
        raiseBallElevator(); //17 seconds required for full up stroke
        resetActuators2(); // stops ball gate actuator mid stroke
      }
        
      if (time >= 20500 && time < 22500) {
        // pause for 2 seconds to allow ball to exit ball elevator
        resetActuators3(); // assures ball elevagtor actuator not moving
      }
            
      if (time >= 22500 && time < 37500) {
        lowerBallElevator(); //15 seconds required for full down stroke
      }
            
      if (time >= 37500 && time < 40500) {
        closeBallGate(); // allow 3 seconds to close
      }

      if (time >= 40500) {
        resetActuators2(); // stops ball gate actuator mid stroke
        ballReturn = false; // changes ball return status to off after 40.5 seconds
      }
    }
  
  // ________________________________________________________________________
  // Detect Service Interrupt // Note: may interrupt any Mode
  // ________________________________________________________________________
  
  int serviceButtonState = digit        
alRead(22); // Check if the service button has been pushed

  if (serviceButtonState == LOW && serviceButtonPressed == false) { // conditions when button just pressed
    pressStartTime = millis();
    serviceButtonPressed = true;
  }

  if (serviceButtonState == HIGH && serviceButtonPressed == true) { // conditions when pressed button just released
    if(millis() - pressStartTime > 500) {
      if (millis() - pressStartTime >= 2500) { // request made to reset all pins if service button held for > 2.5 seconds
        Mode = 5;
        statusVar5 = 1;
      }
      else 
        Mode = 4; // request made to reset some pins if service button held for < 2.5 seconds
        statusVar4 = 1;
    }
 
    serviceButtonPressed = false;
  }

  
  // ________________________________________________________________________
  // Detect High Current in Actuators // Note: may interrupt any Mode
  // ________________________________________________________________________
  
  for (int ii = 0; ii < 12; ii++) {
    if(maxCurrentEvent[ii] == false) {
      voltageOut[ii] = analogRead(ii); // read analog pins 0 to 9 to detect string tangle
      int jj = ii + 1;
      current[jj] = (voltageOut[ii] - 2.5) / 0.066; // formula to convert sensor reading to amps

      if (current[jj] > currentMax) { // detects high current on linear actuator jj
        lastCurrentDebounceTime[jj] = millis();
      }

      if (millis() - lastCurrentDebounceTime[jj] > currentDebounceDelay) { // overlooks actuator start up current
        if (current[jj] > currentMax) {
          maxCurrentEvent[jj] == true;
        }
      
        if (jj < 11) {
          if (time >= 50 && time < 1500) {
            digitalWrite(49, HIGH); // turns on service light
            digitalWrite(solenoidExtend[jj], LOW); // stop linear actuator with high current
            digitalWrite(solenoidRetract[jj], LOW); 
          }
        
          if (time >= 50 && time < 1500) {
            digitalWrite(solenoidExtend[jj], LOW); // raise linear actuator with high current
            digitalWrite(solenoidRetract[jj], HIGH);
          }
  
          if (time >= 1500 && time < 1550){
            digitalWrite(solenoidExtend[jj], LOW); // stop linear actuator with high current
            digitalWrite(solenoidRetract[jj], LOW);
          }

          if (time >= 1550 && time < 4500) {
            digitalWrite(solenoidExtend[jj], HIGH); // lower linear actuator with high current
            digitalWrite(solenoidRetract[jj], LOW);
          }
  
          if (time >=4500) {
            maxCurrentEvent[ii] == false;
          }
        }

        else {
          digitalWrite(solenoidExtend[jj], LOW); // stops movement of elevator or sweep
          digitalWrite(solenoidRetract[jj], LOW);
          digitalWrite(49, LOW); // turns on service light as elevator or sweep needs attention from attendant
          Mode = 6;
          maxCurrentEvent[ii] == false;
          
        }
      }
    }
  }

  
  // ________________________________________________________________________
  // Mode 1: Monitor Bowling Ball Trigger Sensor for Next Ball Rolled
  // ________________________________________________________________________

    if (Mode = 1) {

      ballRolledState = digitalRead(6); // Check to see if a ball has been rolled

      if (ballRolledState = !lastBallRolledState) { // if state changes to LOW, ball has been rolled
        ballRolledTime = millis(); // sets time ball was rolled
        Mode = 2;
      }

    lastBallRolledState = ballRolledState;
    
    }


  // ________________________________________________________________________
  // Mode 2: Determine How Many Pins are Left
  // ________________________________________________________________________

    if (Mode = 2) {

      int time = ballRolledTime - millis(); // Keeps track

      if (time > 3250 && statusVar3 == 0) { 
        // NOTE:  After ball sensor is triggered, computer has camera take photo of bowling pin deck.  Computer determines what bowling
        // pins have been knocked down and, in turn, sends data to UNO.  Uno releases this data 3 seconds after ball sensor is triggered 
        // through the Uno pins defined as pinDesignation(ii)

        for (int ii = 1; ii < 11; ii++) 
          bowlpinState[ii] = digitalRead (pinDesignation[ii]); //High = Pin has fallen, low = Pin still standing  
      }
      
      if (time > 4000) {
        Mode = 3;
        statusVar3 = 1;
      }

    }


  // ________________________________________________________________________
  // Mode 3: Prepare Lane for Next Ball
  // ________________________________________________________________________

    if (Mode = 3) {

      if(statusVar3 = 1) {
      time3 = millis(); // Determines that start time of Mode 3
      statusVar3 = 0;
      }
  
      int time = time3 - millis();

      if (time < 50) {
        resetActuators1(); // assures pin actuators not moving
        resetActuators4(); // assures sweep actuator not moving
      }

      if (time >= 50 && time < 7000) {
        lowerBallSweep(); // 6 seconds required to lower sweep
      }
  
      if (time >= 4000 && time < 7000){
        raisePins(); //3 seconds required to raise pins which can overlap sweep
      }
        
      if (time >= 7000 && time < 7500) {
        // pause for 1/2 second to allow pins to settle/untangle
        resetActuators1(); // Ensures actuators for bowling pins are off
        resetActuators4(); // Ensures actuator or ball sweep is off
      }
  
      if (time >= 7500 && time < 13500) {
        raiseBallSweep(); // allow 6 seconds to close
      }

      if (time >= 9000 && time < 12000) {
        lowerSomePins(); //3 seconds required to lower pins
      }
      
      if (time >= 12000) {
        Mode = 1;
      }

    }

 
  // ________________________________________________________________________
  // Mode 4: Manual Request to Reset Intended Pin Placement
  // ________________________________________________________________________
  
    if (Mode = 4) {

      if(statusVar4 = 1) {
        time4 = millis();
        statusVar4 =0;
      }
  
      int time = time4 - millis();
   
      if (time < 50) {
        resetActuators1(); // assures pin actuators not moving
        resetActuators4(); // assures sweep actuator not moving
      }
      
      if (time >= 50 && time < 7000) {
        closeBallGate(); // 6 seconds required to lower sweep
      }
  
      if (time >= 4000 && time < 7000){
        raisePins(); //3 seconds required to raise pins which can overlap sweep
      }
        
      if (time >= 7000 && time < 7500) {
        // pause for 1/2 second to allow pins to settle
        resetActuators1(); // assures ball elevagtor actuator not moving
        resetActuators4(); // assures sweep actuator not moving
      }
  
      if (time >= 7500 && time < 13500) {
        closeBallGate(); // allow 6 seconds to close
      }

      if (time >= 9000 && time < 12000) {
        lowerSomePins(); //3 seconds required to lower pins
      }
      
      if (time >=12000) {
        Mode = 1;
      }

    }


  // ________________________________________________________________________
  // Mode 5: Manual Request to Reset to Ball 1
  // ________________________________________________________________________
  
    if (Mode = 5) {
      if(statusVar5 = 1) {
        time5 = millis();
        statusVar5 =0;
      }
   
      int time = time5 - millis();
      
      if (time < 50) {
        resetActuators1(); // assures pin actuators not moving
        resetActuators4(); // assures sweep actuator not moving
      }
      
      if (time >= 50 && time < 7000) {
        closeBallGate(); // 6 seconds required to lower sweep
      }
  
      if (time >= 4000 && time < 7000){
        raisePins(); //3 seconds required to raise pins which can overlap sweep
      }
        
      if (time >= 7000 && time < 7500) {
        // pause for 1/2 second to allow pins to settle
        resetActuators1(); // assures ball elevagtor actuator not moving
        resetActuators4(); // assures sweep actuator not moving
      }
  
      if (time >= 7500 && time < 13500) {
        closeBallGate(); // allow 6 seconds to close
      }

      if (time >= 9000 && time < 12000) {
        lowerAllPins(); //3 seconds required to lower pins
      }
      
      if (time >=12000) {
        Mode = 1;
      }

    }
 
  // ________________________________________________________________________
  // Mode 6: Service Required
  // ________________________________________________________________________

  if (Mode = 6) {
    delay(36000000); // shut down game for 10 minutes until service button pressed
    digitalWrite(49, LOW); // turns off service light
  }
      
}


// ________________________________________________________________________ //
// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //
// void subroutines
// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //
// ________________________________________________________________________ //

void resetActuators1() {
  for (int ii = 1; ii < 11; ii++) {
    digitalWrite(solenoidExtend[ii], LOW);
    digitalWrite(solenoidRetract[ii], LOW); 
  }
    Serial.println("Reset all bowling pin actuators"); // Prints text
}   

void resetActuators2() {
  digitalWrite(solenoidExtend[11], LOW);
  digitalWrite(solenoidRetract[11], LOW); 
  Serial.println("Reset ball gate actuator"); // Prints text
}  

void resetActuators3() {
  digitalWrite(solenoidExtend[12], LOW);
  digitalWrite(solenoidRetract[12], LOW); 
  Serial.println("Reset ball elevator actuator"); // Prints text
}  

void resetActuators4() {
  digitalWrite(solenoidExtend[13], LOW);
  digitalWrite(solenoidRetract[13], LOW); 
  Serial.println("Reset sweep actuator"); // Prints text
}  

void raisePins() {
  for (int ii = 1; ii < 11; ii++) {
  digitalWrite(solenoidExtend[ii], LOW);
  digitalWrite(solenoidRetract[ii], HIGH); 
  delay(50);
  }
  Serial.println("Raise Pins"); // Prints text
}

void lowerAllPins() {
  for (int ii = 1; ii < 11; ii++) {
    digitalWrite(solenoidExtend[ii], LOW);
    digitalWrite(solenoidRetract[ii], HIGH);
    Serial.println("Lower All Pins"); // Prints text
  }
}

void lowerSomePins() {
  for (int ii = 1; ii < 11; ii++) {
    if (bowlpinState[ii] == LOW) {
      digitalWrite(solenoidExtend[ii], LOW);
      digitalWrite(solenoidRetract[ii], HIGH);
      Serial.print("This pin still standing: ");
      Serial.println(ii);
    }
    else if (bowlpinState[ii] == HIGH) {
      digitalWrite(solenoidExtend[ii], LOW);
      digitalWrite(solenoidRetract[ii], HIGH); 
      Serial.print("This pin has fallen: ");
      Serial.println(ii);
    }  
  Serial.println("Lower Some Pins"); // Prints text
  }
}

void lowerBallSweep() {
    digitalWrite(solenoidExtend[13], LOW);
    digitalWrite(solenoidRetract[13], HIGH);
    Serial.println("Lower Ball Sweep"); // Prints text
}

void raiseBallSweep() {
    digitalWrite(solenoidExtend[12], HIGH);
    digitalWrite(solenoidRetract[12], LOW);
    delay(50);
    Serial.println("Raise ball sweep"); // Prints text
}

void openBallGate() {
    digitalWrite(solenoidExtend[11], LOW);
    digitalWrite(solenoidRetract[11], HIGH);
    Serial.println("Open Ball Gate"); // Prints text
}

void closeBallGate() {
    digitalWrite(solenoidExtend[10], HIGH);
    digitalWrite(solenoidRetract[10], LOW);
    Serial.println("Close ball gate"); // Prints text
}

void raiseBallElevator() {
    digitalWrite(solenoidExtend[12], HIGH);
    digitalWrite(solenoidRetract[12], LOW); 
    Serial.println("Raise Elevator"); // Prints text
}

void lowerBallElevator() {
    digitalWrite(solenoidExtend[12], LOW);
    digitalWrite(solenoidRetract[12], HIGH); 
    Serial.println("Lower Elevator"); // Prints text
}

Wiring Diagram B.pdf (220.8 KB)

Wiring Diagram A.pdf (308.6 KB)

Bowling Arcade Game Manual.pdf (3.4 MB)

ScoreMoreDocumentation.pdf (2.8 MB)

The code you posted does that already.

Six times with the same error for modes 1 through 6.

I wrote that code for reading the Uno pins so I’m questioning if it looks good enough or should be corrected/improved. What do you think? As for the trigger, the software developer pointed out I can monitor the status of UNO pin 8 so that would be an easy fix

Got it and thanks

Two changes to code:

  1. Mega sketch modified to correct use of “==” in place of “=” per your suggested correction.
  2. For Mode =1, I changed the sketch and wiring to now have Mega pin D7 look at Uno pin D8 (instead of D7) per the recommendation of the software developer as this Uno pin can be used for indication the ball has been rolled.

Update on Phase 1 request - the ball trigger question has now been answered. What remains is comments on the code I used for Mode = 2. Does this look good?

for (int ii = 1; ii < 11; ii++) 
          bowlpinState[ii] = digitalRead (pinDesignation[ii]); //High = Pin has fallen, low = Pin still standing 
// //////////////////////////////////////////////////////////// //
//                                                              //
//                Arduino Sketch for Bowling Game               //
//                           Rev 1.0                            //
//                       December 26.2025                       //
//                         Deron Butler                         //
//                dbutler@josephdouglashomes.com                //
//                                                              //
// /////////////////////////////////////////////////////////// ///


// *********************************************************************** //
// Libraries
// *********************************************************************** //

// #include <FastLED.h> // Library for LED controls (future use)

// *********************************************************************** //
// Definitions for MP3 Players
// *********************************************************************** //

// (future use)

// *********************************************************************** //
// Constants/Variables for Set Up
// *********************************************************************** //

int Mode = 1;
const int solenoidExtend[14] = {0, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47}; // Defines pinout for extending solenoid
const int solenoidRetract[14] = {0, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48}; // Defines pinout for retracting solenoid
const int pinDesignation[11] = {0, 8, 2, 3, 4, 5, 9, 10, 11, 12, 13}; // Defines pinout for bowling pin status
// NOTE:  1st position of an index is intentionally not used in this sketch

unsigned long time = 0; // Assigns value of relative time in milliseconds
unsigned long time1 = 0; // Assigns value of relative time in milliseconds
unsigned long time2 = 0; // Assigns value of relative time in milliseconds
unsigned long time3 = 0; // Assigns value of relative time in milliseconds
unsigned long time4 = 0; // Assigns value of relative time in milliseconds
unsigned long time5 = 0; // Assigns value of relative time in milliseconds
unsigned long time6 = 0; // Assigns value of relative time in milliseconds
unsigned long time7 = 0; // Assigns value of relative time in milliseconds
unsigned long currentTime = 0; // Assigns value of relative time in milliseconds
bool bowlpinState[] = {LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW}; // LOW = pin standing; HIGH = pin has fallen
// NOTE:  1st position of an index is position 0 which is purposely chosen to be ignored in this sketch

int statusVar1 = 0; // Variable to toggle (0 = OFF, 1 = ON)
int statusVar2 = 0; // Variable to toggle (0 = OFF, 1 = ON)
int statusVar3 = 0; // Variable to toggle (0 = OFF, 1 = ON)
int statusVar4 = 0; // Variable to toggle (0 = OFF, 1 = ON)
int statusVar5 = 0; // Variable to toggle (0 = OFF, 1 = ON)
int statusVar6 = 0; // Variable to toggle (0 = OFF, 1 = ON)
int statusVar7 = 0; // Variable to toggle (0 = OFF, 1 = ON)

// *********************************************************************** //
// Variables for Ball Return
// *********************************************************************** //
int ballReturnState = LOW; // Current reading from the button
int lastBallReturnState = LOW; // Previous reading from the button
bool ballReturn = LOW;

unsigned long ballReturnStartTime  = 0; // Assigns value of relative time in milliseconds
unsigned long lastDebounceTime1 = 0; // Last time the button state changed
unsigned long debounceDelay1 = 500;   // Debounce time in milliseconds

// *********************************************************************** //
// Variables for Service Button
// *********************************************************************** //
bool serviceButtonPressed = false;
int serviceButtonState = LOW;     // Current reading from the button
unsigned long pressStartTime = 0;

// *********************************************************************** //
// Variables for Current Sensing
// *********************************************************************** //

float voltageOut[13] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
float current[13] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int currentMax = 2;
bool maxCurrentEvent[13] = {false,false,false,false,false,false,false,false,false,false,false,false,false};
unsigned long lastCurrentDebounceTime[13] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // Last time the current state changed
unsigned long currentDebounceDelay = 350;   // Debounce time in milliseconds

// *********************************************************************** //
// Variables for Modes
// *********************************************************************** //

unsigned long ballRolledTime = 0;
int ballRolledState = HIGH;
int lastBallRolledState = HIGH;

// ________________________________________________________________________ //
// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //
void setup() {
// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //
// ________________________________________________________________________ //

  // area reserved for future MP3 Player

  Serial.begin(9600); // Opens the serial port at 9600 bps
  
  // Mega Arduino Pin Assignments

    // pins 0-1 not used

    for (int ii = 2; ii < 14; ii++) { // Define pins 2-13
      pinMode(ii, INPUT_PULLUP);
    }

    // pins 14-21 not used

    pinMode(22, INPUT_PULLUP);
  
    for (int ii = 23; ii < 51; ii++) { // Define pins 23-50
      pinMode(ii, OUTPUT);
    }

    // pins 51-53 not used  

    pinMode (A0, INPUT); // Analog
    pinMode (A1, INPUT); // Analog
    pinMode (A2, INPUT); // Analog
    pinMode (A3, INPUT); // Analog
    pinMode (A4, INPUT); // Analog
    pinMode (A5, INPUT); // Analog
    pinMode (A6, INPUT); // Analog
    pinMode (A7, INPUT); // Analog
    pinMode (A8, INPUT); // Analog
    pinMode (A9, INPUT); // Analog
    pinMode (A10, INPUT_PULLUP); // Digital
    pinMode (A11, INPUT_PULLUP); // Digital
  
}


// ________________________________________________________________________ //
// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //
void loop() {
// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //
// ________________________________________________________________________ //
  
// currentTime = millis(); // future use

// ________________________________________________________________________
// Ball Return Idle // Note:  Elevator may run concurrently with any Mode
// ________________________________________________________________________
  
 if (ballReturn == false) { //Ball return is not in use = false
 int reading1 = digitalRead(A10);

   if (reading1 != lastBallReturnState) { // Check to see if ball is at ball return sensor
    lastDebounceTime1 = millis(); // Reset debounce timer
   }

  if ((millis() - lastDebounceTime1) > debounceDelay1) { // If enough time has passed, confirm the change
    if (reading1 != ballReturnState) {
      ballReturnState = reading1;

      if (ballReturnState == LOW) { // Only toggle when ball sensor actually detects the ball (LOW with INPUT_PULLUP)
        ballReturn = true; // Ball return now active
        ballReturnStartTime = millis();
        // Serial.print("Status variable changed to: ");
        // Serial.println(statusVar1);
      }
    }
  }

  lastBallReturnState = reading1;
 }
  
  // ________________________________________________________________________
  // Ball Return Operating
  // ________________________________________________________________________
    
    if (ballReturn = true) { // Ball elevator = true when operating
      time = millis() - ballReturnStartTime; // keeps track of how long ball elevator has been running

      if (time < 500) {
        resetActuators2(); // assures ball gate actuator not moving
        resetActuators3(); // assures ball elevator actuator not moving
      }
      
      if (time >= 500 && time < 3500) {
        openBallGate();
      }
          
      if (time >= 3500 && time < 20500) {
        raiseBallElevator(); //17 seconds required for full up stroke
        resetActuators2(); // stops ball gate actuator mid stroke
      }
        
      if (time >= 20500 && time < 22500) {
        // pause for 2 seconds to allow ball to exit ball elevator
        resetActuators3(); // assures ball elevagtor actuator not moving
      }
            
      if (time >= 22500 && time < 37500) {
        lowerBallElevator(); //15 seconds required for full down stroke
      }
            
      if (time >= 37500 && time < 40500) {
        closeBallGate(); // allow 3 seconds to close
      }

      if (time >= 40500) {
        resetActuators2(); // stops ball gate actuator mid stroke
        ballReturn = false; // changes ball return status to off after 40.5 seconds
      }
    }
  
  // ________________________________________________________________________
  // Detect Service Interrupt // Note: may interrupt any Mode
  // ________________________________________________________________________
  
  int serviceButtonState = digit        
alRead(22); // Check if the service button has been pushed

  if (serviceButtonState == LOW && serviceButtonPressed == false) { // conditions when button just pressed
    pressStartTime = millis();
    serviceButtonPressed = true;
  }

  if (serviceButtonState == HIGH && serviceButtonPressed == true) { // conditions when pressed button just released
    if(millis() - pressStartTime > 500) {
      if (millis() - pressStartTime >= 2500) { // request made to reset all pins if service button held for > 2.5 seconds
        Mode = 5;
        statusVar5 = 1;
      }
      else 
        Mode = 4; // request made to reset some pins if service button held for < 2.5 seconds
        statusVar4 = 1;
    }
 
    serviceButtonPressed = false;
  }

  
  // ________________________________________________________________________
  // Detect High Current in Actuators // Note: may interrupt any Mode
  // ________________________________________________________________________
  
  for (int ii = 0; ii < 12; ii++) {
    if(maxCurrentEvent[ii] == false) {
      voltageOut[ii] = analogRead(ii); // read analog pins 0 to 9 to detect string tangle
      int jj = ii + 1;
      current[jj] = (voltageOut[ii] - 2.5) / 0.066; // formula to convert sensor reading to amps

      if (current[jj] > currentMax) { // detects high current on linear actuator jj
        lastCurrentDebounceTime[jj] = millis();
      }

      if (millis() - lastCurrentDebounceTime[jj] > currentDebounceDelay) { // overlooks actuator start up current
        if (current[jj] > currentMax) {
          maxCurrentEvent[jj] == true;
        }
      
        if (jj < 11) {
          if (time >= 50 && time < 1500) {
            digitalWrite(49, HIGH); // turns on service light
            digitalWrite(solenoidExtend[jj], LOW); // stop linear actuator with high current
            digitalWrite(solenoidRetract[jj], LOW); 
          }
        
          if (time >= 50 && time < 1500) {
            digitalWrite(solenoidExtend[jj], LOW); // raise linear actuator with high current
            digitalWrite(solenoidRetract[jj], HIGH);
          }
  
          if (time >= 1500 && time < 1550){
            digitalWrite(solenoidExtend[jj], LOW); // stop linear actuator with high current
            digitalWrite(solenoidRetract[jj], LOW);
          }

          if (time >= 1550 && time < 4500) {
            digitalWrite(solenoidExtend[jj], HIGH); // lower linear actuator with high current
            digitalWrite(solenoidRetract[jj], LOW);
          }
  
          if (time >=4500) {
            maxCurrentEvent[ii] == false;
          }
        }

        else {
          digitalWrite(solenoidExtend[jj], LOW); // stops movement of elevator or sweep
          digitalWrite(solenoidRetract[jj], LOW);
          digitalWrite(49, LOW); // turns on service light as elevator or sweep needs attention from attendant
          Mode = 6;
          maxCurrentEvent[ii] == false;
          
        }
      }
    }
  }

  
  // ________________________________________________________________________
  // Mode 1: Monitor Bowling Ball Trigger Sensor for Next Ball Rolled
  // ________________________________________________________________________

    if (Mode == 1) {

      // THE NEXT TWO LINES OF CODE CHANGED AFTER INITIAL SKETCH POSTED ON ARDUINO FORUM ON 1/15/2026 
      
      /*ballRolledState = digitalRead(6); // Check to see if a ball has been rolled
      */

      ballRolledState = digitalRead(7) // CHANGED MEGA PIN REFERERNCE FROM 6 TO 7 AND WIRING TO BE CHANGED TO CONNECT MEGA D7 TO UNO D8
        
      if (ballRolledState = !lastBallRolledState) { // if state changes to LOW, ball has been rolled
        ballRolledTime = millis(); // sets time ball was rolled
        Mode = 2;
      }
  
    lastBallRolledState = ballRolledState;
    
    }


  // ________________________________________________________________________
  // Mode 2: Determine How Many Pins are Left
  // ________________________________________________________________________

    if (Mode == 2) {

      int time = ballRolledTime - millis(); // Keeps track

      if (time > 3250 && statusVar3 == 0) { 
        // NOTE:  After ball sensor is triggered, computer has camera take photo of bowling pin deck.  Computer determines what bowling
        // pins have been knocked down and, in turn, sends data to UNO.  Uno releases this data 3 seconds after ball sensor is triggered 
        // through the Uno pins defined as pinDesignation(ii)

        for (int ii = 1; ii < 11; ii++) 
          bowlpinState[ii] = digitalRead (pinDesignation[ii]); //High = Pin has fallen, low = Pin still standing  
      }
      
      if (time > 4000) {
        Mode = 3;
        statusVar3 = 1;
      }

    }


  // ________________________________________________________________________
  // Mode 3: Prepare Lane for Next Ball
  // ________________________________________________________________________

    if (Mode == 3) {

      if(statusVar3 = 1) {
      time3 = millis(); // Determines that start time of Mode 3
      statusVar3 = 0;
      }
  
      int time = time3 - millis();

      if (time < 50) {
        resetActuators1(); // assures pin actuators not moving
        resetActuators4(); // assures sweep actuator not moving
      }

      if (time >= 50 && time < 7000) {
        lowerBallSweep(); // 6 seconds required to lower sweep
      }
  
      if (time >= 4000 && time < 7000){
        raisePins(); //3 seconds required to raise pins which can overlap sweep
      }
        
      if (time >= 7000 && time < 7500) {
        // pause for 1/2 second to allow pins to settle/untangle
        resetActuators1(); // Ensures actuators for bowling pins are off
        resetActuators4(); // Ensures actuator or ball sweep is off
      }
  
      if (time >= 7500 && time < 13500) {
        raiseBallSweep(); // allow 6 seconds to close
      }

      if (time >= 9000 && time < 12000) {
        lowerSomePins(); //3 seconds required to lower pins
      }
      
      if (time >= 12000) {
        Mode = 1;
      }

    }

 
  // ________________________________________________________________________
  // Mode 4: Manual Request to Reset Intended Pin Placement
  // ________________________________________________________________________
  
    if (Mode == 4) {

      if(statusVar4 = 1) {
        time4 = millis();
        statusVar4 =0;
      }
  
      int time = time4 - millis();
   
      if (time < 50) {
        resetActuators1(); // assures pin actuators not moving
        resetActuators4(); // assures sweep actuator not moving
      }
      
      if (time >= 50 && time < 7000) {
        closeBallGate(); // 6 seconds required to lower sweep
      }
  
      if (time >= 4000 && time < 7000){
        raisePins(); //3 seconds required to raise pins which can overlap sweep
      }
        
      if (time >= 7000 && time < 7500) {
        // pause for 1/2 second to allow pins to settle
        resetActuators1(); // assures ball elevagtor actuator not moving
        resetActuators4(); // assures sweep actuator not moving
      }
  
      if (time >= 7500 && time < 13500) {
        closeBallGate(); // allow 6 seconds to close
      }

      if (time >= 9000 && time < 12000) {
        lowerSomePins(); //3 seconds required to lower pins
      }
      
      if (time >=12000) {
        Mode = 1;
      }

    }


  // ________________________________________________________________________
  // Mode 5: Manual Request to Reset to Ball 1
  // ________________________________________________________________________
  
    if (Mode == 5) {
      if(statusVar5 = 1) {
        time5 = millis();
        statusVar5 =0;
      }
   
      int time = time5 - millis();
      
      if (time < 50) {
        resetActuators1(); // assures pin actuators not moving
        resetActuators4(); // assures sweep actuator not moving
      }
      
      if (time >= 50 && time < 7000) {
        closeBallGate(); // 6 seconds required to lower sweep
      }
  
      if (time >= 4000 && time < 7000){
        raisePins(); //3 seconds required to raise pins which can overlap sweep
      }
        
      if (time >= 7000 && time < 7500) {
        // pause for 1/2 second to allow pins to settle
        resetActuators1(); // assures ball elevagtor actuator not moving
        resetActuators4(); // assures sweep actuator not moving
      }
  
      if (time >= 7500 && time < 13500) {
        closeBallGate(); // allow 6 seconds to close
      }

      if (time >= 9000 && time < 12000) {
        lowerAllPins(); //3 seconds required to lower pins
      }
      
      if (time >=12000) {
        Mode = 1;
      }

    }
 
  // ________________________________________________________________________
  // Mode 6: Service Required
  // ________________________________________________________________________

  if (Mode == 6) {
    delay(36000000); // shut down game for 10 minutes until service button pressed
    digitalWrite(49, LOW); // turns off service light
  }
      
}


// ________________________________________________________________________ //
// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //
// void subroutines
// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //
// ________________________________________________________________________ //

void resetActuators1() {
  for (int ii = 1; ii < 11; ii++) {
    digitalWrite(solenoidExtend[ii], LOW);
    digitalWrite(solenoidRetract[ii], LOW); 
  }
    Serial.println("Reset all bowling pin actuators"); // Prints text
}   

void resetActuators2() {
  digitalWrite(solenoidExtend[11], LOW);
  digitalWrite(solenoidRetract[11], LOW); 
  Serial.println("Reset ball gate actuator"); // Prints text
}  

void resetActuators3() {
  digitalWrite(solenoidExtend[12], LOW);
  digitalWrite(solenoidRetract[12], LOW); 
  Serial.println("Reset ball elevator actuator"); // Prints text
}  

void resetActuators4() {
  digitalWrite(solenoidExtend[13], LOW);
  digitalWrite(solenoidRetract[13], LOW); 
  Serial.println("Reset sweep actuator"); // Prints text
}  

void raisePins() {
  for (int ii = 1; ii < 11; ii++) {
  digitalWrite(solenoidExtend[ii], LOW);
  digitalWrite(solenoidRetract[ii], HIGH); 
  delay(50);
  }
  Serial.println("Raise Pins"); // Prints text
}

void lowerAllPins() {
  for (int ii = 1; ii < 11; ii++) {
    digitalWrite(solenoidExtend[ii], LOW);
    digitalWrite(solenoidRetract[ii], HIGH);
    Serial.println("Lower All Pins"); // Prints text
  }
}

void lowerSomePins() {
  for (int ii = 1; ii < 11; ii++) {
    if (bowlpinState[ii] == LOW) {
      digitalWrite(solenoidExtend[ii], LOW);
      digitalWrite(solenoidRetract[ii], HIGH);
      Serial.print("This pin still standing: ");
      Serial.println(ii);
    }
    else if (bowlpinState[ii] == HIGH) {
      digitalWrite(solenoidExtend[ii], LOW);
      digitalWrite(solenoidRetract[ii], HIGH); 
      Serial.print("This pin has fallen: ");
      Serial.println(ii);
    }  
  Serial.println("Lower Some Pins"); // Prints text
  }
}

void lowerBallSweep() {
    digitalWrite(solenoidExtend[13], LOW);
    digitalWrite(solenoidRetract[13], HIGH);
    Serial.println("Lower Ball Sweep"); // Prints text
}

void raiseBallSweep() {
    digitalWrite(solenoidExtend[12], HIGH);
    digitalWrite(solenoidRetract[12], LOW);
    delay(50);
    Serial.println("Raise ball sweep"); // Prints text
}

void openBallGate() {
    digitalWrite(solenoidExtend[11], LOW);
    digitalWrite(solenoidRetract[11], HIGH);
    Serial.println("Open Ball Gate"); // Prints text
}

void closeBallGate() {
    digitalWrite(solenoidExtend[10], HIGH);
    digitalWrite(solenoidRetract[10], LOW);
    Serial.println("Close ball gate"); // Prints text
}

void raiseBallElevator() {
    digitalWrite(solenoidExtend[12], HIGH);
    digitalWrite(solenoidRetract[12], LOW); 
    Serial.println("Raise Elevator"); // Prints text
}

void lowerBallElevator() {
    digitalWrite(solenoidExtend[12], LOW);
    digitalWrite(solenoidRetract[12], HIGH); 
    Serial.println("Lower Elevator"); // Prints text
}

Still some issues with == and = in your conditionals.

EDIT:
I suggest that in the ide you set compiler warnings to all in Preferences. There is plenty more to fix

I’ve been using the cloud version instead of the full version. I used the full IDE version, looked, and found, the “all” in compiling preferences and re-checked the code. It pointed out a number of “==” errors which I’ve corrected. Thanks for that suggestion as i was not aware of the compiling options. There may be other corrections/typos in the sketch which I’m thankful corrections are being pointed out. Additionally, I’m still looking for a conversation of the code I created for digitalRead of the Uno pinouts for bowling pin status? That snippet of code is shown immediately below. Any obvious issues with my approach?

 // ________________________________________________________________________
  // Mode 2: Determine How Many Pins are Left
  // ________________________________________________________________________

    if (Mode == 2) {

      int time = ballRolledTime - millis(); // Keeps track of how much time has passed since the ball was rolled

      if (time > 3250 && statusVar3 == 0) { 
        // NOTE:  After ball sensor is triggered, computer has camera take photo of bowling pin deck.  Computer determines what bowling
        // pins have been knocked down and, in turn, sends data to UNO.  Uno releases this data 3 seconds after ball sensor is triggered 
        // through the Uno pins defined as pinDesignation(ii)

        for (int ii = 1; ii < 11; ii++) 
          bowlpinState[ii] = digitalRead (pinDesignation[ii]); //High = Pin has fallen, low = Pin still standing  
      }
      
      if (time > 4000) {
        Mode = 3;
        statusVar3 = 1;
      }

    }

The entire sketch was updated with the == corrections as shown below.

// //////////////////////////////////////////////////////////// //
//                                                              //
//                Arduino Sketch for Bowling Game               //
//                           Rev 1.0                            //
//                       December 26.2025                       //
//                         Deron Butler                         //
//                dbutler@josephdouglashomes.com                //
//                                                              //
// /////////////////////////////////////////////////////////// ///


// *********************************************************************** //
// Libraries
// *********************************************************************** //

// #include <FastLED.h> // Library for LED controls (future use)

// *********************************************************************** //
// Definitions for MP3 Players
// *********************************************************************** //

// (future use)

// *********************************************************************** //
// Constants/Variables for Set Up
// *********************************************************************** //

int Mode = 1;
const int solenoidExtend[14] = {0, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47}; // Defines pinout for extending solenoid
const int solenoidRetract[14] = {0, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48}; // Defines pinout for retracting solenoid
const int pinDesignation[11] = {0, 8, 2, 3, 4, 5, 9, 10, 11, 12, 13}; // Defines pinout for bowling pin status
// NOTE:  1st position of an index is intentionally not used in this sketch

unsigned long time = 0; // Assigns value of relative time in milliseconds
unsigned long time1 = 0; // Assigns value of relative time in milliseconds
unsigned long time2 = 0; // Assigns value of relative time in milliseconds
unsigned long time3 = 0; // Assigns value of relative time in milliseconds
unsigned long time4 = 0; // Assigns value of relative time in milliseconds
unsigned long time5 = 0; // Assigns value of relative time in milliseconds
unsigned long time6 = 0; // Assigns value of relative time in milliseconds
unsigned long time7 = 0; // Assigns value of relative time in milliseconds
unsigned long currentTime = 0; // Assigns value of relative time in milliseconds
bool bowlpinState[] = {LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW}; // LOW = pin standing; HIGH = pin has fallen
// NOTE:  1st position of an index is position 0 which is purposely chosen to be ignored in this sketch

int statusVar1 = 0; // Variable to toggle (0 = OFF, 1 = ON)
int statusVar2 = 0; // Variable to toggle (0 = OFF, 1 = ON)
int statusVar3 = 0; // Variable to toggle (0 = OFF, 1 = ON)
int statusVar4 = 0; // Variable to toggle (0 = OFF, 1 = ON)
int statusVar5 = 0; // Variable to toggle (0 = OFF, 1 = ON)
int statusVar6 = 0; // Variable to toggle (0 = OFF, 1 = ON)
int statusVar7 = 0; // Variable to toggle (0 = OFF, 1 = ON)

// *********************************************************************** //
// Variables for Ball Return
// *********************************************************************** //
int ballReturnState = LOW; // Current reading from the button
int lastBallReturnState = LOW; // Previous reading from the button
bool ballReturn = LOW;

unsigned long ballReturnStartTime  = 0; // Assigns value of relative time in milliseconds
unsigned long lastDebounceTime1 = 0; // Last time the button state changed
unsigned long debounceDelay1 = 500;   // Debounce time in milliseconds

// *********************************************************************** //
// Variables for Service Button
// *********************************************************************** //
bool serviceButtonPressed = false;
int serviceButtonState = LOW;     // Current reading from the button
unsigned long pressStartTime = 0;

// *********************************************************************** //
// Variables for Current Sensing
// *********************************************************************** //

float voltageOut[13] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
float current[13] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int currentMax = 2;
bool maxCurrentEvent[13] = {false,false,false,false,false,false,false,false,false,false,false,false,false};
unsigned long lastCurrentDebounceTime[13] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // Last time the current state changed
unsigned long currentDebounceDelay = 350;   // Debounce time in milliseconds

// *********************************************************************** //
// Variables for Modes
// *********************************************************************** //

unsigned long ballRolledTime = 0;
int ballRolledState = HIGH;
int lastBallRolledState = HIGH;

// ________________________________________________________________________ //
// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //
void setup() {
// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //
// ________________________________________________________________________ //

  // area reserved for future MP3 Player

  Serial.begin(9600); // Opens the serial port at 9600 bps
  
  // Mega Arduino Pin Assignments

    // pins 0-1 not used

    for (int ii = 2; ii < 14; ii++) { // Define pins 2-13
      pinMode(ii, INPUT_PULLUP);
    }

    // pins 14-21 not used

    pinMode(22, INPUT_PULLUP);
  
    for (int ii = 23; ii < 51; ii++) { // Define pins 23-50
      pinMode(ii, OUTPUT);
    }

    // pins 51-53 not used  

    pinMode (A0, INPUT); // Analog
    pinMode (A1, INPUT); // Analog
    pinMode (A2, INPUT); // Analog
    pinMode (A3, INPUT); // Analog
    pinMode (A4, INPUT); // Analog
    pinMode (A5, INPUT); // Analog
    pinMode (A6, INPUT); // Analog
    pinMode (A7, INPUT); // Analog
    pinMode (A8, INPUT); // Analog
    pinMode (A9, INPUT); // Analog
    pinMode (A10, INPUT_PULLUP); // Digital
    pinMode (A11, INPUT_PULLUP); // Digital
  
}


// ________________________________________________________________________ //
// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //
void loop() {
// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //
// ________________________________________________________________________ //
  
// currentTime = millis(); // future use

// ________________________________________________________________________
// Ball Return Idle // Note:  Elevator may run concurrently with any Mode
// ________________________________________________________________________
  
 if (ballReturn == false) { //Ball return is not in use = false
 int reading1 = digitalRead(A10);

   if (reading1 != lastBallReturnState) { // Check to see if ball is at ball return sensor
    lastDebounceTime1 = millis(); // Reset debounce timer
   }

  if ((millis() - lastDebounceTime1) > debounceDelay1) { // If enough time has passed, confirm the change
    if (reading1 != ballReturnState) {
      ballReturnState = reading1;

      if (ballReturnState == LOW) { // Only toggle when ball sensor actually detects the ball (LOW with INPUT_PULLUP)
        ballReturn = true; // Ball return now active
        ballReturnStartTime = millis();
        // Serial.print("Status variable changed to: ");
        // Serial.println(statusVar1);
      }
    }
  }

  lastBallReturnState = reading1;
 }
  
  // ________________________________________________________________________
  // Ball Return Operating
  // ________________________________________________________________________
    
    if (ballReturn == true) { // Ball elevator = true when operating
      time = millis() - ballReturnStartTime; // keeps track of how long ball elevator has been running

      if (time < 500) {
        resetActuators2(); // assures ball gate actuator not moving
        resetActuators3(); // assures ball elevator actuator not moving
      }
      
      if (time >= 500 && time < 3500) {
        openBallGate();
      }
          
      if (time >= 3500 && time < 20500) {
        raiseBallElevator(); //17 seconds required for full up stroke
        resetActuators2(); // stops ball gate actuator mid stroke
      }
        
      if (time >= 20500 && time < 22500) {
        // pause for 2 seconds to allow ball to exit ball elevator
        resetActuators3(); // assures ball elevagtor actuator not moving
      }
            
      if (time >= 22500 && time < 37500) {
        lowerBallElevator(); //15 seconds required for full down stroke
      }
            
      if (time >= 37500 && time < 40500) {
        closeBallGate(); // allow 3 seconds to close
      }

      if (time >= 40500) {
        resetActuators2(); // stops ball gate actuator mid stroke
        ballReturn = false; // changes ball return status to off after 40.5 seconds
      }
    }
  
  // ________________________________________________________________________
  // Detect Service Interrupt // Note: may interrupt any Mode
  // ________________________________________________________________________
  
  int serviceButtonState = digitalRead(22); // Check if the service button has been pushed

  if (serviceButtonState == LOW && serviceButtonPressed == false) { // conditions when button just pressed
    pressStartTime = millis();
    serviceButtonPressed = true;
  }

  if (serviceButtonState == HIGH && serviceButtonPressed == true) { // conditions when pressed button just released
    if(millis() - pressStartTime > 500) {
      if (millis() - pressStartTime >= 2500) { // request made to reset all pins if service button held for > 2.5 seconds
        Mode = 5;
        statusVar5 = 1;
      }
      else 
        Mode = 4; // request made to reset some pins if service button held for < 2.5 seconds
        statusVar4 = 1;
    }
 
    serviceButtonPressed = false;
  }

  
  // ________________________________________________________________________
  // Detect High Current in Actuators // Note: may interrupt any Mode
  // ________________________________________________________________________
  
  for (int ii = 0; ii < 12; ii++) {
    if(maxCurrentEvent[ii] == false) {
      voltageOut[ii] = analogRead(ii); // read analog pins 0 to 9 to detect string tangle
      int jj = ii + 1;
      current[jj] = (voltageOut[ii] - 2.5) / 0.066; // formula to convert sensor reading to amps

      if (current[jj] > currentMax) { // detects high current on linear actuator jj
        lastCurrentDebounceTime[jj] = millis();
      }

      if (millis() - lastCurrentDebounceTime[jj] > currentDebounceDelay) { // overlooks actuator start up current
        if (current[jj] > currentMax) {
          maxCurrentEvent[jj] = true;
        }
      
        if (jj < 11) {
          if (time >= 50 && time < 1500) {
            digitalWrite(49, HIGH); // turns on service light
            digitalWrite(solenoidExtend[jj], LOW); // stop linear actuator with high current
            digitalWrite(solenoidRetract[jj], LOW); 
          }
        
          if (time >= 50 && time < 1500) {
            digitalWrite(solenoidExtend[jj], LOW); // raise linear actuator with high current
            digitalWrite(solenoidRetract[jj], HIGH);
          }
  
          if (time >= 1500 && time < 1550){
            digitalWrite(solenoidExtend[jj], LOW); // stop linear actuator with high current
            digitalWrite(solenoidRetract[jj], LOW);
          }

          if (time >= 1550 && time < 4500) {
            digitalWrite(solenoidExtend[jj], HIGH); // lower linear actuator with high current
            digitalWrite(solenoidRetract[jj], LOW);
          }
  
          if (time >=4500) {
            maxCurrentEvent[ii] = false;
          }
        }

        else {
          digitalWrite(solenoidExtend[jj], LOW); // stops movement of elevator or sweep
          digitalWrite(solenoidRetract[jj], LOW);
          digitalWrite(49, LOW); // turns on service light as elevator or sweep needs attention from attendant
          Mode = 6;
          maxCurrentEvent[ii] = false;
          
        }
      }
    }
  }

  
  // ________________________________________________________________________
  // Mode 1: Monitor Bowling Ball Trigger Sensor for Next Ball Rolled
  // ________________________________________________________________________

    if (Mode == 1) {

      // THE NEXT TWO LINES OF CODE CHANGED AFTER INITIAL SKETCH POSTED ON ARDUINO FORUM ON 1/15/2026 
      
      /*ballRolledState = digitalRead(6); // Check to see if a ball has been rolled
      */

      ballRolledState = digitalRead(7); // CHANGED MEGA PIN REFERERNCE FROM 6 TO 7 AND WIRING TO BE CHANGED TO CONNECT MEGA D7 TO UNO D8
        
      if (ballRolledState == !lastBallRolledState) { // if state changes to LOW, ball has been rolled
        ballRolledTime = millis(); // sets time ball was rolled
        Mode = 2;
      }
  
    lastBallRolledState = ballRolledState;
    
    }


  // ________________________________________________________________________
  // Mode 2: Determine How Many Pins are Left
  // ________________________________________________________________________

    if (Mode == 2) {

      int time = ballRolledTime - millis(); // Keeps track

      if (time > 3250 && statusVar3 == 0) { 
        // NOTE:  After ball sensor is triggered, computer has camera take photo of bowling pin deck.  Computer determines what bowling
        // pins have been knocked down and, in turn, sends data to UNO.  Uno releases this data 3 seconds after ball sensor is triggered 
        // through the Uno pins defined as pinDesignation(ii)

        for (int ii = 1; ii < 11; ii++) 
          bowlpinState[ii] = digitalRead (pinDesignation[ii]); //High = Pin has fallen, low = Pin still standing  
      }
      
      if (time > 4000) {
        Mode = 3;
        statusVar3 = 1;
      }

    }


  // ________________________________________________________________________
  // Mode 3: Prepare Lane for Next Ball
  // ________________________________________________________________________

    if (Mode == 3) {

      if(statusVar3 == 1) {
      time3 = millis(); // Determines that start time of Mode 3
      statusVar3 = 0;
      }
  
      int time = time3 - millis();

      if (time < 50) {
        resetActuators1(); // assures pin actuators not moving
        resetActuators4(); // assures sweep actuator not moving
      }

      if (time >= 50 && time < 7000) {
        lowerBallSweep(); // 6 seconds required to lower sweep
      }
  
      if (time >= 4000 && time < 7000){
        raisePins(); //3 seconds required to raise pins which can overlap sweep
      }
        
      if (time >= 7000 && time < 7500) {
        // pause for 1/2 second to allow pins to settle/untangle
        resetActuators1(); // Ensures actuators for bowling pins are off
        resetActuators4(); // Ensures actuator or ball sweep is off
      }
  
      if (time >= 7500 && time < 13500) {
        raiseBallSweep(); // allow 6 seconds to close
      }

      if (time >= 9000 && time < 12000) {
        lowerSomePins(); //3 seconds required to lower pins
      }
      
      if (time >= 12000) {
        Mode = 1;
      }

    }

 
  // ________________________________________________________________________
  // Mode 4: Manual Request to Reset Intended Pin Placement
  // ________________________________________________________________________
  
    if (Mode == 4) {

      if(statusVar4 == 1) {
        time4 = millis();
        statusVar4 =0;
      }
  
      int time = time4 - millis();
   
      if (time < 50) {
        resetActuators1(); // assures pin actuators not moving
        resetActuators4(); // assures sweep actuator not moving
      }
      
      if (time >= 50 && time < 7000) {
        closeBallGate(); // 6 seconds required to lower sweep
      }
  
      if (time >= 4000 && time < 7000){
        raisePins(); //3 seconds required to raise pins which can overlap sweep
      }
        
      if (time >= 7000 && time < 7500) {
        // pause for 1/2 second to allow pins to settle
        resetActuators1(); // assures ball elevagtor actuator not moving
        resetActuators4(); // assures sweep actuator not moving
      }
  
      if (time >= 7500 && time < 13500) {
        closeBallGate(); // allow 6 seconds to close
      }

      if (time >= 9000 && time < 12000) {
        lowerSomePins(); //3 seconds required to lower pins
      }
      
      if (time >=12000) {
        Mode = 1;
      }

    }


  // ________________________________________________________________________
  // Mode 5: Manual Request to Reset to Ball 1
  // ________________________________________________________________________
  
    if (Mode == 5) {
      if(statusVar5 == 1) {
        time5 = millis();
        statusVar5 = 0;
      }
   
      int time = time5 - millis();
      
      if (time < 50) {
        resetActuators1(); // assures pin actuators not moving
        resetActuators4(); // assures sweep actuator not moving
      }
      
      if (time >= 50 && time < 7000) {
        closeBallGate(); // 6 seconds required to lower sweep
      }
  
      if (time >= 4000 && time < 7000){
        raisePins(); //3 seconds required to raise pins which can overlap sweep
      }
        
      if (time >= 7000 && time < 7500) {
        // pause for 1/2 second to allow pins to settle
        resetActuators1(); // assures ball elevagtor actuator not moving
        resetActuators4(); // assures sweep actuator not moving
      }
  
      if (time >= 7500 && time < 13500) {
        closeBallGate(); // allow 6 seconds to close
      }

      if (time >= 9000 && time < 12000) {
        lowerAllPins(); //3 seconds required to lower pins
      }
      
      if (time >= 12000) {
        Mode = 1;
      }

    }
 
  // ________________________________________________________________________
  // Mode 6: Service Required
  // ________________________________________________________________________

  if (Mode == 6) {
    delay(36000000); // shut down game for 10 minutes until service button pressed
    digitalWrite(49, LOW); // turns off service light
  }
      
}


// ________________________________________________________________________ //
// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //
// void subroutines
// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //
// ________________________________________________________________________ //

void resetActuators1() {
  for (int ii = 1; ii < 11; ii++) {
    digitalWrite(solenoidExtend[ii], LOW);
    digitalWrite(solenoidRetract[ii], LOW); 
  }
    Serial.println("Reset all bowling pin actuators"); // Prints text
}   

void resetActuators2() {
  digitalWrite(solenoidExtend[11], LOW);
  digitalWrite(solenoidRetract[11], LOW); 
  Serial.println("Reset ball gate actuator"); // Prints text
}  

void resetActuators3() {
  digitalWrite(solenoidExtend[12], LOW);
  digitalWrite(solenoidRetract[12], LOW); 
  Serial.println("Reset ball elevator actuator"); // Prints text
}  

void resetActuators4() {
  digitalWrite(solenoidExtend[13], LOW);
  digitalWrite(solenoidRetract[13], LOW); 
  Serial.println("Reset sweep actuator"); // Prints text
}  

void raisePins() {
  for (int ii = 1; ii < 11; ii++) {
  digitalWrite(solenoidExtend[ii], LOW);
  digitalWrite(solenoidRetract[ii], HIGH); 
  delay(50);
  }
  Serial.println("Raise Pins"); // Prints text
}

void lowerAllPins() {
  for (int ii = 1; ii < 11; ii++) {
    digitalWrite(solenoidExtend[ii], LOW);
    digitalWrite(solenoidRetract[ii], HIGH);
    Serial.println("Lower All Pins"); // Prints text
  }
}

void lowerSomePins() {
  for (int ii = 1; ii < 11; ii++) {
    if (bowlpinState[ii] == LOW) {
      digitalWrite(solenoidExtend[ii], LOW);
      digitalWrite(solenoidRetract[ii], HIGH);
      Serial.print("This pin still standing: ");
      Serial.println(ii);
    }
    else if (bowlpinState[ii] == HIGH) {
      digitalWrite(solenoidExtend[ii], LOW);
      digitalWrite(solenoidRetract[ii], HIGH); 
      Serial.print("This pin has fallen: ");
      Serial.println(ii);
    }  
  Serial.println("Lower Some Pins"); // Prints text
  }
}

void lowerBallSweep() {
    digitalWrite(solenoidExtend[13], LOW);
    digitalWrite(solenoidRetract[13], HIGH);
    Serial.println("Lower Ball Sweep"); // Prints text
}

void raiseBallSweep() {
    digitalWrite(solenoidExtend[12], HIGH);
    digitalWrite(solenoidRetract[12], LOW);
    delay(50);
    Serial.println("Raise ball sweep"); // Prints text
}

void openBallGate() {
    digitalWrite(solenoidExtend[11], LOW);
    digitalWrite(solenoidRetract[11], HIGH);
    Serial.println("Open Ball Gate"); // Prints text
}

void closeBallGate() {
    digitalWrite(solenoidExtend[10], HIGH);
    digitalWrite(solenoidRetract[10], LOW);
    Serial.println("Close ball gate"); // Prints text
}

void raiseBallElevator() {
    digitalWrite(solenoidExtend[12], HIGH);
    digitalWrite(solenoidRetract[12], LOW); 
    Serial.println("Raise Elevator"); // Prints text
}

void lowerBallElevator() {
    digitalWrite(solenoidExtend[12], LOW);
    digitalWrite(solenoidRetract[12], HIGH); 
    Serial.println("Lower Elevator"); // Prints text
}

Good job getting the compiling issues cleared up.

Yes, Your use use of millis() for timing is fundamentally wrong in the section you highlight, and is different from the other uses of millis() for timing in the code.

In Mode 1

if (ballRolledState == !lastBallRolledState) { // if state changes to LOW, ball has been rolled
        ballRolledTime = millis(); // sets time ball was rolled
        Mode = 2;
      }

But then in Mode 2 you have this.

int time = ballRolledTime - millis(); // Keeps track

As millis() grows larger and larger, the value of time will get more and more negative, yet your conditionals in this section depend on a value greater than something.

A careful review of this millis() tutorial will be helpful
https://forum.arduino.cc/t/using-millis-for-timing-a-beginners-guide/483573

I’ve gone over the code dozens of times and didn’t notice I had that formula backwards for Modes = 2-4. It’s errors in code like that which can be difficult to find and correct when debugging myself. Thanks for catching that. The 3 occurrences were corrected similar to what is shown below. I now have millis() in front where it should be so each equation has a positive result:

int time = millis() - ballRolledTime;

At this point, my primary concern and the reason for this discussion still remains. I’ll be more specific. What is the best way for one Arduino to read the output of another Arduino? In my case, how should the Mega digitalRead the Uno’s output pins associated with the “trigger” signal as well as pins associated with the status of the bowling pins. My code is written so that the Mega digitalRead the Uno’s pins associated for each bowling pin ONE TIME (for each of the 10 pins) 3.25 seconds after the ball has been rolled (Uno signal available from 3 to 3.5 seconds after the ball has been rolled). Should I be concerned about reliability with one read, the need for debouncing, etc? Would I be better off monitoring when the signal is first available and/or reading the signal more than once for reliability? If so, suggestions how to do so?

The code in question is this:

  // ________________________________________________________________________
  // Mode 2: Determine How Many Pins are Left
  // ________________________________________________________________________

    if (Mode == 2) {

      int time = millis() - ballRolledTime; // Keeps track of how much time has passed since the ball was rolled

      if (time > 3250 && statusVar2 == 0) { 
        // NOTE:  After ball sensor is triggered, computer has camera take photo of bowling pin deck.  Computer determines what bowling
        // pins have been knocked down and, in turn, sends data to UNO.  Uno releases this data 3 seconds after ball sensor is triggered 
        // through the Uno pins defined as pinDesignation(ii)

        for (int ii = 1; ii < 11; ii++) {
          bowlpinState[ii] = digitalRead (pinDesignation[ii]); //High = Pin has fallen, low = Pin still standing
        }
        statusVar2 = 1; // Insures Uno pins are read just one time
      }
      
      if (time > 4000) {
        Mode = 3;
        statusVar2 = 0; // resets time variable for Mode 2
      }

    }

Full corrected sketch is as follows:

// //////////////////////////////////////////////////////////// //
//                                                              //
//                Arduino Sketch for Bowling Game               //
//                           Rev 1.0                            //
//                       December 26.2025                       //
//                         Deron Butler                         //
//                dbutler@josephdouglashomes.com                //
//                                                              //
// /////////////////////////////////////////////////////////// ///


// *********************************************************************** //
// Libraries
// *********************************************************************** //

// #include <FastLED.h> // Library for LED controls (future use)

// *********************************************************************** //
// Definitions for MP3 Players
// *********************************************************************** //

// (future use)

// *********************************************************************** //
// Constants/Variables for Set Up
// *********************************************************************** //

int Mode = 1;
const int solenoidExtend[14] = {0, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47}; // Defines pinout for extending solenoid
const int solenoidRetract[14] = {0, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48}; // Defines pinout for retracting solenoid
const int pinDesignation[11] = {0, 8, 2, 3, 4, 5, 9, 10, 11, 12, 13}; // Defines pinout for bowling pin status
// NOTE:  1st position of an index is intentionally not used in this sketch

unsigned long time = 0; // Assigns value of relative time in milliseconds
unsigned long time1 = 0; // Assigns value of relative time in milliseconds
unsigned long time2 = 0; // Assigns value of relative time in milliseconds
unsigned long time3 = 0; // Assigns value of relative time in milliseconds
unsigned long time4 = 0; // Assigns value of relative time in milliseconds
unsigned long time5 = 0; // Assigns value of relative time in milliseconds
unsigned long time6 = 0; // Assigns value of relative time in milliseconds
unsigned long time7 = 0; // Assigns value of relative time in milliseconds
unsigned long currentTime = 0; // Assigns value of relative time in milliseconds
bool bowlpinState[] = {LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW}; // LOW = pin standing; HIGH = pin has fallen
// NOTE:  1st position of an index is position 0 which is purposely chosen to be ignored in this sketch

int statusVar1 = 0; // Variable to toggle (0 = OFF, 1 = ON)
int statusVar2 = 0; // Variable to toggle (0 = OFF, 1 = ON)
int statusVar3 = 0; // Variable to toggle (0 = OFF, 1 = ON)
int statusVar4 = 0; // Variable to toggle (0 = OFF, 1 = ON)
int statusVar5 = 0; // Variable to toggle (0 = OFF, 1 = ON)
int statusVar6 = 0; // Variable to toggle (0 = OFF, 1 = ON)
int statusVar7 = 0; // Variable to toggle (0 = OFF, 1 = ON)

// *********************************************************************** //
// Variables for Ball Return
// *********************************************************************** //
int ballReturnState = LOW; // Current reading from the button
int lastBallReturnState = LOW; // Previous reading from the button
bool ballReturn = LOW;

unsigned long ballReturnStartTime  = 0; // Assigns value of relative time in milliseconds
unsigned long lastDebounceTime1 = 0; // Last time the button state changed
unsigned long debounceDelay1 = 500;   // Debounce time in milliseconds

// *********************************************************************** //
// Variables for Service Button
// *********************************************************************** //
bool serviceButtonPressed = false;
int serviceButtonState = LOW;     // Current reading from the button
unsigned long pressStartTime = 0;

// *********************************************************************** //
// Variables for Current Sensing
// *********************************************************************** //

float voltageOut[13] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
float current[13] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int currentMax = 2;
bool maxCurrentEvent[13] = {false,false,false,false,false,false,false,false,false,false,false,false,false};
unsigned long lastCurrentDebounceTime[13] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // Last time the current state changed
unsigned long currentDebounceDelay = 350;   // Debounce time in milliseconds

// *********************************************************************** //
// Variables for Modes
// *********************************************************************** //

unsigned long ballRolledTime = 0;
int ballRolledState = HIGH;
int lastBallRolledState = HIGH;

// ________________________________________________________________________ //
// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //
void setup() {
// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //
// ________________________________________________________________________ //

  // area reserved for future MP3 Player

  Serial.begin(9600); // Opens the serial port at 9600 bps
  
  // Mega Arduino Pin Assignments

    // pins 0-1 not used

    for (int ii = 2; ii < 14; ii++) { // Define pins 2-13
      pinMode(ii, INPUT_PULLUP);
    }

    // pins 14-21 not used

    pinMode(22, INPUT_PULLUP);
  
    for (int ii = 23; ii < 51; ii++) { // Define pins 23-50
      pinMode(ii, OUTPUT);
    }

    // pins 51-53 not used  

    pinMode (A0, INPUT); // Analog
    pinMode (A1, INPUT); // Analog
    pinMode (A2, INPUT); // Analog
    pinMode (A3, INPUT); // Analog
    pinMode (A4, INPUT); // Analog
    pinMode (A5, INPUT); // Analog
    pinMode (A6, INPUT); // Analog
    pinMode (A7, INPUT); // Analog
    pinMode (A8, INPUT); // Analog
    pinMode (A9, INPUT); // Analog
    pinMode (A10, INPUT_PULLUP); // Digital
    pinMode (A11, INPUT_PULLUP); // Digital
  
}


// ________________________________________________________________________ //
// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //
void loop() {
// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //
// ________________________________________________________________________ //
  
// currentTime = millis(); // future use

// ________________________________________________________________________
// Ball Return Idle // Note:  Elevator may run concurrently with any Mode
// ________________________________________________________________________
  
 if (ballReturn == false) { //Ball return is not in use = false
 int reading1 = digitalRead(A10);

   if (reading1 != lastBallReturnState) { // Check to see if ball is at ball return sensor
    lastDebounceTime1 = millis(); // Reset debounce timer
   }

  if ((millis() - lastDebounceTime1) > debounceDelay1) { // If enough time has passed, confirm the change
    if (reading1 != ballReturnState) {
      ballReturnState = reading1;

      if (ballReturnState == LOW) { // Only toggle when ball sensor actually detects the ball (LOW with INPUT_PULLUP)
        ballReturn = true; // Ball return now active
        ballReturnStartTime = millis();
        // Serial.print("Status variable changed to: ");
        // Serial.println(statusVar1);
      }
    }
  }

  lastBallReturnState = reading1;
 }
  
  // ________________________________________________________________________
  // Ball Return Operating
  // ________________________________________________________________________
    
    if (ballReturn == true) { // Ball elevator = true when operating
      time = millis() - ballReturnStartTime; // keeps track of how long ball elevator has been running

      if (time < 500) {
        resetActuators2(); // assures ball gate actuator not moving
        resetActuators3(); // assures ball elevator actuator not moving
      }
      
      if (time >= 500 && time < 3500) {
        openBallGate();
      }
          
      if (time >= 3500 && time < 20500) {
        raiseBallElevator(); //17 seconds required for full up stroke
        resetActuators2(); // stops ball gate actuator mid stroke
      }
        
      if (time >= 20500 && time < 22500) {
        // pause for 2 seconds to allow ball to exit ball elevator
        resetActuators3(); // assures ball elevagtor actuator not moving
      }
            
      if (time >= 22500 && time < 37500) {
        lowerBallElevator(); //15 seconds required for full down stroke
      }
            
      if (time >= 37500 && time < 40500) {
        closeBallGate(); // allow 3 seconds to close
      }

      if (time >= 40500) {
        resetActuators2(); // stops ball gate actuator mid stroke
        ballReturn = false; // changes ball return status to off after 40.5 seconds
      }
    }
  
  // ________________________________________________________________________
  // Detect Service Interrupt // Note: may interrupt any Mode
  // ________________________________________________________________________
  
  int serviceButtonState = digitalRead(22); // Check if the service button has been pushed

  if (serviceButtonState == LOW && serviceButtonPressed == false) { // conditions when button just pressed
    pressStartTime = millis();
    serviceButtonPressed = true;
  }

  if (serviceButtonState == HIGH && serviceButtonPressed == true) { // conditions when pressed button just released
    if(millis() - pressStartTime > 500) {
      if (millis() - pressStartTime >= 2500) { // request made to reset all pins if service button held for > 2.5 seconds
        Mode = 5;
        statusVar5 = 0;
      }
      else 
        Mode = 4; // request made to reset some pins if service button held for < 2.5 seconds
        statusVar4 = 0;
    }
 
    serviceButtonPressed = false;
  }

  
  // ________________________________________________________________________
  // Detect High Current in Actuators // Note: may interrupt any Mode
  // ________________________________________________________________________
  
  for (int ii = 0; ii < 12; ii++) {
    if(maxCurrentEvent[ii] == false) {
      voltageOut[ii] = analogRead(ii); // read analog pins 0 to 9 to detect string tangle
      int jj = ii + 1;
      current[jj] = (voltageOut[ii] - 2.5) / 0.066; // formula to convert sensor reading to amps

      if (current[jj] > currentMax) { // detects high current on linear actuator jj
        lastCurrentDebounceTime[jj] = millis();
      }

      if (millis() - lastCurrentDebounceTime[jj] > currentDebounceDelay) { // overlooks actuator start up current
        if (current[jj] > currentMax) {
          maxCurrentEvent[jj] = true;
        }
      
        if (jj < 11) {
          if (time >= 50 && time < 1500) {
            digitalWrite(49, HIGH); // turns on service light
            digitalWrite(solenoidExtend[jj], LOW); // stop linear actuator with high current
            digitalWrite(solenoidRetract[jj], LOW); 
          }
        
          if (time >= 50 && time < 1500) {
            digitalWrite(solenoidExtend[jj], LOW); // raise linear actuator with high current
            digitalWrite(solenoidRetract[jj], HIGH);
          }
  
          if (time >= 1500 && time < 1550){
            digitalWrite(solenoidExtend[jj], LOW); // stop linear actuator with high current
            digitalWrite(solenoidRetract[jj], LOW);
          }

          if (time >= 1550 && time < 4500) {
            digitalWrite(solenoidExtend[jj], HIGH); // lower linear actuator with high current
            digitalWrite(solenoidRetract[jj], LOW);
          }
  
          if (time >=4500) {
            maxCurrentEvent[ii] = false;
          }
        }

        else {
          digitalWrite(solenoidExtend[jj], LOW); // stops movement of elevator or sweep
          digitalWrite(solenoidRetract[jj], LOW);
          digitalWrite(49, LOW); // turns on service light as elevator or sweep needs attention from attendant
          Mode = 6;
          maxCurrentEvent[ii] = false;
          
        }
      }
    }
  }

  
  // ________________________________________________________________________
  // Mode 1: Monitor Bowling Ball Trigger Sensor for Next Ball Rolled
  // ________________________________________________________________________

    if (Mode == 1) {
      
      ballRolledState = digitalRead(7); // CHANGED MEGA PIN REFERERNCE FROM 6 TO 7 AND WIRING TO BE CHANGED TO CONNECT MEGA D7 TO UNO D8
        
      if (ballRolledState == !lastBallRolledState) { // if state changes to LOW, ball has been rolled
        ballRolledTime = millis(); // sets time ball was rolled
        Mode = 2;
        statusVar2 = 0;
      }
  
    lastBallRolledState = ballRolledState;
    
    }


  // ________________________________________________________________________
  // Mode 2: Determine How Many Pins are Left
  // ________________________________________________________________________

    if (Mode == 2) {

      int time = millis() - ballRolledTime; // Keeps track of how much time has passed since the ball was rolled

      if (time > 3250 && statusVar2 == 0) { 
        // NOTE:  After ball sensor is triggered, computer has camera take photo of bowling pin deck.  Computer determines what bowling
        // pins have been knocked down and, in turn, sends data to UNO.  Uno releases this data 3 seconds after ball sensor is triggered 
        // through the Uno pins defined as pinDesignation(ii)

        for (int ii = 1; ii < 11; ii++) {
          bowlpinState[ii] = digitalRead (pinDesignation[ii]); //High = Pin has fallen, low = Pin still standing
        }
        statusVar2 = 1; // Insures Uno pins are read just one time
      }
      
      if (time > 4000) {
        Mode = 3;
        statusVar3 = 0;
      }

    }


  // ________________________________________________________________________
  // Mode 3: Prepare Lane for Next Ball
  // ________________________________________________________________________

    if (Mode == 3) {

      if(statusVar3 == 0) {
        time3 = millis(); // Determines the start time of Mode 3
      statusVar3 = 1;
      }
  
      int time = millis() - time3;

      if (time < 50) {
        resetActuators1(); // assures pin actuators not moving
        resetActuators4(); // assures sweep actuator not moving
      }

      if (time >= 50 && time < 7000) {
        lowerBallSweep(); // 6 seconds required to lower sweep
      }
  
      if (time >= 4000 && time < 7000){
        raisePins(); //3 seconds required to raise pins which can overlap sweep
      }
        
      if (time >= 7000 && time < 7500) {
        // pause for 1/2 second to allow pins to settle/untangle
        resetActuators1(); // Ensures actuators for bowling pins are off
        resetActuators4(); // Ensures actuator or ball sweep is off
      }
  
      if (time >= 7500 && time < 13500) {
        raiseBallSweep(); // allow 6 seconds to close
      }

      if (time >= 9000 && time < 12000) {
        lowerSomePins(); //3 seconds required to lower pins
      }
      
      if (time >= 12000) {
        Mode = 1;
      }

    }

 
  // ________________________________________________________________________
  // Mode 4: Manual Request to Reset Intended Pin Placement
  // ________________________________________________________________________
  
    if (Mode == 4) {

      if(statusVar4 == 0) {
        time4 = millis();
        statusVar4 =1;
      }
  
      int time = millis() - time4;
   
      if (time < 50) {
        resetActuators1(); // assures pin actuators not moving
        resetActuators4(); // assures sweep actuator not moving
      }
      
      if (time >= 50 && time < 7000) {
        closeBallGate(); // 6 seconds required to lower sweep
      }
  
      if (time >= 4000 && time < 7000){
        raisePins(); //3 seconds required to raise pins which can overlap sweep
      }
        
      if (time >= 7000 && time < 7500) {
        // pause for 1/2 second to allow pins to settle
        resetActuators1(); // assures ball elevagtor actuator not moving
        resetActuators4(); // assures sweep actuator not moving
      }
  
      if (time >= 7500 && time < 13500) {
        closeBallGate(); // allow 6 seconds to close
      }

      if (time >= 9000 && time < 12000) {
        lowerSomePins(); //3 seconds required to lower pins
      }
      
      if (time >=12000) {
        Mode = 1;
      }

    }


  // ________________________________________________________________________
  // Mode 5: Manual Request to Reset to Ball 1
  // ________________________________________________________________________
  
    if (Mode == 5) {
      if(statusVar5 == 0) {
        time5 = millis();
        statusVar5 = 1;
      }
   
      int time = millis() - time5;
      
      if (time < 50) {
        resetActuators1(); // assures pin actuators not moving
        resetActuators4(); // assures sweep actuator not moving
      }
      
      if (time >= 50 && time < 7000) {
        closeBallGate(); // 6 seconds required to lower sweep
      }
  
      if (time >= 4000 && time < 7000){
        raisePins(); //3 seconds required to raise pins which can overlap sweep
      }
        
      if (time >= 7000 && time < 7500) {
        // pause for 1/2 second to allow pins to settle
        resetActuators1(); // assures ball elevagtor actuator not moving
        resetActuators4(); // assures sweep actuator not moving
      }
  
      if (time >= 7500 && time < 13500) {
        closeBallGate(); // allow 6 seconds to close
      }

      if (time >= 9000 && time < 12000) {
        lowerAllPins(); //3 seconds required to lower pins
      }
      
      if (time >= 12000) {
        Mode = 1;
      }

    }
 
  // ________________________________________________________________________
  // Mode 6: Service Required
  // ________________________________________________________________________

  if (Mode == 6) {
    delay(36000000); // shut down game for 10 minutes or until service button pressed
    digitalWrite(49, LOW); // turns off service light
  }
      
}


// ________________________________________________________________________ //
// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //
// void subroutines
// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //
// ________________________________________________________________________ //

void resetActuators1() {
  for (int ii = 1; ii < 11; ii++) {
    digitalWrite(solenoidExtend[ii], LOW);
    digitalWrite(solenoidRetract[ii], LOW); 
  }
    Serial.println("Reset all bowling pin actuators"); // Prints text
}   

void resetActuators2() {
  digitalWrite(solenoidExtend[11], LOW);
  digitalWrite(solenoidRetract[11], LOW); 
  Serial.println("Reset ball gate actuator"); // Prints text
}  

void resetActuators3() {
  digitalWrite(solenoidExtend[12], LOW);
  digitalWrite(solenoidRetract[12], LOW); 
  Serial.println("Reset ball elevator actuator"); // Prints text
}  

void resetActuators4() {
  digitalWrite(solenoidExtend[13], LOW);
  digitalWrite(solenoidRetract[13], LOW); 
  Serial.println("Reset sweep actuator"); // Prints text
}  

void raisePins() {
  for (int ii = 1; ii < 11; ii++) {
  digitalWrite(solenoidExtend[ii], LOW);
  digitalWrite(solenoidRetract[ii], HIGH); 
  delay(50);
  }
  Serial.println("Raise Pins"); // Prints text
}

void lowerAllPins() {
  for (int ii = 1; ii < 11; ii++) {
    digitalWrite(solenoidExtend[ii], LOW);
    digitalWrite(solenoidRetract[ii], HIGH);
    Serial.println("Lower All Pins"); // Prints text
  }
}

void lowerSomePins() {
  for (int ii = 1; ii < 11; ii++) {
    if (bowlpinState[ii] == LOW) {
      digitalWrite(solenoidExtend[ii], LOW);
      digitalWrite(solenoidRetract[ii], HIGH);
      Serial.print("This pin still standing: ");
      Serial.println(ii);
    }
    else if (bowlpinState[ii] == HIGH) {
      digitalWrite(solenoidExtend[ii], LOW);
      digitalWrite(solenoidRetract[ii], HIGH); 
      Serial.print("This pin has fallen: ");
      Serial.println(ii);
    }  
  Serial.println("Lower Some Pins"); // Prints text
  }
}

void lowerBallSweep() {
    digitalWrite(solenoidExtend[13], LOW);
    digitalWrite(solenoidRetract[13], HIGH);
    Serial.println("Lower Ball Sweep"); // Prints text
}

void raiseBallSweep() {
    digitalWrite(solenoidExtend[12], HIGH);
    digitalWrite(solenoidRetract[12], LOW);
    delay(50);
    Serial.println("Raise ball sweep"); // Prints text
}

void openBallGate() {
    digitalWrite(solenoidExtend[11], LOW);
    digitalWrite(solenoidRetract[11], HIGH);
    Serial.println("Open Ball Gate"); // Prints text
}

void closeBallGate() {
    digitalWrite(solenoidExtend[10], HIGH);
    digitalWrite(solenoidRetract[10], LOW);
    Serial.println("Close ball gate"); // Prints text
}

void raiseBallElevator() {
    digitalWrite(solenoidExtend[12], HIGH);
    digitalWrite(solenoidRetract[12], LOW); 
    Serial.println("Raise Elevator"); // Prints text
}

void lowerBallElevator() {
    digitalWrite(solenoidExtend[12], LOW);
    digitalWrite(solenoidRetract[12], HIGH); 
    Serial.println("Lower Elevator"); // Prints text
}

How far apart are the Uno and the Mega?
How is the current arrangement working?
Are you seeing reliability issues?

For best reliability you can use soldered wire connections instead of jumper cables.
I would also suggest stronger external pulls of 2.2K - 4.7K instead of INPUT_PULLUP which is pretty weak.

If I remember correctly the UNO polls the trigger pin for the signal break, and if the state of that pin is mirrored on the Mega, than polling it there should be sufficient.

I would run the system and look for real issues to fix instead of trying to optimize for potential problems which may or may not be real.

@cattledog The Uno and Mega are right next to one another and i am using short jumper wires between the two. I show a picture of my control panel in the bowling manual attached in Post #1. Please excuse the loose boards in the panel. I struggled with getting wiring to the relays and knocked everything loose from the back panel. I am in the process of re-securing things to clean that all up.

Briefly, I am using the Arduino signals to power solenoid relays. The other side of the relays is being powered by a 25 amp power supply for the 12 volt signals (the 13 linear actuators peak out at 2 amps each but normally run in the 1/2 amp range). I also have a smaller, separate, 8 amp power supply for the many 5 volt signals needed. I had previously attached a bunch of game information in Post 1 including 2 wiring diagrams if you’d like to take a look.

I know enough to be very dangerous but @cattledog I don’t understand your comment above about the resisters in place of INPUT_PULLUP. I’m guessing you mean I may need to create a pcb with a bunch of resistors instead of using the Mega internal ones for the wires between the Arduinos.

It’ll be about a month before I can test the code and will report back under a new post should I run into any problems. I’ll leave this post open for a few more hours and then mark it solved to give anyone a last chance to comment. Thanks!

I don’t understand your comment above about the resisters in place of INPUT_PULLUP.

I maybe wrong. If all your connections between the Uno and the Mega are from an output pin written H or L and an input pin with INPUT_PULLUP or just INPUT you will not need external pull ups as you will have active signals between the two devices,

As you think about this project going forward, putting everything on the Mega and eliminating the Uno would be worth another look. Any time you can use one processor instead of two, eliminating the inter processor communication will make things more simple and reliable. (As well as cleaning up your cabinet enclosure. :wink:)

Note the author of ScoreMore states the trigger monitoring done by the Uno is very sensitive. As such I am inclined NOT to try to eliminate the Uno by transferring its functions to the Mega although I am open to a conversation about that once the string pinsetter is automated.

I see nothing in the Uno code that is special for the trigger pin reading and would prevent the integration to the Mega.

This post is to document that we have reached a perceived solution to these two issues:

  1. How the Mega can pick up the signal from Uno for the sensor that monitors the bowling ball rolling down the lane - Solution - I am working with the ScoreMore software developer to see if the Mega will digitalRead an output pin from the Uno that is currently assigned that task (or can be assigned that task in which case i will need help modifying the Uno sketch).
  2. Getting the Mega to digitalRead the output pins form the Uno to determine if bowling pins are still standing. Solution - it has been agreed the sketch presented in Post #10 is a good starting point now that it has been modified (errors corrected) during the course of this discussion. The sketch will be downloaded onto the bowling machine and any future issues will be opened in a new discussion.
  3. Thanks to all especially @cattledog