Timer Input Widget not passing parameters from app to sketch on boot

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--;
  
}

The first thing I would do is to add some serial print statements to the BLYNK_WRITE callbacks so that you know when they’ve been triggered, and can see what parameter values you are getting.

Also, the “V” in the virtual pin identifier is optional, so you could simply do:

#define ZONE_1_TIMER 10

This can be handy if ever you need to loop through a number if pins with a for statement.

You can also use the BLYNK_WRITE_DEFAULT() callback if you have multiple BLYNK_WRITE(vPin) callbacks that do very similar things.
Not really needed for this situation, but you might find it handy in future.
An example of how to do this is in this post:

Pete.

Thank you, Pete. Very much appreciate your input. I’ve added the Serial.print() lines as you suggest replaced the serial output in my post for better readability. The problem seems to be in the corrupted/non-existent parameters of the second timer, but only at start up.

Have you checked the widget setup in the app?

What happens if you call the Blynk.syncVirtual(ZONE_2_TIMER); twice in BLYNK_CONNECTED() ?

Pete.

Thank you again, Pete.

I also changed the Virtual Pin to see if I was somehow overwriting it with another MCU and that seems to have fixed the problem. So, I was corrupting the data at the memory location on the server, making it unrecognisable as the object.

Sorry to trouble you and thank you again for your help.

1 Like

Glad it’s sorted!

Pete.