Trouble with "Particle.function" and Blynk.begin" in Setup working together


#1

This may be another code error on my part but… When I include:

 Particle.function( "LED_control",  LED_control); 

and

 Blynk.begin(auth);

in the void setup() together,
It causes the “D3” command in the code below to be skipped:

int LED_control(String command)
{ 
        for (int i = 0; i < 5; i++)
        {
            digitalWrite(D6, HIGH); // flash the WHITE LED 
            delay(200);             // wait xx ms
            digitalWrite(D6, LOW);  // turn off LED
            delay(100);
        }
        for (int i = 0; i < 15; i++)
        {
            digitalWrite(D7, HIGH); // flash the on-board LED 
            delay(30);             // wait xx ms
            digitalWrite(D7, LOW);  // turn off LED
            delay(100);
        }
        for (int i = 0; i < 25; i++)
        { 
            digitalWrite(D3, HIGH); //Flash the RED RGB LED "D3"
            delay(30);
            digitalWrite(D3, LOW);
            delay(100);
        }

When I delete the Blynk.begin(auth) from setup, the code works every time. And obviously won’t talk to Blynk.

I also tried to change the order in the setup, no change in the issue.

Of course, when Blynk.begin(auth) is in the setup, Blynk works perfectly. But the D3 routine is skipped.

I want this to work with the particle cloud and be seen and controlled with Blynk.

It all compiles without errors with or without Blynk.begin(auth) in the code.

Here is the complete setup() code:

void setup()
{
    Particle.function( "LED_control",  LED_control); // create a cloud function ("LED_control")
    pinMode(D0, OUTPUT); // BLUE LED
    pinMode(D1, OUTPUT); // GREEN LED
    pinMode(D3, OUTPUT); // RED LED 
    pinMode(D7, OUTPUT); // On Board BLUE LED
    pinMode(D6, OUTPUT); // WHITE LED
    pinMode(btnPin, INPUT_PULLUP); // Setup physical button pin (active low)
    timer.setInterval(1000L, buttonLedWidget);
    Blynk.begin(auth);
   }

Any help is appreciated.


#2

Hmm… that’s strange. Only the D3 loop doesn’t work? One thing I see is that you have a lot of delays in a particle function (and don’t seem to return an int, which you should). A particle function should return fairly quickly, so you should just set a flag in that function, and run all your digitalWrite code in loop(). Just for a test, if you move the D3 code to the beginning of the function, does it run?


#3

Thanks Ric, if I move D3 to the first routine, still gets skipped. If I comment out the “Blynk.begin” it doesn’t get skipped.
The delays in the routines are blinking Different LEDs. If there is a better way, I’m interested.
At the end of the LED routines, there is a "return 1;"
It is strange that just including the Blynk.begin would cause an issue.
I can send more code if it will help.


#4

The better way is to put all that LED blinking code in loop() as I said. Just create a global bool, say shouldBlink, and set it to true when the function handler is called. In loop(), you would have an if-clause that checks to see if shouldBlink is true, and if it is, run all the code that you now have in the function handler (also set shouldBlink to false as the first line).

However, I don’t know if this will solve your problem; it’s just best practice not to have delays in a function handler.

The fact that moving the D3 code to the beginning of the function has no effect would seem to indicate that it’s not some sort of timing problem caused by all the delays. If you switch that code to another pin, say D4 or D5, does it still get skipped?

After Edit: I’m not very familiar with Blynk (haven’t used it myself), but from what I’ve read on the forum, it’s not good practice to have delays in loop when you’re using Blynk. So, it would be best to replace all your delays with millis() “timers”, though again, I don’t know if this would solve your problem (but it should keep you from screwing up Blynk).


#5

You’d also need to show the rest of your code, just in case any Blynk stuff acquires control over D3


#6

@chris7, I agree with @ScruffR that seeing your code and knowing if you having any Blynk item tied to D3 is what’s needed.


#7

Thanks Everyone. I am not a coder so I have collected parts of other examples to build a project. This is a general purpose breadboard to test software to build other projects. If you could send an example of the “shouldBlink”, it would be great.
Also, here is another twist. I noticed the Photon data sheet comment; “PWM timer peripheral is duplicated on two pins (A5/D2) and (A4/D3)”. If I make A5 HIGH using Blynk, then the routine works with the Blynk.begin(auth) included. This is also strange since A5 is a shared PWM with D2, not D3. So these should be independent. I moved the D3 function from D2 earlier to see if this was the issue and the problem went to D3.
Just an FYI, the Blynk RSSI and Switch all work fine (when Blynk.begin" included), Blynk also can operate all the LEDS with no issues. Hope the code isn’t too scary !

Here is the complete code:

// This version adds the WiFi Signal Strength Reporting to Blynk, ALSO ADDS THE SWITCH
// This #include statement was automatically added by the Particle IDE.
#include <photon_book.h>
// This #include statement was automatically added by the Particle IDE.
#include <blynk.h>
#define BLYNK_PRINT Serial// added this for switch
char auth[] = "xxxxxxxxxx"; // Put your blynk token here

const int btnPin = D5; //For Switch
BlynkTimer timer; //For Switch

void setup()
{
    //Blynk.begin(auth);
    Particle.function( "LED_control",  LED_control); // create a cloud function ("LED_control")
    
    pinMode(D0, OUTPUT); // BLUE LED
    pinMode(D1, OUTPUT); // GREEN LED
    pinMode(D3, OUTPUT); // RED LED 
    pinMode(D7, OUTPUT); // On Board BLUE LED
    pinMode(D6, OUTPUT); // WHITE LED
    pinMode(btnPin, INPUT_PULLUP); // Setup physical button pin (active low)
    timer.setInterval(1000L, buttonLedWidget);
    Blynk.begin(auth);
    }

WidgetLED led3(V3); //For Switch

// V3 LED Widget represents the physical button state
boolean btnState = false;
void buttonLedWidget()
{
// Read button
    boolean isPressed = (digitalRead(btnPin) == LOW);
    // If state has changed...
    if (isPressed != btnState) 
    {
        if (isPressed) 
        {
        led3.on();
        Blynk.notify(" Switch Activated ");
        } 
    else 
    {
    led3.off();
    }
    btnState = isPressed;
    }
}

int LED_control(String command)
{
        for (int i = 0; i < 5; i++)
        {
            digitalWrite(D6, HIGH); // flash the WHITE LED 
            delay(200);             // wait xx ms
            digitalWrite(D6, LOW);  // turn off LED
            delay(100);
        }
        for (int i = 0; i < 15; i++)
        {
            digitalWrite(D7, HIGH); // flash the on-board LED 
            delay(30);             // wait xx ms
            digitalWrite(D7, LOW);  // turn off LED
            delay(100);
        }
        for (int i = 0; i < 25; i++)
        {
            
            digitalWrite(D3, HIGH); //Flash the RED RGB LED "D3"
            delay(30);
            digitalWrite(D3, LOW);
            delay(100);
        }
        for (int i = 0; i < 25; i++)
        {
            digitalWrite(D1, HIGH); // flash the GREEN RGB LED 
            delay(30);             // wait xx ms
            digitalWrite(D1, LOW);  // turn off LED
            delay(100);
        }
        for (int i = 0; i < 25; i++)
        {
            digitalWrite(D0, HIGH); // flash the BLUE RGB LED 
            delay(30);
            digitalWrite(D0, LOW);
            delay(100);
        }
        for (int i = 0; i < 25; i++)
        {
            digitalWrite(D6, HIGH); // flash the WHITE LED 
            delay(20);             // wait xx ms
            digitalWrite(D6, LOW);  // turn off LED
            delay(100);
        }
        return 1;  // tell the Particle cloud that this function completed
}

int wifiStrength;
float startTime;
 
void loop()

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

     if (millis() > startTime + 60000){ 
       startTime = millis(); 
        //wifiStrength = map(WiFi.RSSI(), -100, 0, 0, 100); // This version sends a value between 0-100 instead of -100 to 0.
       wifiStrength = WiFi.RSSI();  // This version of RSSI sends the true value in -127dBm to 0dBm
       Blynk.virtualWrite(V20, wifiStrength);
   } 
}

#8

@chris7, the entire animation in LED_control() takes 16.2 seconds! You will a) loose cloud connectivity, b) prevent Blynk.run() from running and c) cause general mayhem.

You need to take the animation out of LED_control() and only set a flag there. In loop(), read the flag and set off a set of non-blocking events, ideally using an FSM. The idea is a bit like this:

In LED_control(), set the LED state to 1 and repeat counter to 5
FSM follows
State == 1: if repeat counter < 5 turn on D6 and start 200ms timer.  Set state to 2.  Otherwise set repeat counter to 15 and set state to 4 
State == 2: if timer not elapsed, continue, otherwise turn off D6 and start 100ms timer.  Set state to 3
State == 3: if timer not elapsed, continue, otherwise increment repeat counter and set state to 1
State == 4: if repeat counter < 15 turn on D7 and start 30ms timer.  Set state to 5.  Otherwise set repeat counter to 25 and set state to...

This can be done with a big switch() statement. On each pass of loop(), the FSM will jump to the current state until another state is set. This creates a non-blocking Finite State Machine. You can create an “idle” state once the animation is done so it will sit in that state until kicked off again by LED_control(). :wink:


#9

Thanks for the help ! I will go off an work this, find a tutor maybe and work it some more :wink: Thanks again.