I am using the following library because it calculates dew point and heat index, whereas other libraries don't: GitHub - finitespace/BME280: Provides an Arduino library for reading and interpreting Bosch BME280 data over I2C, SPI or Sw SPI.
My project notifies me through Telegram when motion is detected, sends me weather values upon command and periodically uploads them to Thingspeak so I can keep a graphical record.
During this testing phase, I've been keeping a small digital thermometer next to the project so I can confirm if they are showing similar values or not.
I noticed that if the temperature doesn't vary much during the day, I get similar readings between them. However, there's been a few days with temperatures rising from 10ºC to 25ºC around lunch time, but the BME280 still shows lows temperatures. When I reboot the device, it sends me around 25ºC.
I have read the library files and the datasheet but still can't figure this how.
Should I set global variables and keep polling the BME280 every second in the loop() section, then do something with the values? Or should I read the BME280 only when I want a reading or when it's timeto send a reading to Thingspeak?
/*******************************************************************
ESP8266
HC-SR501 PIR output to GPIO13: send message to Telegram channel upon interrupt
BME280 to D1 D2: sends weather data to Telegram chat upon request with "/status"
Send periodically to Thingspeak
Using library ESP8266WiFi at version 1.0 in folder: E:\arduino-1.8.13\portable\packages\esp8266\hardware\esp8266\3.0.2\libraries\ESP8266WiFi
Using library UniversalTelegramBot at version 1.3.0 in folder: E:\arduino-1.8.13\portable\sketchbook\libraries\UniversalTelegramBot
Using library ArduinoJson at version 6.19.4 in folder: E:\arduino-1.8.13\portable\sketchbook\libraries\ArduinoJson
Using library BME280 at version 3.0.0 in folder: E:\arduino-1.8.13\portable\sketchbook\libraries\BME280
Using library Wire at version 1.0 in folder: E:\arduino-1.8.13\portable\packages\esp8266\hardware\esp8266\3.0.2\libraries\Wire
Using library SPI at version 1.0 in folder: E:\arduino-1.8.13\portable\packages\esp8266\hardware\esp8266\3.0.2\libraries\SPI
https://en.allmetsat.com/index.html
https://pt.allmetsat.com/metar-taf/portugal-espanha.php?icao=LPPT
https://moja-elka.blogspot.com/2018/01/bme280-czujnik-wilgotnosci-cisnienia-i.html
*******************************************************************/
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>
String apiKey = "blablabla"; // Enter your Write API key from ThingSpeak
const char* server = "api.thingspeak.com";
unsigned long thingspeak_lasttime = 0;
WiFiClient client;
// Wifi network station credentials
#define WIFI_SSID "blablabla"
#define WIFI_PASSWORD "blablabla"
#define BOT_TOKEN "blablabla" // Telegram BOT Token (Get from Botfather)
const unsigned long BOT_MTBS = 5000; // mean time between scan messages
X509List cert(TELEGRAM_CERTIFICATE_ROOT);
WiFiClientSecure secured_client;
UniversalTelegramBot bot(BOT_TOKEN, secured_client);
unsigned long bot_lasttime; // last time messages' scan has been done
String chat_id;
#define CHANNEL_ID "blablabla"
#define INT_PIN 13 //D7
volatile bool interruptFlag;
boolean pir_active = false;
int counter = 0;
bool reboot_request = false;
bool reset_request = false;
#include <EnvironmentCalculations.h>
#include <BME280I2C.h>
#include <Wire.h>
// https://pt.allmetsat.com/metar-taf/portugal-espanha.php?icao=LPPT
// Assumed environmental values:
float referencePressure = 1020.1; // hPa local QFF (official meteor-station reading)
float outdoorTemp = 16.1; // °C measured local outdoor temp.
float barometerAltitude = 108.1; // meters ... map readings + barometer position
float temp(NAN), hum(NAN), pres(NAN);
float altitude, dewPoint, seaLevel, absHum, heatIndex;
EnvironmentCalculations::AltitudeUnit envAltUnit = EnvironmentCalculations::AltitudeUnit_Meters;
EnvironmentCalculations::TempUnit envTempUnit = EnvironmentCalculations::TempUnit_Celsius;
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
BME280::PresUnit presUnit(BME280::PresUnit_hPa);
BME280I2C::Settings settings(
BME280::OSR_X1,
BME280::OSR_X1,
BME280::OSR_X1,
BME280::Mode_Forced,
BME280::StandbyTime_1000ms,
BME280::Filter_16,
BME280::SpiEnable_False,
BME280I2C::I2CAddr_0x76
);
BME280I2C bme(settings);
ICACHE_RAM_ATTR void handleInterrupt() {
Serial.println("movement detected");
interruptFlag = true;
}
void handleNewMessages(int numNewMessages) {
Serial.print("handleNewMessages ");
Serial.println(numNewMessages);
for (int i = 0; i < numNewMessages; i++)
{
chat_id = bot.messages[i].chat_id;
String text = bot.messages[i].text;
String from_name = bot.messages[i].from_name;
if (from_name == "")
from_name = "Guest";
if (text == "/enpir")
{
pir_active = 1;
bot.sendMessage(chat_id, "PIR activated", "");
}
if (text == "/dispir")
{
pir_active = 0;
bot.sendMessage(chat_id, "PIR deactivated", "");
}
if (text == "/status")
{
readBME280(); // get values from weather sensor
String stat = "Rssi: " + String(WiFi.RSSI());
stat += "\n\nPIR Status: " + String(pir_active);
stat += "\n\nTemperature: " + String(temp) + " ºC";
stat += "\nHumidity: " + String(hum) + " %";
stat += "\nPressure: " + String(pres) + " hPa";
stat += "\n\nAltitude: " + String(altitude) + " m";
stat += "\nHeat Index: " + String(heatIndex) + " ºC";
stat += "\nDew Point: " + String(dewPoint) + " ºC";
stat += "\n\nAbsolute Humidity: " + String(absHum) + " ";
stat += "\nEquivalent Sea Level Pressure: " + String(seaLevel) + " hPa";
bot.sendMessage(chat_id, stat, "Markdown");
}
if (text == "/reboot") {
// String stat = "Rebooting on request\nRssi: " + String(WiFi.RSSI()) + "\nip: " + WiFi.localIP().toString() ;
// bot.sendMessage(chat_id, stat, "");
reboot_request = true;
}
if (text == "/reset") {
reset_request = true;
}
if (text == "/start")
{
String welcome = "Motion Detection & Weather Station Bot\n\n";
welcome += "/enpir: enable PIR alert\n";
welcome += "/dispir: disable PIR alert\n\n";
welcome += "/status: PIR state & weather readings\n\n";
welcome += "/reset: reset wifi params\n";
welcome += "/reboot: reboot\n";
bot.sendMessage(chat_id, welcome, "Markdown");
}
}
}
void setup() {
delay(500);
// Serial.begin(115200);
Serial.println();
Wire.begin();
while (!bme.begin())
{
Serial.println("Could not find BME280 sensor!");
delay(500);
counter++;
if (counter >= 30) {
counter = 0;
break;
}
}
// Interrupt on HIGH output from PIR
pinMode(INT_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(INT_PIN), handleInterrupt, RISING);
// attempt to connect to Wifi network:
configTime(0, 0, "pool.ntp.org"); // get UTC time via NTP
secured_client.setTrustAnchors(&cert); // Add root certificate for api.telegram.org
Serial.print("Connecting to Wifi SSID ");
Serial.print(WIFI_SSID);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
counter++;
if (counter >= 60) {
counter = 0;
ESP.restart(); //restart board if wifi not connected within 30sec
}
}
Serial.print("\nWiFi connected. IP address: ");
Serial.println(WiFi.localIP());
// Check NTP/Time, usually it is instantaneous and you can delete the code below.
int counter = 0;
Serial.print("Retrieving time: ");
time_t now = time(nullptr);
while (now < 24 * 3600)
{
Serial.print(".");
delay(500);
now = time(nullptr);
counter++;
if (counter >= 120) {
counter = 0;
ESP.restart(); //restart board if wifi not connected within 30sec
}
}
Serial.println(now);
}
void loop() {
// Check for Telegram messages
if (millis() - bot_lasttime > BOT_MTBS)
{
if (WiFi.status() != WL_CONNECTED) {
Serial.println("***** WiFi reconnect *****");
WiFi.reconnect();
delay(5000);
if (WiFi.status() != WL_CONNECTED) {
ESP.restart();
}
}
int numNewMessages = bot.getUpdates(bot.last_message_received + 1);
while (numNewMessages)
{
Serial.println("got response");
handleNewMessages(numNewMessages);
numNewMessages = bot.getUpdates(bot.last_message_received + 1);
}
bot_lasttime = millis();
}
// When interrupt is triggered by motion, don't send message if PIR is set as inactive
if (interruptFlag && pir_active) {
bot.sendMessage(CHANNEL_ID, "/clip", ""); // send message to Telegram channel
interruptFlag = false;
} else {
interruptFlag = false;
}
// Update Thingspeak values every 30min 1800000
if (millis() - thingspeak_lasttime >= 1800000) {
thingspeak_lasttime = millis();
readBME280();
delay(100);
SendToThingspeak();
}
if (reboot_request) {
String stat = "Rebooting on request\nRssi: " + String(WiFi.RSSI()) + "\nip: " + WiFi.localIP().toString() ;
bot.sendMessage(chat_id, stat, "");
delay(5000);
ESP.restart();
}
if (reset_request) {
// wm.resetSettings();
reset_request = false;
}
}//end of loop()
void readBME280() {
bme.read(pres, temp, hum, tempUnit, presUnit);
altitude = EnvironmentCalculations::Altitude(pres, envAltUnit, referencePressure, outdoorTemp, envTempUnit);
dewPoint = EnvironmentCalculations::DewPoint(temp, hum, envTempUnit);
seaLevel = EnvironmentCalculations::EquivalentSeaLevelPressure(barometerAltitude, temp, pres, envAltUnit, envTempUnit);
absHum = EnvironmentCalculations::AbsoluteHumidity(temp, hum, envTempUnit);
heatIndex = EnvironmentCalculations::HeatIndex(temp, hum, envTempUnit);
}
void SendToThingspeak() {
if (client.connect(server, 80)) // "184.106.153.149" or api.thingspeak.com
{
String sendData = apiKey + "&field1=" + String(temp) + "&field2=" + String(heatIndex) + "&field3=" + String(pres) + "&field4=" + String(hum) + "&field5=" + String(dewPoint) + "\r\n\r\n";
Serial.println(sendData);
client.print("POST /update HTTP/1.1\n");
client.print("Host: api.thingspeak.com\n");
client.print("Connection: close\n");
client.print("X-THINGSPEAKAPIKEY: " + apiKey + "\n");
client.print("Content-Type: application/x-www-form-urlencoded\n");
client.print("Content-Length: ");
client.print(sendData.length());
client.print("\n\n");
client.print(sendData);
}
client.stop();
Serial.println("Sending....");
}
