Blinking a led with "if" out of loop()

Hi! I wanted to understand if it is possible, to keep the loop() clean, to blink a physical led on a gpio based on the state of a variable. Right now I have this function inside the loop that makes the LED blink slowly or quickly based on the status of the variable “inMovimento”:


void loop()
{
  Blynk.run();
  timer.run();
  tripWire.run();

if (inMovimento == HIGH) {
  const long interval = 200;
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
  previousMillis = currentMillis;
  if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }
    digitalWrite(ledboard, ledState);
    }  
    }

if (inMovimento == LOW) {
  const long interval = 1000;
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
  previousMillis = currentMillis;
  if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }
    digitalWrite(ledboard, ledState);
    }  
    }
   
}

Everyone rightly says to keep the loop as clean as possible. Is there a way to do this? Thank you!

If you have a look at @Gunner’s C++ code tutorials around timeout timers and lambda timers you’ll see some examples.

Personally I take the easy option and use the ticker library!

Pete.

1 Like

Here I’m using a Button widget to switch between a fast timer and a slow timer …

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

char auth[] = "xxx";
char ssid[] = "xxx";
char pass[] = "xxx";

BlynkTimer timer;

boolean ledState = LOW;
int     ledBoard = D0;  // <- substitue your pin here
int     fast_timer_id;
int     slow_timer_id;

BLYNK_WRITE(V0) {  // <- tied to Button widget
   timer.toggle(slow_timer_id);
   timer.toggle(fast_timer_id);
}

void setup(void) {
   Serial.begin(115200);
   Blynk.begin(auth, ssid, pass);
   while (!Blynk.connect());
   pinMode(ledBoard, OUTPUT);
   digitalWrite(ledBoard, ledState);
   fast_timer_id = timer.setInterval(200L, inMovimento);
   slow_timer_id = timer.setInterval(1000L, inMovimento);
   timer.disable(slow_timer_id);
}

void loop(void) {
   Blynk.run();
   timer.run();
}

void inMovimento(void) {
   ledState = !ledState;
   digitalWrite(ledBoard, ledState);
}

I read the usage of ticker and seems Perfect for my purpose, tomorrow I try, thanks

But here is based on a widget app, i need always check based only with the variable… Or i dont understand something?

I was hoping you could tailor the code to suit your needs.

I’m newby, sorry. Anyway, tomorrow I try to play with your code too, thanks

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

char auth[] = "xxx";
char ssid[] = "xxx";
char pass[] = "xxx";

BlynkTimer timer;

boolean inMovimento = LOW;
boolean ledState = LOW;
int     ledBoard = D0;  // <- substitue your pin here
int     fast_timer_id;
int     slow_timer_id;

void setup(void) {
   Serial.begin(115200);
   Blynk.begin(auth, ssid, pass);
   while (!Blynk.connect());
   pinMode(ledBoard, OUTPUT);
   digitalWrite(ledBoard, ledState);
   fast_timer_id = timer.setInterval(200L, fInMovimento);
   timer.disable(fast_timer_id);
   slow_timer_id = timer.setInterval(1000L, fInMovimento);
}

void loop(void) {
   Blynk.run();
   timer.run();
}

void fInMovimento(void) {
   if ((inMovimento && timer.isEnabled(slow_timer_id)) || 
      (!inMovimento && timer.isEnabled(fast_timer_id))) {
      timer.toggle(slow_timer_id);
      timer.toggle(fast_timer_id);
   }
   ledState = !ledState;
   digitalWrite(ledBoard, ledState);
}
2 Likes

:scream: It is impossible for me to find a solution of this type, even if I try to make do with it whenever possible … Every day I learn something new thanks to reading many forums and examples of users like you! thanks a lot wickedbeernut and Peteknight!

There is always a solution… but as with most cases, it will be custom solution for your specific needs.

Start with examples and experiment until you make it work the way you need.

Here is just one LED Blinking option I made that you can tweek as needed.

1 Like

Wickedbeernut, your code works perfectly!!!

Thanks thanks and thanks!!!

You’re welcome.

It would be better if you could toggle the timer intervals at the point in your code you change inMovimento. The way it’s currently written, we’re using the fInMovimento() function to essentially “poll” for a change in inMovimento. It’ll take up to one second from the time inMovimento changes until the LED flash rate changes from slow to fast.

If you invoke this toggleTimers() function in changing inMovimento, the LED flash rate will change within 200 ms,

void toggleTimers(void) {
   timer.toggle(slow_timer_id);
   timer.toggle(fast_timer_id);
}

void fInMovimento(void) {
   ledState = !ledState;
   digitalWrite(ledBoard, ledState);
}

It’s a minor point, but the delay would bug me to death. :wink: You see how much cleaner the code is if you eliminate the polling. This was my original example. I toggled the timers corresponding to a change in the state of the Button widget. I’m not exactly sure what inMovimento is tied to or how it gets updated. If you don’t have an issue with the added 800 ms delay, leave it as is.

1 Like

Delay is not a problem for my purpose. My esp does open a gate with a NO relay, and (only once opened after xx seconds) it can be stopped with a second relay (NC). The led blinking is just a game (fast blinking when the gate is in movement), to add an extra function in the sketch and learn new codes (the toggle was new for me, very useful!). So, if the code I used doesn’t create problems, I keep what is perfect. Very kind, thanks again

This is my app for testing 2 esp8266 and 1 sonoff :slight_smile:

“Keep the loop () as clean as possible”.

OK! Perfect! I realized that keeping the loop() clean is wise.
But I am a curious boy and I like to understand the why of things! So, why? What changes from a sketch of this type with code in the loop():

void loop () {
  Blynk.run ();
  timer.run ();

  if (digitalRead (btnPin) == LOW) {
        xxxxx
        } else {
        xxxxx
        }
}

from this, with clean loop():

timer.setInterval (100L, checkPhysicalButton);

void checkPhysicalButton () {
  if (digitalRead (btnPin) == LOW) {
  xxxxx
  } else {
  xxxxx
  }

void loop () {
  Blynk.run ();
  timer.run ();
}

I mean, I realized that he does less checks on that pin every second, but what can happen? Can the system crash? Really? So if it is an external void the system does not freeze because there is some kind of “protection from crash” in the blynk code or in the timer code?

Looking at a blynk site, the “Button Interrupt” example has control right inside the loop ()! So is it wrong?

volatile bool pinChanged = false;
volatile int  pinValue   = 0;

void checkPin() {
  pinValue = !digitalRead(2);
  pinChanged = true;
}

void setup() {
 attachInterrupt(digitalPinToInterrupt(2), checkPin, CHANGE);
}

void loop() {
  Blynk.run();

  if (pinChanged) {
    if (pinValue) {
      led1.on();
    } else {
      led1.off();
    }
    pinChanged = false;
    }
}

thanks! :slight_smile:

It’s about keeping the Blynk background process fed with processor time. The longer the void loop is, and the more things that the processor has to do during each loop through the void loop, the less time it has for Blynk.
In your example it makes little difference, but when you have multiple digital pin reads, ‘if’ tests, and potentially chunks of code that need to be executed when an ‘if’ test evaluates to true, you will experience Blynk disconnections.

Blynk is a very powerful software library that does an enormous amount of ‘magic’ in the background. That comes at a cost though, and you have to work with that limitation when you write your code.

Pete.

1 Like

There’s no “protection from crash” (disconnections) in using a timer. If you do “bad things” in the context of a timer interval function, it’s fundamentally the same (although not quite as bad) as doing bad things in the context of the loop() routine. The timer interval ensures the corresponding function is only invoked as needed. And it provides a means of eliminating the need for the blocking delay() function which everyone is so fond of. If applied properly, a timer results in more modular, readable and maintainable firmware.

2 Likes

I asked this because when I started with Arduino IDE + Arduino UNO board, I started copying, studying and using sketches where the loop() was used a lot. As soon as I discovered Blynk, I noticed that it is the opposite, and I wanted to understand why. And now I know why. Very clear explanations, thanks.

2 Likes