Just my battery operated ESP8266 enviro sensor node with OTA update

here is my enviro sensor node, it has been developed with the enduring assistance of @Costas, @Lichtsignaal, @psoro and probably several others who i have code-hacked or just read how they solved their issues…

THANKS BLYNKERS :heart_eyes:

the node has these features:

  • BME280 as the temperature and humidity sensor
  • NOAA dew point calculator
  • BH1750 as the light sensor
  • ESP.deepSleep
  • OTA code updating
  • thingspeak data logging
  • max/min display

it runs off two 18350 (eBay) batteries to a MP2307 buck converter.

i recharge the batteries ever 3-4 weeks…

//#define BLYNK_PRINT Serial //this is the debugging for Blynk, turn off to reduce processor use
//#define BLYNK_DEBUG        // Optional, this enables 'full' debugging detailed prints
#define debug 0 // this is the debugging tag - change to 0 to turn off debugging  serial prints

#include <ESP8266WiFi.h>

#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <ESP8266HTTPUpdateServer.h>

#include <BlynkSimpleEsp8266.h>
#include <SimpleTimer.h>
#include <BME280.h>
#include <BH1750FVI.h>
#include <Wire.h>

WiFiClient client;
BH1750FVI LightSensor;

const char* host = "esp8266"; // will be "esp8266.local/update" in web browser
ESP8266WebServer httpServer(80);
ESP8266HTTPUpdateServer httpUpdater;

BME280 bme;                   // Default : forced mode, standby time = 1000 ms - this can be played with in the library, let me know if you have tried this!!!
SimpleTimer timer;

ADC_MODE(ADC_VCC);

IPAddress ip(192, 168, 0, 14); //check this!
IPAddress gateway(192, 168, 0, 1); //check this!
IPAddress subnet(255, 255, 255, 0); // check this!

int vcc = ESP.getVcc(); 
float humMin, humMax;
float tempMin, tempMax, newTemp, PreviousTempMin, PreviousTempMax;
double node3DewPoint;
int setProgramming, setProgrammingMode, resetMinMax;
int resetTemps;

// Time to sleep (in seconds):
const int sleepTimeS = 720; //this is 12 minutes (i.e. readings done 5 times per hour, 120 times per day)

const char* SSID = "insert";
const char* pass = "insert";

const char* serverThingspeak = "api.thingspeak.com"; //this is the Thingspeak address
String apiKeyThingspeak = "insert"; // Channel 78844

char authBlynk[] = "insert"; //insert token generated by Blynk

bool metric = true; // for BME280 outputs

BLYNK_WRITE(V5)
{
  tempMin = param.asFloat();
  Blynk.virtualWrite(V5, tempMin);
}

BLYNK_WRITE(V6)
{
  tempMax = param.asFloat();
  Blynk.virtualWrite(V6, tempMax);
}

BLYNK_WRITE(V7)   // reset min/max temps
{
  resetMinMax = param.asInt();
  if (resetMinMax == 1) {
    resetTemps = 1;
    Blynk.virtualWrite(V7, 0);
  }
}

BLYNK_WRITE(V10)   // progamming mode - set this to prevent sleep
{
  setProgrammingMode = param.asInt();
  if (setProgrammingMode == 1) 
{ // this stops esp.sleep so it can accept the OTA reprogramming
    setProgramming = 1;  
    Serial.println(F("set programing ACTIVATED"));
  }
  else if (setProgrammingMode == 0) 
{
    setProgramming = 0;  
    Serial.println(F("set programing INACTIVE"));
  }
}

void printBME280Data()
{
  float temp, hum, pres;
  long rssi = WiFi.RSSI();
  uint8_t pressureUnit(1);     // unit: B000 = Pa, B001 = hPa, B010 = Hg, B011 = atm, B100 = bar, B101 = torr, B110 = N/m^2, B111 = psi
  uint16_t lux = LightSensor.GetLightIntensity();// Get Lux value

  bme.ReadData(pres, temp, hum, metric, pressureUnit);   // Parameters: (float& pressure, float& temp, float& humidity, bool celsius = false, uint8_t pressureUnit = 0x0)
  node3DewPoint = dewPointAccurate(temp, hum);

  if (debug == 1)
  {
    Serial.print("Temp: ");
    Serial.print(temp);
    Serial.println("'C");
    Serial.print("Humidity: ");
    Serial.print(hum);
    Serial.println("% RH");
    Serial.print("Pressure: ");
    Serial.print(pres);
    Serial.println(" hPa");
    Serial.print("Dew point: ");
    Serial.print(node3DewPoint);
    Serial.println("'C");
    Serial.print("Light: ");
    Serial.print(lux);
    Serial.println(" lux");
    Serial.println("-------------------------------------------");
  }

  Blynk.virtualWrite(V11, temp); // this sends the reading to the Blynk virtual pin
  Blynk.virtualWrite(V9, hum); // this sends the reading to the Blynk virtual pin
  Blynk.virtualWrite(V2, pres); // this sends the reading to the Blynk virtual pin
  Blynk.virtualWrite(V8, node3DewPoint); // this sends the reading to the Blynk virtual pin
  Blynk.virtualWrite(V19, vcc); // this sends the reading to the Blynk virtual pin
  Blynk.virtualWrite(V18, rssi); // this sends the reading to the Blynk virtual pin
  Blynk.virtualWrite(V4, lux); // this sends the reading to the Blynk virtual pin

  newTemp = temp;
  if (debug == 1)
  {
    Serial.println("newTemp:");
    Serial.println(temp);
    Serial.println("current tempMin:");
    Serial.println(tempMin);
    Serial.println("current tempMax:");
    Serial.println(tempMax);
  }
  if (resetTemps == 1)
  {
    if (debug == 1)
    {
      Serial.println("resetting temps!");
    }
    tempMin = 50;
    tempMax = 0;
  }

  if (tempMin <= newTemp)
  {
    tempMin = tempMin;
    if (debug == 1)
    {
      Serial.println("no change to tempMin ");
    }
  }
  else if (tempMin > newTemp)
  {
    tempMin = newTemp;
    Blynk.virtualWrite(V5, tempMin);
    if (debug == 1)
    {
      Serial.println("tempMin updated");
    }
  }

  if (tempMax >= newTemp)
  {
    tempMax = tempMax;
    if (debug == 1)
    {
      Serial.println("no change to tempMax ");
    }
  }
  else if (tempMax < newTemp)
  {
    tempMax = newTemp;
    Blynk.virtualWrite(V6, tempMax);
    if (debug == 1)
    {
      Serial.println("tempMax updated");
    }
  }

  if ((vcc < 3260) && (vcc > 3245))
  {
    Blynk.notify(String("NODE06 - Outside BME280 Sensor battery low: ") + vcc + ("mV"));
  }
  else if (vcc <= 3235)
  {
    Blynk.notify(String("NODE06 - Outside BME280 Sensor BATTERY CRITICAL:") + vcc + ("mV"));
  }

  if (client.connect(serverThingspeak, 80))
  {
    String postStr = apiKeyThingspeak;
    postStr += "&field1=";
    postStr += String(temp);
    postStr += "&field2=";
    postStr += String(hum);
    postStr += "&field3=";
    postStr += String(pres);
    postStr += "&field4=";
    postStr += String(rssi);
    postStr += "&field5=";
    postStr += String(vcc);
    //postStr += "&field6=";
    //postStr += String(lux);
    postStr += "&field7=";
    postStr += String(node3DewPoint);
    postStr += "\r\n\r\n";

    client.print("POST /update HTTP/1.1\n");
    client.print("Host: api.thingspeak.com\n");
    client.print("Connection: close\n");
    client.print("X-THINGSPEAKAPIKEY: " + apiKeyThingspeak + "\n");
    client.print("Content-Type: application/x-www-form-urlencoded\n");
    client.print("Content-Length: ");
    client.print(postStr.length());
    client.print("\n\n");
    client.print(postStr);
  }
  if (debug == 1)
  {
    Serial.println(F("just thingspoke"));
  }
  delay(10);
  if (setProgramming == 0)
  {
    Blynk.virtualWrite(12, 0); // programming LED off
    ESP.deepSleep(sleepTimeS * 1000000);
    delay(10);
  }
  else if (setProgramming == 1)
  {
    Blynk.virtualWrite(12, 1023); //programming LED on
  }
}

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

    if (debug == 1)
    { Serial.print(F("File name: "));
      Serial.println(F(""));
      Serial.println(F("NODE06 - TPL Bug prototype BATTERY POWER - with Thingspeak & Blynk & Deep Sleep"));
      Serial.print(F("File name: "));
      Serial.println(__FILE__);
      Serial.println(F(""));
      Serial.print(F("ESP voltage: "));
      Serial.print(vcc);
      Serial.println(F("mV"));
      Serial.println(F(""));
      Serial.println(F("Where's Blynk??"));
    }

    WiFi.mode(WIFI_STA);
    WiFi.config(ip, gateway, subnet); // this sets the ESP IP configuration
    WiFi.setOutputPower(0); // this is from conkerkh sets wifi to lowest power

    Blynk.begin(authBlynk, SSID, pass, IPAddress(192, 168, 0, 7));

    ArduinoOTA.setHostname("Basement_plenum_ESP8266_controller");
    ArduinoOTA.onStart([]()
    {
      Serial.println("Start");
    });
    ArduinoOTA.onEnd([]()
    {
      Serial.println("\nEnd");
    });

    ArduinoOTA.onError([](ota_error_t error)
    {
      Serial.printf("Error[%u]: ", error);
      if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
      else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
      else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
      else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
      else if (error == OTA_END_ERROR) Serial.println("End Failed");
    });
    ArduinoOTA.begin();
    Serial.println("Ready - OTA Success!!!");
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
    MDNS.begin(host);
    httpUpdater.setup(&httpServer);
    httpServer.begin();
    MDNS.addService("http", "tcp", 80);
    String ipaddress = WiFi.localIP().toString();
    String chipID = String(ESP.getChipId(), HEX);
    char charChipID[10];
    chipID.toCharArray(charChipID, sizeof(charChipID));
    char charipaddress[16];
    ipaddress.toCharArray(charipaddress, sizeof(charipaddress));
    Serial.printf("Now open http://%s.local/update in your browser or \n", host);
    Serial.printf("http://%s/update or http://%s.lan/update if you prefer.\n", charipaddress, charChipID);

    while (!Blynk.connect())
    {
      delay(500);
      Serial.print(F("."));
    }

    long rssi = WiFi.RSSI();

    if (debug == 1)
    {
      Serial.println(F(""));
      Serial.println(F("Found some WiFi!"));
      Serial.print(F("WiFi signal strength (RSSI): "));
      Serial.print(rssi);
      Serial.println(F(" dBm"));
      Serial.println("");
      Serial.println(F("Blynk started! "));
      Serial.println(F("------------"));
    }
    
    if (debug == 0)
    {
      Serial.println(F("***************************debug is OFF***************************"));
    }

    Blynk.syncAll();

    LightSensor.begin();
    Wire.begin();
    LightSensor.SetAddress(Device_Address_L);//'L' = Address 0x5C ?
    LightSensor.SetMode(Continuous_H_resolution_Mode);
    timer.setInterval(60L * 1000L, printBME280Data); // runs main function every 60 seconds
    
    while (!Serial)
    {
    } // Wait

    while (!bme.begin())
    {
      Serial.println("Could not find BME280 sensor!");
      delay(1000);
    }
  }
}

void loop()
{
  Blynk.run(); // Initiates Blynk
  timer.run(); // Initiates SimpleTimer
  ArduinoOTA.handle();
  httpServer.handleClient();
}

/*-----( Declare User-written Functions )-----*/
// dewPoint function NOAA
// reference (1) : http://wahiduddin.net/calc/density_algorithms.htm
// reference (2) : http://www.colorado.edu/geography/weather_station/Geog_site/about.htm
//
double dewPointAccurate (double celsius, double humidity)
{
  // (1) Saturation Vapor Pressure = ESGG(T)
  double RATIO = 373.15 / (273.15 + celsius);
  double RHS = -7.90298 * (RATIO - 1);
  RHS += 5.02808 * log10(RATIO);
  RHS += -1.3816e-7 * (pow(10, (11.344 * (1 - 1 / RATIO ))) - 1) ;
  RHS += 8.1328e-3 * (pow(10, (-3.49149 * (RATIO - 1))) - 1) ;
  RHS += log10(1013.124); // NB = 1013 = air pressure, which you can substitute from BME280 if you want to, but it needs to be converted to suit your specific altitude i think?

  // factor -3 is to adjust units - Vapor Pressure SVP * humidity
  double VP = pow(10, RHS - 3) * humidity;

  // (2) DEWPOINT = F(Vapor Pressure)
  double T = log(VP / 0.61078); // temp var
  return (241.88 * T) / (17.558 - T);
}
/* ==== END Functions ==== */

i think all of these:

    Blynk.virtualWrite(12, 1023);

should be:

    Blynk.virtualWrite(V12, 255);

but i might change them one day…

i am using LOCAL SERVER on Raspberry Pi “Zero” and also the Spark Fun red/white skin:

this screen does funny faces sometimes, this one is an “unsure” look:

i am also going to put barometer trend as a feature, but other things are priority at the moment…

10 Likes

Thanks for sharing @Dave1829, nice project!
I wasn’t aware (as many many other things…) about ADC_MODE(ADC_VCC); function. I like it!!

Regards!

Very good work! Thanks for sharing
Really… A great work! Love it

One little question about battery drain… I think is too low. Fake battery? Do you have measured power consumption in deep sleep and in “operation” mode?
Time that turn on, take measures and then shut down?

Hi. How did you change the colors of blynk app?

If you buy the Sparkfun Blynk Board you get the red and white color scheme

Using the Local Server you can change the theme. At the moment there are two options, the Green and the Sparkfun theme.

Super. I’m using local server. Where is the option? Tanks for relay.

Go to “Blynk Administration Page” ->User list -> Click on your user, and sroll down till you find “Theme” at the dasboard you want to change:

http://docs.blynk.cc/#blynk-server-advanced-local-server-setup-administration-panel-ui

Does theme change possible for blynk cloud server.??

I guess it’s on the roadmap but no idea regarding timing…

No. It is planned for future.

1 Like

they were certainly CHEAP…

no, but it would be more important as i am going to place more nodes around the environment, (in a tree) so i will be more concerned about battery life in the future, plus consider solar)

i can probably re-add this to code… last time i did it i think it was 3 seconds? (but that was not the exact code above…)

thanks, it has a few things others can code-hack, so hopefully helps/inspires in some way or another…

the code has been developed with the generous help of committed Blynkers, that is for sure! :heart_eyes:

Great project!

Nice :+1:

Hi why write arduino ide 1.6.5 : sketch_nov23a.ino: In function ‘void BlynkWidgetWrite5(BlynkReq&, const BlynkParam&)’:
sketch_nov23a:54: error: ‘const class BlynkParam’ has no member named ‘asFloat’
sketch_nov23a.ino: In function ‘void BlynkWidgetWrite6(BlynkReq&, const BlynkParam&)’:
sketch_nov23a:60: error: ‘const class BlynkParam’ has no member named ‘asFloat’
sketch_nov23a.ino: In function ‘void printBME280Data()’:
sketch_nov23a:98: error: ‘debug’ was not declared in this scope
sketch_nov23a:127: error: ‘debug’ was not declared in this scope
sketch_nov23a:138: error: ‘debug’ was not declared in this scope
sketch_nov23a:149: error: ‘debug’ was not declared in this scope
sketch_nov23a:158: error: ‘debug’ was not declared in this scope
sketch_nov23a:167: error: ‘debug’ was not declared in this scope
sketch_nov23a:176: error: ‘debug’ was not declared in this scope
sketch_nov23a:220: error: ‘debug’ was not declared in this scope
sketch_nov23a.ino: In function ‘void setup()’:
sketch_nov23a:242: error: ‘debug’ was not declared in this scope
sketch_nov23a:258: error: ‘class ESP8266WiFiClass’ has no member named ‘setOutputPower’
sketch_nov23a:289: error: ‘class IPAddress’ has no member named ‘toString’
sketch_nov23a:306: error: ‘debug’ was not declared in this scope
sketch_nov23a:318: error: ‘debug’ was not declared in this scope
‘const class BlynkParam’ has no member named ‘asFloat’ ? thanks

update to latest IDE

Thank. I try Arduino IDE 1:6.12 and 13 but something is still wrong… ?:

C:\Users\boss\Desktop\_1\_1.ino: In function 'void printBME280Data()':

_1:88: error: 'debug' was not declared in this scope

   if (debug == 1)

       ^

_1:117: error: 'debug' was not declared in this scope

   if (debug == 1)

       ^

_1:128: error: 'debug' was not declared in this scope

     if (debug == 1)

         ^

_1:139: error: 'debug' was not declared in this scope

     if (debug == 1)

         ^

_1:148: error: 'debug' was not declared in this scope

     if (debug == 1)

         ^

_1:157: error: 'debug' was not declared in this scope

     if (debug == 1)

         ^

_1:166: error: 'debug' was not declared in this scope

     if (debug == 1)

         ^

_1:210: error: 'debug' was not declared in this scope

   if (debug == 1)

       ^

C:\Users\boss\Desktop\_1\_1.ino: In function 'void setup()':

_1:232: error: 'debug' was not declared in this scope

     if (debug == 1)

         ^

_1:248: error: 'class ESP8266WiFiClass' has no member named 'setOutputPower'

     WiFi.setOutputPower(0); // this is from conkerkh sets wifi to lowest power

          ^

_1:279: error: 'class IPAddress' has no member named 'toString'

     String ipaddress = WiFi.localIP().toString();

                                       ^

_1:296: error: 'debug' was not declared in this scope

     if (debug == 1)

         ^

_1:308: error: 'debug' was not declared in this scope

     if (debug == 0)

         ^

exit status 1
'debug' was not declared in this scope

what code are you trying to use?

please wrap it in the these code tags:

looks like you also need to update your IDE libraries…

Now this and Arduino IDE this sketch translate but ESP 8266 12E no connecting to internet and blynk-( I try write: esp8266.local/update to web browser but no working…


#define debug 0
#include <ESP8266WiFi.h>

#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <ESP8266HTTPUpdateServer.h>

#include <BlynkSimpleEsp8266.h>
#include <SimpleTimer.h>
#include <BME280.h>
#include <BH1750FVI.h>
#include <Wire.h>

WiFiClient client;
BH1750FVI LightSensor;

const char* host = "esp8266"; // will be "esp8266.local/update" in web browser
ESP8266WebServer httpServer(80);
ESP8266HTTPUpdateServer httpUpdater;

BME280 bme;                   // Default : forced mode, standby time = 1000 ms - this can be played with in the library, let me know if you have tried this!!!
SimpleTimer timer;

ADC_MODE(ADC_VCC);

IPAddress ip(192, 168, 0, 14); //check this!
IPAddress gateway(192, 168, 0, 1); //check this!
IPAddress subnet(255, 255, 255, 0); // check this!

int vcc = ESP.getVcc(); 
float humMin, humMax;
float tempMin, tempMax, newTemp, PreviousTempMin, PreviousTempMax;
double node3DewPoint;
int setProgramming, setProgrammingMode, resetMinMax;
int resetTemps;

// Time to sleep (in seconds):
const int sleepTimeS = 720; //this is 12 minutes (i.e. readings done 5 times per hour, 120 times per day)

const char* SSID = "ASUS";
const char* pass = "Jersin72";

const char* serverThingspeak = "api.thingspeak.com"; //this is the Thingspeak address
String apiKeyThingspeak = "insert"; // Channel 78844

char authBlynk[] = ""; //insert token generated by Blynk

bool metric = true; // for BME280 outputs



BLYNK_WRITE(V7)   // reset min/max temps
{
  resetMinMax = param.asInt();
  if (resetMinMax == 1) {
    resetTemps = 1;
    Blynk.virtualWrite(V7, 0);
  }
}

BLYNK_WRITE(V10)   // progamming mode - set this to prevent sleep
{
  setProgrammingMode = param.asInt();
  if (setProgrammingMode == 1) 
{ // this stops esp.sleep so it can accept the OTA reprogramming
    setProgramming = 1;  
    Serial.println(F("set programing ACTIVATED"));
  }
  else if (setProgrammingMode == 0) 
{
    setProgramming = 0;  
    Serial.println(F("set programing INACTIVE"));
  }
}

void printBME280Data()
{
  float temp, hum, pres;
  long rssi = WiFi.RSSI();
  uint8_t pressureUnit(1);     // unit: B000 = Pa, B001 = hPa, B010 = Hg, B011 = atm, B100 = bar, B101 = torr, B110 = N/m^2, B111 = psi
  uint16_t lux = LightSensor.GetLightIntensity();// Get Lux value

  bme.ReadData(pres, temp, hum, metric, pressureUnit);   // Parameters: (float& pressure, float& temp, float& humidity, bool celsius = false, uint8_t pressureUnit = 0x0)
  node3DewPoint = dewPointAccurate(temp, hum);

  if (debug == 1)
  {
    Serial.print("Temp: ");
    Serial.print(temp);
    Serial.println("'C");
    Serial.print("Humidity: ");
    Serial.print(hum);
    Serial.println("% RH");
    Serial.print("Pressure: ");
    Serial.print(pres);
    Serial.println(" hPa");
    Serial.print("Dew point: ");
    Serial.print(node3DewPoint);
    Serial.println("'C");
    Serial.print("Light: ");
    Serial.print(lux);
    Serial.println(" lux");
    Serial.println("-------------------------------------------");
  }

  Blynk.virtualWrite(V11, temp); // this sends the reading to the Blynk virtual pin
  Blynk.virtualWrite(V9, hum); // this sends the reading to the Blynk virtual pin
  Blynk.virtualWrite(V2, pres); // this sends the reading to the Blynk virtual pin
  Blynk.virtualWrite(V8, node3DewPoint); // this sends the reading to the Blynk virtual pin
  Blynk.virtualWrite(V19, vcc); // this sends the reading to the Blynk virtual pin
  Blynk.virtualWrite(V18, rssi); // this sends the reading to the Blynk virtual pin
  Blynk.virtualWrite(V4, lux); // this sends the reading to the Blynk virtual pin

  newTemp = temp;
  if (debug == 1)
  {
    Serial.println("newTemp:");
    Serial.println(temp);
    Serial.println("current tempMin:");
    Serial.println(tempMin);
    Serial.println("current tempMax:");
    Serial.println(tempMax);
  }
  if (resetTemps == 1)
  {
    if (debug == 1)
    {
      Serial.println("resetting temps!");
    }
    tempMin = 50;
    tempMax = 0;
  }

  if (tempMin <= newTemp)
  {
    tempMin = tempMin;
    if (debug == 1)
    {
      Serial.println("no change to tempMin ");
    }
  }
  else if (tempMin > newTemp)
  {
    tempMin = newTemp;
    Blynk.virtualWrite(V5, tempMin);
    if (debug == 1)
    {
      Serial.println("tempMin updated");
    }
  }

  if (tempMax >= newTemp)
  {
    tempMax = tempMax;
    if (debug == 1)
    {
      Serial.println("no change to tempMax ");
    }
  }
  else if (tempMax < newTemp)
  {
    tempMax = newTemp;
    Blynk.virtualWrite(V6, tempMax);
    if (debug == 1)
    {
      Serial.println("tempMax updated");
    }
  }

  if ((vcc < 3260) && (vcc > 3245))
  {
    Blynk.notify(String("NODE06 - Outside BME280 Sensor battery low: ") + vcc + ("mV"));
  }
  else if (vcc <= 3235)
  {
    Blynk.notify(String("NODE06 - Outside BME280 Sensor BATTERY CRITICAL:") + vcc + ("mV"));
  }

  if (client.connect(serverThingspeak, 80))
  {
    String postStr = apiKeyThingspeak;
    postStr += "&field1=";
    postStr += String(temp);
    postStr += "&field2=";
    postStr += String(hum);
    postStr += "&field3=";
    postStr += String(pres);
    postStr += "&field4=";
    postStr += String(rssi);
    postStr += "&field5=";
    postStr += String(vcc);
    //postStr += "&field6=";
    //postStr += String(lux);
    postStr += "&field7=";
    postStr += String(node3DewPoint);
    postStr += "\r\n\r\n";

    client.print("POST /update HTTP/1.1\n");
    client.print("Host: api.thingspeak.com\n");
    client.print("Connection: close\n");
    client.print("X-THINGSPEAKAPIKEY: " + apiKeyThingspeak + "\n");
    client.print("Content-Type: application/x-www-form-urlencoded\n");
    client.print("Content-Length: ");
    client.print(postStr.length());
    client.print("\n\n");
    client.print(postStr);
  }
  if (debug == 1)
  {
    Serial.println(F("just thingspoke"));
  }
  delay(10);
  if (setProgramming == 0)
  {
    Blynk.virtualWrite(12, 0); // programming LED off
    ESP.deepSleep(sleepTimeS * 1000000);
    delay(10);
  }
  else if (setProgramming == 1)
  {
    Blynk.virtualWrite(12, 1023); //programming LED on
  }
}

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

    if (debug == 1)
    { Serial.print(F("File name: "));
      Serial.println(F(""));
      Serial.println(F("NODE06 - TPL Bug prototype BATTERY POWER - with Thingspeak & Blynk & Deep Sleep"));
      Serial.print(F("File name: "));
      Serial.println(__FILE__);
      Serial.println(F(""));
      Serial.print(F("ESP voltage: "));
      Serial.print(vcc);
      Serial.println(F("mV"));
      Serial.println(F(""));
      Serial.println(F("Where's Blynk??"));
    }

    WiFi.mode(WIFI_STA);
    WiFi.config(ip, gateway, subnet); // this sets the ESP IP configuration
    WiFi.setOutputPower(0); // this is from conkerkh sets wifi to lowest power

    Blynk.begin(authBlynk, SSID, pass, IPAddress(192, 168, 0, 7));

    ArduinoOTA.setHostname("Basement_plenum_ESP8266_controller");
    ArduinoOTA.onStart([]()
    {
      Serial.println("Start");
    });
    ArduinoOTA.onEnd([]()
    {
      Serial.println("\nEnd");
    });

    ArduinoOTA.onError([](ota_error_t error)
    {
      Serial.printf("Error[%u]: ", error);
      if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
      else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
      else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
      else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
      else if (error == OTA_END_ERROR) Serial.println("End Failed");
    });
    ArduinoOTA.begin();
    Serial.println("Ready - OTA Success!!!");
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
    MDNS.begin(host);
    httpUpdater.setup(&httpServer);
    httpServer.begin();
    MDNS.addService("http", "tcp", 80);
    String ipaddress = WiFi.localIP().toString();
    String chipID = String(ESP.getChipId(), HEX);
    char charChipID[10];
    chipID.toCharArray(charChipID, sizeof(charChipID));
    char charipaddress[16];
    ipaddress.toCharArray(charipaddress, sizeof(charipaddress));
    Serial.printf("Now open http://%s.local/update in your browser or \n", host);
    Serial.printf("http://%s/update or http://%s.lan/update if you prefer.\n", charipaddress, charChipID);

    while (!Blynk.connect())
    {
      delay(500);
      Serial.print(F("."));
    }

    long rssi = WiFi.RSSI();

    if (debug == 1)
    {
      Serial.println(F(""));
      Serial.println(F("Found some WiFi!"));
      Serial.print(F("WiFi signal strength (RSSI): "));
      Serial.print(rssi);
      Serial.println(F(" dBm"));
      Serial.println("");
      Serial.println(F("Blynk started! "));
      Serial.println(F("------------"));
    }
    
    if (debug == 0)
    {
      Serial.println(F("***************************debug is OFF***************************"));
    }

    Blynk.syncAll();

    LightSensor.begin();
    Wire.begin();
    LightSensor.SetAddress(Device_Address_L);//'L' = Address 0x5C ?
    LightSensor.SetMode(Continuous_H_resolution_Mode);
    timer.setInterval(60L * 1000L, printBME280Data); // runs main function every 60 seconds
    
    while (!Serial)
    {
    } // Wait

    while (!bme.begin())
    {
      Serial.println("Could not find BME280 sensor!");
      delay(1000);
    }
  }
}

void loop()
{
  Blynk.run(); // Initiates Blynk
  timer.run(); // Initiates SimpleTimer
  ArduinoOTA.handle();
  httpServer.handleClient();
}

/*-----( Declare User-written Functions )-----*/
// dewPoint function NOAA
// reference (1) : http://wahiduddin.net/calc/density_algorithms.htm
// reference (2) : http://www.colorado.edu/geography/weather_station/Geog_site/about.htm
//
double dewPointAccurate (double celsius, double humidity)
{
  // (1) Saturation Vapor Pressure = ESGG(T)
  double RATIO = 373.15 / (273.15 + celsius);
  double RHS = -7.90298 * (RATIO - 1);
  RHS += 5.02808 * log10(RATIO);
  RHS += -1.3816e-7 * (pow(10, (11.344 * (1 - 1 / RATIO ))) - 1) ;
  RHS += 8.1328e-3 * (pow(10, (-3.49149 * (RATIO - 1))) - 1) ;
  RHS += log10(1013.124); // NB = 1013 = air pressure, which you can substitute from BME280 if you want to, but it needs to be converted to suit your specific altitude i think?

  // factor -3 is to adjust units - Vapor Pressure SVP * humidity
  double VP = pow(10, RHS - 3) * humidity;

  // (2) DEWPOINT = F(Vapor Pressure)
  double T = log(VP / 0.61078); // temp var
  return (241.88 * T) / (17.558 - T);
}
/* ==== END Functions ==== */