Two different Blink intervals.....

Hi.

Working on a 2 lane timer. Got most of it done so far.

Question, I have 2 led blinking when the two timers are running. Just for fun and to learn, I set them at different intervals: Lane1 at 500ms and Lane2 at 200ms.

If I start Lane2 it blinks at 200ms but when I start Lane1 it blinks the same as Lane1, 500ms.
Seem like Lane1 overides Lane2 blinking.

Can’t figure it out.

#include <LiquidCrystal.h>   //Seriel LCD Here
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define ledtimingPin  10
#define ledreadyPin  11
#define ledrunoverPin  12
#define startPin 6
#define stopPin 8
#define resetPin 7

// LANE2----------------------------------------------
#define ledtimingPin2 5 
#define ledreadyPin2  13 
#define ledrunoverPin2  9
#define startPin2 2
#define stopPin2 3


LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address 

int value = LOW;                    // previous value of the LED
int buttonState1;                   // variable to store button state 1
int buttonState2;                   // variable to store button state 2
int lastButtonState1;               // variable to store last button state 1
int lastButtonState2;               // variable to store last button state 2
int stateReset;                     // variable to store reset button state
int blinking;                       // condition for blinking - timer is timing
long interval = 500;                // blink interval - change to suit
long previousMillis = 0;            // variable to store last time LED was updated
long startTime ;                    // start time for stop watch
long elapsedTime ;                  // elapsed time for stop watch
int fractional;                     // variable used to store fractional part of time

//LANE 2
int value2 = LOW;                    // previous value of the LED
int buttonState3;                   // variable to store button state 2
int buttonState4;                   // variable to store button state 3
int lastButtonState3;               // variable to store last button state 3
int lastButtonState4;               // variable to store last button state 4
int blinking2;                       // condition for blinking - timer is timing
long interval2 = 200;                // blink interval - change to suit
long previousMillis2 = 0;            // variable to store last time LED was updated
long startTime2 ;                    // start time for stop watch
long elapsedTime2 ;                  // elapsed time for stop watch
int fractional2;                     // variable used to store fractional part of time


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

  pinMode(ledtimingPin, OUTPUT);       // sets the digital pin as output
  pinMode(ledreadyPin, OUTPUT);        // sets the digital pin as output
  pinMode(ledrunoverPin, OUTPUT);      // sets the digital pin as output
  pinMode(startPin, INPUT);            // not really necessary, pins default to INPUT anyway
  pinMode(stopPin, INPUT);             // not really necessary, pins default to INPUT anyway
  pinMode(resetPin, INPUT);            // not really necessary, pins default to INPUT anyway
  digitalWrite(startPin, HIGH);        // turn on pullup resistors. Wire button so that press shorts pin to ground.
  digitalWrite(stopPin, HIGH);         // turn on pullup resistors. Wire button so that press shorts pin to ground.
  digitalWrite(resetPin, HIGH);

  //LANE2
  pinMode(ledtimingPin2, OUTPUT);       // sets the digital pin as output
  pinMode(ledreadyPin2, OUTPUT);        // sets the digital pin as output
  pinMode(ledrunoverPin2, OUTPUT);      // sets the digital pin as output
  pinMode(startPin2, INPUT);            // not really necessary, pins default to INPUT anyway
  pinMode(stopPin2, INPUT);             // not really necessary, pins default to INPUT anyway
  digitalWrite(startPin2, HIGH);        // turn on pullup resistors. Wire button so that press shorts pin to ground.
  digitalWrite(stopPin2, HIGH);         // turn on pullup resistors. Wire button so that press shorts pin to ground.

  lcd.begin(16, 2);                      // set up the LCD's number of columns and rows:
  lcd.print("  Slalom Timer");         // Print a message to the LCD
  lcd.setCursor(0, 1);
  lcd.print("  Timer ready!");

  digitalWrite(ledreadyPin, HIGH);
  digitalWrite(ledrunoverPin, LOW);

  //---LANE2-
  digitalWrite(ledreadyPin2, HIGH);
  digitalWrite(ledrunoverPin2, LOW);
}


void loop()
{
  buttonState1 = digitalRead(startPin);                  // read the start button state and store
  buttonState2 = digitalRead(stopPin);                   // read the stop button state and store
  stateReset = digitalRead(resetPin);                    // read the reset button state and store

  if (buttonState1 == LOW && lastButtonState1 == HIGH)   // check for a high to low transition
  {
    if(!blinking)                                           // if true then found a new button press while clock is not running - start the clock 
      startTime = millis();                                   // store the start time
    blinking = true;                                        // turn on blinking while timing
    delay(5);                                               // short delay to debounce switch
    lastButtonState1 = buttonState1;                        // store buttonState1 in lastButtonState1, to compare next time

    //lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("L1 Running....");
    digitalWrite(ledreadyPin, LOW);

  }

rest of code

else if (buttonState2 == LOW && lastButtonState2 == HIGH)// check for a high to low transition
  {
    if(blinking)                                           // if true then found a new button press while clock is running - stop the clock and report
      elapsedTime =   millis() - startTime;                  // store elapsed time
    blinking = false;                                      // turn off blinking, all done timing
    lastButtonState2 = buttonState2;                       // store buttonState2 in lastButtonState2, to compare next time

    // routine to report elapsed time
    Serial.print( (int)(elapsedTime / 1000L));             // divide by 1000 to convert to seconds - then cast to an int to print
    Serial.print(".");                                     // print decimal point

      fractional = (int)(elapsedTime % 1000L);              // use modulo operator to get fractional part of time

    if (fractional == 0)                                  // pad in leading zeros - wouldn't it be nice if
      Serial.print("000");                                // add three zero's
    else if (fractional < 10)                             // if fractional < 10 the 0 is ignored giving a wrong time, so add the zeros
      Serial.print("00");                                 // add two zeros
    else if (fractional < 100)
      Serial.print("0");                                  // add one zero
    Serial.println(fractional);                            // print fractional part of time

    //LCD L1
    lcd.setCursor(0, 0);  
    lcd.print("L1:  ");
    lcd.setCursor(5, 0);
    lcd.print((int)(elapsedTime / 1000));
    lcd.print(":");
    lcd.print(fractional);
    lcd.print(" ms");

    digitalWrite(ledrunoverPin, HIGH);
  }
  else
  {
    lastButtonState1 = buttonState1;                         // store buttonState in lastButtonState, to compare next time
    lastButtonState2 = buttonState2;                         // store buttonState in lastButtonState, to compare next time
  }

  // blink routine - blink the LED while timing

  if ( (millis() - previousMillis > interval) ) 
  {
    if (blinking == true)
    {
      previousMillis = millis();                         // remember the last time we blinked the LED

      // if the LED is off turn it on and vice-versa.
      if (value == LOW)
        value = HIGH;
      else
        value = LOW;
      digitalWrite(ledtimingPin, value);
    }
    else
    {
      digitalWrite(ledtimingPin, LOW);                         // turn off LED when not blinking
    }

    //LANE2

    // check for button press
    buttonState3 = digitalRead(startPin2);                  // read the start button state and store
    buttonState4 = digitalRead(stopPin2);                   // read the stop button state and store


    if (buttonState3 == LOW && lastButtonState3 == HIGH)   // check for a high to low transition
    {
      if(!blinking2) 
        // if true then found a new button press while clock is not running - start the clock

      startTime2 = millis();                                   // store the start time
      blinking2 = true;                                        // turn on blinking while timing
      delay(5);                                               // short delay to debounce switch
      lastButtonState3 = buttonState3;                        // store buttonState1 in lastButtonState1, to compare next time

      //lcd.clear(); 
      lcd.setCursor(0, 1);
      lcd.print("L2 Running....");
      digitalWrite(ledreadyPin2, LOW);

    }

    else if (buttonState4 == LOW && lastButtonState4 == HIGH)// check for a high to low transition
    {
      if(blinking2)      
        // if true then found a new button press while clock is running - stop the clock and report

      elapsedTime2 =   millis() - startTime2;              // store elapsed time
      blinking2 = false;                                  // turn off blinking, all done timing
      lastButtonState4 = buttonState4;                   // store buttonState4 in lastButtonState, to compare next time

      // routine to report elapsed time
      Serial.print( (int)(elapsedTime2 / 1000L));         // divide by 1000 to convert to seconds - then cast to an int to print

      Serial.print(".");                             // print decimal point

        // use modulo operator to get fractional part of time
      fractional2 = (int)(elapsedTime2 % 1000L);

      // pad in leading zeros - wouldn't it be nice if
      // Arduino language had a flag for this? :)
      if (fractional2 == 0)
        Serial.print("000");      // add three zero's
      else if (fractional2 < 10)    // if fractional < 10 the 0 is ignored giving a wrong time, so add the zeros
        Serial.print("00");       // add two zeros
      else if (fractional2 < 100)
        Serial.print("0");        // add one zero

      Serial.println(fractional2);  // print fractional part of time


      lcd.setCursor(0, 1);
      lcd.print("L2:  ");
      lcd.setCursor(5, 1);
      lcd.print((int)(elapsedTime2 / 1000));
      lcd.print(":");
      lcd.print(fractional2);
      lcd.print(" ms");
      digitalWrite(ledrunoverPin2, HIGH);  //Red led L2 lights - run over
    }

    else
    {
      lastButtonState3 = buttonState3;                         // store buttonState in lastButtonState, to compare next time
      lastButtonState4 = buttonState4;                         // store buttonState in lastButtonState, to compare next time
    }


    if (stateReset == LOW) {
      blinking = false;
      lcd.clear();
      lcd.print("  Slalom Timer");
      lcd.setCursor(0, 1);
      lcd.print("  Timer ready!");
      digitalWrite(ledreadyPin, HIGH);
      digitalWrite(ledrunoverPin, LOW);

      // LANE 2-
      if (blinking2 = false);
      digitalWrite(ledreadyPin2, HIGH);
      digitalWrite(ledrunoverPin2, LOW);
    }

    // blink routine - blink the LED while timing

    if ( (millis() - previousMillis2 > interval2) ) 
    {
      if (blinking2 == true)
      {
        previousMillis2 = millis();                         // remember the last time we blinked the LED

        // if the LED is off turn it on and vice-versa.
        if (value2 == LOW)
          value2 = HIGH;
        else
          value2 = LOW;
        digitalWrite(ledtimingPin2, value2);
      }
      else
      {
        digitalWrite(ledtimingPin2, LOW);                         // turn off LED when not blinking
      }
    }
  }
}

Have you looked at the demo several things at a time? I think it would be easier to follow the logic of your code if you break it up into separate functions. I suspect your blinking stuff is more complex than it needs to be - but because it is all mixed up with other stuff it is hard to see.

...R

Hi,

I have read that and done the whole tutorial Planning and Implementing an Arduino Program.
Very good articles.

Agree it would be a good idea to section it to make it easier to read and actually be more efficient.

However, I'm not sure on what section to group into functions.

Will have a go anyway.

Would the following be an idea?

Button presses
Timing (millis)
Print results to LCD
Print to Serial
Leds - Blinking

Thanks

no66:
Would the following be an idea?

My own preference is to include the timing within the function it relates to. That way I can copy the function to another short program and test it on its own if needs be.

Based on your list you might have code in loop() like this

 void loop() {
    currentMillis = millis(); // so you have one value for all situations
    readButtons();
    writeToLCD();
    writeToPC();
    switchLEDs();
  }

One thing to watch is that the code writing to the LCD and Serial don’t take too long - i.e. they MUST be shorter than the blink interval. You certainly don’t need to update them every iteration of loop() so they should be controlled by millis() as well. If writing to the LCD or serial does take too long you could break that stuff into (maybe) two parts operating at different intervals. But keep it simple until you know there is a problem.

…R

Thank you Robin.

I will have a go, but still have a lot to learn when going from scratch.

I understand code when I see other examples, but fall short when I have to do it myself :slight_smile:

Will do one lane first to keep it simple and only a one led for when the timer is running.

Btw, will only be writing to the LCD and pc after the timing is finished.

I've tried with showing the timing on the lcd when running, but it doesn't look good. Printing "L1 Running" is good enough...