SOLVED:
I was writing to the same VPin from different devices which corrupted the expected data type. I leave the question here in case it helps others to try that solution first!
========
I am building a garden irrigation timer with esp32
I have two timer Input Widgets, V10 and V20
On startup the V10 works as planned but V20 does not appear to load its parameters into the TimeInputParam object
When I change either V10 or V20 timer settings in the Blynk app (android) the parameters are passed fine and the code works as expected. BLYNK_WRITE() appears to be working fine for both as the code works when I change the Timer Input, but not when Blynk.syncVirtual(V20) is called.
You can see from the serial output below that the first timer params are passed fine but the second timer’s are not.
Totally flummoxed!
#define BLYNK_PRINT Serial
#define DEBUG_PRINT Serial
#define DEBUG_PRINT //
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <TimeLib.h>
#include <WidgetRTC.h>
#include <LiquidCrystal_I2C.h>
#define TERMINAL_VPIN V19
#define ZONE_1_TIMER V10
#define ZONE_2_TIMER V20
// GPIO Pins for Irrigation
#define POWER_SWITCH_PIN 19
#define REVERSE_POLARITY_RELAY 18
#define ZONE1_RELAY 5
#define ZONE2_RELAY 17
#define ZONE3_RELAY 16
#define ZONE4_RELAY 4
#define TWENTYFOUR_V_RAIL_SENSOR 36
#define FIVE_V_RAIL_SENSOR 39
#define VALVE_POWER_TIME 500 // the length of time that the valve receives a power pulse
#define CAPACITOR_CHARGE_DURATION_PRESET 15000 // time taken to charge the capacitor
#define RELAY_ON LOW
#define RELAY_OFF HIGH
#define POWER_SWITCH_ON LOW
#define POWER_SWITCH_OFF HIGH
LiquidCrystal_I2C lcd(0x27, 20, 4);
// Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "";
// WiFi credentials.
char ssid[] = "";
char pass[] = "";
// The number of zones.
const uint8_t max_zones = 4; // for loops and array size declaration for (i = 0; i < max_zones; i++)
uint8_t watering_zone_start_hour[max_zones];
uint8_t watering_zone_start_mins[max_zones];
uint16_t watering_zone_start_min_of_day[max_zones];
uint8_t watering_zone_ends_hour[max_zones];
uint8_t watering_zone_ends_mins[max_zones];
uint16_t watering_zone_ends_min_of_day[max_zones];
bool day_of_week_selected[max_zones][8];
const char* daylabels[] = {" ", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
// arrays start at zero, whereas Blynk returns a number where 1 = Monday... and 7 = Sunday.
// weekday() function (from Time), however, has 1 = Sunday to 7 = Saturday
bool water_flow = false;
uint8_t active_zone = 0; // placeholder to take the index of the zone currently watering
// - it's used so the system knows which zone to turn off so it doesn't need to keep looping once it is on
BlynkTimer timer;
WidgetRTC rtc;
WidgetTerminal terminal(TERMINAL_VPIN);
BLYNK_CONNECTED() {
// Synchronize time on connection
rtc.begin();
// Syncronize the irrigation timer settings with those on the server (set by the app)
Blynk.syncVirtual(ZONE_1_TIMER);
Blynk.syncVirtual(ZONE_2_TIMER);
}
BLYNK_WRITE(ZONE_1_TIMER) { //Data is pushed to MCU when it is changed on Blynk app
TimeInputParam t(param);
uint8_t zone_index = 0; //the array index for the variables for this particular zone associated with this virtual pin
updateZoneTimer(t, zone_index);
}
BLYNK_WRITE(ZONE_2_TIMER) { //Data is pushed to MCU when it is changed on Blynk app
TimeInputParam t(param);
uint8_t zone_index = 1; //the array index for the variables for this particular zone associated with this virtual pin
updateZoneTimer(t, zone_index);
}
This is the serial port output on startup…
12:18:44.582 → / _ )/ /_ _____ / /__
12:18:44.582 → / _ / / // / _ / '/
12:18:44.582 → ///_, /////_
12:18:44.582 → /__/ v0.6.7 on ESP32
12:18:44.582 →
12:18:44.582 → [3734] Connecting to blynk-cloud.com:80
12:18:44.653 → [3803] Ready (ping: 22ms).
12:18:44.833 → [3960] Time sync: OK
12:18:44.871 →
12:18:44.871 → In BLYNK_WRITE(ZONE_1_TIMER)
12:18:44.871 →
12:18:44.871 → ==== DEBUG ====
12:18:44.871 →
12:18:44.871 → First, get the parameters directly from the TimeInputParam object…
12:18:44.905 →
12:18:44.905 → t.getStartHour(): 9
12:18:44.905 → t.getStartMinute(): 27
12:18:44.905 → t.getStopHour(): 9
12:18:44.905 → t.getStopMinute(): 29
12:18:44.905 →
12:18:44.905 → Then display the values in the array once they have been set in the function…
12:18:44.905 →
12:18:44.905 → Start time updated for zone 1
12:18:44.905 → Stop time updated for zone 1
12:18:44.905 →
12:18:44.905 → Zone 1 Set
12:18:44.905 → … Tuesday… Thursday… Saturday… Sunday
12:18:44.905 → Start time: 9:27
12:18:44.905 → Stop time: 9:29
12:18:44.939 → Start time in minutes since midnight: 567
12:18:44.939 → Stop time in minutes since midnight: 569
12:18:44.939 → Current time: 12:18:44
12:18:44.939 →
12:18:44.939 → Leaving BLYNK_WRITE(ZONE_1_TIMER)
12:18:44.939 →
12:18:44.939 →
12:18:44.939 → In BLYNK_WRITE(ZONE_2_TIMER)
12:18:44.939 → ==== DEBUG ====
12:18:44.939 →
12:18:44.939 → First, get the parameters directly from the TimeInputParam object…
12:18:44.974 →
12:18:44.974 → t.getStartHour(): 0
12:18:44.974 → t.getStartMinute(): 0
12:18:44.974 → t.getStopHour(): 1193046
12:18:44.974 → t.getStopMinute(): 28
12:18:44.974 →
12:18:44.974 → Then display the values in the array once they have been set in the function…
12:18:44.974 →
12:18:44.974 → Start time updated for zone 2
12:18:44.974 → No Stop time set for zone 2
12:18:44.974 →
12:18:44.974 → Zone 2 Set
12:18:44.974 → … Monday… Tuesday… Wednesday… Thursday… Friday… Saturday… Sunday
12:18:44.974 → Start time: 0:0
12:18:44.974 → Stop time: 0:0
12:18:45.007 → Start time in minutes since midnight: 0
12:18:45.007 → Stop time in minutes since midnight: 0
12:18:45.007 → Current time: 12:18:44
12:18:45.007 →
12:18:45.007 → Leaving BLYNK_WRITE(ZONE_2_TIMER)
12:19:04.937 →
12:19:04.937 → Minute of day now: 739
12:19:04.937 → Current time: 12:19:4
This is the function responsible for the above output…
void updateZoneTimer( TimeInputParam t, uint8_t zone_index) { //Data is pushed to MCU when it is changed on Blynk app
// DEBUG
// Check parameters actually exist in the object received
Serial.println("\n==== DEBUG ====");
Serial.print("Start hour: ");
Serial.println(t.getStartHour());
Serial.print("Start minute: ");
Serial.println(t.getStartMinute());
Serial.print("Stop hour: ");
Serial.println(t.getStopHour());
Serial.print("Stop minute: ");
Serial.println(t.getStopMinute());
// Process start time
if (t.hasStartTime())
{
watering_zone_start_hour[zone_index] = t.getStartHour();
watering_zone_start_mins[zone_index] = t.getStartMinute();
watering_zone_start_min_of_day[zone_index] = (uint16_t)watering_zone_start_hour[zone_index] * 60 + watering_zone_start_mins[zone_index];
Serial.print("Start time updated for zone ");
Serial.println(zone_index + 1);
}
else
{
// Do nothing
Serial.print("No Start time set for zone ");
Serial.println(zone_index + 1);
}
// Process stop time
if (t.hasStopTime())
{
watering_zone_ends_hour[zone_index] = t.getStopHour();
watering_zone_ends_mins[zone_index] = t.getStopMinute();
watering_zone_ends_min_of_day[zone_index] = (uint16_t)watering_zone_ends_hour[zone_index] * 60 + watering_zone_ends_mins[zone_index];
Serial.print("Stop time updated for zone ");
Serial.println(zone_index + 1);
}
else
{
// Do nothing: no stop time was set
Serial.print("No Stop time set for zone ");
Serial.println(zone_index + 1);
}
Serial.println();
Serial.println(String("Zone ") + (zone_index+1) + " Set"); // index starts at zero whereas real world counting starts at 1
// Process weekdays (1. Mon, 2. Tue, 3. Wed, ...)
for (int i = 1; i <= 7; i++) {
if (t.isWeekdaySelected(i)) {
Serial.print(String("... ") + daylabels[i]);
day_of_week_selected[zone_index][i] = true;
}
else{
day_of_week_selected[zone_index][i] = false;
}
}
Serial.println();
Serial.println(String("Start time: ") + watering_zone_start_hour[zone_index] + ":" + watering_zone_start_mins[zone_index]) ;
Serial.println(String("Stop time: ") + watering_zone_ends_hour[zone_index] + ":" + watering_zone_ends_mins[zone_index]) ;
Serial.println(String("Start time in minutes since midnight: ") + watering_zone_start_min_of_day[zone_index]) ;
Serial.println(String("Stop time in minutes since midnight: ") + watering_zone_ends_min_of_day[zone_index]) ;
Serial.println(String("Current time: ") + hour() + ":" + minute() + ":" + second());
uint8_t dayofweek = weekday();
if( dayofweek == 1) dayofweek = 7; // need to do this because RTC weekday function and Blynk return different numbers for the days of the week
else dayofweek--;
}