Sequencing and merging programs

Ok. I'm learning and making progress here but I still am struggling when it comes to merging codes together and getting them to operate in the right sequence. Here are the two codes I'm trying to merge.

#include <LiquidCrystal_I2C.h>  // LiquidCrystal I2C - Version: 1.1.2
#include <fastIO.h>  // fastIO - Version: Latest 
#include <Wire.h>
#include "DHT.h"
#define DHT11Pin 4
#define DHTType DHT11 //OLED

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

DHT HT(DHT11Pin,DHTType);
float humi;
float tempC;
float tempF;

#define SCREEN_WIDTH 128 // OLED display width, in pixels  
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
LiquidCrystal_I2C lcd(0x27,20,4); // double check your LCD address first using: i2C_scanner

int analogInPin1 = A0;  // Speed Trap beam Analog input Lane 1 A0 Pin
int analogOutPin1 = A1; // Finish line beam lane 1
int analogInPin2 = A3;  // Speed trap beam Analog input Lane 2 A3 Pin
int analogOutPin2 = A2; // Finish line beam lane 2

const int ledPin1 = 11; //lane 1 win LED 
const int ledPin2 = 12; //Lane 2 win LED 
int StartSwitch = 2;

int sensorValueStart1 = 0; 
int sensorValueFinish1 = 0; 
int sensorValueStart2 = 0; 
int sensorValueFinish2 = 0;
int StartState = 0;

int sensorThresh = 800; //adjustable trigger sensing threshold of the IR receivers. 1000 = unblocked(high)

unsigned long timeFirst1; //lane 1 speed trap beam
unsigned long timeSecond1; //lane 1 finish line 
unsigned long timeFirst2; //lane 2 speed trap beam
unsigned long timeSecond2; //lane 2 finish line 
float StartTime = 0;
float StartTime1 = 0;
float trapTime1 = 0;
float velocity1 = 0;
float trapTime2 = 0;
float velocity2 = 0;
float speedConst = 1800; // ((distance between the Speed Gate and Finish IR sensors in mm) x 3600)/1000)to convert mm/millis to km/h) 
                         // In this project we have 500mm between IR sensors on proto board >>> 500x3600/1000 = 1800
float ET1 = 0;
float ET2 = 0;



void setup() 
{

  Serial.begin(9600);
  
  pinMode(StartSwitch, INPUT);
  pinMode(11, OUTPUT); //lane 1
  pinMode(12, OUTPUT); //lane 2
  
  
  digitalWrite(11, HIGH);
  digitalWrite(12, HIGH);
  delay(1000);
  digitalWrite(11, LOW);
  digitalWrite(12, LOW);
    timeSecond1 = 0;
    timeFirst1= 0; 
    timeSecond2 = 0;
    timeFirst2= 0; 
    trapTime2 = 0;
    trapTime1 = 0;
    StartTime = 0;
    
      lcd.init();
      lcd.backlight();
      lcd.setCursor(2,0);
      lcd.print("Drag Strip Timer");    
      lcd.setCursor(3,1);
      lcd.print("by Ricky Kelso"); 
      lcd.setCursor(1,2);
      
      lcd.print("EET411L Sr Project"); 
      delay(2000);
      lcd.setCursor(1,3);
      lcd.print("Ready to race...v6"); 
      
    HT.begin();//For DHT11
    if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64  //For OLED I2C
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }
  
  display.display(); //Display logo
  display.clearDisplay();
  
   pinMode(5, OUTPUT);
   pinMode(6, OUTPUT);
   pinMode(7, OUTPUT);
   
  delay(3000);
  digitalWrite(5, HIGH);    // turn on LED2
  delay(1000);                 // wait for 1000ms
  digitalWrite(5, LOW);     // turn off LED1
  digitalWrite(6, HIGH);    // turn on LED2
  delay(1000);
  digitalWrite(6, LOW);     // turn off LED2
  digitalWrite(7, HIGH);    // turn on LED3 
  delay(1000);              // wait for 1000ms
  digitalWrite(7, LOW);
}

void loop()

{
  
  StartState = digitalRead(StartSwitch); //Check state of start gate. 0 = closed & 1 = open.
  if(StartState == 0)
  {
     StartTime = 0;
     ET1 = 0;
     ET2 = 0;
  }

      // NOTE: Race timer will reset itself when the startgate is closed, so don't close the gate when the race is still going!
  
  StartState = digitalRead(StartSwitch); //if start gate is trigger, race started. 1 = open.
  if(StartState == 1 && StartTime == 0)
  {
    StartTime = micros(); //use micro seconds since the races can be that close!
  }
  
  //read the analog in value of IR's:
  sensorValueStart1 = analogRead(analogInPin1); // Speed trap Lane 1
  sensorValueStart2 = analogRead(analogInPin2); // Finish line Lane 1
  sensorValueFinish1 = analogRead(analogOutPin1); // Speed trap Lane 2
  sensorValueFinish2 = analogRead(analogOutPin2); //Finish line Lane 2

   // wait for the speed trap start sensors to be triggered
  
   if(sensorValueStart1 < sensorThresh)
     {
      timeFirst1 = micros(); //Lane 1 speed trap start time (First IR Sensor)
     }

   if(sensorValueStart2 < sensorThresh)
     {
      timeFirst2 = micros(); //Lane 2 Speed trap start time (First IR Sensor)
     }

// wait/check for the Finish Line sensors to be triggered
  
  if(sensorValueFinish1 < sensorThresh && timeFirst1 > 0 && ET1 == 0)
  {
    timeSecond1 = micros();
    ET1 = timeSecond1 - StartTime;
    ET1 = ET1 / 1000000; //converting microseconds to milliseconds
  }

 if(sensorValueFinish2 < sensorThresh && timeFirst2 > 0 && ET2 == 0)
  {
    timeSecond2 = micros();
    ET2 = timeSecond2 - StartTime;
    ET2 = ET2 / 1000000; //converting microseconds to milliseconds
  }


if (ET1 < ET2 && ET1 != 0 && ET2 != 0)// Set winner Lane 1, turn on winner LED
   {
   digitalWrite(11, HIGH);
   }

 if(ET1 > ET2 && ET2 != 0 && ET1 != 0) // Set winner Lane 2, turn on winner LED
   {
   digitalWrite(12, HIGH);
   }

 if(ET1 > 0 && ET2 > 0) // Race is over, display times for both lanes.
  {
    trapTime1 = timeSecond1 - timeFirst1;
    trapTime2 = timeSecond2 - timeFirst2;
    trapTime1 = trapTime1 / 1000;
    velocity1 = speedConst / trapTime1;//get the Speed converted from mm/millis to km/h.
    velocity1 = velocity1 * 0.621371;  // use this line to convert KM/H to MP/H
    trapTime2 = trapTime2 / 1000;
    velocity2 = speedConst / trapTime2;//get the Speed converted from mm/millis to km/h.
    velocity2 = velocity2 * 0.621371;  // use this line to convert KM/H to MP/H
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Lane 1" );
    lcd.setCursor(0,1);
    lcd.print("ET:");
    lcd.setCursor(3,1);
    lcd.print(ET1, 4);
    lcd.setCursor(10,1);
    lcd.print("@ ");
    lcd.print(velocity1);
    lcd.setCursor(17,1);
    lcd.print("mph");  //km or mph 
    if (digitalRead(11) == HIGH)
       {
         lcd.setCursor(10,0);
         lcd.print("*WINNER*");
       }
    lcd.setCursor(0,2);
    lcd.print("Lane 2" );
    lcd.setCursor(0,3);
    lcd.print("ET:");
    lcd.setCursor(3,3);
    lcd.print(ET2, 4);
    lcd.setCursor(10,3);
    lcd.print("@ ");
    lcd.print(velocity2);
    lcd.setCursor(17,3);
    lcd.print("mph");  //km or mph 
      if (digitalRead(12) == HIGH)
       {
         lcd.setCursor(10,2);
         lcd.print("*WINNER*");
       }
    delay(10000);
    digitalWrite(11, LOW); //turn off lane winner LED
    digitalWrite(12, LOW); //turn off lane winner LED
    timeSecond1 = 0;
    timeFirst1= 0; 
    timeSecond2 = 0;
    timeFirst2= 0; 
    trapTime2 = 0;
    trapTime1 = 0;
    velocity1 = 0;
    velocity2 = 0;
    StartTime = 0;
    ET1 = 0;
    ET2 = 0;
  }
  
 humi = HT.readHumidity();
 tempC = HT.readTemperature();
 tempF = HT.readTemperature(true);

 display.clearDisplay();
 oledDisplayHeader();
 
 oledDisplay(3,5,28,humi,"%");
 oledDisplay(3,60,28,tempF,"F");
 
 display.display(); 
 
}
void oledDisplayHeader(){
 display.setTextSize(2);
 display.setTextColor(WHITE);
 display.setCursor(0, 0);
 display.print(" Hum  ");
 display.setCursor(60, 0);
 display.print(" Temp");
}
void oledDisplay(int size, int x,int y, float value, String unit){
 int charLen=12;
 int xo=x+charLen*3.2;
 int xunit=x+charLen*3.6;
 int xval = x; 
 display.setTextSize(size);
 display.setTextColor(WHITE);
 
 if (unit=="%"){
   display.setCursor(x, y);
   display.print(value,0); //decimal places for humidity
   display.print(unit);
 } else {
   if (value>99){
    xval=x;
   } else {
    xval=x+charLen;
   }
   display.setCursor(xval, y);
   display.print(value,0);
   display.drawCircle(xo, y+2, 2, WHITE);  // print degree symbols (  )
   display.setCursor(xunit, y);
   display.print(unit);
 }
 
}

This is the second code-

void setup() {

  Serial.begin(9600);
  pinMode(9, OUTPUT); //Lane 1 prestage. 
  pinMode(A6, INPUT); //Lane 1.
  pinMode(8, OUTPUT); //Lane 2 prestage
  pinMode(A7, INPUT); // Lane 2 
}
void loop()
{
  digitalWrite(9, analogRead(A6) <= 300);// LED on, if analog input <= 300
 digitalWrite(8, analogRead(A7) <= 300);
}


These 2 leds need to come on before the countdown starts here

 pinMode(5, OUTPUT);
   pinMode(6, OUTPUT);
   pinMode(7, OUTPUT);
   
  delay(3000);
  digitalWrite(5, HIGH);    // turn on LED2
  delay(1000);                 // wait for 1000ms
  digitalWrite(5, LOW);     // turn off LED1
  digitalWrite(6, HIGH);    // turn on LED2
  delay(1000);
  digitalWrite(6, LOW);     // turn off LED2
  digitalWrite(7, HIGH);    // turn on LED3 
  delay(1000);              // wait for 1000ms
  digitalWrite(7, LOW);

After this the button is depressed, the cars roll off and then the two leads should go out. I've tried every placement of the second code I can think of and I can't get it to work. Is the delay (xx) throwing me off or what?

Without analyzing your code, you would benefit a lot by making the loop() function a lot smaller. Break it into functions. For example, instead of

  if (StartState == 0)
  {
    StartTime = 0;
    ET1 = 0;
    ET2 = 0;
  }

Move your code into a function named doStart().

  void doStart()
  {
    StartTime = 0;
    ET1 = 0;
    ET2 = 0;
  }

Then in your loop,

  if (StartState == 0)
  {
    doStart();
  }

This will make the flow of the sketch easier to follow.

Note also, when you are in a delay(), NOTHING else happens. Especially reading the state of switches.

Thanks. That will help clean up my code a lot. How can I get rid of the delay() though? Wouldn't the program start right up where it left off after the delay, though?

Yes, but if you were expecting to handle a button, for example, the button won't be read during the delay.

gotcha. So if my code said,

xxx
delay(1000)
push button
The time delay needs to be there but what would replace it so if the button was depressed a tad early, it would still function?

If you push the button and release it while the code is stuck in the delay(), it's as if you never pushed it at all.

That's what millis is for. Look at the example sketch "blinkWithoutDelay" for an example of how to use it.

blink-nodelay

Thanks SteveMann,
How would I integrate this v VB ode into my countdown? There would be 3 lights total

Since I am not sure what you are trying to do, I won't write your code for you.
Look at the BlinkWithoutDelay sketch to learn how to do timing without using the delay() function. Then build from there.

After you have written some code, if you run into problems then come back to the forum and start a new thread with your specific question.

I understand and that’s where I’m stuck. How do I write the blink code for 3 LEDs in sequence? Do I repeat them and name them as light 1,2, and 3?

This post describes a state machine which will do what you want - with some modifications, mainly adding states to account for all the LEDs.

If you choose to explore this I suggest you start at the opening post since the state machine is the culmination of a progression of small steps.

Good luck!

Thanks…

consider following support racing down 2 lanes

const byte pinStart = A1;
const byte pinGate1 = A2;
const byte pinGate2 = A3;

const byte pinLeds [] = { 13, 12, 11, 10 };
enum { Off = HIGH, On = LOW };

const byte pinInps [] = { pinGate1, pinGate2, pinStart };
byte stateInps [sizeof(pinInps)];

enum { InpGate1, InpGate2, InpStart };  // indices of input pins

#define N_GATES 2
unsigned long time [N_GATES];
unsigned long timeStart;
unsigned long msec;

int  cntGates;

enum { ST_START, ST_RACE, ST_FINISH };
int state = ST_START;

char s0 [40];
char s1 [40];

// -----------------------------------------------------------------------------
bool
chkInp (
    byte idx )
{
    byte inp = digitalRead (pinInps [idx]);
    if (stateInps [idx] != inp)  {
        stateInps [idx] = inp;

        if (LOW == inp)
            return true;
    }

    return false;
}

// -----------------------------------------------------------------------------
void disp (
    char *s0,
    char *s1)
{
    if (NULL != s0)
        Serial.println (s0);
    if (NULL != s1)
        Serial.println (s1);
    Serial.println ();
}

// -----------------------------------------------------------------------------
void loop ()
{
    msec = millis ();

    switch (state)  {
    case ST_START:
        if (chkInp (InpStart))  {
            for (unsigned n = 0; n < sizeof(pinLeds); n++)  {
                delay (1000);
                digitalWrite (pinLeds [n], On);
            }

            state     = ST_RACE;
            timeStart = millis ();
            disp ((char*)"Race", (char*)"");
        }
        break;

    case ST_RACE:
        for (unsigned n = 0; n < N_GATES; n++)  {
            if (chkInp (n))  {
                time [n] = msec - timeStart;
                cntGates++;
            }
        }

        if (N_GATES <= cntGates)
            state = ST_FINISH;
        break;

    case ST_FINISH:
        for (unsigned n = 0; n < sizeof(pinLeds); n++)
            digitalWrite (pinLeds [n], Off);
        cntGates = 0;

        sprintf (s0, "Winner Lane %d", time [0] < time [1] ? 1 : 2);
        sprintf (s1, " %2ld.%03ld %2ld.%03ld sec",
                    time [0] / 1000, time [0] % 1000,
                    time [1] / 1000, time [1] % 1000 );
        disp (s0, s1);
        state = ST_START;
        break;

    }
}

// -----------------------------------------------------------------------------
void setup ()
{
    Serial.begin (9600);

    for (unsigned n = 0; n < sizeof(pinLeds); n++)  {
        digitalWrite (pinLeds [n], Off);
        pinMode      (pinLeds [n], OUTPUT);
    }

    for (unsigned n = 0; n < sizeof(pinInps); n++)  {
        pinMode (pinInps [n], INPUT_PULLUP);
        stateInps [n] = digitalRead (pinInps [n]);
    }

    disp ((char*)"Press to Start", (char*)"");
}

1 Like