Dit bericht is een aanvulling op het vorige bericht. Het beschrijft een temperatuursensor met ESP8266 die de huidige temperatuur om de vijf minuten naar de thermometer in het laatste artikel stuurt. In de pauze tussen twee metingen wordt de ESP8266 in de diepe slaapstand gezet waarin hij nauwelijks energie verbruikt. Om de gegevens te verzenden, wordt het ESP Now-protocol gebruikt, dat de gegevens rechtstreeks naar het MAC-adres van de thermometer verzendt zonder complexe verbindingsinstellingen.
Wij gebruiken dat ESP8266-E12-module met adapter, omdat dit in tegenstelling tot de ESP8266-01 module de wake pin GPIO-16 heeft opgeleverd en geen permanent brandende LED op de voedingsspanning heeft. We hebben de wake-pin nodig om uit een diepe slaap te ontwaken en de power-LED verbruikt alleen onnodig energie.
Circuit:
De oranje draad verbindt de wake pin met de reset-ingang en zorgt ervoor dat de module opnieuw wordt gestart aan het einde van de slaapstop. De sensor is verbonden met de GPIO2 (witte draad).
Om het programma te uploaden hebben we een FDTI-adapter nodig om de ESP8266 via de seriële interface te programmeren.
We verbinden de FDTI-adapter met de GND-connector en TX met RX en RX met TX. Bovendien moet de Flash Pin GPIO 0 worden verbonden met aarde (groene draad) zodat de ESP8266 in de programmeermodus gaat.
De groene draad moet na het programmeren worden verwijderd. Als DEBUG in de schets is ingesteld op true, kunnen de berichten van de module worden gevolgd via de seriële interface.
Waarschuwing: Een voeding van de ESP8266 door de FDTI-kaart leidt tot crashes wanneer de scanNetwork-functie wordt aangeroepen omdat het huidige verbruik dan te hoog is.
Schets:
Om het bord samen te stellen
aanpassen !!
/* WLAN temperatuursensor ESP Nu met de thermometer Als er nog geen MAC-adres is bepaald de sensor is op zoek naar een WLAN met SSID-thermometer Wanneer hij het AP vindt, onthoudt hij het MAC-adres zolang de stroomtoevoer niet is onderbroken Het ESP Now-protocol is erg snel, dus slechts een zeer korte tijd (us) hogere stroom vloeit. De sensor verzendt temperatuurgegevens en gaat vervolgens gedurende 5 minuten in Diepe slaap zodat heel weinig energie wordt gebruikt en dat Sensor kan daarom op batterijen worden gebruikt. */ // bibliotheek voor wifi # opnemen <ESP8266WiFi.h> // Bibliotheken voor temperatuursensor DS18B20 # opnemen <OneWire.h> // Bibliotheek voor ESP nu # opnemen <DallasTemperatuur.h> extern "C" { # opnemen <vooral.h> } // Debug vlag indien false alle debug berichten worden onderdrukt // om extra elektriciteit te besparen #define DEBUG waar // Constanten voor wifi #define WIFI_CHANNEL 1 #define SEND_TIMEOUT 2450 // Time-out van 245 milliseconden // Pinnen voor temperatuursensor const byte bus = 2;// pin GPIO2 // Gegevensstructuur voor gegevensuitwisseling struct DATA_STRUCTURE { zweven temp = 0; }; // Gegevensstructuur voor het Rtc-geheugen met controlesom voor geldigheid // controleer of het MAC-adres is opgeslagen struct MEMORYDATA { uint32_t crc32; uint8_t mac[6]; }; // Wereldwijde gegevens vluchtig dwaas callbackCalled; MEMORYDATA statinfo; OneWire oneWire(bus); DallasTemperatuur sensoren(&oneWire); // array om sensoradressen op te slaan DeviceAddress adressen; // Subroutine voor het berekenen van de controlesom uint32_t berekenCRC32(const uint8_t *gegevens, size_t lengte) { uint32_t crc = 0xffffffff; terwijl (lengte--) { uint8_t c = *gegevens++; voor (uint32_t ik = 0x80; ik > 0; ik >>= 1) { dwaas beetje = crc & 0x80000000; als (c & ik) { beetje = !beetje; } crc <<= 1; als (beetje) { crc ^= 0x04c11db7; } } } terug crc; } // Schrijft de statinfo-gegevensstructuur met de juiste controlesom naar het RTC-geheugen nietig UpdateRtcMemory() { uint32_t crcOfData = berekenCRC32(((uint8_t*) &statinfo) + 4, De grootte van(statinfo) - 4); statinfo.crc32 = crcOfData; ESP.rtcUserMemoryWrite(0,(uint32_t*) &statinfo, De grootte van(statinfo)); } // sucht nach einem geeigneten AccessPoint nietig ScanForSlave() { dwaas slaveFound = 0; int8_t scanresultaten = Wifi.scanNetworks(); // reset bij elke scan als (DEBUG) Serie.println("Scan gereed"); als (scanresultaten == 0) { als (DEBUG) Serie.println("Geen wifi-apparaten in AP-modus gevonden"); } anders { als (DEBUG) Serie.afdrukken("Gevonden"); als (DEBUG) Serie.afdrukken(scanresultaten); als (DEBUG) Serie.println("apparaten"); voor (int ik = 0; ik < scanresultaten; ++ik) { // SSID en RSSI afdrukken voor elk gevonden apparaat Draad SSID = Wifi.SSID(ik); int32_t RSSI = Wifi.RSSI(ik); Draad BSSIDstr = Wifi.BSSIDstr(ik); als (DEBUG) { Serie.afdrukken(ik + 1); Serie.afdrukken(": "); Serie.afdrukken(SSID); Serie.afdrukken(" ("); Serie.afdrukken(RSSI); Serie.afdrukken(")"); Serie.println(""); } vertraging(10); // Controleer of het huidige apparaat start met `Thermometer` als (SSID.index van("Thermometer") == 0) { // SSID van belang als (DEBUG) { Serie.println("Een slaaf gevonden."); Serie.afdrukken(ik + 1); Serie.afdrukken(": "); Serie.afdrukken(SSID); Serie.afdrukken(" ["); Serie.afdrukken(BSSIDstr); Serie.afdrukken("]"); Serie.afdrukken(" ("); Serie.afdrukken(RSSI); Serie.afdrukken(")"); Serie.println(""); } int Mac[6]; // wir ermitteln die MAC Adresse und speichern sie im RTC Memory als ( 6 == sscanf(BSSIDstr.c_str(), "%x:%x:%x:%x:%x:%x%c", &Mac[0], &Mac[1], &Mac[2], &Mac[3], &Mac[4], &Mac[5] ) ) { voor (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 breken; } } } als (DEBUG) { als (slaveFound) { Serie.println("Slave gevonden, bezig met verwerken ..."); } anders { Serie.println("Slave Not Found, probeert het opnieuw."); } } // RAM freigeben Wifi.scanVerwijderen(); } // functie um eine Sensoradresse zu drucken nietig printAdres(DeviceAddress adressen) { voor (uint8_t ik = 0; ik < 8; ik++) { als (adressen[ik] < 16) Serie.afdrukken("0"); Serie.afdrukken(adressen[ik], HEX); } } nietig opstelling() { als (DEBUG) { Serie.beginnen(115200); Serie.println("Begin"); } pinMode(bus,INPUT_PULLUP); // Wir ermitteln die Anzah der Sensoren am Eindraht-Bus sensoren.beginnen(); als (DEBUG) { Serie.afdrukken(sensoren.getDeviceCount(), DEC); Serie.println("Sensoren gefunden."); } // Geen druk op de sensor voor bus en temperatuursensor als (!sensoren.getAddress(adressen,0)) { als (DEBUG) Serie.println("Kein Temperatursensor vorhanden!"); } // adressen anzeigen als (DEBUG) { Serie.afdrukken("Adresse:"); printAdres(adressen); Serie.println(); } // Nun setzen wir noch die gewünschte Auflösung (9, 10, 11 of 12 bit) sensoren.setResolution(adressen,10); // Zur Kontrolle lesen wir den Wert wieder aus als (DEBUG) { Serie.afdrukken("Auflösung ="); Serie.afdrukken(sensoren.getResolution(adressen), DEC); Serie.println(); } sensoren.requestTemperatures(); // Commando um die Temperaturen auszulesen // Wir lesen aus dem RTC-geheugen ESP.rtcUserMemoryRead(0, (uint32_t*) &statinfo, De grootte van(statinfo)); als (DEBUG) Serie.println("RTC gereed"); uint32_t crcOfData = berekenCRC32(((uint8_t*) &statinfo) + 4, De grootte van(statinfo) - 4); Wifi.modus(WIFI_STA); // Station-modus voor esp-now sensorknooppunt als (DEBUG) Serie.println("WifiMode"); als (statinfo.crc32 != crcOfData) { // wir haben keine gültige MAC Adresse als (DEBUG) Serie.println("Scan vor Slave"); ScanForSlave(); als (DEBUG) { Serie.printf("Deze mac:% s,", Wifi.Mac adres().c_str()); Serie.printf("target mac:% 02x% 02x% 02x% 02x% 02x% 02x", statinfo.Mac[0], statinfo.Mac[1], statinfo.Mac[2], statinfo.Mac[3], statinfo.Mac[4], statinfo.Mac[5]); Serie.printf(", kanaal:% i \ n", WIFI_CHANNEL); } } als (esp_now_init() != 0) { als (DEBUG) Serie.println("*** ESP_Now init mislukt"); ESP.herstarten(); } // ESP Now-controller esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER); // Peer Daten initialisieren esp_now_add_peer(statinfo.Mac, ESP_NOW_ROLE_SLAVE, WIFI_CHANNEL, NUL, 0); // wir registrieren die Funktion, die nach dem Senden aufgerufen werden soll esp_now_register_send_cb([](uint8_t* Mac, uint8_t sendStatus) { als (DEBUG) { Serie.afdrukken("send_cb, status ="); Serie.afdrukken(sendStatus); Serie.afdrukken(", naar mac:"); char 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]); Serie.println(macString); } callbackCalled = waar; }); // Vlag van valse setzen callbackCalled = fout; // Temperaturmessung starten sensoren.requestTemperatures(); vertraging(750); // 750 ms warten bis die Messung fertig ist // Temperaturwert holen und in Satenstruktur zum Senden speichern DATEN_STRUKTUR gegevens; gegevens.temp = sensoren.getTempC(adressen); uint8_t bs[De grootte van(gegevens)]; // Datenstruktur in den Sendebuffer kopieren memcpy(bs, &gegevens, De grootte van(gegevens)); // Daten an Thermometer senden esp_now_send(NUL, bs, De grootte van(gegevens)); // NULL betekent verzenden naar alle peers als (DEBUG) { Serie.afdrukken("Temperatur:"); Serie.afdrukken(gegevens.temp); Serie.println("° C"); } } nietig lus() { // warten bis Daten gesendet wurden als (callbackCalled || (millis() > SEND_TIMEOUT)) { als (DEBUG) Serie.println("Slaap"); vertraging(100); // Für 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.diepe slaap(300E6); } }
Testen:
Nachdem das Modul mit Strom versorgt wurde kennt es noch keine gültige MAC-adresse des thermometers. Es versucht ein offenes Netwerk met der SSID "Thermometer" zu finden. Da Thermometer en temperatuur Minuten na dem Start seine SSID versteckt, müssen wir einen Neustart des Thermometers auslösen. Geen sensor Sensormodule Temperatuur thermometer en alle temperatuur Minuten den aktuellen Temperaturwert übermitteln. Das Thermometer sollte abwechselnd die lokale Temperatur (Häuschen Symbol) und die Temperatur vom Sensor Modul (Baum Symbol) anzeigen.
5 Reacties
esp tester
Tolles Projekt!
Peter
Wie weit können die Module denn voneinander entfernt sein?
Peter
Tolles Projekt! Ist es möglich mehrere entfernte Module zu betreiben?
Viele Grüße Peter
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
Super, genau so etwas habe ich gesucht.
Vielen Dank für die interessanten Projektvorstellungen.