Trying a "state machine"

non-blocking waiting that avoids delay() is done with additional states
for your example
as pseudo-code
switch led on
change to the "wait_1_second_state"
check inside the "wait_1_second_state" if one second has passed by
when really one second HAS passed by
change to next state

The state-machine example that I have posted has such a "waiting"-state

additionally here is a set of debug-macros that I add at the top of each code

// MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START *
// a detailed explanation how these macros work is given in this tutorial
// https://forum.arduino.cc/t/comfortable-serial-debug-output-short-to-write-fixed-text-name-and-content-of-any-variable-code-example/888298

#define dbg(myFixedText, variableName) \
  Serial.print( F(#myFixedText " "  #variableName"=") ); \
  Serial.println(variableName);

#define dbgi(myFixedText, variableName,timeInterval) \
  { \
    static unsigned long intervalStartTime; \
    if ( millis() - intervalStartTime >= timeInterval ){ \
      intervalStartTime = millis(); \
      Serial.print( F(#myFixedText " "  #variableName"=") ); \
      Serial.println(variableName); \
    } \
  }

#define dbgc(myFixedText, variableName) \
  { \
    static long lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " "  #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  }

#define dbgcf(myFixedText, variableName) \
  { \
    static float lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " "  #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  }
// MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END *

The advantage is that in a single line of code you get

  1. an identifier (the fixed text")
  2. the variable-name
  3. the value of the variable
  4. functionality only print once on
  • a variable changed its value
  • b after a user-defined intervall (only once every 2 seconds or whativer interval you want

Turn on the LED and start a timer:

    ledIsOn = true;
    digitalWrite(theLEDPin, HIGH);
    ledTimer = millis();

Any elsewhere, such that it gets execute every loop or very frequently, independently turn off the LED if it is time:

  if (ledIsOn && millis() - ledTimer > 777) {
    ledIsOn = false;
    digitalWrite(theLEDPin, LOW);
  } 

I find 777 milliseconds to be a nice stab of the lamp. Adjust to taste.

Non-blocking.

a7

The way to think of that is as it's own "DisplayingFrobnicatingLed" state--If you look at the device and think OK now it's supposed to be doing X and it should move on after 1sec, then it is in the middle of "DisplayingFrobicatingLED" or whatever. One turns on the FrobinicatingLed when transitioning into the DisplayingFrobicatingLED state, and one turns off the led when transitioning into the next state. Something like this completely untested snippet:

case PreFrobnicating:
   ...
   if(FrobnicatingButton == PRESSED){
      digitalWrite(FrobnicatingButton,HIGH);
      stateChangeTime = millis();
      WandStartUpID = DisplayingFrobnicatingLed;
   }
   break;
...
case DisplayingFrobnicatingLed:
   ...
   if(millis() - stateChangeTime >= 1000){ // done frobnicating?
      digitalWrite(FrobnicatingButton,HIGH);
      WandStartUpID = Transmogrifying; // next thing
      stateChangeTime = millis();
   }
   break;
...

@camsysca's suggestion in #19 of a changestate(n) is a way of doing the state-change accounting and providing a easy hook for debugging transitions.

The set of "states" are the names you'd use as answers to @StefanL38 -style plain language questions like "What is my device doing now" or "what should my device do next". In trying to decode your enum/states I might think of them as {ERROR, COLDSTART, TestingVentButton, TestingBargraphSwitch, TestingStartupSwitch, PassedTestingAnimation,Armed,...} etc...

I failed to mention, it also provides an easy way to turn off that reporting in just one place, until it's needed again, rather than neutralizing the dozens, or hundreds, of localized 'print state' code instances. Yech.

thank iā€˜ll try it hopefully tomorrow and tell if it worked.

nice. I love switch/case/break, it's like steroids for Arduino. Really lets you do a bunch of different stuff on one board in a logical way

Do your very best to learn millis() and avoid delay altogether unless you're using it for the specific purpose of halting everything for some time. Yes, if you're not used to it, millis() will twist your brain around a bit (or maybe not, I'm not that smart) but it's one of the core skills to get under your belt in Arduino, no question about it.

If it will twist your brain or not depends on what code and what explanation you use to learn it.

The standard blink without delay()-example in the arudino-IDE does:

not emphasise and point onto the fundamental difference between delay() and non-blocking timing based on millis().

If somebody does not yet know about this fundamental difference and tries to see a delay()-similar thing in millis() sure she/he will twist her/his brain with extra-confusion which is only caused by trying to see the wrong thing in the code.

As soon as non-blocking timing is explained with an everyday example it becomes easier to understand.

@IDE-Team: you keep up a tradition of extra-confusion for new-comers with this "classical" blink without delay()-code in the IDE-examples.

i know the millis stuff as i wrote in my code. the delay stuff is only for me for debugging, because if i don't use it the serial print output is so fast i cannot read it.

delay()s interact with millis-based code, (and everything else,) so your debugging behavior might not be the same as the non-debugging behavior.

Even worse, printing alone can introduce delays that change your code's behavoiur. There have been more than one "works with the diagnostic printing, doesn't without" threads. The unsatisfactory answer is to leave that in the final code…

Especially if you use grandpa's baud rate

  Serial.begin(9600);

Bump that up to 115200.

Above have been presented ways to reduce the serial monitor traffic. They are effective, pick one you like or take the basic idea and roll your own.

a7

so the 115200 goes with every current board like the nanos?

yeah i really really have a looong way to go.

Yes. All boards using the Atmega 328P-chip like Nano, Uno can do 115200 baud with easyness on the hardware-UART which is the one you connect your microcontroller with your computer.

Arduino Mega, Arduino Micro, and all other microcontroller-boards with a clockfrequency equal to 16 MHz or higher can handle 115200 baud

Other boards using other microcontrollers can use even higher baudrates

Your code is not time-critical at all
You are sensing switches and switch on / off LEDs except maybe an animation of Neopixel LEDs.

If something is really time-critical you could use free io-pins to switch them on/off by direct port-manipulation.