How to check for button status while leds are blinking

If you don't gloss the point, you might get the point.

The millis() and micros() functions return unsigned long values.
If you use unsigned math which can easily be modeled by moving round clock hands, there Never is overflow. Big hand on the 2, how long since 10? Move big hand 10 hours back (for minus start time) and the answer is 4, it's been 4 hours since 10. Only this clock has over 4 billion divisions.

The millis() timed interval can be 49.71-some DAYS long.
The millis() return value may be +/-1 millisecond due to skipping 6 of 256 possible lower 8-bit returns.

The micros() timed interval can be a bit over 70 minutes long.
The micros() return value with be a multiple of 4. The lower 8 bits always ??????00.
When close timing matters, use micros().

You can code it with signed values and get half the maximum interval along with code that does extra steps, ie runs slower.

if ( end - start >= timeout ) // runs after timeout

if ( end - start < timeout ) // runs until timeout

if ( timeout > 0 ) // runs something once then quits
if ( end - start >= timeout ) // runs after timeout
// do the thing
timeout = 0; // finished, turn off

Incorrect? Please at least check. I killed words like this in 3rd grade spelling back in 66.




[ adverb

in a mistaken way; wrongly.

"his name had been spelled incorrectly"

not in accordance with particular standards or rules.

"this dispute was handled incorrectly by the club"

and the question is?

1 Like

you choose a word "incorrect" incorrect. you think wrongly.
anyway, say if my code doesn’t do what TO asked.

Whatever. Years spent debugging taught me to tighten my code and recycle it as functions and libraries. It's funny how with code, garbage isn't worth recycling.

Whether it's reading, writing, sports, music or code, you get better by doing better. Teachers may show us better than we knew, we get better by learning.

Want to write a good sketch? Write it twice and throw the first one away. Learn from yourself.

1 Like

No to both. Maybe you will understand when you stop confusing code for face.

1 Like

What's the easiest way to hang onto bad habits?

That is the Answer to the
Ultimate Question of Life, the Universe and Everything.

1 Like

Okay, what's the hardest part about doing nothing?

Hi there, I am back for a while - as I am somewhat new to this Forum I am not sure what 'collaboration' entails - could you kindly educate me.

I have looked at most of the above suggestions- all seem to have a 'flasher' led - crossing signals have at least two in each direction they do not flash at the same time the left is on and the right is off then vice versa I cant seem to get any of the above to do that.
Any suggestions.
I am leaning toward using the LCbaseTools as the (idle) works well for me but the led sequence does not.

Maybe try..

blinker LEDBlinker(LED_PIN,300,600);

And don't worry about "collaborate" That's just me & StephanL38 yapping at each other. Been going on for years. :slight_smile:

-jim lee

1 Like

Ok I didn't see the bit where the lights blink alternately. Duh!

Here you go : Wokwi simulation

-jim lee

Having been stopped at a real railway level crossing this week, I now believe there should be no gaps when neither LED is on and I think LEDs should be on for 500ms. I have therefore modified my code:

int x;

void loop() {
  digitalWrite(crossingL1, x==0 && (!digitalRead(button3)) );
  digitalWrite(crossingR1, x==1 && (!digitalRead(button3)) );

Other code can be inserted within the loop, ensuring there is nothing that delays the loop significantly.

You don't need the really amazing amount of code that others are suggesting in this thread. Nor do you need to use any library functions.

As it stands, my code does not produce a full 500ms initial flash: but who is going to notice that?

The UK sequence is shown here on page 9:

Wow - wish I had known about that site some months ago - it is mind blowing... can anyone use it?
Anyhow thanks for the correction - it worked just fine for me.

Thanks for the info - and yes the code does work well.
The info on the signals is interesting - I sent it some of my like minded train peole.

If your led pins are on the same port, you can toggle them both in the same cycle by writing a mask to the port PINS register. The time when the led states may match will be in the nanoseconds.
Put an inverter gate on the led pin, make the leds always opposite.

It's only worth adding an integrated circuit (or a transistor) for an inverter gate if you run out of input/output pins on your Arduino. Anyway it would prevent you generating the UK sequence.

Just for fun I have now extended the code to give the full UK sequence. I have changed the button to a switch because the input needs to be held low while the lights are required: not just a quick press of a button. I have added an amber LED on crossingA1 pin. Also the variable names all end in "1" with regard to the possibility of controlling two or more sets of level crossing lights from the same Arduino.

unsigned long startMillis1, elapsed1;
bool switchState1;
int x1;

void setup() {

void loop() {
  // detect switch input going high to low
  if(switchState1==HIGH && digitalRead(switch1)==LOW) startMillis1=millis();
  switchState1  = digitalRead(switch1);    // for next loop iteration
  if(switchState1==LOW) elapsed1 = millis() - startMillis1;
  else elapsed1 = 0;   // then all LEDs will be turned off by code below
  //amber LED on for 3 seconds
  digitalWrite(crossingA1, elapsed1>0 && elapsed1<3000 );  

  // both red LEDs on for 1 second
  digitalWrite(crossingL1, elapsed1>3000 && elapsed1<4000);
  digitalWrite(crossingR1, elapsed1>3000 && elapsed1<4000);

  // no LEDs on 0.25 seconds

  // alternating red LEDs 0.5 seconds each
  x1 = (elapsed1-4250)%1000/500;
  digitalWrite(crossingL1, elapsed1>4250 && x1==0 );
  digitalWrite(crossingR1, elapsed1>4250 && x1==1 );

When the input from the switch goes low the start time is stored in startMillis1. On each iteration of the loop the elapsed time since then is in the elapsed1 variable. You will see the digitalWrite statements have a Boolean expression in their second parameter instead of the more usual HIGH or LOW. The red lights start alternate flashing after 4250 milliseconds. The expression for the integer variable x1 makes use of the remainder operator (%) to generate a value that is either 0 or 1. When the switch pin goes high after the train has passed, the variable elapsed is set to 0 which causes all LEDs to to be turned off.

You can still add more code inside the loop to control other things such as level crossing barriers: just make sure nothing delays the loop significantly.

The barrier type crossings her are red only but your code will come in handy for some other signal lights.

That was an alternate solution.

Using direct port manipulation is about 5x faster than using Arduino digitalRead/Write.
Putting both pins on one port to control in a single cycle is twice as efficient yet again and chip doc timing diagrams might tell how long between one bit changing and the next in a 62 nanosecond cycle.