Hi
I have created a 2-zone timer irrigation Controller based on the amazing work and posts of everyone in thIs Blynk Community post.
Ive managed to get the 2 zones working based on 2 time input widgets with a on/off button for both.
The next bit of functionality im keen to add is a ‘cycle/soak’ where the Selected time input (I.e. watering time) is split up to allow time for the water to soak in before more water is added. I.E. Water for 5 minutes, turn off for 5 minutes, run again for 5 minutes and so on.
I’d be very keen to get some good ideas on how best to achieve this.
My very crude attempt is to divide the total time input duration by 5 (3 running intervals and 2 soak intervals) and run a new function turning the relay on/off and then calling the next function (cycle_soak_1/2/3/4/5).
You’ll see the first timer called in the “BLYNK_WRITE(V10)//Zone 1 time input handling” section and then the subsequent cycle_soak functions at the end of the V10 Write.
Some of the problems i’m having with this
-
The 10 second check doesnt seem to happen once the Zone 1 Cycle/Soak has kicked off (no updated on the terminal.
-
reinstating to normal checking of the next input time doesnt appear to be working
A couple of notes
- i’ve only implemented the CYcle/soak on Zone1 at this stage for testing
- i’ve commented out some of the original code From link above while I’m testing incase i need to retrieve later on
Any help, or better ideas on how to achieve would be greatly appreciated.
// changes to allow cycle and soak in auto mode
/**************************************************************
* timeinput.ino Demonstrate interaction of Time library with
* Blynk's TimeInput widget.
* App project setup:
* RTC widget (no pin required!!!)
* V1 : Manual/auto1 button
* V2: On-off button
* Terminal on V3 // Label will be the clock + wifi signal!!!!
*
* Time Input widget on V10 (Auto)
* Button selection for Time Input (Auto) on V11
*
**************************************************************/
#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
//#include <SimpleTimer.h>
#include <TimeLib.h>
#include <WidgetRTC.h>
SimpleTimer timer;
WidgetRTC rtc;
WidgetTerminal terminal(V3);
//#define server "blynk.cloud-com" // or "blynk.cloud-com" for Blynk's cloud server
#define TestLED 2 // on board LED pin assignment
char Date[16];
char Time[16];
char auth[] = "xxxx";
char ssid[] = "xxxx";
char pass[] = "xxxx";
long startsecondswd; // weekday start time in seconds
long stopsecondswd; // weekday stop time in seconds
long nowseconds; // time now in seconds
bool isFirstConnect = true;
String displaycurrenttimepluswifi;
int wifisignal;
int manual=0;
int oldstatus;
int zone1 = 4; // digital pin for relay 1
int zone2 = 5; // digital pin for relay 2
int auto1;
int zone1_state;
int zone2_state;
int timerID;
long cycle_soak_int;
void setup()
{
pinMode(TestLED, OUTPUT);
digitalWrite(TestLED, LOW); // set LED OFF
digitalWrite(zone1, LOW);
digitalWrite(zone2,LOW);
pinMode(zone1,OUTPUT);
pinMode(zone2,OUTPUT);
Serial.begin(115200);
Serial.println("\Starting");
Blynk.begin(auth, ssid, pass);
int mytimeout = millis() / 1000;
while (Blynk.connect() == false) { // try to connect to server for 10 seconds
if((millis() / 1000) > mytimeout + 8){ // try local server if not connected within 9 seconds
break;
}
}
rtc.begin();
Blynk.syncVirtual(V2);
Blynk.syncVirtual(V6);
Blynk.syncVirtual(V1);
timer.setInterval(10000L, activetoday); // check every 10 SECONDS if schedule should run today
timer.setInterval(30000L, reconnectBlynk); // check every 30s if still connected to server
timer.setInterval(5000L, clockvalue); // check value for time
timer.setInterval(5000L, sendWifi); // Wi-Fi singal
}
BLYNK_CONNECTED() {
if (isFirstConnect) {
Blynk.syncAll();
Blynk.notify("TIMER STARTING!!!!");
isFirstConnect = false;
}
}
void sendWifi() {
wifisignal = map(WiFi.RSSI(), -105, -40, 0, 100);
}
void clockvalue() // Digital clock display of the time
{
int gmthour = hour();
if (gmthour == 24){
gmthour = 0;
}
String displayhour = String(gmthour, DEC);
int hourdigits = displayhour.length();
if(hourdigits == 1){
displayhour = "0" + displayhour;
}
String displayminute = String(minute(), DEC);
int minutedigits = displayminute.length();
if(minutedigits == 1){
displayminute = "0" + displayminute;
}
displaycurrenttimepluswifi = " Clock: " + displayhour + ":" + displayminute + " Signal: " + wifisignal +" %";
Blynk.setProperty(V3, "label", displaycurrenttimepluswifi);
}
void activetoday(){ // check if schedule should run today
if(year() != 1970){
if (auto1==1) {
Blynk.syncVirtual(V10); // sync timeinput widget
Blynk.syncVirtual(V20);
}
}
}
void checklastbuttonpressed (){
if((auto1==1)){ oldstatus=1;}
}
void restorelastbuttonpressed (){
if(oldstatus==1){auto1=1;}
}
//void resetTerminal()
//{
// timer.setTimeout(50, checklastbuttonpressed);
// terminal.println();
// terminal.println();
// terminal.println("New MODE has been selected");
// terminal.println("Wait for update (Max 10 Seconds)");
// terminal.println();
// terminal.println();
// terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
// terminal.flush();
//}
void resetManual()
{
Blynk.virtualWrite(V1, 0); //Turn OFF Manual Mode Widget
Blynk.virtualWrite(V2, 0); //Turn OFF Button Widget Device
Blynk.virtualWrite(V6, 0); //Turn OFF Button Widget Device
digitalWrite(TestLED, LOW); // set LED OFF
digitalWrite(zone1, LOW);
digitalWrite(zone2, LOW);
}
BLYNK_WRITE(V1) // Manual/auto selection
{
if (param.asInt()==1) {
manual=1;
terminal.println();
terminal.println("Manual MODE is ON");
terminal.println("Press Zone ON/OFF buttons as required");
terminal.println();
terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
terminal.flush();
checklastbuttonpressed ();
auto1=0;
} else {
restorelastbuttonpressed ();
manual=0;
//timer.setTimeout(50, resetTerminal);
timer.setTimeout(50, resetManual);
timer.setTimeout(50, checklastbuttonpressed);
auto1=1;
terminal.println();
terminal.println("Manual MODE is OFF");
terminal.println("Auto MODE restored from last status");
terminal.println("Wait for update (Max 10 Seconds)");
terminal.println();
terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
terminal.flush();
}
}
BLYNK_WRITE(V2) // Zone 1 ON-OFF Manual
{
if (param.asInt()==1) { // boton encendido
terminal.println();
terminal.println("Manual MODE is ON");
terminal.println("Zone 1 is ON");
terminal.println();
terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
terminal.flush();
if (manual==0){ //está en modo auto1mático
checklastbuttonpressed ();
manual=1;
auto1=0;
digitalWrite(TestLED, HIGH); // set LED ON
digitalWrite(zone1, HIGH);
Blynk.virtualWrite(V2, 1); //Turn ON Button Widget
Blynk.virtualWrite(V1, 1); //Turn OFF Auto Mode
} else { //está en modo manual
auto1=0;
Blynk.virtualWrite(V2, 1); //Turn ON Button Widget
Blynk.virtualWrite(V1, 1); //Turn OFF Auto Mode
digitalWrite(TestLED, HIGH); // set LED ON
digitalWrite(zone1, HIGH);
}
}else {
terminal.println();
terminal.println("Manual MODE is ON");
terminal.println("Press ON/OFF button if required");
terminal.println("Zone 1 is OFF");
terminal.println();
terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
terminal.flush();
if (manual==0){ //modo auto1mático
checklastbuttonpressed ();
manual=1;
auto1=0;
Blynk.virtualWrite(V1, 1); //Turn OFF Auto Mode
digitalWrite(TestLED, LOW); // set LED OFF
digitalWrite(zone1, LOW);
Blynk.virtualWrite(V2, 0); //Turn OFF Button Widget
} else {
auto1=0;
Blynk.virtualWrite(V1, 1); //Turn OFF Auto Mode
digitalWrite(TestLED, LOW); // set LED OFF
digitalWrite(zone1, LOW);
Blynk.virtualWrite(V2, 0); //Turn OFF Button Widget
}
}
}
BLYNK_WRITE(V6) // Zone 2 ON-OFF Manual
{
if (param.asInt()==1) { // boton encendido
terminal.println();
terminal.println("Manual MODE is ON");
terminal.println("Zone 2 is ON");
terminal.println();
terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
terminal.flush();
if (manual==0){ //está en modo auto1mático
checklastbuttonpressed ();
manual=1;
auto1=0;
digitalWrite(TestLED, HIGH); // set LED ON
digitalWrite(zone2, HIGH);
Blynk.virtualWrite(V6, 1); //Turn ON Button Widget
Blynk.virtualWrite(V1, 1); //Turn OFF Auto Mode
} else { //está en modo manual
auto1=0;
Blynk.virtualWrite(V6, 1); //Turn ON Button Widget
Blynk.virtualWrite(V1, 1); //Turn OFF Auto Mode
digitalWrite(TestLED, HIGH); // set LED ON
digitalWrite(zone2, HIGH);
}
}else {
terminal.println();
terminal.println("Manual MODE is ON");
terminal.println("Press ON/OFF button if required");
terminal.println("Zone 2 is OFF");
terminal.println();
terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
terminal.flush();
if (manual==0){ //modo auto1mático
checklastbuttonpressed ();
manual=1;
auto1=0;
Blynk.virtualWrite(V1, 1); //Turn OFF Auto Mode
digitalWrite(TestLED, LOW); // set LED OFF
digitalWrite(zone2, LOW);
Blynk.virtualWrite(V6, 0); //Turn OFF Button Widget
} else {
auto1=0;
Blynk.virtualWrite(V1, 1); //Turn OFF Auto Mode
digitalWrite(TestLED, LOW); // set LED OFF
digitalWrite(zone2, LOW);
Blynk.virtualWrite(V6, 0); //Turn OFF Button Widget
}
}
}
BLYNK_WRITE(V10)//Zone 1 time input handling
{
if (auto1==1) {
sprintf(Date, "%02d/%02d/%04d", day(), month(), year());
sprintf(Time, "%02d:%02d:%02d", hour(), minute(), second());
TimeInputParam t(param);
terminal.println("GENERAL:");
terminal.println(String(" Time zone: ") + t.getTZ()); // Timezone is already added to start/stop time
terminal.println(" Ensure at least ONE day is selected for each zone");
terminal.println();
terminal.println("ZONE 1:");
terminal.print(" Schedule checked at: ");
terminal.println(Time);
terminal.flush();
int dayadjustment = -1;
if(weekday() == 1){
dayadjustment = 6; // needed for Sunday, Time library is day 1 and Blynk is day 7
}
if(t.isWeekdaySelected(weekday() + dayadjustment)){ //Time library starts week on Sunday, Blynk on Monday
terminal.println(" Auto ACTIVE today");
terminal.println(" Cycle/Soak Active. 3 equal intervals of watering split up by 2 equal intervals of soak");
terminal.flush();
if (t.hasStartTime()) // Process start time
{
if(t.getStartMinute()<10){
terminal.println(String(" Scheduled Start: ") + t.getStartHour() + ":0" + t.getStartMinute());
}else{
terminal.println(String(" Scheduled Start: ") + t.getStartHour() + ":" + t.getStartMinute());
}
terminal.flush();
}
if (t.hasStopTime()) // Process stop time
{
if(t.getStopMinute()<10){
terminal.println(String(" Scheduled Stop : ") + t.getStopHour() + ":0" + t.getStopMinute());
}else{
terminal.println(String(" Scheduled Stop : ") + t.getStopHour() + ":" + t.getStopMinute());
}
int durationwd = ((t.getStopHour()*3600 + t.getStopMinute()*60 + t.getStopSecond()) - (t.getStartHour()*3600 + t.getStartMinute()*60 + t.getStartSecond()))/60;
cycle_soak_int = (durationwd*60*1000)/5;
terminal.print(" Total Duration (mins):");
terminal.println(durationwd);
terminal.print(" Total Watering Time over 3 intervals (mins):");
terminal.println((cycle_soak_int/1000/60)*3);
terminal.print(" Total Soak Time over 2 intervals (mins):");
terminal.println((cycle_soak_int/1000/60)*2);
terminal.flush();
}
// Display timezone details, for information purposes only
terminal.flush();
// for (int i = 1; i <= 7; i++) { // Process weekdays (1. Mon, 2. Tue, 3. Wed, ...)
// if (t.isWeekdaySelected(i)) {
// terminal.println(String("Zone 1 Days ") + i + " is selected");
// terminal.flush();
// }
// }
nowseconds = ((hour() * 3600) + (minute() * 60) + second());
startsecondswd = (t.getStartHour() * 3600) + (t.getStartMinute() * 60);
//Serial.println(startsecondswd); // used for debugging
if(nowseconds >= startsecondswd){
terminal.print(" Auto STARTED at");
if(t.getStartMinute()<10){
terminal.println(String(" ") + t.getStartHour() + ":0" + t.getStartMinute());
}else{
terminal.println(String(" ") + t.getStartHour() + ":" + t.getStartMinute());
}
terminal.flush();
if(nowseconds <= startsecondswd + 90){ // 90s on 60s timer ensures 1 trigger command is sent
digitalWrite(TestLED, HIGH); // set LED ON
digitalWrite(zone1, HIGH);
Serial.println("Zone 1 active");
timer.deleteTimer(timerID);
timerID = timer.setTimeout(cycle_soak_int, cycle_soak_1);
Serial.print("Cycle for: ");
Serial.print(cycle_soak_int/1000/60);
Serial.println(" minutes");
Blynk.virtualWrite(V2, 1);
// code here to switch the relay ON
}
}
else{
Blynk.virtualWrite(V2,0);
terminal.println();
terminal.println(" Auto NOT STARTED today");
terminal.flush();
}
stopsecondswd = (t.getStopHour() * 3600) + (t.getStopMinute() * 60);
//Serial.println(stopsecondswd); // used for debugging
if(nowseconds >= stopsecondswd){
digitalWrite(TestLED, LOW); // set LED OFF
digitalWrite(zone1, LOW);
Blynk.virtualWrite(V2, 0);
terminal.print(" Auto STOPPED at");
if(t.getStopMinute()<10){
terminal.println(String(" ") + t.getStopHour() + ":0" + t.getStopMinute());
}else{
terminal.println(String(" ") + t.getStopHour() + ":" + t.getStopMinute());
}
terminal.flush();
if(nowseconds <= stopsecondswd + 90){ // 90s on 60s timer ensures 1 trigger command is sent
digitalWrite(TestLED, LOW); // set LED OFF
digitalWrite(zone1, LOW);
Blynk.virtualWrite(V2, 0);
// code here to switch the relay OFF
}
}
else{
if(nowseconds >= startsecondswd){
digitalWrite(TestLED, HIGH); // set LED ON
digitalWrite(zone1, HIGH);
Blynk.virtualWrite(V2, 1);
terminal.println(" Auto is ON");
terminal.flush();
}
}
}
else{
terminal.println();
terminal.println(" Auto INACTIVE today");
terminal.flush();
// nothing to do today, check again in 30 SECONDS time
}
terminal.println();
}
}
void cycle_soak_1(){
Serial.print("Soak for : ");
Serial.print(cycle_soak_int/1000/60);
Serial.println(" minutes");
digitalWrite(zone1, LOW);
Blynk.virtualWrite(V2, 0);
timer.deleteTimer(timerID);
timerID = timer.setTimeout(cycle_soak_int, cycle_soak_2);
}
void cycle_soak_2(){
Serial.print("Cycle (2nd) for: ");
Serial.print(cycle_soak_int/1000/60);
Serial.println(" minutes");
digitalWrite(zone1, HIGH);
Blynk.virtualWrite(V2, 1);
timer.deleteTimer(timerID);
timerID = timer.setTimeout(cycle_soak_int, cycle_soak_3);
}
void cycle_soak_3(){
Serial.print("Soak (2nd) for: ");
Serial.print(cycle_soak_int/1000/60);
Serial.println(" minutes");
digitalWrite(zone1, LOW);
Blynk.virtualWrite(V2, 0);
timer.deleteTimer(timerID);
timerID = timer.setTimeout(cycle_soak_int, cycle_soak_4);
}
void cycle_soak_4(){
Serial.print("Cycle (3rd) for: ");
Serial.print(cycle_soak_int/1000/60);
Serial.println(" minutes");
digitalWrite(zone1, HIGH);
Blynk.virtualWrite(V2, 1);
timer.deleteTimer(timerID);
timerID = timer.setTimeout(cycle_soak_int, cycle_soak_5);
}
void cycle_soak_5(){
Serial.print("End of cycle/soak");
digitalWrite(zone1, LOW);
Blynk.virtualWrite(V2, 0);
timer.deleteTimer(timerID);
}
BLYNK_WRITE(V20)//Zone 2 time input handling
{
if (auto1==1) {
sprintf(Date, "%02d/%02d/%04d", day(), month(), year());
sprintf(Time, "%02d:%02d:%02d", hour(), minute(), second());
TimeInputParam t(param);
terminal.println("ZONE 2:");
terminal.print(" Schedule checked at: ");
terminal.println(Time);
terminal.flush();
int dayadjustment = -1;
if(weekday() == 1){
dayadjustment = 6; // needed for Sunday, Time library is day 1 and Blynk is day 7
}
if(t.isWeekdaySelected(weekday() + dayadjustment)){ //Time library starts week on Sunday, Blynk on Monday
terminal.println(" Auto ACTIVE today");
terminal.flush();
if (t.hasStartTime()) // Process start time
{
if(t.getStartMinute()<10){
terminal.println(String(" Scheduled Start: ") + t.getStartHour() + ":0" + t.getStartMinute());
}else{
terminal.println(String(" Scheduled Start: ") + t.getStartHour() + ":" + t.getStartMinute());
}
terminal.flush();
}
if (t.hasStopTime()) // Process stop time
{
if(t.getStopMinute()<10){
terminal.println(String(" Scheduled Stop : ") + t.getStopHour() + ":0" + t.getStopMinute());
}else{
terminal.println(String(" Scheduled Stop : ") + t.getStopHour() + ":" + t.getStopMinute());
}
int durationwd = ((t.getStopHour()*3600 + t.getStopMinute()*60 + t.getStopSecond()) - (t.getStartHour()*3600 + t.getStartMinute()*60 + t.getStartSecond()))/60;
terminal.print(" Duration (mins):");
terminal.println(durationwd);
terminal.flush();
}
// Display timezone details, for information purposes only
// terminal.println(String("Time zone offset: ") + t.getTZ_Offset()); // Get timezone offset (in seconds)
terminal.flush();
// for (int i = 1; i <= 7; i++) { // Process weekdays (1. Mon, 2. Tue, 3. Wed, ...)
// if (t.isWeekdaySelected(i)) {
// terminal.println(String("Zone 2 Days ") + i + " is selected");
// terminal.flush();
// }
// }
nowseconds = ((hour() * 3600) + (minute() * 60) + second());
startsecondswd = (t.getStartHour() * 3600) + (t.getStartMinute() * 60);
//Serial.println(startsecondswd); // used for debugging
if(nowseconds >= startsecondswd){
terminal.print(" Auto STARTED at");
if(t.getStartMinute()<10){
terminal.println(String(" ") + t.getStartHour() + ":0" + t.getStartMinute());
}else{
terminal.println(String(" ") + t.getStartHour() + ":" + t.getStartMinute());
}
terminal.flush();
if(nowseconds <= startsecondswd + 90){ // 90s on 60s timer ensures 1 trigger command is sent
digitalWrite(TestLED, HIGH); // set LED ON
digitalWrite(zone2, HIGH);
Blynk.virtualWrite(V6, 1);
// code here to switch the relay ON
}
}
else{
Blynk.virtualWrite(V6,0);
terminal.println();
terminal.println(" Auto NOT STARTED today");
terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
terminal.flush();
}
stopsecondswd = (t.getStopHour() * 3600) + (t.getStopMinute() * 60);
//Serial.println(stopsecondswd); // used for debugging
if(nowseconds >= stopsecondswd){
digitalWrite(TestLED, LOW); // set LED OFF
digitalWrite(zone2, LOW);
Blynk.virtualWrite(V6, 0);
terminal.print(" Auto STOPPED at");
if(t.getStopMinute()<10){
terminal.println(String(" ") + t.getStopHour() + ":0" + t.getStopMinute());
}else{
terminal.println(String(" ") + t.getStopHour() + ":" + t.getStopMinute());
}
terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
terminal.flush();
if(nowseconds <= stopsecondswd + 90){ // 90s on 60s timer ensures 1 trigger command is sent
digitalWrite(TestLED, LOW); // set LED OFF
digitalWrite(zone2, LOW);
Blynk.virtualWrite(V6, 0);
// code here to switch the relay OFF
}
}
else{
if(nowseconds >= startsecondswd){
digitalWrite(TestLED, HIGH); // set LED ON
digitalWrite(zone2, HIGH);
Blynk.virtualWrite(V6, 1);
terminal.println(" Auto is ON");
terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
terminal.flush();
}
}
}
else{
terminal.println();
terminal.println(" Auto INACTIVE today");
terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
terminal.flush();
// nothing to do today, check again in 30 SECONDS time
}
terminal.println();
}
}
void reconnectBlynk() {
if (!Blynk.connected()) {
if(Blynk.connect()) {
BLYNK_LOG("Reconnected");
} else {
BLYNK_LOG("Not reconnected");
}
}
}
void loop()
{
if (Blynk.connected()) {
Blynk.run();
}
timer.run();
}