BLYNK
BLYNK.IO       📲 GETTING STARTED       📗 DOCS       👉 SKETCH BUILDER

Button Widget turn on solenoid for a set time

HI Guys,

Big Picture - I have a project running where I press a button widget and it turns on a solenoid that allows water to flow to water my plants. I want to have it turn off after 5 minutes.

I want to use mills() (and have done so in the past) but am really struggling with this seemingly simple process.

As a test setup I am using a simple Arduino Uno with an LED and Button (I press the button and the LAD should turn on for 3 seconds). I can do this easily with delay() - but have spent four hours trying to replicate with millis() - I am clearly missing something very, very basic - HELP! Please!:weary::weary::weary:

const int buttonPin = 2;     // the number of the pushbutton pin
const int ledPin =  13;      // the number of the LED pin
int buttonState = 0;         // variable for reading the pushbutton status
unsigned long currentMillis;
long previousMillis = 0;
long interval = 3000;        // wait before turn off led


void setup() 
{
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT);
}

void loop() 
{
  buttonState = digitalRead(buttonPin);
  Serial.println(buttonState);
    
  if(buttonState == HIGH)       // pressed button
  {     
    digitalWrite(ledPin, HIGH); // turn on led
    delay(3000);
    //unsigned long currentMillis = millis();           // wait 3 secs
      //if(currentMillis - previousMillis > interval)
      //{
      //previousMillis = currentMillis;
        digitalWrite(ledPin, LOW);                    // then turn off led   
      //}
  }  
}

Once I get this working with millis() I’ll implement it into my existing Blynk watering project.

cul

billd

PS. Yes, I know this is not a strictly Blynk issue, but I get far more useful, helpful and meaningful response in this community than other other I’m apart of . . .and the delay()/millis() issue is core to keeping Blynk projects working well. Thnx

Actually the BlynkTimer (which does use millis) is the best way for Blynk. Avoid delay() as it actually stops ALL processing for the set time.

Use a timeout timer, set for whatever time you need. I use them all the “time” :wink: for blinking things, timed relays, etc.

Probably becasue we regulate it to only Blynk related issues as much as possible :stuck_out_tongue_winking_eye: hint

1 Like

Thnx mate, this is really doing my head in! I know its simple, and I should be able to get it, but have been going round in circles for hours!

help much appreciated!

cul
billd

Same thing with a timeout timer (using the Lambda shortcut)

if(buttonState == HIGH)  // pressed button
  {     
    digitalWrite(ledPin, HIGH);   // turn on led
  // Timed Lambda Function
  timer.setTimeout(3000L, []() {  // Run following command(s) after set time.
    digitalWrite(ledPin, LOW);   // then turn off led 
  });  // END Lambda Function
}

And long form use (non-Lambda)…

if(buttonState == HIGH) // pressed button
{ 
    digitalWrite(ledPin, HIGH);   // turn on led
    timer.setTimeout(3000L, TurnOffLED) {  // Run function after set time.
}


void TurnOffLED() 
{
    digitalWrite(ledPin, LOW);   // then turn off led 
}

5 minutes will be 300000L

Remember to add in all the BlynkTimer (or SimpleTimer library if not using Blynk) setup and timer.run() in the void loop()

1 Like

Or 3e5, which ever floats your boat :stuck_out_tongue:
Yes I am still alive! ^.^

1 Like

Don’t want to float a boat . . . just want to water my chilli plants . . .:stuck_out_tongue_winking_eye::hot_pepper::hot_pepper::hot_pepper::droplet::droplet::droplet:

Thnx for the examples, I can make this work perfectly with a physical button (I press the button, LED turns on for 5 seconds then goes off) - but not with a button widget.

Sketch start as planned, button widget is OFF, LED is OFF, nothing is printed on Serial Monitor (SM). I press the widget button, LED lights ON and SM prints as expected . . .after 5 seconds LED stays ON (should go OFF); and SM shows the sketch switching in and out of TurnOnWater() and TurnOffWater() in sequence.

#define BLYNK_PRINT Serial
#include <BlynkSimpleEsp8266.h>
#include <SimpleTimer.h>

char auth[] = "nnn";
char ssid[] = "nnn";
char pass[] = "nnn";
BlynkTimer timer;                                      // define Blynk timere to determine when to check sensors
const int ledPin =  2;
int pinValue = 0;
long interval = 5000;                                  // stop watering after interval

BLYNK_WRITE(V5) {
  digitalWrite(ledPin, param.asInt());                // Sets ledPin HIGH or LOW depending on state of Button Widget.
}

void TurnOnWater(){
  pinValue = 0;
  Serial.print("TurnOnWater(); ");
  Serial.println(pinValue);
  timer.setTimeout(interval, TurnOffWater);         // Run TurnOffLWater() after set time.
}

void TurnOffWater(){
  pinValue = 0;
  Blynk.virtualWrite(V5, 0);  // set buttom LOW
  Serial.print("TurnOffWater(); ");
  Serial.println(pinValue);
}

void setup(){
  Serial.begin(9600);
  Blynk.begin(auth, ssid, pass);
  Blynk.virtualWrite(V5, 0);  // set button LOW on startup
  pinMode(2, OUTPUT);         // test led
}

void loop(){
  Blynk.run();
  timer.run();
  pinValue = digitalRead(ledPin);
  if (pinValue == 1)                         // if button pressed
    {
      TurnOnWater();
    }
}

*Note the delays are just there to slow down the SM output.

I want to use the Button Widget as a SWITCH (not button), so that when I press it the LED turns ON, the widget stays on showing me that it is active, then after a set time it goes OFF.

What is wrong with my code please? As I said this works perfectly with a physical buttn, but not with the Blynk Button Widget in switch mode.

thnx
billd

OK, as usually happens immediately after I posted I got it working . . . (I find articulating the problem in detail on this forum helps me see the logical errors . . . sometimes :stuck_out_tongue_winking_eye:

My working code is included as a reference for others if needed.

Basically I needed to explicitly set the state of ledPIN (digitalWrite(ledPin, HIGH); ) in each function. then I had to do another digital read in each function (pinValue = digitalRead(ledPin);) otherwise the value of ledPin was unknown.

Working now, thnx again for the examples and thnx for listening

cul
billd

/*************************************************************
  Wemos D1 + Blynk button widget + led on wemos to test the auto time of function
  Button V5 to trigger led
  Timer to auto off
  
*************************************************************/

#define BLYNK_PRINT Serial
#include <BlynkSimpleEsp8266.h>
#include <SimpleTimer.h>
#include <ArduinoOTA.h>                                // OTA

char auth[] = "nnn";
char ssid[] = "nnn";
char pass[] = "nnn";
//BlynkTimer timer;                                      // define Blynk timere to determine when to check sensors
SimpleTimer timer;
const int ledPin = 2;
int testOTA = 391234;                                  // int that i can change to prove OTA it appears in a labeled value widget
int pinValue = 0;
long interval = 5000;                                  // stop watering after interval



BLYNK_WRITE(V5) 
{
  digitalWrite(ledPin, param.asInt());                // Sets ledPin HIGH or LOW depending on state of Button Widget.
}

void TurnOnWater()
{
  digitalWrite(ledPin, HIGH);
  Serial.print("TurnOnWater(); ");
  pinValue = digitalRead(ledPin);
  Serial.println(pinValue);
  timer.setTimeout(interval, TurnOffWater);         // Run TurnOffLWater() after set time.
}

void TurnOffWater()
{
  digitalWrite(ledPin, LOW);
  Blynk.virtualWrite(V5, LOW);                        // set button LOW
  Serial.print("TurnOffWater(); ");
  pinValue = digitalRead(ledPin);
  Serial.println(pinValue);
}

void setup()
{
  Serial.begin(9600);
  Blynk.begin(auth, ssid, pass);
  IPAddress strWiFiIp = WiFi.localIP();               // gets local IP address
  Serial.println("");
  Serial.print("Local IP Address: ");
  Serial.println(strWiFiIp);                          // prints to serial monitor
  Blynk.virtualWrite(V2, testOTA);                    // OTA test
  Blynk.virtualWrite(V4, WiFi.localIP().toString());  // local IP address
  Blynk.virtualWrite(V5, LOW);  // set buttom LOW on startup
  pinMode(2, OUTPUT); 
    
  ArduinoOTA.begin();                                 // OTA last line of setup()
}

void loop()
{
  ArduinoOTA.handle();                                // OTA first line of loop()
  Blynk.run();
  timer.run();
  pinValue = digitalRead(ledPin);
  
  if (pinValue == 1)                            // if button pressed
    {
      TurnOnWater();
    }
}
1 Like