Aurdino 2 lane drag tree

I have successfully built a one lane drag tree with sensors and timing and lcd, I am no pro by any means but I really could use some help hopefully I post the current code correctly. I am trying to configure a 2nd lane and for the life of me I can not figure it out

#include <LiquidCrystal.h>

#define FEET_PER_MILE 5280
#define TRACK_LEN 66
#define RESET_BTN 47
const byte RS = 52;
const byte EN = 49;
const byte D4 = 53;
const byte D5 = 50;
const byte D6 = 51;
const byte D7 = 48;
const byte BAUD_RATE = 9600;
const byte LED_Prestage = 8;
const byte LED_Stage = 7;
const byte LED_Y1 = 6;
const byte LED_Y2 = 5;
const byte LED_Y3 = 4;
const byte LED_Start = 3;
const byte LED_RED_Light = 2;
const byte Pre_Stage_Sensor = A0;
const byte Stage_Sensor = A1;
const byte Finish_Sensor = A2;
const byte Start_Button = 46;
//how long is the countdown
const int  CountDownFin = 2000;

//define missing slash char for Flip ani..
uint8_t slash[8] = {
  0b10000,
  0b10000,
  0b01000,
  0b00100,
  0b00100,
  0b00010,
  0b00001,
  0b00001,
};

byte flip = 0;
unsigned long AniMilli = 0;
int IntervalAni = 50;

int state = 0;
bool StartFlag = false;
unsigned long countdownStart;
unsigned long raceStart;
unsigned long reactionTime;
unsigned long vehicleStart;
bool FinishFlag;
unsigned long FinishET;
//float ReactSec;


int Pre_Stage_Sensor_Value;
int Stage_Sensor_Value;
int Finish_Sensor_Value;

bool Staged = false;



LiquidCrystal lcd(RS, EN, D4, D5, D6, D7);

void setup() {
  pinMode(LED_Prestage, OUTPUT);
  pinMode(LED_Stage, OUTPUT);
  pinMode(LED_Y1, OUTPUT);
  pinMode(LED_Y2, OUTPUT);
  pinMode(LED_Y3, OUTPUT);
  pinMode(LED_Start, OUTPUT);
  pinMode(LED_RED_Light, OUTPUT);

  pinMode(Pre_Stage_Sensor, INPUT);
  pinMode(Stage_Sensor, INPUT);
  pinMode(Finish_Sensor, INPUT);
  pinMode(Start_Button, INPUT_PULLUP);
  pinMode(RESET_BTN, INPUT_PULLUP);
  //Serial.begin(BAUD_RATE);
  Serial.begin(115200);
  lcd.begin(16, 2);
  lcd.createChar(1, slash);
  lcd.setCursor(0, 1);
  lcd.print(F("System Ready"));
  delay(2000);
  lcd.clear();
}

void loop()
{

  //read in our sensors start of every loop..
  //don't need anymore analogRead anywhere else but here..

  Pre_Stage_Sensor_Value = analogRead(Pre_Stage_Sensor);
  Stage_Sensor_Value = analogRead(Stage_Sensor);
  Finish_Sensor_Value = analogRead (Finish_Sensor);
  /*
    Serial.print("PreStage: ");
    Serial.println(Pre_Stage_Sensor_Value);
    Serial.print("Stage: ");
    Serial.println(Stage_Sensor_Value);
    Serial.print("Finish: ");
    Serial.println(Finish_Sensor_Value);
    Serial.print("State: ");
    Serial.println(state);
    Serial.println();
    delay(2000);
  */
  //enter the state machine..
  switch (state) {
    case 0: //prestasge state..
      if (Pre_Stage_Sensor_Value > 500) {
        digitalWrite(LED_Prestage, LOW);
      }
      else {
        digitalWrite(LED_Prestage, HIGH);
        state++;
      }
      break;

    case 1: // Vehicle Staging State
      if (Stage_Sensor_Value > 500) {
        digitalWrite(LED_Stage, LOW);
      }
      else {
        digitalWrite(LED_Stage, HIGH);

      }

      if (Stage_Sensor_Value < 500) {
        lcd.clear();
        lcd.print("Vehicle Ready");
        state++;
      }
      else {
        if (!Staged) {
          lcd.clear();
          lcd.print("Please Stage");
          Staged = true;
          state--;
        }
      }

      break;

    case 2: //check stage sensor and roll state back
      if (Stage_Sensor_Value > 501) {
        state--;
        Staged = false;
      }
      else
      { //staged good .. check start button
        if (digitalRead(Start_Button) == LOW)
        {
          countdownStart = millis();
          state++;
        }
      }
      break;

    case 3: //state 3 counts down leds and checks for early start..
      //check for early start first..
      if (!CheckEarlyStart()) {
        //not an early start, countdown
        if (millis() - countdownStart > 2000) //countdown done
        { //check sensor just before dropping the flag
          digitalWrite(LED_Y3, LOW);
          digitalWrite(LED_Start, HIGH);
          StartFlag = true;
          raceStart = millis();//start counting race from here..
          state++;
        }
        else if (millis() - countdownStart > 1500)
        {
          digitalWrite(LED_Y2, LOW);
          digitalWrite(LED_Y3, HIGH);
        }
        else if (millis() - countdownStart > 1000)
        {
          digitalWrite(LED_Y1, LOW);
          digitalWrite(LED_Y2, HIGH);
        }
        else if (millis() - countdownStart > 500)
        {
          digitalWrite(LED_Y1, HIGH);
        }

      }
      break;

    case 4: //stage to get reaction time
      //need to see car move before next state..
      if (Stage_Sensor_Value > 500 && StartFlag)
      {
        vehicleStart = millis();
        reactionTime = millis();
        state++;
      }

      break;

    case 5:
      //prints go and reaction time..
      {
        float ReactSecs = float(reactionTime - raceStart) / 1000;
        lcd.clear();
        lcd.print("   GO  ");
        lcd.setCursor(0, 1);
        lcd.print("RT:"); lcd.print(ReactSecs, 2);
        Serial.print("RT:"); Serial.println(ReactSecs, 2);
        state = 6;
      }
      break;

    case 6:
      if (Finish_Sensor_Value < 500)
      { if (!FinishFlag)
        { FinishFlag = true;
          FinishET = millis() - vehicleStart;
          lcd.clear();
          lcd.print("ET:");
          float secs = float(FinishET) / 1000;
          lcd.print(secs);
          lcd.setCursor(8, 0);
          float ReactSecs = float(reactionTime - raceStart) / 1000;
          lcd.print("RT:"); lcd.print(ReactSecs, 2);
          lcd.setCursor(0, 1);
          lcd.print("MPH:");
          float fps = (TRACK_LEN / secs);
          Serial.print("ET:"); Serial.println(secs, 2);
          float mph = (fps / FEET_PER_MILE) / 0.00028;
          Serial.print("MPH:"); Serial.println(mph, 2);
          lcd.print(mph, 2);
          state = 7;
        } else FlipAni();
      } else FlipAni();

      break;


    case 7:
      if (digitalRead(RESET_BTN) == LOW)
      {
        digitalWrite(LED_Start, LOW);
        digitalWrite(LED_Stage, LOW);
        digitalWrite(LED_RED_Light, LOW);
        StartFlag = false;
        FinishFlag = false;
        Staged = false;
        state = 0;
      }
      break;


  }
}// END LOOP BRACKETS

bool CheckEarlyStart()
{
  bool early = false;
  if (Stage_Sensor_Value > 501) {
    reactionTime = CountDownFin - (millis() - countdownStart);
    digitalWrite(LED_Y3, LOW);
    digitalWrite(LED_Prestage, LOW);
    digitalWrite(LED_Stage, LOW);
    digitalWrite(LED_RED_Light, HIGH);
    float ReactSecs = (float(reactionTime) / 1000) * -1;
    lcd.clear();
    lcd.print("!!Bad Start!!");
    lcd.setCursor(0, 1);
    lcd.print("RT:"); lcd.print(ReactSecs, 2);
    Serial.print("RT:"); Serial.println(ReactSecs, 2);
    state = 7;//bad start .. wait for reset..
    early = true;
  }
  return early;
}



void FlipAni() {
  if (millis() - AniMilli >= IntervalAni)
  {
    AniMilli = millis();
    switch (flip) {
      case 0: flip = 1; lcd.setCursor(0, 0); lcd.print("|"); lcd.setCursor(15, 0); lcd.print("|"); break;
      case 1: flip = 2; lcd.setCursor(0, 0); lcd.print("/"); lcd.setCursor(15, 0); lcd.print("/"); break;
      case 2: flip = 3; lcd.setCursor(0, 0); lcd.print("-"); lcd.setCursor(15, 0); lcd.print("-"); break;
      case 3: flip = 4; lcd.setCursor(0, 0); lcd.print("\x01"); lcd.setCursor(15, 0); lcd.print("\x01"); break;
      case 4: flip = 0; lcd.setCursor(0, 0); lcd.print("|"); lcd.setCursor(15, 0); lcd.print("|"); break;
    }
  }
}

Do both lanes have the same timing, or does one lane have a handicap?

3 Likes

Same timing

How do you start and stop the timers?

1 Like

Laser sensor modules. So far everything works great I just need it 2 lanes instead of one and as I started to add the second lane I was burried in errors. I have the yellow and green lights going in sequence just fine but as for getting the lcd and timers to repeat a second lane im beyond lost

Are you wanting to add a set of LEDs and two more potentiometers?

  • In this simulation I left the yellow and green wired and programmed together.
  • I separated Pre-stage, Stage and Foul for Left and Right, but not programmed.
  • I have two sets of potentiometers in, but not programmed.
1 Like

there would be a total of 4x white, 3x yellow, 2x green, and 2 red per lane. I am using laser and receiver for pre-stage, stage, and finish per lane so 6 complete, yellow and green are tied together. I just need to figure coding out for adding the 3 sensors to work as lane 1 so I can keep my MPH and lane timefound this and literally same thing different lane timing sequence

Okay... I think our simulations look the same. I saw a few things to address before adding lane 2

  1. There is no "Please Pre-stage" so I added it to right lane.
    The rest of these work in your code... I do not have a "return" on my stage dial.
  2. No reaction to a finish (pressing the Finish button).
  3. Determine "finish" (variable state case 6)
  4. Reset
  5. Readings only show when "Stage" is dialed below 500.

I added the LEDs in my sim... look at code for recognizing the first and second lane (not just one lane)

1 Like

see now your simulation looks just like mine it is only seeing one lane and not the other. only one lane stage lights light up when staging. I am about to the point of running a separate board for the other lane. I hate to do that as I am not sure how or even if possible to tie them together

Yes... I feel you want a solution faster than I can create it. I think your idea of creating a duplicate will be better than my re-working the original.

I'm in no rush at all. Sorry if I gave you that impression, more or less happy I have made it this far at all and the fact we are about even on progress for that matter. I am working on this as well so we shall see what comes up.

I think your sketch works great as a single lane. I still need to figure out a way to "auto return" my Pre-stage and Stage simulation sensors in order to trigger the results page on the LCD... However; it is hard-coded for one lane. I started to do a "lane1" and "lane2" re-write, but soon realized (today) that method would create a sketch twice as long with duplicate-everything... Now I see that it would do better with an array of lanes "lane[x]" to keep track of all the starts, stops, reactions, staging, fouls, et c... so I will start again with your original and use the "array of lane[]" method. I know you said you tried before, but maybe if you also give this method a try, it will be a better outcome? Anyway... I will check in later this day.

In general - Arrays and structs are your friends.
Don't duplicate code in your sketch. Write code once - use it multiple times.

1 Like

I so greatly appreciate it! I am still new and not familiar with "arrays/structs" as well as I would like. This is a big learning curve and I am scratching the surface! Appreciate your efforts regardless.

I am still in the process of learning them well enough to use here

That is okay. You will understand in time and use.

Here is a YouTube channel that I like showing how to use Arrays (they made very good introductions to programming).

1 Like

Thank you so much for your help!! Hopefully I can get this running

why did this seem so easy in my head

You will find that it will only be a matter of identifying Left or Right lane. Your original sketch works just fine. In your head, you saw correctly... every variable (Prestage, Stage, Start, Time, Reaction, MPH, et c.) will have a second "lane" (laneRight[0][0] and laneLeft[1][0] will be the same piece of information, but from each lane. Give that "array" video a look... and the same YouTube channel has another "array" video. I will get to it later today. It will make better sense the more you know... so keep studying the Array, until then.

1 Like

I am deep into the rabbit hole now. A lot to look at considering indexes and real easy to get lost but I am sure like anything else it has a benefit worthwhile. Thanks again!!!