Perhaps???.. I am actually not good at following others (or for that matter my own) code flow and logic just by looking at it without spending a lot of time with it running in front of me to compare what I think should happen with what does
But as far as a basic if else() then yes that should work… but can be made fractionaly simpler since there is only the two options of HIGH or LOW for the btnState…
if (btnState=HIGH)
{
onRelay();
}
else
{
timer.disable(timerId1);
timer.disable(timerId2);
}
Now, where you put this logic code is another matter that may or may not affect its functionality.
Nope nope nope … You could put it in another fast timed function (100-250ms?) or a Blynk function (reacting to a button or timer widget call), depending on your needs.
Not sure where it’s at now, I compiled it (without error) so I uploaded and nothing happens when I turn D5 on.
The reason I picked Pin 4 for the RelayPin is so when this turns HIGH I can see via the built in LED on the NodeMCU. A separate D4 button I created works, when I press that I see the LED light up on the NodeMCU.
Here’s the code, but nothing’s happening.
I now have a feeling the onRelay and offRelay functions should be nested inside the new function I created (mainfunction)
Also should the btnstate be LOW when declaring it?
#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
float MistRunTime;
int DelayTime;
int RelayState = LOW; //assuming active HIGH relay, change to LOW if active LOW
int btnState = HIGH;
int timerId1;
int timerId2;
// Set your Relay and physical button pins here
const int RelayPin = 4;
const int btnPin = 5;
BlynkTimer timer;
// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "";
// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "";
char pass[] = "";
// Every time we connect to the cloud...
BLYNK_CONNECTED() {
// Request the latest state from the server
Blynk.syncVirtual(V2);
Blynk.syncVirtual(V3);
Blynk.syncVirtual(V4);
// Alternatively, you could override server state using:
//Blynk.virtualWrite(V2, RelayState);
}
// When App button is pushed - switch the state
BLYNK_WRITE(V2) {
RelayState = param.asInt();
digitalWrite(RelayPin, RelayState);
}
void checkPhysicalButton()
{
if (digitalRead(btnPin) == LOW) {
// btnState is used to avoid sequential toggles
if (btnState != LOW) {
// Toggle Relay state
RelayState = !RelayState;
digitalWrite(RelayPin, RelayState);
// Update Button Widget
Blynk.virtualWrite(V2, RelayState);
}
btnState = LOW;
} else {
btnState = HIGH;
}
}
BLYNK_WRITE (V3) // Time interval for misting 0.5-10 seconds
{
MistRunTime = param.asFloat(); // assigning incoming value from Virtual Pin V3 to a variable
Serial.println(MistRunTime);
}
BLYNK_WRITE (V4) // Time interval for delay 5-120 seconds
{
DelayTime = param.asInt(); // assigning incoming value from Virtual Pin 4 to a variable
Serial.println(DelayTime);
}
void onRelay()
{
digitalWrite(RelayPin, HIGH); //turn relay ON
timerId1 = timer.setTimeout(MistRunTime*1000, offRelay); //run after
}
void offRelay()
{
digitalWrite(RelayPin, LOW);//turn relay OFF
timerId2 = timer.setTimeout(DelayTime*1000, onRelay); //run after
}
void setup()
{
// Debug console
Serial.begin(9600);
Blynk.begin(auth, ssid, pass);
// You can also specify server:
//Blynk.begin(auth, ssid, pass, "blynk-cloud.com", 80);
//Blynk.begin(auth, ssid, pass, IPAddress(192,168,1,100), 8080);
pinMode(RelayState, OUTPUT);
pinMode(btnPin, INPUT_PULLUP);
digitalWrite(RelayState, RelayState);
// Setup a function to be called every 100 ms
timer.setInterval(100L, checkPhysicalButton);
}
void mainfuction()
{
if (btnState=HIGH)
{
onRelay();
}
else
{
timer.disable(timerId1);
timer.disable(timerId2);
}
}
void loop()
{
Blynk.run();
timer.run();
}
I would merge that last timer disabling code into your timed checkPhysicalButton() function… so that if Button ON it works, if OFF it stops… no need to have yet another function like your mainfuction() that, BTW, doesn’t seem to be called from anywhere else anyhow
This is correct, hence why I recommended the use of a flag.
Same here. I tend to have to read and then re-read and then re-read again before I start to understand some snippets of code. Especially when they are not quite finished.
Yes, you did, but this is not the same as D4. Usually, D4 (GPIO 2) is connected to the built-in LED, but this is also one of the pins you want to avoid using (unless you know what you are doing). If it is pulled to the wrong state on boot, your esp may boot in the wrong mode. I think you need to do some research on the difference between the D numbers listed on the board, and the GPIO numbers best used for programming.
No, but I guess it wouldn’t matter that much. It is used as more of a way to avoid rapid toggling of the relay if the button is held down. If you declare it LOW and are holding the button at startup, it will allow the relay to trigger. With it declared as HIGH holding the button on startup will do nothing. You will have to release the button first and then press it again to trigger the relay.
As mentioned before, you should take the time to understand what the code is doing. Otherwise, when attempting future projects it will be like starting from the beginning. I do a lot of cut-and-paste programming, but not blindly. Before using a snippet of code, I take the time to understand what it is doing, how it is doing it and why. When you know these things, it is easier to know where and when to apply them to different projects. It will also aid in situations where you cannot find a code snippet to copy, as you will have a better understanding of how to code.
Well here is my code for an adjustable cycling relay. I have not done a full hardware to test, but the virtual LED does flash in the APP as it should. So I suspect it would work just fine once all hardware is connected. I did notice that the timer for the physical button was behaving strangely once the cycling function was triggered. After trying a few different thing I found that adding a second timer seemed to fix it. I never really got to the root of the issue (it has something to do with the timer.deleteTimer(timerId1) and timer.deleteTimer(timerId2)), as once I figured out adding the second timer fixed it I stopped there. Maybe I will revisit it once I get the rest of the project sorted out.
/* Comment this out to disable prints and save space */
#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "AUTH";
// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "WIFI";
char pass[] = "PASSWORD";
BlynkTimer timer;
BlynkTimer timer2;
const int relayPin = 12; //GPIO pin relay is attached to (D6)
const int btnPin = 14; //pin physical button is attached to. wired between GPIO13 (D7) and GND
int cycleState = LOW;
int btnState = HIGH;
float RunTime = 1;
int DelayTime = 1;
int timerId1;
int timerId2;
int timerId3;
int ReCnctFlag; // Reconnection Flag
int ReCnctCount = 0; // Reconnection counter
int onFlag = 0;
WidgetLED led1(V10);
// Every time we connect to the cloud...
BLYNK_CONNECTED() {
// Request the latest state from the server
Blynk.syncVirtual(V1, V2, V7);
ReCnctCount = 0;
}
// When App button is pushed - switch the state. The button should be on virtual pin 7 and set to switch
BLYNK_WRITE(V7) {
cycleState = param.asInt();
if (cycleState == HIGH) {
onFlag = 1;
onRelay();
}
else if (cycleState == LOW) {
onFlag = 0;
}
}
void checkPhysicalButton()
{
//Serial.println("BUTTON CHECK");
if (digitalRead(btnPin) == LOW) {
// btnState is used to avoid sequential toggles
//Serial.println("BUTTON PRESSED");
if (btnState != LOW) {
// Toggle cycleState
cycleState = !cycleState;
Blynk.virtualWrite(V7, cycleState);
if (cycleState == HIGH) {
onFlag = 1;
onRelay();
}
else if (cycleState == LOW) {
onFlag = 0;
}
}
btnState = LOW;
}
else {
btnState = HIGH;
}
}
BLYNK_WRITE (V1) // Time interval for misting 0.5-10 seconds
{
RunTime = param.asFloat(); // assigning incoming value from pin V1 to a variable
Serial.println(RunTime);
}
BLYNK_WRITE (V2) // Time interval for delay 5-120 seconds
{
DelayTime = param.asInt(); // assigning incoming value from pin V2 to a variable
Serial.println(DelayTime);
}
void onRelay()
{
if (onFlag == 1) {
timer.deleteTimer(timerId1);//delete timers in case they are still running, that is buttons turned on/off/on too fast
timer.deleteTimer(timerId2);//delete timers in case they are still running, that is buttons turned on/off/on too fast
digitalWrite(relayPin, HIGH); //turn relay ON
led1.on();
Serial.println("ON");
timerId1 = timer.setTimeout(RunTime * 1000, offRelay); //run after
}
}
void offRelay()
{
digitalWrite(relayPin, LOW);//turn relay OFF
led1.off();
Serial.println("OFF");
timerId2 = timer.setTimeout(DelayTime * 1000, onRelay); //run after
}
void setup()
{
// Debug console
Serial.begin(115200);
pinMode(relayPin, OUTPUT);
pinMode(btnPin, INPUT_PULLUP);
digitalWrite(relayPin, LOW); //relay is active HIGH, start with relay OFF
WiFi.begin(ssid, pass); // Non-blocking if no WiFi available
Blynk.config(auth);
Blynk.connect();
// Setup a function to be called every 100 ms
timerId3 = timer2.setInterval(100L, checkPhysicalButton);
}
void loop()
{
if (Blynk.connected()) { // If connected run as normal
Blynk.run();
} else if (ReCnctFlag == 0) { // If NOT connected and not already trying to reconnect, set timer to try to reconnect in 30 seconds
ReCnctFlag = 1; // Set reconnection Flag
Serial.println("Starting reconnection timer in 30 seconds...");
timer2.setTimeout(30000L, []() { // Lambda Reconnection Timer Function
ReCnctFlag = 0; // Reset reconnection Flag
ReCnctCount++; // Increment reconnection Counter
Serial.print("Attempting reconnection #");
Serial.println(ReCnctCount);
Blynk.connect(); // Try to reconnect to the server
}); // END Timer Function
}
timer.run();
timer2.run();
}