Help! Diecast Drag Racing Christmas Tree with False Start

Hello from South-Africa Arduino World.
Any assistance would be greatly appreciated. Apologies for the horrible coding attempt and the spiderman wiring diagram.
I built a few old school electronics circuits with 555 timers etc, so I'm ok on the hardware side (ps. I did not add in the LED's resistors etc (that I'll do with the hardware side) first I need coding to at least then start that.
What I have so far after weeks of trying different coding and loops. I'm so stuck.

What I need:
Funcionality needed.
As per my very badly coded and built circuit.
This part sequence is working fine.

This simulates a Car Drag Racing Christmas Tree with False Start. Two Lanes - Each with their set of
3 x Yellow LED's (Get ready, 3, 2, 1 Countdown)
1 x Green LED (GO !!! Race started)
1 x Red LED (If Pedal is pressed before Green is lit (Using Photointerrupter sensor) This is a False Start and the Red LED in that lane should light up.

  1. Switch on Arduino.
  2. When button is pressed a countdown with yellow LED's start.
  3. In sequency they will light up. 1, 2, 3....
  4. Green will then light up (this is for cars to pull away)
  5. With this Arduino I will use photointerrupters built into each Racer's Foot Pedal.
    6 = If a racer pulls away before Green is lit then he is disqualified - False start and the RED LED is lit.

Reset on Arduino board can be used to reset the system or code so that system resets in one minute to start another race.

This is my code so far. The LED's start countdown when the button is pressed. That all works great. I just don't know how to tell arduino to light up the Red for a false start if Photointerrupters give signal that foot pedal was pressed before Green LED is lit.

// constants won't change. They're used here to
// set pin numbers:
const int buttonPin = 2;     // the number of the pushbutton pin
// variables will change:
int buttonState = 0;         // variable for reading the pushbutton status

void setup() {
  // initialize the LED pin as an output:
pinMode(13, OUTPUT);
pinMode(12, OUTPUT);
pinMode(11, OUTPUT);
pinMode(10, OUTPUT);
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);
}

void loop() {
  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);

  // check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
  if (buttonState == HIGH) {
    // turn LED on:
    digitalWrite(13, HIGH);
    delay(1000);
    digitalWrite(12, HIGH);
    delay(1000);
    digitalWrite(11, HIGH);
    delay(1000);
    digitalWrite(10,HIGH);
  }
}

Each LED must have its own current limiting resistor. Limit the current from any output to no more than 20mA. No more than 100mA per port and no more than 200mA, total, for the processor.

The use of the delay() function makes for blocking code that cannot be responsive. Use millis() timing.

Non-blocking timing tutorials:
Blink without delay().
Beginner's guide to millis().
Several things at a time.

Where are the photo interrupters in the code and fritzy diagram (not a schematic).

Here is an example using millis() for timing. Note that my switches are wired to ground and use the internal pullup resistors as is common practice. Also I use the state change detection method to sense the start switch. You can see the state change detection method explained and the switch wiring in my state change detection for active low inputs tutorial. Also I replaced the Pedal Photointerrupter sensors with push button switches for development. This code uses the state machine approach. Another state machine tutorial.

The yellow lights are simultaneous for each lane so I represent them with one set of 3. There are green and red LEDs for each lane. A false start while any yellow is lit results in a red light for that lane. The first pedal button after the last yellow goes out will light that lanes green and lock the other out. The green lights come on right after the last yellow goes out. Restart by pressing the start button (no need to reset the processor).

const byte y1ledPin = 4;
const byte y2ledPin = 5;
const byte y3ledPin = 6;
const byte gLeftLedPin = 7;
const byte rLeftLedPin = 8;
const byte gRightLedPin = 9;
const byte rRightLedPin = 10;

const byte lPedalButtonPin = 11;
const byte rPedalButtonPin = 12;

const byte startButtonPin = A0;

unsigned long yellowInterval = 1000;

void setup()
{
   Serial.begin(115200);
   Serial.println("christmas tree starting");
   pinMode(y1ledPin, OUTPUT);
   pinMode(y2ledPin, OUTPUT);
   pinMode(y3ledPin, OUTPUT);
   pinMode(gLeftLedPin, OUTPUT);
   pinMode(rLeftLedPin, OUTPUT);
   pinMode(gRightLedPin, OUTPUT);
   pinMode(rRightLedPin, OUTPUT);

   pinMode(lPedalButtonPin, INPUT_PULLUP);
   pinMode(rPedalButtonPin, INPUT_PULLUP);
   pinMode(startButtonPin, INPUT_PULLUP);
}

void loop()
{
   static byte mode = 0;
   static unsigned long timer = 0;
   static bool lastStartButtonState = HIGH;
   if (mode == 0)
   {
      bool startButtonState = digitalRead(startButtonPin);
      if (startButtonState != lastStartButtonState)
      {
         if (startButtonState == LOW)
         {            
            digitalWrite(rRightLedPin, LOW);
            digitalWrite(rLeftLedPin, LOW);
            digitalWrite(gLeftLedPin, LOW);
            digitalWrite(gRightLedPin, LOW);
            timer = millis();
            mode = 1;
         }
      }
   }
   // yellow light #1
   if (mode == 1)
   {
      digitalWrite(y1ledPin, HIGH);
      if (millis() - timer >= yellowInterval)
      {
         digitalWrite(y1ledPin, LOW);
         timer = millis();
         mode = 2;
      }
      // left red light
      if (digitalRead(lPedalButtonPin) == LOW)
      {
         digitalWrite(y1ledPin, LOW);
         digitalWrite(rLeftLedPin, HIGH);
         mode = 0;
      }

      if (digitalRead(rPedalButtonPin) == LOW)
      {
         digitalWrite(y1ledPin, LOW);
         digitalWrite(rRightLedPin, HIGH);
         mode = 0;
      }
   }
   
   // yellow light #2
   if (mode == 2)
   {
      digitalWrite(y2ledPin, HIGH);
      if (millis() - timer >= yellowInterval)
      {
         digitalWrite(y2ledPin, LOW);
         timer = millis();
         mode = 3;
      }
      // left red light
      if (digitalRead(lPedalButtonPin) == LOW)
      {
         digitalWrite(y2ledPin, LOW);
         digitalWrite(rLeftLedPin, HIGH);
         mode = 0;
      }

      if (digitalRead(rPedalButtonPin) == LOW)
      {
         digitalWrite(y2ledPin, LOW);
         digitalWrite(rRightLedPin, HIGH);
         mode = 0;
      }
   }

    // yellow light #3
   if (mode == 3)
   {
      digitalWrite(y3ledPin, HIGH);
      if (millis() - timer >= yellowInterval)
      {
         digitalWrite(y3ledPin, LOW);
         timer = millis();
         mode = 4;
      }
      // left red light
      if (digitalRead(lPedalButtonPin) == LOW)
      {
         digitalWrite(y3ledPin, LOW);
         digitalWrite(rLeftLedPin, HIGH);
         mode = 0;
      }

      if (digitalRead(rPedalButtonPin) == LOW)
      {
         digitalWrite(y3ledPin, LOW);
         digitalWrite(rRightLedPin, HIGH);
         mode = 0;
      }
   }
   // green lights
   if (mode == 4)
   {
      //if(digitalRead(lPedalButtonPin) == LOW)
      //{
         digitalWrite(gLeftLedPin, HIGH);
         mode = 0;
      //}
      //if(digitalRead(rPedalButtonPin) == LOW)
      //{
         digitalWrite(gRightLedPin, HIGH);
         mode = 0;
      //}
   }
}

Use what you can. Hopefully this helps.

Hello groundFungus
So I've been busy with this project for months now, the hardware, the electronics sourcing and then .... the CODE.

Honestly it was a long shot when I posted this topic. I was expecting a reply maybe in a few weeks and then with suggestions that will only send me further down the rabbit hole. I was definitely not expecting an answer within a hour or so.

This is exactly what I need.

Thank you for also describing the process and functions. This is way more intricate than I could have conceived. It is elegant and covers so many variables.
When I started researching drag race setups I learned that there's staging and deep staging and the timing sequences etc.

I am building a diecast dual lane racing track for community center and then I'll use it among family and friends. I am simulating the quarter mile in scale, so it's not the usual diecast racing down a 45 degree angle track. My track is 1:64 (6.2 meters long and a leisurely angle of around 7 degrees of straight track (not a bow) so there's constant acceleration It's only raised 30 cm in starting end.

Thank you again for this. I've been trying to do this months now. The closest I got was to let the red shine on false start...problem was it was only on last yellow and then green and when it goes in a loop the red comes on even if it was good start.
I digress...thank you
I've tested this angle against real races on youtube and it's very similar.

Do a forum search. Drag trees have been discussed here before.

There is some repetitive code (checkng the pedal buttons, for instance) that should be in functions. I left it because it seemed simpler.

I built a full size tree for junior drags years ago. Well before Arduino. I used truck marker lights on the tree and lasers pointers and photo trasistors for the staging beams. A 8051 processor programmed in MCS-51 assembly. I am going to use the code that I wrote for you to make a reaction time game. Might be fun.

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