Salve a tutti, ho costruito una stazione meteorologica con esp32, sensori BMP 280 per la pressione (e come temp secondaria) e dht22 per la temperatura e l'umidità. Il microcontrollore invia dati ogni ora ad un BOT telegram e inoltre posso richiamare i dati quando mi pare e piace con la dicitura /readings. Chiedo scusa se lo sketch sottostante possa non essere il massimo della scrittura, ma nel mio caso funziona egregiamente, e fa ciò che mi interessa.
Ho solo un problema, ossia ogni tot di tempo si blocca il microcontrollore e non invia più i dati e non risponde ai /readings e devo riavviarlo manualmente. Ho capito subito che il problema possono essere le variabili String che infatti vanno ad intasare la memoria RAM. Nello sketch è inserita anche una funzione per resettare la esp32, e di conseguenza i dati (temp e Ur min e max), che si attiva ogni 24 ore; però purtroppo il microcontrollore si blocca prima che passino appunto queste 24h. Ho letto che il problema delle String potrebbe essere ovviato grazie alla libreria PROGMEM che mette i contenuti delle String nella flash rom, ma nel mio caso non saprei proprio come utilizzarla, dato che ci sono tante variabili String. Qualcuno mi potrebbe aiutare a capire come ovviare a questo problema?
PS. tengo a precisare che nello sketch sono inserite due librerie per il bot di telegram, la Universal telegram bot che era quella che ho utilizzato inizialmente, e poi successivamente ho integrato la CTbot.h che è quella che fortunatamente mi permette di inviare in automatico i dati ogni ora. Questa automazione con la Universal telegram bot funzionava ma relativamente: i dati venivano inviati in automatico solo nel momento in cui facevo almeno una lettura con /readings mentre la libreria CTBot invia in automatico i dati senza che ci sia stato almeno un messaggio /readings al momento dell'avvio.
Ecco lo sketch:
#include <WiFi.h>
#include "CTBot.h" //////////////////Libreria per farmi mandare i dati in automatico
CTBot myBot;
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h> // Universal Telegram Bot per ricevere tramite /readings i dati
#include <ArduinoJson.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
// DHT Sensor Library
#include <Adafruit_BMP280.h>
#define DHTTYPE DHT22 // Type of DHT Sensor DHT22 (AM2302)
#define DHTPIN 25 // Digital pin connected to the DHT sensor
DHT dht(DHTPIN, DHTTYPE); // creating dht Instance
//////////////////////Variabili per invio messaggi su telegram/////////////////////
String chat_id;
String readings;
int i; //////////Riguarda il FOR contenuto nel void handleNewMessages
String message;
/////////////////temp e UR min e max sensore dht22////////////////////////////////
float temp = 0; //raccoglie misura temperatura
float um = 0; //raccoglie misura umidità
float temp_min = 0; //si ricorda della temperatura min. registrata
float um_min = 0; //si ricorda dell’umidità min. registrata
float temp_max = 0; //si ricorda della temperatura max. registrata
float um_max = 0; //si ricorda dell’umidità min. registrata
float v1, v2; //variabili iniziali per um_min e temp_min
/////////////////temp min e max sensore bmp280////////////////////////////////
float temp2 = 0; //raccoglie misura temperatura
float temp2_min = 0; //si ricorda della temperatura min. registrata
float temp2_max = 0; //si ricorda della temperatura max. registrata
float v4; //variabili iniziali per um_min e temp_min
/////////////TIME//////////////////////////////
#include <NTPClient.h>
#include <WiFiUdp.h>
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org");
//Week Days
String weekDays[7] = {"Domenica", "Lunedì", "Martedì", "Mercoledì", "Giovedì", "Venerdì", "Sabato"};
//Month names
String months[12] = {"Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre"};
////Variabili per il TIME///////////////
int monthDay;
int currentMonth;
int currentYear;
String currentMonthName;
String weekDay;
int currentHour;
int currentMinute;
String formattedTime;
// BMP280 connect to ESP32 I2C (GPIO 21 = SDA, GPIO 22 = SCL)
Adafruit_BMP280 bmp; // Create bmp instance
// Replace with your network credentials
const char* ssid = "XXXXXXXXXXXXXX";
const char* password = "XXXXXXXXXXXXX";
// Use @myidbot to find out the chat ID of an individual or a group
// Also note that you need to click "start" on a bot before it can
// message you
int64_t CHAT_IDD3 = XXXXXXXXXXXX; ////////////USATO PER MESSAGGIO AUTOMATICO CON LIBRERIA CTBBOT.H
#define CHAT_ID "XXXXXXXXXX"
#define CHAT_ID2 "XXXXXXXXXX" // Your Chat ID
#define CHAT_ID3 "XXXXXXXXXXX"
// Initialize Telegram BOT
#define BOTtoken "XXXXXXXXXXXXXXXXXXXXXXXXXXX" // your Bot Token (Got from Botfather)
WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);
//Checks for new messages every 1 second.
int botRequestDelay = 1000;
unsigned long lastTimeBotRan;
// Get BMP280 & DHT22 sensor readings and return them as a String variable
String getReadings() {
float temperature, temperature2,humidity, pressureR, pressure2, Altitude,pressure,pressureA, pressure2plus, heatIndex, Dew_Point, Wet_Bulb, Dew_PointC, realealtitude, pressurelvm;
String Mese, Giorno, Anno; String giornosettimana; long minuti; int ora; String orario;
temperature = dht.readTemperature();
temperature2 = bmp.readTemperature();
humidity = dht.readHumidity();
pressure = bmp.readPressure();
pressureA = (bmp.readPressure() / 100);
pressure2 = (bmp.readPressure() / 100)+ 4.41;////////toglie 9 hpa ogni 100m (9 x ettometri di altitudine)
pressureR = (bmp.readPressure() / pow((1 - (0.0065 * 49 / (dht.readTemperature() + 0.0065 * 49 + 273.15))), 5.25588)) /100;/////hypsometric equation
Altitude = bmp.readAltitude();
heatIndex = dht.computeHeatIndex(temperature, humidity, false);
Dew_Point = (log(humidity / 100) + ((17.27 * temperature) / (237.3 + temperature))) / 17.27;
Dew_PointC = (237.3 * Dew_Point) / (1 - Dew_Point);
Wet_Bulb = temperature * (0.45 + 0.006 * humidity * (pressureA / 1060));
realealtitude = (44330.0 * (1.0 - pow((pressureA / pressureR), 0.19029495)));
Mese = currentMonthName;
Giorno = monthDay;
Anno = currentYear;
giornosettimana = weekDay;
ora = currentHour;
minuti = currentMinute;
orario = formattedTime;
message = "Ciao! \n";
message += "Oggi è: " + String(giornosettimana) + ", " + String(Giorno) + " " + String(Mese) + " " + String(Anno) + " e sono le " + String(orario) + "\n\n";
message += "I dati meteo attuali sono: \n\n";
message += "Temperatura: " + String(temperature) + " ºC \n\n";
message += "Temp min: " + String (temp_min) + " ºC \n\n";
message += "Temp max: " + String (temp_max) + " ºC \n\n";
message += "Temperatura sensore 2: " + String(temperature2) + " ºC \n\n";
message += "Temp min 2: " + String (temp2_min) + " ºC \n\n";
message += "Temp max 2: " + String (temp2_max) + " ºC \n\n";
message += "Umidità: " + String (humidity) + " % \n\n";
message += "UR min: " + String (um_min) + " % \n\n";
message += "UR max: " + String (um_max) + " % \n\n";
message += "Pressione a lvm: " + String (pressureR) + " hpa (equazione ipsometrica) \n\n";
message += "Pressione a lvm 2ª equazione: " + String (pressure2) + " hPa (equazione che riduce 1 hpa ogni 8m di alt.) \n\n";
message += "Pressione all'altitudine: " + String (pressureA) + " hPa \n\n";
message += "Altitudine reale: " + String (realealtitude) + " m slm \n\n";
message += "Altitudine in base hPa: " + String (Altitude) + " m slm \n\n";
message += "Indice di calore: " + String (heatIndex) + " ºC \n\n";
message += "Dew Point: " + String (Dew_PointC) + " ºC \n\n";
message += "Wet Bulb: " + String (Wet_Bulb) + " ºC \n\n";
return message;
}
//Handle what happens when you receive new messages
void handleNewMessages(int numNewMessages) {
Serial.println("handleNewMessages");
Serial.println(String(numNewMessages));
////////////la variabile Int i è nel globale////////////////7
for (i = 0; i < numNewMessages; i++) {
// Chat id of the requester
chat_id = String(bot.messages[i].chat_id);
if (chat_id != CHAT_ID && chat_id != CHAT_ID2 && chat_id != CHAT_ID3) {
bot.sendMessage(chat_id, "Unauthorized user", "");
continue;
}
// Print the received message
String text = bot.messages[i].text;
Serial.println(text);
String from_name = bot.messages[i].from_name;
if (text == "/start") {
String welcome = "Benvenuto nella tua stazione meteo, " + from_name + ".\n\n";
welcome += "Utilizza il seguente comando per verificare i dati in tempo reale.\n\n";
welcome += "/readings \n\n";
welcome += "Ultima foto dalla tua webcam.\n\n";
welcome += "/photo \n\n";
bot.sendMessage(chat_id, welcome, "");
}
if (text == "/photo") {
bot.sendPhoto(chat_id, "http://saldinapoli.altervista.org/webcam.php");
}
if (text == "/readings") {
readings = getReadings();
bot.sendMessage(chat_id, readings, "");
}
}
}
void setup() {
Serial.begin(115200);
// Init BMP280 sensor
if (!bmp.begin(0x76)) {
Serial.println("Could not find a valid BMP280 sensor, check wiring!");
while (1);
}
// Init DHT22 sensor
dht.begin();
float t = dht.readTemperature();
// Connect to Wi-Fi
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
client.setCACert(TELEGRAM_CERTIFICATE_ROOT);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
// Print ESP32 Local IP Address
Serial.println(WiFi.localIP());
delay(5000);
myBot.wifiConnect(ssid, password); //////////////per la liberia CTbot.h////////////////////////
myBot.setTelegramToken (BOTtoken);
timeClient.begin();
// Set offset time in seconds to adjust for your timezone, for example:
// GMT +1 = 3600
// GMT +8 = 28800
// GMT -1 = -3600
// GMT 0 = 0
timeClient.setTimeOffset(7200);
}
void(* resetFunc) (void) = 0; //declare reset function at address 0 - MUST BE ABOVE LOOP ---> PER RESETTARE
void loop() {
if(mytimer3(0)){ //////MESSAGGIO AUTOMATICO CHAT_IDD3
readings = getReadings();
myBot.sendMessage(CHAT_IDD3, readings, ""); /////////INVIO MESSAGGIO AUTOMATICO CTbot.h
}
if ( millis() >= 86400000) resetFunc(); //chiama reset ogni 24 hours (1 Day).
if (millis() > lastTimeBotRan + botRequestDelay) {
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);
}
lastTimeBotRan = millis();
}
/////////FUNZIONI PER TEMP E UMIDITA' MIN E MAX///////////////
temp = dht.readTemperature();
um = dht.readHumidity();
temp2 = bmp.readTemperature();
if (v1 == 0) { um_min = um;}
if (v2 == 0) { temp_min = temp;}
if (temp > temp_max) { temp_max = temp;}
if (um > um_max) { um_max = um; }
if (um_min >= um) { um_min = um; v1++; }
if (temp_min >= temp) { temp_min = temp; v2++; }
if (v4 == 0) { temp2_min = temp2;}
if (temp2 > temp2_max) { temp2_max = temp2;}
if (temp2_min >= temp2) { temp2_min = temp2; v4++; }
Serial.print("Current humidity = ");
Serial.print(dht.readHumidity());
Serial.print("% ");
Serial.print("temperature = ");
Serial.print(dht.readTemperature());
Serial.println("C ");
delay(1000);
//////////TIME//////////////////
timeClient.update();
unsigned long epochTime = timeClient.getEpochTime();
Serial.print("Epoch Time: ");
Serial.println(epochTime);
formattedTime = timeClient.getFormattedTime();
Serial.print("Formatted Time: ");
Serial.println(formattedTime);
currentHour = timeClient.getHours();
Serial.print("Hour: ");
if (timeClient.getHours() < 10) Serial.print("0");
Serial.println(currentHour);
currentMinute = timeClient.getMinutes();
Serial.print("Minutes: ");
if (timeClient.getMinutes() < 10) Serial.print("0");
Serial.println(currentMinute);
int currentSecond = timeClient.getSeconds();
Serial.print("Seconds: ");
Serial.println(currentSecond);
weekDay = weekDays[timeClient.getDay()];
Serial.print("Week Day: ");
Serial.println(weekDay);
//Get a time structure
struct tm *ptm = gmtime ((time_t *)&epochTime);
monthDay = ptm->tm_mday;
Serial.print("Month day: ");
Serial.println(monthDay);
currentMonth = ptm->tm_mon + 1;
Serial.print("Month: ");
Serial.println(currentMonth);
currentMonthName = months[currentMonth - 1];
Serial.print("Month name: ");
Serial.println(currentMonthName);
currentYear = ptm->tm_year + 1900;
Serial.print("Year: ");
Serial.println(currentYear);
//Print complete date:
String currentDate = String(currentYear) + "-" + String(currentMonth) + "-" + String(monthDay);
Serial.print("Current date: ");
Serial.println(currentDate);
Serial.println("");
delay(2000);
}
int mytimer3 (int timer13){ ///////////TIMER MILLIS PER INVIO DATI AUTOMATICAMENTE OGNI ORA////////
static long t23, dt23;
int ret3 = 0;
dt23 = millis() - t23;
if(dt23 >= 3600000){
t23 = millis();
ret3 =1;
}
return ret3;
}