Sensore di temperatura remoto per termometro con ESP8266

Questo post integra il post precedente. Descrive un sensore di temperatura con ESP8266 che invia la temperatura corrente al termometro presentato nell'ultimo articolo ogni cinque minuti. Nella pausa tra due misurazioni, l'ESP8266 viene messo in modalità di sonno profondo in cui quasi non consuma energia. Il protocollo ESP Now viene utilizzato per inviare i dati, che inviano i dati direttamente all'indirizzo MAC del termometro senza la necessità di impostare una connessione.

Lo usiamo Modulo ESP8266-E12 con adattatore, perché contrariamente al modulo ESP8266-01 questo ha portato al perno di riattivazione GPIO-16 e non ha LED permanentemente accesi sulla tensione di alimentazione. Abbiamo bisogno del perno di riattivazione per il sonno profondo e il LED di alimentazione utilizza solo energia inutilmente.

circuito:

Il filo arancione collega il perno di attivazione all'ingresso di ripristino e garantisce che il modulo venga riavviato al termine dell'interruzione del sonno. Il sensore è collegato al GPIO2 (filo bianco).

Per caricare il programma è necessario un adattatore FDTI per programmare ESP8266 tramite l'interfaccia seriale.

Colleghiamo l'adattatore FDTI con il connettore GND e TX con RX e RX con TX. Inoltre, il Flash Pin GPIO 0 deve essere collegato a terra (filo verde) in modo che ESP8266 passi in modalità di programmazione.

Il filo verde deve essere rimosso dopo la programmazione. Se DEBUG era impostato su true nello schizzo, i messaggi del modulo possono essere tracciati tramite l'interfaccia seriale.

Attenzione:  Una fornitura di ESP8266 da parte della scheda FDTI provoca arresti anomali quando viene chiamata la funzione scanNetwork perché il consumo corrente è quindi troppo elevato.

Sketch:

Per compilare la scheda

regolare !!

 

/*
  Sensore di temperatura WLAN
  ESP Ora con il termometro
  Se nessun indirizzo MAC è stato ancora determinato
  il sensore è alla ricerca di una WLAN con termometro SSID
  Quando trova l'AP, si ricorda l'indirizzo MAC 
  purché l'alimentazione non sia stata interrotta
  Il protocollo ESP Now è molto veloce, quindi solo un tempo molto breve (noi)
  flussi di corrente più elevati. Il sensore invia i dati di temperatura e quindi entra per 5 minuti 
  Sonno profondo in modo che venga utilizzata pochissima energia e quello
  Il sensore può quindi funzionare con batterie. 
*/

// libreria per WiFi
#include <ESP8266WiFi.B>
// Librerie per sensore di temperatura DS18B20
#include <OneWire.B>

// Libreria per ESP Now
#include <Dallas Temperatura.B>
esterno "C" {   #include <espnow.B>
}

// Flag di debug se false vengono soppressi tutti i messaggi di debug
// per risparmiare elettricità aggiuntiva
#define DEBUG vero

// Costanti per WiFi
#define WIFI_CHANNEL 1
#define send_timeout 2450  // Timeout di 245 millisecondi 

// Pin per sensore di temperatura
const byte autobus = 2;// pin GPIO2

// Struttura dei dati per lo scambio di dati
struct DATEN_STRUKTUR {     galleggiante Temp = 0;
};

// Struttura dei dati per la memoria RTC con checksum per validità
// controlla che l'indirizzo MAC sia salvato
struct DATI DI MEMORIA {   uint32_t crc32;   uint8_t mac[6];
};

// Dati globali
volatile bool callbackCalled;

DATI DI MEMORIA statinfo;

OneWire OneWire(autobus);

Dallas Temperatura sensori(&OneWire);

// array per memorizzare gli indirizzi dei sensori
Indirizzo dispositivo indirizzi;

// Sottoprogramma per il calcolo del checksum
uint32_t calculateCRC32(const uint8_t *dati, size_t lunghezza)
{   uint32_t crc = 0xffffffff;   mentre (lunghezza--) {     uint8_t c = *dati++;     per (uint32_t io = 0x80; io > 0; io >>= 1) {       bool po ' = crc & 0x80000000;       se (c & io) {         po ' = !po ';       }       crc <<= 1;       se (po ') {         crc ^= 0x04c11db7;       }     }   }   ritorno crc;
}

// Scrive la struttura dei dati statinfo con il checksum corretto nella memoria RTC
vuoto UpdateRtcMemory() {     uint32_t crcOfData = calculateCRC32(((uint8_t*) &statinfo) + 4, taglia di(statinfo) - 4);     statinfo.crc32 = crcOfData;     ESP.rtcUserMemoryWrite(0,(uint32_t*) &statinfo, taglia di(statinfo));
}

// sucht nach einem geeigneten AccessPoint
vuoto ScanForSlave() {   bool slaveFound = 0;      int8_t scanResults = Wi-Fi.scanNetworks();   // ripristina su ogni scansione   Se (DEBUG) Seriale.println("Scansione eseguita");   Se (scanResults == 0) {     Se (DEBUG) Seriale.println("Nessun dispositivo WiFi trovato in modalità AP");   } altro {     Se (DEBUG) Seriale.Stampa("Trovato ");      Se (DEBUG) Seriale.Stampa(scanResults);      Se (DEBUG) Seriale.println(" dispositivi ");     per (int io = 0; io < scanResults; ++io) {       // Stampa SSID e RSSI per ogni dispositivo trovato       Corda SSID = Wi-Fi.SSID(io);       int32_t RSSI = Wi-Fi.RSSI(io);       Corda BSSIDstr = Wi-Fi.BSSIDstr(io);       Se (DEBUG) {         Seriale.Stampa(io + 1);         Seriale.Stampa(": ");         Seriale.Stampa(SSID);         Seriale.Stampa(" (");         Seriale.Stampa(RSSI);         Seriale.Stampa(")");         Seriale.println("");       }       ritardo(10);       // Controlla se il dispositivo corrente inizia con "Termometro"       Se (SSID.indice di("Termometro") == 0) {         // SSID di interesse         Se (DEBUG) {           Seriale.println("Trovato uno schiavo.");           Seriale.Stampa(io + 1); Seriale.Stampa(": "); Seriale.Stampa(SSID); Seriale.Stampa(" ["); Seriale.Stampa(BSSIDstr); Seriale.Stampa("]"); Seriale.Stampa(" ("); Seriale.Stampa(RSSI); Seriale.Stampa(")"); Seriale.println("");         }         int Mac[6];         // wir ermitteln die MAC Adresse und speichern sie im RTC Memory         Se ( 6 == sscanf(BSSIDstr.c_str(), "%x:%x:%x:%x:%x:%x%c",  &Mac[0], &Mac[1], &Mac[2], &Mac[3], &Mac[4], &Mac[5] ) ) {           per (int ii = 0; ii < 6; ++ii ) {             statinfo.Mac[ii] = (uint8_t) Mac[ii];           }           UpdateRtcMemory();         }         slaveFound = 1;         // Nachdem der AP gefunden wurde können wir abbrechen         rompere;       }     }   }         Se (DEBUG) {     Se (slaveFound) {       Seriale.println("Slave Found, processing ..");     } altro {       Seriale.println("Slave Not Found, riprovando.");     }   }   // RAM freigeben   Wi-Fi.scanDelete();
}
// function um eine Sensoradresse zu drucken
vuoto printAddress(DeviceAddress Adressen)
{   per (uint8_t io = 0; io < 8; io++)   {     Se (Adressen[io] < 16) Seriale.Stampa("0");     Seriale.Stampa(Adressen[io], ESADECIMALE);   }
}

vuoto impostare() {   Se (DEBUG) {     Seriale.inizio(115200);      Seriale.println("Inizio");   }   pinMode(autobus,INPUT_PULLUP);   // Wir ermitteln die Anzah der Sensoren am Eindraht-Bus   Sensori.inizio();   Se (DEBUG) {     Seriale.Stampa(Sensori.getDeviceCount(), Dicembre);     Seriale.println("Sensoren gefunden.");   }   // Nun prüfen wir ob einer der Sensoren am Bus ein Temperatureatur Sensor ist   Se (!Sensori.getAddress(Adressen,0)) {     Se (DEBUG) Seriale.println("Kein Temperatursensor vorhanden!");   }   // adressen anzeigen   Se (DEBUG) {     Seriale.Stampa("Indirizzo:");     printAddress(Adressen);     Seriale.println();   }   // Nun setzen wir noch die gewünschte Auflösung (9, 10, 11 o 12 bit)   Sensori.setResolution(Adressen,10);   // Zur Kontrolle les wir den Wert wieder aus   Se (DEBUG) {     Seriale.Stampa("Auflösung =");     Seriale.Stampa(Sensori.getResolution(Adressen), dicembre);     Seriale.println();   }   Sensori.requestTemperatures(); // Commando um die Temperaturen auszulesen   // Wir lesen aus dem RTC Memory   ESP.rtcUserMemoryRead(0, (uint32_t*) &statinfo, taglia di(statinfo));   Se (DEBUG) Seriale.println("RTC Fatto");   uint32_t crcOfData = calculateCRC32(((uint8_t*) &statinfo) + 4, taglia di(statinfo) - 4);   Wi-Fi.modalità(WIFI_STA); // Modalità stazione per nodo sensore esp-now   Se (DEBUG) Seriale.println("WifiMode");   Se (statinfo.crc32 != crcOfData) { // wir haben keine gültige MAC Adresse     Se (DEBUG) Seriale.println("Scan vor Slave");     ScanForSlave();     Se (DEBUG) {       Seriale.printf("Questo mac:% s", Wi-Fi.indirizzo MAC().c_str());        Seriale.printf("mac target:% 02x% 02x% 02x% 02x% 02x% 02x", statinfo.Mac[0], statinfo.Mac[1], statinfo.Mac[2], statinfo.Mac[3], statinfo.Mac[4], statinfo.Mac[5]);        Seriale.printf(", canale:% i \ n", WIFI_CHANNEL);      }   }   Se (esp_now_init() != 0) {     Se (DEBUG) Seriale.println("*** Init ESP_Now non riuscito");     ESP.ricomincia();   }   // Controller ESP Now   esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);   // Initisieren Peer Daten   esp_now_add_peer(statinfo.Mac, ESP_NOW_ROLE_SLAVE, WIFI_CHANNEL, NULLO, 0);   // wir registrieren die Funktion, die nach dem Senden aufgerufen werden soll   esp_now_register_send_cb([](uint8_t* Mac, uint8_t sendStatus) {     Se (DEBUG) {       Seriale.Stampa("send_cb, status ="); Seriale.Stampa(sendStatus);        Seriale.Stampa(", per mac:");        carbonizzare macString[50] = {0};       sprintf(macString,"% 02X:% 02X:% 02X:% 02X:% 02X:% 02X", statinfo.Mac[0], statinfo.Mac[1], statinfo.Mac[2], statinfo.Mac[3], statinfo.Mac[4], statinfo.Mac[5]);       Seriale.println(macString);     }     callbackCalled = vero;   });      // Flag auf false setzen   callbackCalled = falso;   // Temperaturmessung starten   Sensori.requestTemperatures();      ritardo(750); // 750 ms warten bis die Messung fertig ist   // Temperaturwert holen und in Satenstruktur zum Senden speichern   DATEN_STRUKTUR dati;   dati.Temp = Sensori.getTempC(Adressen);   uint8_t bs[taglia di(dati)];   // Datenstruktur in den Sendebuffer kopieren   memcpy(bs, &dati, taglia di(dati));   // Invia un termometro inviato   esp_now_send(NULLO, bs, taglia di(dati)); // NULL significa inviare a tutti i peer   Se (DEBUG) {     Seriale.Stampa("Temperatur:"); Seriale.Stampa(dati.Temp); Seriale.println("° C");   }
}

vuoto ciclo continuo() {   // warten bis Daten gesendet wurden   Se (callbackCalled || (millis() > send_timeout)) {     Se (DEBUG) Seriale.println("Dormire");     ritardo(100);     // Per 300 Sekunden in den Tiefschlafmodus     // dann erfolgt ein Reset und der ESP8266 wird neu gestartet     // Daten im RTC Memory werden beim Reset nicht gelöscht.     ESP.sonno profondo(300E6);   }
}




Testen:

Nachdem das Modul mit Strom versorgt wurde kennt es noch keine gültige MAC-Indirizzo dei termometri. Es versucht ein offenes Netzwerk mit der SSID "Thermometer" zu finden. Da das Thermometer etwa fünf Minuten nach dem Start seine SSID versteckt, müssen wir einen Neustart des Thermometers auslösen. Nun sollte das Sensor Modul das Thermometer finden und alle fünf Minuten den aktuellen Temperaturwert übermitteln. Das Thermometer sollte abwechselnd die lokale Temperatur (Häuschen Symbol) und die Temperatur vom Sensor Modul (Baum Symbol) anzeigen.

Esp-8266Projekte für fortgeschritteneSensoren

2 Kommentare

Carsten Jürges

Carsten Jürges

Wenn kein “Thermometer” gefunden wird, landet irgendeine MAC-Adresse in statinfo und das war’s dann erstmal. Daher habe ich Funktion DeleteRtcMemory spendiert, den CRC-Wert “zerstört”. Diese Funktionen wird aufgerufen, wenn das Senden nicht erfolgreich (sendStatus) war …
Dann gibt es beim nächsten Start einen neuen Verbindungsversuch …

Jörg

Jörg

Super, genau so etwas habe ich gesucht.
Vielen Dank für die interessanten Projektvorstellungen.

Einen Kommentar hinterlassen

Alle Kommentare werden vor der Veröffentlichung moderiert