//#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 1 // 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 <BME280I2C.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;
BME280I2C 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, 1, 114); //check this!
IPAddress gateway(192, 168, 1, 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 xxxxxxx
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.read(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);
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 ==== */
Fixed!
I add a legend because is a big script and can be difficult take all in one shot:
V11 -> Temp
V9 -> Hum
V2 -> Pressure
V4 -> Lux
V8 -> Dew Point
V5 -> Temp Min
V6 -> Temp Max
V7 -> Reset Temp
V19 -> Vcc
V18 -> RSSI
V3 -> Barometer
V12 -> LED
V10 -> Slider
Used these libs:
Some questions:
- where is the PIN for BH1750? I’m using D1/D2 on NodeMCU (for testing) for the BME280
- it seems that temp min/max doesn’t work, can you check?
- dew point is standard for all? or we need to modify related to our zone?