Using OTA with more than just a blinking LED

Hi everyone, I am new at the OTA thing and all the videos/articles I see consist of basiclaly just editing the loop code in the Edgent example. Below is my code, it’s a simple weather station. If i want to update the code, for example tune the barometric pressure a bit or what ever, how can I add the Blynk.Air functionality? The weather staion will be sealed in a box, so I want to be able to update code when necessary.

Normally I run it to take measurements and then deep sleep, but if pin 2 is high it stays on so it can be programmed OTA, this will be facilitated by a physical switch on my box.

Any help will be appreciated, thanks!

/*************************************************************

  This is a simple demo of sending and receiving some data.
  Be sure to check out other examples!
 *************************************************************/

/* Fill-in information from Blynk Device Info here */
#define BLYNK_TEMPLATE_ID           "TMPL289zSINuI"
#define BLYNK_TEMPLATE_NAME         "Janre"
#define BLYNK_AUTH_TOKEN          
#define BLYNK_FIRMWARE_VERSION "0.0.2"

#define BLYNK_TEMPLATE_ID "TMPL289zSINuI"
#define BLYNK_TEMPLATE_NAME "Janre"

#define BLYNK_PRINT Serial
//#define BLYNK_DEBUG

#define APP_DEBUG

/* Comment this out to disable prints and save space */
#define BLYNK_PRINT Serial

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <DHT.h>
#include <Wire.h>
#include <Adafruit_BMP280.h>
Adafruit_BMP280 bmp; // I2C

#define DHTPIN 13        // DHT sensor pin
#define DHTTYPE DHT11    // DHT sensor type

DHT dht(DHTPIN, DHTTYPE);

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "Janrewifi";
char pass[] = "Janre123";

BlynkTimer timer;

// Pin 2 definition
#define SKIP_DEEP_SLEEP_PIN 2

// This function sends DHT11 data to Blynk
void sendSensorData() {
  // Read temperature and humidity from DHT sensor
  float temperature = bmp.readTemperature();
  float pressure = (bmp.readPressure() / 100.0) + 1000;
  float altitude = bmp.readAltitude(1015);
  float humidity = dht.readHumidity();

  Serial.println("Start Measuring...");

  // Send temperature and humidity data to Blynk
  delay(1000);
  Blynk.virtualWrite(V4, temperature); // Virtual pin V4 for temperature
  delay(1000);
  Serial.println(temperature);

  delay(1000);
  Blynk.virtualWrite(V0, humidity); // Virtual pin V0 for humidity
  delay(1000);
  Serial.println(humidity);

  delay(1000);
  Blynk.virtualWrite(V1, pressure); // Virtual pin V1 for pressure
  delay(1000);
  Serial.println(pressure);

  delay(1000);
  Blynk.virtualWrite(V2, altitude); // Virtual pin V2 for altitude
  delay(1000);
  Serial.println(altitude);

  Serial.println("Measured");

  // Check the state of pin 2
  int pin2State = digitalRead(SKIP_DEEP_SLEEP_PIN);

  if (pin2State == HIGH) {
    // Pin 2 is high, skip deep sleep
    Serial.println("Pin 2 is HIGH. Skipping deep sleep.");
  } else {
    // Pin 2 is low, enter deep sleep for 10 minutes (600 seconds)
    Serial.println("Going to sleep...");
    ESP.deepSleep(600e6); // Deep sleep for 10 minutes (in microseconds)
  }
}

void setup() {
  // Initialize serial communication
  Serial.begin(9600);

  // Initialize pin 2 as an input
  pinMode(SKIP_DEEP_SLEEP_PIN, INPUT);

  // Initialize BMP280 sensor
  Serial.println(F("BMP280 test"));
  unsigned status = bmp.begin(0x76);
  if (!status) {
    Serial.println(F("Could not find a valid BMP280 sensor, check wiring or try a different address!"));
    while (1) delay(10);
  }
  // Set BMP280 sampling settings
  bmp.setSampling(
    Adafruit_BMP280::MODE_NORMAL,
    Adafruit_BMP280::SAMPLING_X2,
    Adafruit_BMP280::SAMPLING_X16,
    Adafruit_BMP280::FILTER_X16,
    Adafruit_BMP280::STANDBY_MS_500
  );

  // Initialize DHT sensor
  dht.begin();

  // Initialize Blynk
  Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
  
  // Setup a function to be called every 2 seconds
  timer.setInterval(2000L, sendSensorData);
}

void loop() {
  // Run Blynk and the timer
  Blynk.run();
  timer.run();
}

I don’t really understand that comment.
The Edgent example already has Blynk.Air OTA built-in, and doesn’t need any editing of the “loop code” to make OTA work.

If you want to add Blynk.Air OTA to a non-Edgent sketch then you should read this…

Also, your Deep sleep sketch is very badly written. It keeps your device awake for far longer than is needed, and most of the delays in your sketch are redundant.

Pete.

Hi Pete, thanks for the reply.

I understand how that could have been understood wrong, no, Edgent works from the basic example etc. I’m just not sure how to implement it for my application.

The documentation to use OTA does basically just one example, I used OTA updates to load new code just once , but the update didn’t contain any Edgent code, so naturally I couldn’t update the code a second time.

Where should I add the Edgent part in my code to try ensure that after I upload it OTA, it will be able to be updated again OTA.

Also, thanks for pointing out the redundant delays etc, I’ve been having issues with some of the variables not updating on Blynk if the delays aren’t present, almost as if the board turns off before the data is sent, but I’ll have a look to see if I can find a better solution.

Kind regards,
Janre

I never suggested that you use any Edgent code in your sketch. I’d suggest you read the link I provided, it has all the answers you need.

That’s down to your poor code structure and not executing Blynk.run() after the Blynk,virtualWrites and before calling deepsleep.

Pete.

Thanks for the help Pete, it’s working well now, I also removed the timer because it’s useless for my case. I just need one reading when it wakes up. I also removed the delays and moved Blynk.run to my sendSensorData function, it’s nice and zippy now and the values update each time without hassle.

I had to however change the OTA code very slightly as the was an obselecence issue, I had to define WiFiCient and change the

http.begin(overTheAirURL);

to

http.begin(client, overTheAirURL);

Here is my updated code:

/*************************************************************

  This is a simple demo of sending and receiving some data.
  Be sure to check out other examples!
 *************************************************************/

/* Fill-in information from Blynk Device Info here */
#define BLYNK_TEMPLATE_ID     ""
#define BLYNK_TEMPLATE_NAME     "Janre"
#define BLYNK_AUTH_TOKEN            ""

#define BLYNK_FIRMWARE_VERSION "0.0.6"

/* Comment this out to disable prints and save space */
#define BLYNK_PRINT Serial

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <DHT.h>
#include <Wire.h>
#include <Adafruit_BMP280.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266httpUpdate.h>
Adafruit_BMP280 bmp; // I2C

#define DHTPIN 13         // DHT sensor pin
#define SKIP_DEEP_SLEEP_PIN 2
#define DHTTYPE DHT11    // DHT sensor type

DHT dht(DHTPIN, DHTTYPE);
WiFiClient client;

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "";
char pass[] = "";

BlynkTimer timer;

// This function sends DHT11 data to Blynk
void sendSensorData()
{
  // Read temperature and humidity from DHT sensor
  float temperature = bmp.readTemperature();
  float pressure = (bmp.readPressure()/100.0)+149;
  float altitude = bmp.readAltitude(1016);
  float humidity = dht.readHumidity();
  Serial.println("Start Measuring...");


  // Send temperature and humidity data to Blynk
  
  Blynk.virtualWrite(V0, temperature); // Virtual pin V4 for temperature
  
  Serial.println(temperature);

  
  Blynk.virtualWrite(V1, humidity);    // Virtual pin V0 for humidity
  
  Serial.println(humidity);

  
  Blynk.virtualWrite(V2, pressure); // Virtual pin V4 for temperature
  
  Serial.println(pressure);

  Blynk.virtualWrite(V4, altitude); // Virtual pin V4 for temperature

  Serial.println(altitude);

  Serial.println("Measured");
  Blynk.run();
  Serial.println("Going to sleep...");
  
  ESP.deepSleep(180e6); // Deep sleep for 10 minutes (in microseconds)

}

void setup()
{

  Serial.begin(9600);
  while ( !Serial ) delay(100);   // wait for native usb
  Serial.println(F("BMP280 test"));
  unsigned status;
  //status = bmp.begin(BMP280_ADDRESS_ALT, BMP280_CHIPID);
  status = bmp.begin(0x76);
  if (!status) {
    Serial.println(F("Could not find a valid BMP280 sensor, check wiring or "
                      "try a different address!"));
    while (1) delay(10);
  }
  /* Default settings from datasheet. */
  bmp.setSampling(Adafruit_BMP280::MODE_NORMAL,     /* Operating Mode. */
                  Adafruit_BMP280::SAMPLING_X2,     /* Temp. oversampling */
                  Adafruit_BMP280::SAMPLING_X16,    /* Pressure oversampling */
                  Adafruit_BMP280::FILTER_X16,      /* Filtering. */
                  Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */
  // Debug console

  // Initialize DHT sensor
  dht.begin();

  Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
  // You can also specify server:
  //Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass, "blynk.cloud", 80);
  //Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass, IPAddress(192,168,1,100), 8080);

  // Setup a function to be called every 5 seconds
  //timer.setInterval(2000L, sendSensorData);
  sendSensorData();
}

void loop()
{
  //Blynk.run();
  //timer.run();
  // You can inject your own code or combine it with other sketches.
  // Check other examples on how to communicate with Blynk. Remember
  // to avoid delay() function!
}

//________________________________________________________________
String overTheAirURL = "";
BLYNK_WRITE(InternalPinOTA) {
  overTheAirURL = param.asString();
  HTTPClient http;
  http.begin(client, overTheAirURL);
  int httpCode = http.GET();
  if (httpCode != HTTP_CODE_OK) {return;}
  int contentLength = http.getSize();
  if (contentLength <= 0) {return; }
  bool canBegin = Update.begin(contentLength);
  if (!canBegin) { return;}
  Client& client = http.getStream();
  int written = Update.writeStream(client);
  if (written != contentLength) {return;}
  if (!Update.end()) {return;}
  if (!Update.isFinished()) {return;}
reboot();
}

void reboot()
{
#if defined(ARDUINO_ARCH_MEGAAVR)
  wdt_enable(WDT_PERIOD_8CLK_gc);
#elif defined(__AVR__)
  wdt_enable(WDTO_15MS);
#elif defined(__arm__)
  NVIC_SystemReset();
#elif defined(ESP8266) || defined(ESP32)
  ESP.restart();
#else
  #error "MCU reset procedure not implemented"
#endif
  for (;;) {}
}
//__________________________________________________________


I just want to know one more thing, lets say I ship an update. Will the board firmware get updated when Blynk.run is called or should I put in something else which ensures the firmware updates once it wakes up from deep sleep?

Janre

Yes, that was covered in the post I linked to.

You’ll need to do some testing.
Generally, the BLYNK_WRITE() callback functions don’t execute until Blynk.run() is executed, so you may need to add more Blynk.run() commands and possibly use BLYNK_CONNECTED().
One option it to put all of your sendsensorData code in BLYNK_CONNECTED

Pete.