Blink without using"delay()", Trying to reset the counter function

In the spirit of not using “delay()” when flashing LEDs and such, I have put together a script from a couple of projects. I am using Particle.function and the Particle App string command to trigger an event that will flash the LED 10 times, then reset at the end of 10 flashes and be ready for another trigger. The problem is: the loop works once , flashes the LED 10 times, then does not reset the flag to allow the loop to run again ( that’s my assumption). The trigger command is getting through to the Photon every time, but it is not triggering the LED to blink 10 times. I am also assuming there is a simple mistake in my method to clear or reset the “blink” flag. Or ??
I am also using the “Blynk” app with this script which works for reading the RSSI.
Many thanks in advance.

Here is the full Code:

// This #include statement was automatically added by the Particle IDE.
#include <blynk.h>
//*****************This is currently on C_M *********************************
// This #include statement was automatically added by the Particle IDE.
#include <photon_book.h>

// On and Off Times (as int)
const unsigned int onTime = 50;
const unsigned int offTime = 100;

// Tracks the last time event fired
unsigned long previousMillis=0;

// Interval is how long we wait
int interval = onTime;
int maxnum = 20;
int count = 0;

// Used to track if LED should be on or off
boolean LED3state = true; //primary LED to blink 10 times first
boolean LED4state = true;  //this would be the next LED to blink right after the first one blinks 10 times (to be added next) FUTURE USE
boolean blink; //Establishes "blink" as boolean, this was "boolean blink=false"

char auth[]= "xxxxxxxxxxxxxxxxxxxxxx";
int wifiStrength;
float startTime; 

void setup() 
{  
    pinMode(2, OUTPUT);
    pinMode(3, OUTPUT);
    Particle.function ("LED_control", LED_control); // create a cloud function ("LED_control"), 
    //this will show up in the Particle app and can be triggered from the app to cause the "LED_control(String command) to go "true" ?, not sure how this works, but it does)
    Particle.function ("Reset", Reset); //This is to manually reset for troubleshooting the "blink" not resetting at the end of the loop.
    Blynk.begin(auth);
    WiFi.selectAntenna(ANT_EXTERNAL);
}

int LED_control(String command) // when you trigger this from the Particle App it starts the script directly following this, 
//it flashes LED 2 to let you know you received the trigger from the Particle App
{
    digitalWrite(2, HIGH);
    delay(100);
    digitalWrite(2, LOW);
    blink = true;  //Sets the "blink flag to "true" to start the "if (blink)"  in the loop
    return 1;  // tells the Particle App the command was sucsessfully received
}

int Reset(String command) //This is a manual reset, This will make the LED on pin 2 come on but does not seem to reset the "blink" to "false".
{
    digitalWrite(2, HIGH);
    delay(100);
    digitalWrite(2, LOW);
    blink = false;  //Sets the "blink flag to "true" to start the "if (blink)"  in the loop (Does not reset to false)
    return 1;  // tells the Particle App the command was sucsessfully received
}

void loop() //this works once when triggered, then the Photon needs to be reset to run this again. The "blink" flag is not being reset after the loop.
{
    if (blink) // this gets triggered from the mini script above "(LED_(String command)"
    
    {
        if (count < maxnum) // used to count the number of times through the loop to count 10 flashes
        {
        // Set Pin 3 to state of LED3state each timethrough loop()  
        // If LED13State hasn't changed, neither will the pin  
        digitalWrite(3, LED3state);   
        // Grab snapshot of current time, this keeps all timing  
        // consistent, regardless of how much code is inside the next if-statement  
        unsigned long currentMillis = millis();   
        // Compare to previous capture to see if enough time has passed 
        if ((unsigned long)(currentMillis - previousMillis) >= interval) 
            {    // Change wait interval, based on current LED state    
            if (LED3state) 
               {      
                // LED is currently on, set time to stay off      
                interval = offTime;    
                } 
                    else 
                    {      
                    // LED is currently off, set time to stay on      
                    interval = onTime;    
                    }    
                    // Toggle the LED's state, Fancy, eh!?    
                    LED3state = !(LED3state);     
                    // Save the current time to compare "later"
                    previousMillis = currentMillis;
                    count++; //increment the counter
            }
        }
    }
    
    if (millis() > startTime + 2000)
        { 
            startTime = millis(); 
            //wifiStrength = map(WiFi.RSSI(), -100, 0, 0, 100); // This version maps -100 to 0 to 0-100 sends a value between 0-100
            wifiStrength = WiFi.RSSI();  // This version of RSSI sends the true value in -dBm to Blynk App 
            Blynk.virtualWrite(V20, wifiStrength); //Sends the wifi RSSI to Blynk widget
            Blynk.run();
            Particle.process();
}
}

// This works but only once through the loop, when the "LED_control" command is received a second or third time it is ignored :-( 
// ??? SOMEWHERE I NEED TO SET THE FLAG BACK TO "FALSE" ? So the loop is ready to receive (blink) again ??

Thanks for the format fix !

One thing, if you want to control your application via Blynk, you should definetly call Blynk.run() without delay.
Next, please adopt a consistent code indentation practice. There are some common conventions, but yours code doesn’t seem to cling to any of them. It just makes following your code that much easier (when done right).
You can edit your post via the image button at the bottom of your post.

The reason why your code is not blinking again after having it done ten times comes from the fact that you never reset your count variable.
And for good practice you should also reset blink once you have finished the ten iterations to “disable” the complete block once done.

Thanks for the feedback. I tried to reset the “count” variable by inserting “count=0” after the “if (count>maxnum)” block and also after the “if blink” block and the LED flashes constantly now.
Also- to reset “blink” to “false” I assume, where should it be placed in the code ?
I have tried some of the same locations as the “count=0” and it causes other problems like a toggle effect (every trigger command toggles the LED on and off)
Thanks again, appreciate your code suggestions.

I’d rewrite the code like this (add missing functions and definitions as original)

const uint32_t onTime         = 50;                   // time to stay on
const uint32_t offTime        = 100;                  // time to stay off
const uint32_t blynkInterval  = 2000;                 // time between Blynk reports

uint32_t       previousMillis = 0;                    // Tracks the last time event fired
uint32_t       interval       = onTime;               // Interval is how long we wait

int LED_control(String dmy)                           // when you trigger this from the Particle App it starts the script directly following this, 
{                                                     // it flashes LED 2 to let you know you received the trigger from the Particle App
  digitalWrite(D2, HIGH);
  delay(100);
  digitalWrite(D2, LOW);
  blink = true;                                       // Sets the "blink flag to "true" to start the "if (blink)"  in the loop
  count = 0;                                          // initialise defined starting state
  LED3state = HIGH;
  interval = onTime;
  previousMillis = millis();
  return 1;                                           // tells the Particle App the command was sucsessfully received
}

int Reset(String dmy)                                 // This is a manual reset, This will make the LED on pin 2 come on but does not seem to reset the "blink" to "false".
{
  digitalWrite(D2, HIGH);
  delay(100);
  digitalWrite(D2, LOW);
  blink = false;                                      // Sets the "blink flag to "true" to start the "if (blink)"  in the loop (Does not reset to false)
  count = 0;                                          
  return 0;                                           // tells the Particle App the command was sucsessfully received
}

void loop()                                           // this works once when triggered, then the Photon needs to be reset to run this again. 
{                                                     // The "blink" flag is not being reset after the loop.
  Blynk.run();

  if (blink)                                          // this gets activated via the mini script above "(LED_(String command)"
  {
    if (count < maxnum)                               // used to count the number of times through the loop to count 10 flashes
    {
      uint32_t currentMillis = millis();              // Grab snapshot of current time, this keeps all timing  
                                                      // consistent, regardless of how much code is inside the next if-statement  
      if (currentMillis - previousMillis >= interval) // Compare to previous capture to see if enough time has passed  
      {                                               // Change wait interval, based on current LED state    
        LED3state = !LED3state;                       // toggle state    
        interval = LED3state ? onTime : offTime;      // set intervall according to state   
        previousMillis = currentMillis;               // Save the current time to compare "later"
        count++;                                      // increment the counter
      }
    }
    else 
    {
      LED3state = LOW;                                // make sure to turn LED off
      count = 0;                                      // reset counter for next time 
      blink = false;                                  // finish blinking phase
    }
    digitalWrite(D3, LED3state);                      // Set Pin D3 to state of LED3state each timethrough loop()  
                                                      // If LED3state hasn't changed, neither will the pin
  }

  if (millis() - startTime >= blynkInterval)
  { 
    startTime = millis(); 
    //wifiStrength = map(WiFi.RSSI(), -100, 0, 0, 100);  // This version maps -100 to 0 to 0-100 sends a value between 0-100
    wifiStrength = WiFi.RSSI();                        // This version of RSSI sends the true value in -dBm to Blynk App 
    Blynk.virtualWrite(V20, wifiStrength);             //Sends the wifi RSSI to Blynk widget
  }
}

Also commenting the obvious is rarely helpful

1 Like

ScruffR;
Thank you, I just got back to working this, that did the trick very nice ! Much appreciated.

Now that it is blinking correctly, an interesting artifact shows up, or is more obvious. When “maxnum” is programmed to blink 10 times for example, there is an 11th blink but only for a few milliseconds (much less than the "onTime).

Also, for my education, I noticed that you changed “int LED_control(String Command)” to " int LED_control(String dmy), I tried to find the use of “dmy” in the Particle Docs, and couldn’t find “(String dmy)” or “dmy”. The only thing that comes to mind is “day, month,year” ?

Thanks again for your solution !!

The reason why I changed the parameter name is to make it clear to the unbiased reader of the function signature that the incoming parameter is not used (dummy) inside the function.

Using telling names for your variables can save you some work commenting/explaining your code.

I guess the same will happen whenever you choose an even number for maxnum.
That's due to the fact that this code treats each phase (ON and OFF) as a blink increment so you will sometimes end on an OFF state and other times on an ON state, but the final else branch for if (count < maxnum) will always turn the LED off on next visit without the interval.

1 Like

Thanks for the clarification, appreciate your help as always!

1 Like