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

Connecting to blynk.cloud:443

I’ve read all the posts I can find related to this, many seem to never get resolved, some appear to be resolved. But for someone new to this (like me), there doesn’t seem to be a clear answer that is easy to follow, and fix.

I regularly get this when trying to upload a sketch:
22:58:53.418 → [72315] Connecting to blynk.cloud:443
22:58:58.431 → [77321] Connecting to blynk.cloud:443
22:59:03.427 → [82331] Connecting to blynk.cloud:443
22:59:08.439 → [87339] Connecting to blynk.cloud:443
22:59:13.442 → [92346] Connecting to blynk.cloud:443
22:59:18.457 → [97348] Connecting to blynk.cloud:443
22:59:23.374 → [102269] Timeout
22:59:23.374 → [102269] Last error code: 702
22:59:23.374 → [102271] Configuration stored to flash
22:59:23.374 → [102271] CONNECTING_CLOUD => ERROR
22:59:33.382 → [112271] Restarting after error.

I’ve seen this with MKR1000, MKR1010, and D1 Mini. I use an iPhone. All software/libraries are current/latest.
The failure to connect is not consistent, the same sketch might connect one time, but with only meaningless changes (like commenting out a serial print) it then won’t connect.
Just now I get the same problem just using a Blynk example sketch with no changes (other than my ID and device name).

Earlier this eve I found a post (Solved - Blynk Community) that
said to:
Ok. So, try this:
var blynk = new Blynk.Blynk(AUTH, options = {
connector : new Blynk.TcpClient()
});
but I don’t know where this change would go. In my sketch? setup? loop? some file in the blynk? Arduino? I tried a few things, with no luck.

I don’t know if this is an SSL issue or not, but this problem is widespread, and there really should be an easy to find, comprehensive, dumbed down to the lowest level, explanation on how to fix this.

Please help if you can, thank you!

// Fill-in information from your Blynk Template here
//#define BLYNK_TEMPLATE_ID           "TMPLxxxxxx"
//#define BLYNK_DEVICE_NAME           "Device"
#define BLYNK_TEMPLATE_ID "TMPLGvxtfc-X"
#define BLYNK_DEVICE_NAME "Greenhouse"

#define BLYNK_FIRMWARE_VERSION        "0.1.0"

#define BLYNK_PRINT Serial
//#define BLYNK_DEBUG

#define APP_DEBUG

#include "BlynkEdgent.h"


void setup()
{
  Serial.begin(115200);
  delay(2000);


  BlynkEdgent.begin();
}

void loop() {
  BlynkEdgent.run();
}

This is NodeJS code, not C++. You are using C++.
In addition, tis was a solution for:
Connecting to blynk-cloud.com:443
not
Connecting to blynk.cloud:443

Use the Wemos D1 Mini.

Start by reading this:

and the latest Edgent_ESP8266 files from GitHub.
Un-comment the #define USE_WEMOS_D1_MINI line of code and add a physical pushbutton between D3 and GND and upload your sketch using the Tools > Erase Flash > Add Flash Contents option in the Arduino IDE.

You should then be able to re-provision your board and it should work correctly.

If not, then post full details of the problem, and please don’t say things like:

when asked questions like which Blynk library version you are using.

Pete.

BLUF (bottom line up front): Still not working. I was able to get the MKR1000 board to connect a couple of times, by resetting the board with double-tap, or 30-second hold, of reset button, and cycling power. I was able to connect with both an empty example sketch, and with my Greenhouse control sketch. But… on the 3rd attempt after just cosmetic changes to the sketch, it won’t connect again (neither the basic Edgent example, or my developed sketch), after 15-20 more tries with different reset attempts.

Details below.

Thank you PeteKnight, I’ve seen you reply to so many of these questions, and I don’t feel too beat down by your reply (I’ll try to never say, “all libraries are current”) again.
I’ve been ‘tinkering’ with this for about 6-8 months, trying to automate our greenhouse (temp control and watering) for times we’re away from home. I’m a retired Naval Flight Officer, not a developer, with just enough computer science education/experience to be dangerous.
I didn’t even notice that the other solution I referenced was for blynk-cloud.com instead of blynk.cloud.
I’ve only been using the new Blynk IoT since I started tinkering.

The code I posted was just a brand new example sketch I tried last night to see if the problem existed in a ‘clean’ sketch, vs one where I’ve added code for sensors, display, timers, functions to do things for the greenhouse. It’s just the Blynk example in the Arduino IDE, all I changed was my template and device info, and set the board to Arduino MKR1000.
And I had the same problem of connection timeout.

What bothers me is that it’s not a consistent problem - the same board/sketch connected just fine many ties earlier, then just stopped working after a meaningless code change (like adding a serial print line, etc.).

I have a different sketch, on a MKR1010 board that connects just fine, all the time. I mention that only to (potentially) rule out that the problem could be related to my wifi setup at home.

So, after many more attempts, and much more reading/searching (including reading Pete’s excellent Troubleshooting post (Troubleshooting Edgent Dynamic Provisioning Problems), I thought I came across a fix, or explanation - resetting the board with 30-second reset button press, and/or double-tap. But, it’s not working again now, and I’m just at a loss.

Still trying different reset options, to figure out what worked an hour ago, but no luck… still get no connection, timeout, last error code 702.
Could it be a hardware problem with the MKR1000 board? It did work fine just a while ago, so I’m inclined to say it’s not the board, and not the sketch, but I don’t know.
Any other ideas?

This is the full Greenhouse sketch I’ve been trying, in addition to the basic Blynk example.


/*  Arduino MKR1000
 */

#define BLYNK_TEMPLATE_ID "TMPLGvxtfc-X"
#define BLYNK_DEVICE_NAME "Greenhouse"

#define BLYNK_FIRMWARE_VERSION        "1.0.1"

#define BLYNK_PRINT Serial
//#define BLYNK_DEBUG        // comment out to not see the debug info
#define APP_DEBUG           // same...

#include "BlynkEdgent.h"      // for the other files (folders) in this sketch

//#include <SPI.h>              // for OLED display
#include <Adafruit_GFX.h>     // OLED
#include <Adafruit_SSD1306.h> // OLED
#define SCREEN_WIDTH 128      // OLED display width, in pixels
#define SCREEN_HEIGHT 64      // OLED display height, in pixels
                              // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
                              // The pins for I2C are defined by the Wire-library. So, son't need to define them here 
#define OLED_RESET     -1     // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C   //< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);   // declaration for OLED display

#include "Adafruit_BME680.h"
/*#define BME_SCK 13
#define BME_MISO 12
#define BME_MOSI 11
#define BME_CS 10*/
// #define SEALEVELPRESSURE_HPA (1021)   // adjust to change altitude
Adafruit_BME680 bme; // I2C
//Adafruit_BME680 bme(BME_CS); // hardware SPI
//Adafruit_BME680 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK);

#include "Adafruit_LTR390.h"
Adafruit_LTR390 ltr = Adafruit_LTR390();

#include "Adafruit_VEML7700.h"
Adafruit_VEML7700 veml = Adafruit_VEML7700();

#include <WidgetRTC.h>
WidgetRTC rtc;
//#include <RTCZero.h>;         // for Real Time Clock  https://www.arduino.cc/en/Reference/RTC
//RTCZero rtc;                  // declaration for RTC instance (of RTCZero), called 'rtc'

//#include <avr/dtostrf.h>      // for the string convertion to get set # of digits to display, used in pressure string

#include <DHT.h>;             // for DHT22 temp/hum sensor
#define DHTPIN1 4             // signal from DHT1
#define DHTPIN2 5             // signal from DHT2
#define DHTTYPE1 DHT22        // DHT 22, power supply 3.3 to 5.5v
#define DHTTYPE2 DHT11        // DHT 11, power supply 3.3 to 5.5v
DHT dht1(DHTPIN1, DHTTYPE1);     // declaration for DHT instance, initialize DHT sensor
DHT dht2(DHTPIN2, DHTTYPE2);     // declaration for DHT instance, initialize DHT sensor

#define soilSensor1 A4        // signal from soil sensor 1 goes into hardwired pin A3 - Grapefruit1

#define valve1 1              // V1, relay_1 hardwired to pin A1, Grapefruit valve 
#define valve2 2              // V2, relay_2 hardwired to pin A2, Shelf valve

BlynkTimer timer;             // to call functions at set intervals

int waterRunning1 = 0;         // V1, for watering, or relayStatus1 
int waterRunning2 = 0;         // V2, for watering, or relayStatus2 
int waterEnabled1 = 0;         // V3, watering enabled or not for Grapefruit, initialy OFF, button in app to turn ON
int waterEnabled2 = 0;         // V4, same for Shelf...
int tempDHT;                   // V5, send to app
int humidDHT;                  // V6, send to app, monitor environment 
int tempDHT2;                  // V7
int humidDHT2;                 // V8
int tempDiff;                  // V28
int percentMoisture1;          // V9, Grapefruit sensor converted to %
int waterPoint1 = 25;          // V11, soil % where start Grapefruit watering - default, change with slider in app
int waterTime1 = 120;          // V12, how long to open VALVE1, in seconds, change with slider in app  
int dayTime = 1;               // V29, variable set to 0 or 1 in flow, to determine if should water (no watering at night), current Lux vs threshold
int luxVEML = 100;             // V26, light reading
int dayLightThreshold = 300;   // V15, threshold to determine dayTime or not, comparing to current Lux level
String dayLightStatus;         // V16, set to "yes" or "no" after dayTime is changed, so can easily see on the app
int dry1 = 0;    //800              // V17, value of completely dry sensor, we'll trigger watering based on a % of moisture, adjust these in the app
int wet1 = 800;  //250              // V18, value of fully wet for the sensor, 
int lowTempWarn = 53;          // V21, when to send notifications on temp, can adjust these in app
int lowTempAlarm = 50;         // V22, same...
String nowTime;                // V25, push current time to display in app (quick way to see status, or when went offline) 
const int GMT = -5;            // set GMT time zone adjust (-5 here on US east coast, or -4 in summer/DST)
int IAQ = 1;                   // V27, to display IAQ in app 

BLYNK_WRITE(V1) {                       // Blynk button tied to V9, to show status of Relay_1, and control the relay on Pin 1, called valve1
  int pinValue1 = param.asInt();        // assign incoming value from virtual pin V9 to a variable (pinValue1)
  digitalWrite(valve1,pinValue1);       // A1 is pin for Relay_1, for Grapefruit, so pushing "ON" button in app, sets HIGH to A1
}
BLYNK_WRITE(V2) {                      // Blynk button tied to V10, show status of Relay_2, and control the relay on Pin 2 called valve2
  int pinValue2 = param.asInt();        // assign incoming value from virtual pin V10 to a variable (pinValue2)
  digitalWrite(valve2,pinValue2);       // pinValue2 is written to valve2 (which is pin A2, going to relay2  
}

BLYNK_WRITE(V3) {                      // 
  waterEnabled1 = param.asInt();
}
BLYNK_WRITE(V4) {                      // 
  waterEnabled2 = param.asInt();
}
BLYNK_WRITE(V11) {                      // Blynk app slider sets value on V11 for watering threshold, in soil moisture %
  waterPoint1 = param.asInt();          //reading the value of slider (sec) passed through V11
}
BLYNK_WRITE(V12) {                      // V12 Blynk app slider sets value for watering time, in seconds
  waterTime1 = param.asInt();           //reading the value of slider (sec) passed through V12, change to mSec below
}


BLYNK_WRITE(V15) {                      // V15 Blynk app slider sets value for 'dayLightThreshold' value, to determine dayTime from Lux
  dayLightThreshold = param.asInt();
}
BLYNK_WRITE(V16) {                      // V16 for 'dayLightStatus' value, also set in function below, yes or no it's light out
  dayLightStatus = param.asInt();
}

BLYNK_WRITE(V17) {                      // 
  dry1 = param.asInt();
}
BLYNK_WRITE(V18) {                      // 
  wet1 = param.asInt();
}


BLYNK_WRITE(V21) {                      // V21 for 'lowTempWarn' value, set by slider in app, to trigger the notofication
  lowTempWarn = param.asInt();
}
BLYNK_WRITE(V22) {                      // V22 for 'lowTempAlarm' value, set by slider in app, to trigger the notofication
  lowTempAlarm = param.asInt();
}

BLYNK_WRITE(V25) {                 // 
  nowTime = param.asInt();
}

BLYNK_CONNECTED() {                     // runs if/when Blynk reconnects, runs included commands...
  Blynk.sendInternal("rtc", "sync");    // request current local time from Blynk CLoud 
  Blynk.syncAll();                      // Command restores all Widget values based on last saved values on the server.
                                        // All analog and digital pin states will be restored. 
                                        // Every Virtual Pin will perform BLYNK_WRITE event.
//  Blynk.syncVirtual(V0, V3);          // Or could update single/multiple pins with this 
}


void setup()
{
  Serial.begin(115200);
  delay(2000);

  BlynkEdgent.begin();        // All the magic
  rtc.begin();                // start the RTC library code, included above

//-----------------+++++++++++++++++++--------------------

  Serial.println("Adafruit LTR-390 test");    // light and UV sensor

  if ( ! ltr.begin() ) {
    Serial.println("Couldn't find LTR sensor!");
    while (1) delay(10);
  }
  Serial.println("Found LTR sensor!");

  ltr.setMode(LTR390_MODE_UVS);   // sensor is EITHER UV or LUX - NOT both
  if (ltr.getMode() == LTR390_MODE_ALS) {
    Serial.println("In ALS mode");
  } else {
    Serial.println("In UVS mode");
  }

  ltr.setGain(LTR390_GAIN_3);
  Serial.print("Gain : ");
  switch (ltr.getGain()) {
    case LTR390_GAIN_1: Serial.println(1); break;
    case LTR390_GAIN_3: Serial.println(3); break;
    case LTR390_GAIN_6: Serial.println(6); break;
    case LTR390_GAIN_9: Serial.println(9); break;
    case LTR390_GAIN_18: Serial.println(18); break;
  }

  ltr.setResolution(LTR390_RESOLUTION_16BIT);
  Serial.print("Resolution : ");
  switch (ltr.getResolution()) {
    case LTR390_RESOLUTION_13BIT: Serial.println(13); break;
    case LTR390_RESOLUTION_16BIT: Serial.println(16); break;
    case LTR390_RESOLUTION_17BIT: Serial.println(17); break;
    case LTR390_RESOLUTION_18BIT: Serial.println(18); break;
    case LTR390_RESOLUTION_19BIT: Serial.println(19); break;
    case LTR390_RESOLUTION_20BIT: Serial.println(20); break;
  }

  ltr.setThresholds(100, 1000);
  ltr.configInterrupt(true, LTR390_MODE_UVS);

  delay(2000);

  
//-----------------+++++++++++++++++++--------------------

  Serial.println(F("BME680 async test"));    // Temp/Hum/Press/Gas sensor

  if (!bme.begin()) {
    Serial.println(F("Could not find a valid BME680 sensor, check wiring!"));
    while (1);
  } else {
    Serial.println("BME680 is good to go");
  }

  // Set up oversampling and filter initialization
  bme.setTemperatureOversampling(BME680_OS_8X);
  bme.setHumidityOversampling(BME680_OS_2X);
  bme.setPressureOversampling(BME680_OS_4X);
  bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
  bme.setGasHeater(320, 150); // 320*C for 150 ms

//-----------------+++++++++++++++++++--------------------

  Serial.println("Adafruit VEML7700 Test");

  if (!veml.begin()) {
    Serial.println("Sensor not found");
    while (1);
  }
  Serial.println("VEML LUX Sensor found");

  veml.setGain(VEML7700_GAIN_1);
  veml.setIntegrationTime(VEML7700_IT_800MS);

  Serial.print(F("Gain: "));
  switch (veml.getGain()) {
    case VEML7700_GAIN_1: Serial.println("1"); break;
    case VEML7700_GAIN_2: Serial.println("2"); break;
    case VEML7700_GAIN_1_4: Serial.println("1/4"); break;
    case VEML7700_GAIN_1_8: Serial.println("1/8"); break;
  }

  Serial.print(F("Integration Time (ms): "));
  switch (veml.getIntegrationTime()) {
    case VEML7700_IT_25MS: Serial.println("25"); break;
    case VEML7700_IT_50MS: Serial.println("50"); break;
    case VEML7700_IT_100MS: Serial.println("100"); break;
    case VEML7700_IT_200MS: Serial.println("200"); break;
    case VEML7700_IT_400MS: Serial.println("400"); break;
    case VEML7700_IT_800MS: Serial.println("800"); break;
  }

  //veml.powerSaveEnable(true);
  //veml.setPowerSaveMode(VEML7700_POWERSAVE_MODE4);

  veml.setLowThreshold(10000);
  veml.setHighThreshold(20000);
  veml.interruptEnable(true);

  delay(2000);
  
//-----------------+++++++++++++++++++--------------------

  pinMode(valve1, OUTPUT);            // A1 (valve1) is hardwired board pin for VALVE1, define it here as output
  pinMode(valve2, OUTPUT);            // A2 (valve2) is hardwired board pin for VALVE2, define it as output
  pinMode(soilSensor1, INPUT);        // A3 is soil sensor1, an input

  dht1.begin();      // Inside data - begin reading temp/humid from DHT22
  dht2.begin();      // Outside data - begin reading temp/humid from second DHT22
  
  SPI.begin();       // for OLED
  delay(100);
  
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {          // test for it working
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }
  // Show initial display buffer contents on the screen --  the library initializes this with an Adafruit splash screen.
  display.display();                  // so we should see the Adafruit logo if it's working
  delay(1000); // Pause for a second
  display.clearDisplay();             // end for OLED      

  delay(2000);     

//-----------------+++++++++++++++++++--------------------

// TIMERS DEFINED HERE, for functions below, with lentgh of time between calls, ie "1000L" 1 sec
  timer.setInterval(2000L, sendToCloud);            // read/send status data every 2 sec
  timer.setInterval(4L*60L*1000L, waterOnOff);      // run waterOnOff() function every 4 min
                                      // Keep interval short since this will also turn off manually-activated watering...
                                      // to prevent accidental over-watering if you forget to turn off manual watering,
                                      // or if something prevents ability to send a manual watering off command.
                                      // like, if the app goes offline when sending the water ON command

//-----------------+++++++++++++++++++--------------------

  nowTime = String(hour()) + ":" + minute() + ":" + second();
//  String currentDate = String(day()) + " " + month() + " " + year();
  Serial.print("In Setup... Current time: ");
  Serial.print(nowTime);
//  Serial.print(" ");
//  Serial.print(currentDate);
  Serial.println();

  Serial.println("setup complete, start Program Loop");

  delay(2000);  
  
}  


void loop() {
  BlynkEdgent.run();
  timer.run();      // calls timer function, that calls the functions for data and watering on defined timing
}


// +++++  END  loop()  ++++++++++  START function definitions  

/*
 * These functions are defined below:
 * void sendToCloud()
 * void waterOnOff()  --  Includes GRAPEFRUIT and SHELF
 */

void sendToCloud() {            // define fuction to read and send environment data, called by timer

  nowTime = String(hour()) + ":" + minute() + ":" + second();
  Blynk.virtualWrite(V25, nowTime);   // should push "mo/dy hr:mn" to app

//-----------------------------

// UV reading from LTR390 sensor...
  if (ltr.newDataAvailable()) {
      Serial.print("LTR390 sensor UV data: "); 
      Serial.println(ltr.readUVS());
  }

//-----------------------------

// Environmental Date from BME680 sensor...

  // Tell BME680 to begin measurement.
  unsigned long endTime = bme.beginReading();
  if (endTime == 0) {
    Serial.println(F("Failed to begin reading :("));
    return;
  }
//  Serial.print(F("BME680 reading started at "));  // put back in to check timning of readings
//  Serial.print(millis());
//  Serial.print(F(" and will finish at "));
//  Serial.print(endTime);

//  Serial.print(F(   "You can do other work during BME680 measurement.  "));
  delay(50); // This represents parallel work.
//  There's no need to delay() until millis() >= endTime: bme.endReading()
//  takes care of that. It's okay for parallel work to take longer than
//  BME680's measurement time.

//  Obtain measurement results from BME680. Note that this operation isn't
//  instantaneous even if milli() >= endTime due to I2C/SPI latency.
  if (!bme.endReading()) {
    Serial.println(F("Failed to complete reading :("));
    return;
  }
//  Serial.print(F("Reading completed at "));
//  Serial.println(millis());

  Serial.print(F("BME680 Temperature = "));
//  Serial.print(bme.temperature);    // is Celcius
//  Serial.println(F(" *C"));
  double fBME = ((bme.temperature * 9/5) + 32);
  Serial.print(fBME);    // is F
  Serial.println(F(" ºF"));

  Serial.print(F("and Pressure = "));
//  Serial.print(bme.pressure / 100.0);
//  Serial.println(F(" hPa"));
  double pressureHg = (bme.pressure / 1000) /3386.39;  // check this math, output was "0.30 inHg"
  Serial.print(pressureHg);
  Serial.println(F(" inHg"));
  
  Serial.print(F("Humidity = "));
  Serial.print(bme.humidity);
  Serial.println(F(" %"));

  Serial.print(F("Gas = "));
  Serial.print(bme.gas_resistance / 1000.0);
  Serial.println(F(" KOhms (higher is better!)"));

//  Serial.print(F("Approx. Altitude = "));
//  Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
//  Serial.println(F(" m"));

  IAQ = (log(bme.gas_resistance / 1000.0) + 0.04 * bme.humidity); // get Indoor Air Quality (IAQ)
  Serial.print("IAQ (lower is better, 0-50 is Good) is:  ");
  Serial.println(IAQ);
  Blynk.virtualWrite(V27, IAQ);           // pushes lux data to cloud app
  
//-----------------------------

  luxVEML = veml.readLux();
  Serial.print("Lux: "); Serial.print(veml.readLux());
  Serial.print(" and White is: "); Serial.println(veml.readWhite());
//  Serial.print("Raw ALS: "); Serial.println(veml.readALS());
  Blynk.virtualWrite(V26, luxVEML);           // pushes lux data to cloud app

/*  
  uint16_t irq = veml.interruptStatus();    // not sure why I would care about this... 
  if (irq & VEML7700_INTERRUPT_LOW) {
    Serial.println("** Low threshold"); 
  }
  if (irq & VEML7700_INTERRUPT_HIGH) {
    Serial.println("** High threshold"); 
  }
*/  
  delay(500);

//-----------------------------

  if (luxVEML > dayLightThreshold) {        // set "dayTime" variable to 0 or 1 (dark or light) 
    dayLightStatus = "Yes!";
    dayTime = 1;
    Blynk.virtualWrite(V16, dayLightStatus);          // pushes it's "day" to cloud app
  } else {
      dayLightStatus = "No";
      dayTime = 0;
      Blynk.virtualWrite(V16, dayLightStatus);        //  pushes it's "dark" to cloud app
    }
  

  tempDHT = dht1.readTemperature(true);            // Read DHT22 sensor  ("true" returns ºF)
//  delay(100);
  humidDHT = dht1.readHumidity();
//  delay(100);
  if (isnan(humidDHT) || isnan(tempDHT)) {         // check that sensor read is working
    Serial.println("Error reading DHT22, inside temp / humidity");
  }

  tempDHT2 = dht2.readTemperature(true);            // Read DHT11 sensor  ("true" returns ºF)
//  delay(100);
  humidDHT2 = dht2.readHumidity();
//  delay(100);
  if (isnan(humidDHT2) || isnan(tempDHT2)) {         // check that sensor read is working
    Serial.println("Error reading DHT11, outside temp / humidity");
  }

  tempDiff = tempDHT - tempDHT2;

  int moisture1 = analogRead(soilSensor1);                // read analog input value of soil sensor #1 and store it
  percentMoisture1 = map(moisture1, wet1, dry1, 100, 0);  // we'll convert to a 0-100 percentage, use wet and dry variables

  Blynk.virtualWrite(V9, percentMoisture1);               // pushes Grapefruit soil moisture value to cloud app
  Blynk.virtualWrite(V5, tempDHT);                        // send all environment data to cloud
  Blynk.virtualWrite(V6, humidDHT);
  Blynk.virtualWrite(V7, tempDHT2);                      // send DHT2 environment data to cloud
  Blynk.virtualWrite(V8, humidDHT2);
  Blynk.virtualWrite(V23, tempDiff);

                                          // Send info to OLED Display...
  display.clearDisplay();                 // Clear the buffer
  display.setTextColor(SSD1306_WHITE);   
  display.setTextSize(1);                 // Draw 2X-scale text
  display.setCursor(0, 1);                // 5 over and 1 down
  display.print("      Grapefruit ");
  display.display();                      // Show that text

  display.setCursor(0, 24);               // cursor to 0 over and 25 down
  display.setTextSize(3);
  display.print("  ");
  display.setTextSize(5);
  display.print(percentMoisture1);
  display.setTextSize(2);
  display.println(" %");
  display.display(); 

  Serial.print("in sendToCloud...  ");           // Send a little info to Serial monitor just to check it's running...
  Serial.print("Inside temp F: ");
  Serial.print(tempDHT);
  Serial.print("     Outside temp F: ");
  Serial.println(tempDHT2);  
  Serial.print("Difference between INSIDE and OUTSIDE temp is : ");
  Serial.println(tempDiff);  
  
if (tempDHT <= lowTempWarn){     
    Blynk.logEvent("low_temp_warning", lowTempWarn) ;
}
if (tempDHT <= lowTempAlarm){
    Blynk.logEvent("low_temp_alarm", lowTempAlarm) ;
}

}  // end of sendToCloud function



void waterOnOff() {        // define the fuction to check soil and turn water on and off, called by timer

  Serial.print("Grapefruit...");

  int waterThisMills1 = waterTime1*1000;                    // change slider set duration to millisec to use in delay for watering
  Serial.print("  grapefruit moisture % is ");
  Serial.println(percentMoisture1);
  
  if (waterEnabled1 == 1) {
              Serial.println("at GF, waterEnabled1 is 1... next check if already watering...");
    if (waterRunning1 == 0) {
              Serial.println("at GF, waterRunning1 is 0, not running... next check moisture...");
      if (percentMoisture1 <= waterPoint1) {   // or could use soil%-3   // check moisture %, if below set %, and is day, then start watering
              Serial.println("at GF, percentMoisture1 is below waterPoint1 (dry)... next check light level...");
        if (dayTime == 1) {                           // if daytime, then water, and start timeout to turn off after duration...
          Serial.println("at GF, dayTime is 1 (it's light)...  all conditions met, so WATER ON for the GF.");
          digitalWrite(valve1, HIGH);                           // send 3.3v signal to the relay, sends 12v to valve, OPENS
          waterRunning1 = 1;
          Blynk.virtualWrite(V1, HIGH);                         // turn ON app button/state for watering ON
          Blynk.virtualWrite(V23, nowTime);                     // update "whenWatered" time in the app
          Blynk.logEvent("grapefruit_water_on", "Watering Grapefruit Now") ;
          timer.setTimeout(waterThisMills1 , []() {              // wait here for 'thisMillls, then run the following
              digitalWrite(valve1, LOW);                         // turn OFF the water after set time
              waterRunning1 = 0;
              Blynk.virtualWrite(V1, LOW);                       // app button to OFF for watering
              Blynk.logEvent("grapefruit_water_off", "Water OFF") ;      
          });
        } else {                                      // else it's dark, no water, but ensure water turned off, if manually on
            digitalWrite(valve1, LOW);                          // turn OFF the water after set time
            Blynk.virtualWrite(V1, LOW);                        // app button to OFF for watering
          }
      } else {        // else from moisture check, if above threshold, don't need to water, ensure water is OFF
          digitalWrite(valve1, LOW);                            // if it's not dry, don't send signal to relay
          Blynk.virtualWrite(V1, LOW);                          // app button to OFF for watering
        }
    }
  }

Serial.println();

}

Update…
I just swapped boards, and the Greenhouse sketch (shown above) which was not connecting on the MKR1000 board, works fine on MKR1010 board… and my YogurtMaking sketch that was working just fine on the MKR1010 board does not connect when running the MKR1000 board.

So, it does seem like there’s a problem with the MKR1000 board. But it’s strange that I have been able to get the MKR1000 board to connect (with the Greenhouse sketch) a bunch of times in the past, as recently as a couple of hours ago. It’s been up and running most of the time during the last 6 months in the greenhouse.

I think I ready to just toss that MKR1000 board.

I’m not familiar with the MKR range of boards, so can’t really comment on your testing results, which is why I said…

I do know that some MKR boards need to have their WiFi firmware updated, to update their certificates file, but I don’t know if this is true of your boards. There are some topic about this on the forum if you want to do some searching.

A few general comments about your code…

This is Legacy code…

Your void setup contains 8 seconds of blocking delays after BlynkEdgent.begin(). This is in addition to the time it takes to execute the void setup code.
Blynk has a 10 second timeout default, which basically means that if the sketch hasn’t encountered a BlynkEdgent.run() for that period of time then it will terminate the connection between the server and the device.
I don’t think these delays are necessary, or if they are then don’t need to be any more than a few hundred milliseconds.
If the long delays are needed then I’d place them before the BlynkEdgent.begin()

This only works for datastreams that have the “Sync with latest server value every time device connects to the cloud” option enabled in the Advanced datastream setup options.

Also, if you’re having issues of the type you are describing, my advice is always to reboot both your router and any other repeater/mesh devices on your network.

Personally, I always preferred jumping out of “perfectly good aeroplanes” :wink:

Pete.

Thanks Pete.

I do have some D1 Mini clone boards, and I will try that. And I learned from your troubleshooting post that I probably need to add a physical reset button. (I had tried a project with a D1 board a while back with no success, and maybe it was because of the reset button.)

And I appreciate your comments on my code.

I recently changed the RTC code when looking for an easy way to set up a stopwatch-like timer (tap button in app to start counting, displayed in app) to keep track of time (along with temp) when making yogurt, in a different sketch. An example I found used WidgetRTC - and as a longshot I tried changing RTC here to fix the connect problem. Obviously it didn’t help, I’ll change it back, everywhere.

// #include <RTCZero.h>;         // for Real Time Clock  https://www.arduino.cc/en/Reference/RTC
// RTCZero rtc;                  // create an object called "rtc" (instance of RTCZero)

#include <WidgetRTC.h>
WidgetRTC rtc;

All those extra delays were just there for troubleshooting (kind of shooting in the dark), trying to see if code running was interfering with connecting to Blynk cloud. That wasn’t it. Those delays are gone.

Yes, the Blynk.syncAll(); is used to sync about a dozen datastreams like thresholds for watering and alarm/notifications, limits for sensors, etc.

I certainly have been regularly checking and resetting wifi throughout this whole process. I have an Eero mesh WiFi setup, and often wondered if that could cause a problem - but I don’t think it has been so far.

And, I never had to eject or jump out of a military plane (thank goodness), but I did tandem skydive once just for fun, and loved it!

Thanks again!

1 Like