Über den Beitrag
In meinem letzten Beitrag hatte ich gezeigt, wie ihr ein 433 MHz Funk Grillthermometer mit grafischer Anzeige des Temperaturverlaufs bauen könnt. Der Bastelaufwand war recht erheblich, was einige von einem Nachbau abhalten könnte. Deshalb möchte ich in diesem Beitrag eine erheblich einfachere Variante auf WLAN Basis vorstellen. Hier müsst ihr nur eine Sendeeinheit bauen, denn als Empfänger dient der Browser eures Smartphones, Tablets, PCs oder Laptops. Auch die Sendeeinheit selbst ist einfacher gehalten, indem ich bei ihr auf ein Display und den externen A/D-Wandler verzichte. Und da ich einen ESP32 als Mikrocontroller verwende, wird auch kein Funkmodul benötigt.
Der Nachteil ist, dass die Grafik mit dem Temperaturverlauf fehlt. Hingegen müsst ihr auf eine Warnung bei Erreichen der Zieltemperatur nicht verzichten. Das realisiere ich über den IFTTT Dienst (if-this-then-that), da eine direkte akustische Warnung über den Browser nur über einige Umwege möglich wäre.
Das Konzept
Hier zunächst die Schaltung:
Der Temperaturfühler wird dabei durch seine Anschlussbuchse repräsentiert.
Und so sah es auf dem Breadboard aus:
Ich benutze übrigens eine LED mit integriertem Vorwiderstand – bevor jemand fragt, warum hier ein Widerstand fehlt.
Temperaturmessung
Wie im letzten Beitrag verwende ich auch hier einen Ersatzfühler für Grillthermometer, den es bei Amazon und anderen Online-Shops für ein paar Euro gibt. Der Temperaturfühler ändert seinen Widerstand mit der Temperatur. Entsprechend ändert sich die über ihn abfallende Spannung, wenn ihr ihn in einem Spannungsteiler einsetzt. Gegenüber dem zuletzt vorgestellten Grillthermometer vereinfache diesen Teil der Schaltung dahin gehend, dass ich nur die Thermometerspannung und nicht die 3.3 Volt Gesamtspannung messe. Dafür ist eine sehr stabile Gesamtspannung erforderlich.
Der A/D-Wandler des ESP32 ist nicht wirklich linear (Details hier) und liefert recht viel Rauschen. Letzteres lässt sich etwas durch Kondensatoren mindern, wie vom Hersteller Espressif empfohlen (siehe hier). Die Nicht-Linearität wird einfach „wegkalibriert“.
Stromversorgung für das WLAN Grillthermometer
Wie ein ESP32 Board am besten mit Batterien oder Akkus betrieben wird, darüber scheiden sich die Geister. Wenn ihr euer Board am PC programmiert, bekommt es seine Versorgungsspannung über die USB Buchse, also 5 Volt. Meistens befindet sich auf dem Board ein AMS1117-3.3 Spannungsregler, der die Versorgungsspannung auf die für den ESP32 benötigten 3.3 Volt reduziert. Der AMS1117-3.3 verträgt laut Datenblatt Spannungen, die bis zu 12 Volt über der Ausgangsspannung liegen dürfen.
Der Pin „V5“ (er mag bei eurem Board etwas anders heißen) ist direkt mit dem Stromanschluss der USB Buchse verbunden und wird normalerweise genutzt, um dort die 5 Volt abzugreifen. Meiner Meinung nach spricht nichts dagegen, diesen als Eingang für die Spannungsversorgung zu nutzen und dabei über die 5 Volt hinauszugehen. Da in einem Spannungsregler Ein- und Ausgangsstrom identisch sind (siehe auch hier) und die Spannung sich ändert, wird die Leistung P=ΔU⋅I in Form von Wärme abgegeben. Aber auch nach längerem Betrieb ist das Teil in meinem Projekt nicht sonderlich warm geworden.
Auswahl des Akkutyps
Als Spannungsversorgung verwende ich einen Lithium-Ionen-Akku. Genau genommen verwende ich zwei hintereinandergeschaltete 3.7 V Akkus. Genauso gut könnt ihr einen 9V Lithium-Akku verwenden. Intern besteht dieser auch aus zwei Lithium-Ionen-Akkus und liefert deswegen übrigens keine 9 Volt, auch wenn die Bezeichnung es suggeriert. Frisch aufgeladen liefern sie ca. 8.4 Volt.
Mit dieser Stromversorgung habe ich eine sehr stabile Spannung am 3.3 Volt Pin erhalten. Die Schwankung lag deutlich unter einem hundertstel Volt, selbst wenn die Akkuladung auf unter 7 Volt fiel. Ab da schreitet die Entladung recht schnell voran und der Akku sollte getauscht werden.
Weitere Verbraucher solltet ihr nicht an den 3.3 Volt Ausgang hängen – oder ihr verwendet doch lieber die Messmethode aus dem letzten Beitrag, bei der ich die Gesamtspannung am 3.3 Volt Ausgang mit gemessen habe.
Die Diode am 5 V Pin dient dem Schutz vor Verpolung. Das ist optional.
Wichtiger Hinweise zum Akkubetrieb – bitte lesen!
Da Pin V5 direkt mit der USB Buchse verbunden ist, dürft ihr auf gar keinen Fall einen Akku verwenden, während das Board am Computer hängt!
Messung der Akkuspannung
Es ist sinnvoll, die Akkuspannung zu überwachen, damit das Thermometer nicht im falschen Moment ausfällt. Da die Akkuspannung zu hoch für den A/D-Wandler des ESP32 ist, messe ich sie indirekt über einen Spannungsteiler. Hier muss allerdings der Fehler des ESP32 A/D-Wandlers berücksichtigt werden. Wenn man den Spannungsteiler aber geschickt dimensioniert, landet man in einem Bereich, in dem der A/D-Wandler linear arbeitet und in erster Näherung um einen festen Offset verschoben ist (siehe rechts). Die Werte könnt ihr dann recht einfach korrigieren. Ich habe einfach verschiedene bekannte Spannungen zwischen 6.5 und 8.5 Volt an den Spannungsteiler angelegt und die geteilte Spannung mit dem A/D-Wandler ausgelesen.
U_{\text{geteilt, ideal}}\;[\text{V}]=\frac{\text{analogRead}(34)}{4095}\cdot 3.3
Die reale geteilte Spannung war um ca. 0.14 Volt höher. Das habe ich mit einem verlässlichen Multimeter gemessen. Die Umrechnung in die Versorgungsspannung erfolgt dann über einen festen Faktor, der durch das Verhältnis der Widerstände bestimmt ist:
U_{\text{Versorgung}}\;[\text{V}]=\left(U_{\text{geteilt, ideal}}+0.14\right)\cdot3.237
Power-On LED
Die LED an GPIO17 hat einfach nur den Sinn euch anzuzeigen, dass das Thermometer angeschaltet ist. Ihr könntet sonst leicht vergessen, es nach Gebrauch auszuschalten. Das ist natürlich auch optional.
Kalibrierung
Für die Aufnahme der Kalibrierkurve habe ich, wie für das letzte Thermometer, einen Topf mit Wasser erhitzt und beim Abkühlen Temperatur-/Spannungswerte mithilfe eines Referenzthermometers meines Vertrauens aufgenommen. Für die Spannungswerte habe ich 50 Einzelwerte gemittelt.
void setup(){ Serial.begin(115200); } void loop(){ unsigned long sum = 0; unsigned int numberOfSamples = 50; for(int i=0; i<numberOfSamples; i++){ sum += analogRead(33); } float milliVolts = (sum /(numberOfSamples*1.0))/4.095 * 3.3; Serial.println(milliVolts); delay(500); }
In Excel habe ich dann ein Ausgleichspolynom („Trendlinie“) durch die Messwerte gelegt. Erst ein Polynom vierter Ordnung passte.
Auch wenn es so funktioniert hätte, habe ich mich am Ende dafür entschieden, die Kurve zu stückeln und kleinere Polynome zu verwenden:
Wie ihr dafür sorgt, dass die Koeffizienten eures Polynoms mit genügend Dezimalstellen ausgegeben werden, habe ich im letzten Beitrag beschrieben.
Der Sketch für das WLAN Grillthermometer
Option 1: Die einfache Lösung
Die einfache Lösung zeigt euch lediglich die Temperatur und die Akkuspannung in einem beliebigen Browser an, beispielsweise auf eurem Smartphone oder Tablet. Die Grundlagen der WLAN Nutzung habe ich hier im Detail behandelt. In diesem Beitrag gehe ich nur grob darauf ein. Hier zunächst der Sketch.
#include <WiFi.h> #include <WebServer.h> #define TEMPERATURE_PIN 33 #define SUPPLY_VOLTAGE_PIN 34 #define LED_PIN 17 // power-on LED const char* ssid = "Your WiFi name"; const char* pass = "Your WiFi password"; WebServer server(80); // creating a webserver object String headString = "<head><style>" // head and CSS style elements ".blueBox {" "background-color: blue;" "color: white;" "width: 600px;" "padding: 20px;" "text-align: center;" "font-size: 50px;" "font-family: arial;" "margin: 20px 35px;" "}" "</style>"; String refreshString = "<meta http-equiv=\"refresh\" content=\"10\"></head>"; String trackTempString = "</BR><h1 align=\"center\">BBQ - Current Temperature</h1></div>"; void setup(){ pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, HIGH); Serial.begin(115200); Serial.println("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, pass); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected..!"); Serial.print("Got IP: "); Serial.println(WiFi.localIP()); server.on("/",trackTemperatureScreen); server.begin(); } void loop(){ server.handleClient(); } void trackTemperatureScreen(){ String message = ""; float bbqTemp = getBbqTemperature(); float supplyVoltage = getSupplyVoltage(); message += headString; message += refreshString; message += trackTempString; message += "<div align=\"center\";>"; message += "<div class=\"blueBox\">"; message += "Current Temperature [˚C]: </BR></BR><span style=\"font-size: 100px;\">"; message += String(bbqTemp, 1); message += "</span>"; message += "</div>"; message += "</BR><h2>Supply Voltage [V]: "; message += String(supplyVoltage,1); message += "</h2></div>"; server.send(200, "text/html", message); } float getBbqTemperature(){ // replace by your calibration function(s) // 70-100°C: y = 28.436x2 - 89.635x + 128.71 // 45-70°C: y = 6.3363x2 - 50.673x + 111.64 // 0-45°C: y = -2.3284x2 - 23.46x + 90.312 float tV = 0.0; // thermometer voltage float tC = 0.0; // temperature Celsius unsigned long tempSum = 0; unsigned int numberOfSamples = 50; for(int i=0; i<numberOfSamples; i++){ tempSum += analogRead(TEMPERATURE_PIN); } tV = (tempSum /(numberOfSamples*1.0))/4095.0 * 3.3; if(tV < 1.0){ tC = 28.436*pow(tV,2) - 89.635*tV + 128.71; } else if(tV < 1.7){ tC = 6.3363*pow(tV,2) - 50.673*tV + 111.64; } else{ tC = -2.3284*pow(tV,2) - 23.46*tV + 90.312; } return tC; } float getSupplyVoltage(){ unsigned long sum = 0; unsigned int numberOfSamples = 50; for(int i=0; i<numberOfSamples; i++){ sum += analogRead(SUPPLY_VOLTAGE_PIN); } float volts = (sum /(numberOfSamples*1.0))/4095.0 * 3.3; volts = (volts + 0.14) * 3.237; return volts; }
Erläuterungen zum Sketch
Der ESP32 dient als Server, der die Temperatur und die Akkuspannung auf einer Website darstellt. Der Inhalt der Website wird als String („message“) an den Client, also den Browser, übertragen. Die Einbettung von HTML Code in Arduino Code ist für die Lesbarkeit nicht förderlich, aber das liegt in der Natur der Sache. Noch ein paar Erklärungen:
- „ssid“ / „pass“ sind die Zugangsdaten für euer WLAN
- In „headString“ wird das Gestaltungselement „blaue Box“ als CSS-Code definiert.
- Der Inhalt von „refreshString“ sorgt für eine Aktualisierung der Website im Abstand von 10 Sekunden.
- Der serielle Monitor zeigt die IP an, die euer Router dem ESP32 zuweist. Am besten stellt ihr in eurem Router ein, dass der ESP32 immer diese IP bekommt.
server.on("/",trackTemperatureScreen);
bewirkt, dass bei Aufruf der IP-Adresse (es gibt nur den Hauptpfad „/“) die FunktiontrackTemperatureScreen()
aufgerufen wird.trackTemperatureScreen()
initiiert neue Messungen, stellt den Inhalt der Website zusammen und sendet ihn an den Server.
Ausgabe der Option 1
Geht in den Browser des Gerätes eurer Wahl und gebt dort die IP eures ESP32 ein. Bei mir ist das „192.168.178.38“. Eventuell müsst ihr auch noch einen Schrägstrich anhängen, also „192.168.178.38/“. Alle 10 Sekunden sollte ein aktualisierter Wert erscheinen.
Wenn ihr Probleme habt, dann hängt den ESP32 direkt an euren Computer und schaut, ob sich der ESP32 mit dem Heimnetz verbindet und ob die IP-Adresse stimmt.
Option 2: Die „Komfort-Lösung“
Die Komfort-Lösung für das WLAN Grillthermometer umfasst die Einstellung eines Temperaturlimits und eine Warnung, wenn das Limit erreicht wurde. Das klingt eigentlich nach einer geringfügigen Ergänzung, aber der resultierende Sketch war am Ende zweieinhalb mal so lang.
Einstellung der Zieltemperatur
Für die Einstellung der Zieltemperatur gibt es einen eigenen Bildschirm (siehe rechts). Er erscheint, wenn die Website aufgerufen wird. Im Sketch geschieht das durch den Aufruf von setTemperatureScreen()
. Die Voreinstellung für die Zieltemperatur ist 55 °C. Durch Tippen auf die Felder +/- 10 °C und +/- 1 °C könnt ihr die Zieltemperatur verändern. Diese Felder sind als HTML Buttons definiert und mit entsprechenden Pfaden der Website verlinkt. Dafür musste ich den Sketch um eine Reihe weiterer server.on()
Funktionen erweitern. Die server.on()
Funktionen rufen wiederum Funktionen auf, die die Zieltemperatur wie angefordert ändern.
Ich habe die Einstellung so programmiert, dass die Zieltemperatur zwischen 40 und 99 °C gewählt werden kann. Das könnt ihr natürlich ändern, wenn es euch sinnvoll erscheint.
Habt ihr die gewünschte Zieltemperatur eingestellt, tippt ihr auf „Accept Target“ und landet dann auf dem „trackTemperatureScreen“ (siehe nächstes Bild).
Verfolgen der Temperatur
Der „trackTemperatureScreen“ für das WLAN Grillthermometer zeigt die aktuelle Temperatur und die Akkuspannung an. Zu Beginn wird die Temperatur in weißer Schrift angezeigt. Bei fünf Grad unter Zieltemperatur wird sie orange. Ab einem Grad unter Zieltemperatur wird sie rot.
Zusätzlich hat der Bildschirm zwei „Buttons“. Der eine heißt „New Target“ und führt zurück zur Zieltemperatureinstellung. Mit dem zweiten Button könnt ihr den Alarm aus- und auch wieder anstellen. Er wechselt dann entsprechend Farbe und Beschriftung. Wenn der Alarm ausgelöst wurde, wird er deaktiviert.
Alarm auslösen mit IFTTT
Aus Sicherheitsgründen ist es Websites nicht direkt möglich, Programme auf eurem Gerät aufzurufen, euer Smartphone zum Klingeln zu bringen oder ähnliche Aktionen zu initiieren, die ihr als Alarm nutzen könntet. Selbst das automatische Abspielen von Audiodateien ist nur über Umwege und Sondereinstellungen möglich.
Um trotzdem einen Alarm auszulösen, nutze ich den kostenlosen Dienst IFTTT (if-this-then-that). Was das genau ist, wie ihr den Zugang einrichtet und mit dem Dienst umgeht habe ich hier beschrieben. Ich werde die Erklärungen in diesem Beitrag deswegen kurz halten.
Auf IFTTT kreiert ihr in wenigen Minuten sogenannte Applets, die aus einem Auslöser („if this“) und einer Aktion („then that“) bestehen. Der Auslöser ist in diesem Fall ein sogenannter „Webhook“. Das ist eine kleine Nachricht in einem bestimmten Format, die von Websites per POST- oder GET-Request an IFTTT geschickt werden. Diese Aufgabe übernimmt in meinem Sketch die Funktion send_webhook()
. Ihr braucht euch also nicht um die Details zu kümmern. Mit dem Webhook könnt ihr bis zu drei Variablen übermitteln, also in diesem Fall die Temperatur eures WLAN Grillthermometers.
Die Aktion, die das Senden des Webhooks auslösen soll, ist eine Benachrichtigung (notification) auf euer Smartphone (siehe oben rechts). Den Text könnt ihr frei variieren. Wie ihr das konkret macht, habe ich in dem schon erwähnten Artikel an dieser Stelle beschrieben. Es ist wirklich einfach.
Einschränkungen
Es gibt da noch zwei kleine Problemchen:
- Wenn sich euer Telefon nach einigen Minuten ohne Benutzung „schlafen legt“, kommen die Benachrichtigungen verzögert.
- Das Update der Temperatur und die Überprüfung des Temperaturlimits wird durch eine Anfrage des Browsers ausgelöst. Schläft euer Smartphone, gibt es kein Update und keinen Alarm.
Zur Lösung von Problem 1 empfehle ich, die Zeit bis zur Aktivierung der Bildschirmsperre hochzusetzen. Das lässt sich in den Einstellungen ändern, ist aber auf Dauer nervend. Mit Apps lässt sich das bequemer realisieren. Screen Alive funktioniert beispielsweise wunderbar für Android Smartphones. Die kostenlose und werbefreie App bietet ein Widget mit dem ihr den „Immer an“ Modus mit einem einzigen Klick aktivieren könnt. Alternativ verwendet ihr nicht die Benachrichtigungen, sondern SMS als „then that“. Der Nachteil ist, dass der Dienst auf 10 SMS pro Monat begrenzt ist.
Das zweite Problem habe ich gelöst, indem ich die Temperatur zusätzlich in loop() abfrage. Das passiert aber nur, wenn mindestens 15 Sekunden seit der letzten Temperaturabfrage vergangen sind.
Der Sketch für die Komfort Lösung
Hier nun der vollständige Sketch für das WLAN Grillthermometer:
#include <WiFi.h> #include <WebServer.h> #define TEMPERATURE_PIN 33 #define SUPPLY_VOLTAGE_PIN 34 #define LED_PIN 17 // power-on LED #define IFTTT_Key "Your IFTTT Key" #define IFTTT_Event "BBQ_Event" #define IFTTT_Value1 "Hi! " #define IFTTT_Value3 "dummy"; const char* ssid = "Your WiFi SSID"; const char* pass = "Your WiFi Password"; unsigned int bbqTargetTemp = 55; unsigned long lastTempMeasurement = 0; volatile bool tempAlert = true; WebServer server(80); String headString = "<head><style>" // head and CSS style elements ".button {" "border: none;" "color: white;" "width: 350px;" "padding: 20px;" "text-align: center;" "margin: 20px 35px;" "}" ".greenButton {background-color: green; font-size: 64px;}" ".greenButton:hover {background-color: darkgreen; font-size: 64px;}" ".redButton {background-color: red; font-size: 64px;}" ".redButton:hover {background-color: darkred; font-size: 64px;}" ".blueButton {background-color: blue; font-size: 50px;}" ".blueButton:hover {background-color: darkblue; font-size: 50px;}" ".blueBox {" "background-color: blue;" "color: white;" "width: 600px;" "padding: 20px;" "text-align: center;" "font-size: 50px;" "font-family: arial;" "margin: 20px 35px;" "}" "</style>"; String refreshString = "<meta http-equiv=\"refresh\" content=\"10\"></head>"; String setTargetString = "</BR><h1 align=\"center\">BBQ - Set your Target Temperature</h1></div>"; String trackTempString = "</BR><h1 align=\"center\">BBQ - Current Temperature</h1></div>"; String plus10String = "<a href=\"/plus_10\"><button class=\"button greenButton\">+ 10˚C</button></a>"; String minus10String = "<a href=\"/minus_10\"><button class=\"button redButton\">- 10˚C</button></a>"; String plus1String = "</BR><a href=\"/plus_1\"><button class=\"button greenButton\">+ 1˚C</button></a>"; String minus1String = "<a href=\"/minus_1\"><button class=\"button redButton\">- 1˚C</button></a>"; String setNewTargetString = "</BR><a href=\"/\"><button class=\"button greenButton\">New Target</button></a>"; String enableAlertString = "</BR><a href=\"/enableAlert\"><button class=\"button greenButton\">Enable Alert</button></a>"; String disableAlertString = "</BR><a href=\"/disableAlert\"><button class=\"button redButton\">Disable Alert</button></a>"; void setup(){ pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, HIGH); Serial.begin(115200); Serial.println("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, pass); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected..!"); Serial.print("Got IP: "); Serial.println(WiFi.localIP()); server.on("/",handleRoot); server.on("/plus_10", plus10); server.on("/minus_10", minus10); server.on("/plus_1", plus1); server.on("/minus_1", minus1); server.on("/enableAlert", enableAlert); server.on("/acceptTemp", trackTemperatureScreen); server.on("/disableAlert", disableAlert); server.on("/trackTemperature", trackTemperatureScreen); server.begin(); } void loop(){ server.handleClient(); if(((lastTempMeasurement - millis()) > 15000) && tempAlert){ float bbqTemp = getBbqTemperature(); alertCheck(bbqTemp); } } void handleRoot() { setTemperatureScreen(); } void plus10(){ bbqTargetTemp += 10; setTemperatureScreen(); } void minus10(){ bbqTargetTemp -= 10; setTemperatureScreen(); } void plus1(){ bbqTargetTemp++; setTemperatureScreen(); } void minus1(){ bbqTargetTemp--; setTemperatureScreen(); } void acceptTemp(){ enableAlert(); } void enableAlert(){ tempAlert = true; trackTemperatureScreen(); } void disableAlert(){ tempAlert = false; trackTemperatureScreen(); } void trackTemperatureScreen(){ String message = ""; float bbqTemp = getBbqTemperature(); float supplyVoltage = getSupplyVoltage(); String colorString = "white"; if((bbqTargetTemp - bbqTemp) < 1.0){ colorString = "red"; } else if((bbqTargetTemp - bbqTemp) < 5.0){ colorString = "orange"; } message += headString; message += refreshString; message += trackTempString; message += "<div align=\"center\";>"; message += "<div class=\"blueBox\">"; message += "Current Temperature [˚C]: </BR></BR><span style=\"font-size: 100px; color: "; message += (colorString + "\">"); message += String(bbqTemp, 1); message += "</span>"; message += "</BR></BR>Target [˚C]: "; message += String(bbqTargetTemp); message += "</div>"; message += setNewTargetString; if(tempAlert){ message += disableAlertString; } else{ message += enableAlertString; } message += "</BR><h2>Supply Voltage [V]: "; message += String(supplyVoltage,1); message += "</h2></div>"; server.send(200, "text/html", message); alertCheck(bbqTemp); } float getBbqTemperature(){ // replace by your calibration function(s) // 70-100°C: y = 28.436x2 - 89.635x + 128.71 // 45-70°C: y = 6.3363x2 - 50.673x + 111.64 // 0-45°C: y = -2.3284x2 - 23.46x + 90.312 float tV = 0.0; // thermometer Voltage float tC = 0.0; // temperature Celsius unsigned long tempSum = 0; unsigned int numberOfSamples = 50; for(int i=0; i<numberOfSamples; i++){ tempSum += analogRead(TEMPERATURE_PIN); } tV = (tempSum /(numberOfSamples*1.0))/4095.0 * 3.3; if(tV < 1.0){ tC = 28.436*pow(tV,2) - 89.635*tV + 128.71; } else if(tV < 1.7){ tC = 6.3363*pow(tV,2) - 50.673*tV + 111.64; } else{ tC = -2.3284*pow(tV,2) - 23.46*tV + 90.312; } lastTempMeasurement = millis(); return tC; } float getSupplyVoltage(){ unsigned long sum = 0; unsigned int numberOfSamples = 50; for(int i=0; i<numberOfSamples; i++){ sum += analogRead(SUPPLY_VOLTAGE_PIN); } float volts = (sum /(numberOfSamples*1.0))/4095.0 * 3.3; volts = (volts + 0.14) * 3.237; return volts; } void alertCheck(float currentTemp){ String tString = String(currentTemp, 1); // convert temperature as float into String if((currentTemp > bbqTargetTemp) && tempAlert){ send_webhook(tString); tempAlert = false; } } void setTemperatureScreen(){ String message = ""; if(bbqTargetTemp >= 100){ bbqTargetTemp -= 60; } if(bbqTargetTemp < 40){ bbqTargetTemp += 60; } message += headString; message += setTargetString; message += "<div align=\"center\";>"; message = message + plus10String + minus10String + plus1String + minus1String; message += "</BR><a href=\"/acceptTemp\"><button class=\"button blueButton\">"; message += "Accept</BR>Target [˚C]: </BR>"; message += String(bbqTargetTemp); message += "</button></a>"; message += "</div>"; server.send(200, "text/html", message); } void send_webhook(String IFTTT_Value2){ WiFiClient client; // construct the JSON payload String jsonString = ""; jsonString += "{\"value1\":\""; jsonString += IFTTT_Value1; jsonString += "\",\"value2\":\""; jsonString += IFTTT_Value2; jsonString += "\",\"value3\":\""; jsonString += IFTTT_Value3; jsonString += "\"}"; int jsonLength = jsonString.length(); String lenString = String(jsonLength); // connect to the Maker event server client.connect("maker.ifttt.com", 80); // construct the POST request String postString = ""; postString += "POST /trigger/"; postString += IFTTT_Event; postString += "/with/key/"; postString += IFTTT_Key; postString += " HTTP/1.1\r\n"; postString += "Host: maker.ifttt.com\r\n"; postString += "Content-Type: application/json\r\n"; postString += "Content-Length: "; postString += lenString + "\r\n"; postString += "\r\n"; postString += jsonString; // combine post request and JSON client.print(postString); delay(500); client.stop(); }
Der Sketch ist aufgrund seiner Länge und der Durchmischung von HTML, CSS, und Arduino Code etwas schwer zu verdauen. Der HTML und CSS Code wird stückweise zusammengesetzt. Alle Anführungsstriche, die nicht Teil des Arduino Codes sind, müssen mit einem vorangestellten Backslash versehen werden, was auch nicht gerade zur besseren Lesbarkeit beiträgt. Wenn ihr hinsichtlich der Website selbst gestalterisch tätig werden wollt, dann empfehle ich, das erst einmal separat mit einem guten Editor wie Notepad++ zu tun. Für alle Variablen setzt ihr Dummies ein. So sieht beispielsweise der reine HTML-/CSS-Code für den „trackTemperatureScreen“ aus:
<head> <style> .button { border: none; color: white; width: 350px; padding: 20px; text-align: center; margin: 20px 35px; } .greenButton {background-color: green; font-size: 64px;} .greenButton:hover {background-color: darkgreen; font-size: 64px;} .redButton {background-color: red; font-size: 64px;} .redButton:hover {background-color: darkred; font-size: 64px;} .blueButton {background-color: blue; font-size: 50px;} .blueButton:hover {background-color: darkblue; font-size: 50px;} .blueBox { background-color: blue; color: white; width: 600px; padding: 20px; text-align: center; font-size: 50px; font-family: arial; margin: 20px 35px; } </style> <meta http-equiv="refresh" content="10"> </head> </BR> <h1 align="center">BBQ - Current Temperature</h1> <div align="center"> <div class="blueBox"> Current Temperature [˚C]: </BR></BR> <span style="font-size: 100px; color: red"> 99.9 </span> </BR></BR> Target [˚C]: 99.9 </div> </BR> <a href="/"><button class="button greenButton">New Target</button></a> </BR> <a href="/disableAlert"><button class="button redButton">Disable Alert</button></a> </BR> <h2>Supply Voltage [V]: 9.9</h2> </div>
Zusammenbau
Ich habe ein einfaches Universal-Elektronikgehäuse verwendet, das nicht viel größer als das ESP32 Board ist. Die Platine habe ich aus einer Lochrasterplatine ausgesägt. Die Platine ist mit Abstandshaltern auf der Bodenplatte befestigt. Das Batteriegehäuse habe ich angeschraubt, die Kabel nach innen verlegt und über ein Loch in das Hauptgehäuse gefühlt. Außerdem musste ich zwei Öffnungen für die LED und die Anschlussbuchse für das Thermometer bohren.
Und hier das komplette, zusammengebaute WLAN Grillthermometer:
Danksagung
Und wieder einmal bedanke ich mich bei fleißigen Künstlern, die ihre Bilder auf Pixabay zur Verfügung gestellt haben. In meinem Beitragsbild habe ich ganz oder in Teilen folgendes verwendet:
- Grill: Clker-Free-Vector-Images
- Smartphone: Leo Romero
- WLAN Symbol: Ricardo_Duque
- WiFi-Symbol: Pixaline
- Feuer: Alexas_Fotos
Hallo Wolfgang,
ich bin beim Grillen immer in Fleischnähe.
Da wäre ein Beeper dieeinfachere Methode.
Der könne auch Vorwarnung geben so wie beim rückwärts fahren
und wenn fertig SOS piepen.
🙂 Jeder, wie er es mag!
Sicherlich,
mich stört da nur „Alarm auslösen mit IFTTT“,
ansonsten sehr gut.
Ich versuche mal die IFTTT Zeilen zu entfernen und den Beeper einzubauen.
Zum Thema LED als Aktivitätsanzeige hätte ich noch einen:
Die NICHIA NSPR510GS (5mm, rot) ist für so etwas bei Akku- / Batteriebetrieb gut geeignet, da man sie bereits mit ca. 10µA (!) zum Leuchten bringen kann. Ich verwende eine an einem selbst gebauten Mikrofon mit Verstärker, das mit 2 CR2032 in Serie betrieben wird, mit einem Vorwiderstand von 410k :-).
Grüße, Stefan
10µA? Cool! Muss ich mir mal anschauen. Die ca. 10mA „normaler“ LEDs gehen bei Dauerbetrib tatsächlich ziemlich auf den Akku. Vielen Dank und viele Grüße, Wolfgang
Cooles Projekt!
Falls sie die grafische Darstellung aufs Smartphones/Tablet/Computer bringen möchten, dann geht das mit JavaScript und einem canvas Objekt recht gut. Ich bastle ja gerade noch in den letzten Zügen an einer Waage die den Körperschwerpunkt im Browser anzeigen kann… im HX711 Beitrag hatte ich schon einmal davon berichtet. Mein Lösungsansatz ist es, die statischen HTML Dateien aus dem SPIFFS zu liefern und die Werte als JSON. Der Browser setzt beides zusammen und malt die Messpunkte in das canvas Objekt. Das funktioniert erstaunlich reibungslos.
Beste Grüße und danke für diesen Beitrag.
Hi, vielen Dank für die Hinweise. Bei JavaScript habe ich noch etwas Nachholbedarf. Ich habe mich mal ein bisschen damit beschäftigt, und das Bisschen ist wieder verschüttet. Guter Anlass mir das mal wieder genauer anzuschauen. VG, Wolfgang