Om deze serie nu af te ronden, is een eenvoudig, goedkoop apparaat gebaseerd ESP8266 met een of twee DS18B20 Temperatuur sensoren. Omdat het apparaat elke 5 minuten slechts enkele milliseconden actief is, kan het heel goed met batterijen worden gebruikt. De batterij op de foto is symbolisch. Als u de + 5V-pin van de D1-Mini gebruikt om de ingebouwde spanningsregelaar op 3,3 V te gebruiken, hebt u minimaal 3 batterijen met elk 1,5 V nodig.
Waarschuwing! De oranje draadverbinding dient om uit de slaapstand te komen en moet worden verwijderd om te knipperen.
Nu de code:
Voor de definitieve versie die u op batterij wilt gebruiken, moet de vlag DEBUG worden ingesteld op onwaar.
/* WLAN temperatuursensor ESP Nu naar de MQTT-gateway Als er nog geen MAC-adres is bepaald de sensor zoekt naar een WLAN met SSID MQTT-gateway 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> # opnemen <DallasTemperatuur.h> # opnemen <CayenneLPP.h> // Bibliotheek voor ESP nu extern "C" { # opnemen <vooral.h> } // SSID van de gateway #define GW_SSID "MQTTGateway" // Debug vlag indien false alle debug berichten worden onderdrukt // om extra elektriciteit te besparen #define DEBUG waar // Constanten voor wifi #define SEND_TIMEOUT 2000 // 2 seconden time-out // kanaaltoewijzing #define CHANNEL_TEMPI 1 #define CHANNEL_TEMPE 2 // Pinnen voor temperatuursensoren const byte bus_int = 2; // GPIO2 const byte bus_ext = 4; // GPIO4 // 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]; uint32_t kanaal; }; // Wereldwijde gegevens vluchtig dwaas callbackCalled; // geheugen voor temperatuurwaarden zweven temp_int = 0; zweven temp_ext = 0; Boolean has_int = 0; Boolean has_ext = 0; // MAC-adres en WiFi-kanaal MEMORYDATA statinfo; // buffer voor gegevens in LPP-indeling CayenneLPP lpp(64); // bus naar de sensoren OneWire oneWire_int(bus_int); OneWire oneWire_ext(bus_ext); DallasTemperatuur sensors_int(&oneWire_int); DallasTemperatuur sensoren_ext(&oneWire_ext); // array om sensoradressen op te slaan DeviceAddress adressen_int; DeviceAddress adressen_ext; // 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, grootte van(statinfo) - 4); statinfo.crc32 = crcOfData; ESP.rtcUserMemoryWrite(0,(uint32_t*) &statinfo, grootte van(statinfo)); } // zoekt naar een geschikt toegangspunt 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 gevonden in AP-modus"); } 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); int32_t chl = Wifi.kanaal(ik); Draad BSSIDstr = Wifi.BSSIDstr(ik); als (DEBUG) { Serie.afdrukken(ik + 1); Serie.afdrukken(": "); Serie.afdrukken(SSID); Serie.afdrukken(" /"); Serie.afdrukken(chl); Serie.afdrukken(" ("); Serie.afdrukken(RSSI); Serie.afdrukken(")"); Serie.println(""); } vertraging(10); // Controleer of het huidige apparaat start met `Thermometer` als (SSID == GW_SSID) { // 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]; } statinfo.kanaal = chl; 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); } } // Unterprogramm zum Initialisieren der DS18B20 Sensoren Boolean initDS18B20(uint8_t pin, DallasTemperatuur sensor, DeviceAddress adres ) { Boolean gevonden = 0; pinMode(pin,INPUT_PULLUP); sensoren_int.beginnen(); als (DEBUG) { Serie.afdrukken(sensor.getDeviceCount(), DEC); Serie.println("Sensoren gefunden."); } // Geen druk op de sensor voor bus en temperatuursensor als (!sensor.getAddress(adres,0)) { als (DEBUG) Serie.println("Kein Temperatursensor vorhanden!"); } anders { // adressen anzeigen als (DEBUG) { Serie.afdrukken("Adresse:"); printAdres(adres); Serie.println(); } // Nun setzen wir noch die gewünschte Auflösung (9, 10, 11 of 12 bit) sensor.setResolution(adres,10); // Zur Kontrolle lesen wir den Wert wieder aus als (DEBUG) { Serie.afdrukken("Auflösung ="); Serie.afdrukken(sensor.getResolution(adres), DEC); Serie.println(); } // Temperaturmessung starten sensor.requestTemperatures(); // Commando um die Temperaturen auszulesen gevonden = 1; } terug gevonden; } nietig opstelling() { uint8_t buf[70]; // sendebuffer als (DEBUG) { Serie.beginnen(115200); Serie.println("Begin"); } // eigen MAC Adresse ermitteln und als Geräte-Id im Sendespeicher ablegen Draad strmac = Wifi.Mac adres(); als (DEBUG) { Serie.afdrukken("Meine MAC Adresse ="); Serie.println(strmac); } int imac[6]; sscanf(strmac.c_str(), "%x:%x:%x:%x:%x:%x%c", &imac[0], &imac[1], &imac[2], &imac[3], &imac[4], &imac[5] ); voor (uint8_t ii = 0; ii<6; ii++) buf[ii]=imac[ii]; als (DEBUG) { Serie.println("Interne Sensoren"); } has_int = initDS18B20(bus_int,sensoren_int,adressen_int); als (DEBUG) { Serie.println("Externe Sensoren"); } has_ext = initDS18B20(bus_ext,sensoren_ext,adressen_ext); // 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) Seriële.println("Scan vor Slave"); ScanForSlave(); //for (uint8_t i = 0; i<6;i++) statinfo.mac[i] = gwmac[i]; als (DEBUG) { Seriële.printf("Deze mac: %s ", WiFi.macAddress().c_str()); Seriële.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]); Seriële.printf(", channel: %i\n", statinfo.kanaal); } } als (esp_now_init() != 0) { als (DEBUG) Seriële.println("*** ESP_Now init failed"); ESP.opnieuw opstarten(); } //ESP-Nu-Controller WiFi.setAutoConnect(valse); esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER); uint8_t ch = esp_now_get_peer_channel(statinfo.mac); Seriële.printf("Channel = %ik\r\n",,ch); //Peer Daten initialisieren int res = esp_now_add_peer(statinfo.mac, ESP_NOW_ROLE_CONTROLLER, 1, NULL, 0); als (res==0) Seriële.println("Erfolgreich gepaart"); //wir registrieren sterven Funktion, die nach dem Senden aufgerufen werden soll esp_now_register_send_cb([](uint8_t* mac, uint8_t sendStatus) { als (DEBUG) { Serieel.afdrukken("send_cb, status = "); Serieel.afdrukken(sendStatus); Serieel.afdrukken(", naar de 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]); Seriële.println(macString); } callbackCalled = true; }); //Vlag op false setzen callbackCalled = false; //Temperaturmessung starten als (has_int) sensoren_int.requestTemperatures(); als (has_ext) sensoren_ext.requestTemperatures(); vertraging(750); //750 ms warten bis sterven Messung fertig ist //Temperaturwert holen en in Datenstruktur zum Senden speichern als (has_int) temp_int = sensoren_int.getTempC(adressen_int); als (has_ext) temp_ext = sensoren_ext.getTempC(adressen_ext); //Buffer löschen lpp.reset(); //Datenpakete in den Buffer schreiben als (has_int) lpp.addTemperature(CHANNEL_TEMPI, temp_int); als (has_ext) lpp.addTemperature(CHANNEL_TEMPE, temp_ext); uint8_t sz = lpp.getSize(); //Datenstruktur in den Sendebuffer kopieren memcpy(&buf[6], lpp.haalbuffer(), sz); //Daten een Thermometer senden esp_now_send(NULL, buf, sz+6); // NULL betekent sturen naar alle peers als (DEBUG) { Serieel.afdrukken("Interne Temperatuur: "); Serieel.afdrukken(temp_int); Seriële.println("°C"); Serieel.afdrukken("Externe Temperatuur: "); Serieel.afdrukken(temp_ext); Seriële.println("°C"); } } void loop() { //warten bis Daten verzonden wurden als (callbackCalled || (millis() > SEND_TIMEOUT)) { als (DEBUG) Seriële.println("Slaap"); delay(100); //Für 300 Sekunden in den Tiefschlafmodus //dann erfolgt ein Reset und der ESP8266 wird neu gestartet //Daten im RTC Geheugen werden beim Reset nicht gelöscht. ESP.deepSleep -(300E6); } }
Nachdem Das Gerät gestartet wurde, sollten wir es auf der Web-Seite des Gateways te zien.
Wir können dem Gerät einen Namen geben und es registrieren.
Das Gerät hoed sterven Gerätenummer 1 erhalten daher sterven Kanäle 8 tot 15. Der Kanal 1 des Gerätes ist ook Kanal 9. Nach internationale verzamelband kurzer Zeit sollten wir im Cayenne Dashboard sterven beiden neuen Kanäle (oder nur einen wenn nur ein Temperatursensor angeschlossen wurde) te zien.
Non kann man die beiden Widgets für Kanal 9 und Kanal 10 hinzufügen und nach Wunsch anpassen.
Viel Spaß beim Nachbau