Präzisions-Temperatur-gesteuerter Holzkohle-Smoker Bausatz – Baue dein eigenes BBQ-Meisterwerk
Komponenten und Zubehör
| Komponente | Menge |
|---|---|
| Arduino MKR1000 | 1 |
| 5V Brushless Blower (Gebläse) | 1 |
| MOSFET IRF520N Treibermodul | 1 |
| 100 kΩ NTC-Thermistoren | 1 |
| Steckbrett (generic) | 1 |
| Steckbrücken (generic) | 1 |
| 3,7 V LiPo-Akku ≥ 700 mAh | 1 |
Apps und Online-Dienste
- Arduino IDE
- Microsoft Visual Studio 2015 (für Windows Universal App)
Projektbeschreibung
Hintergrund
Echte BBQ-Enthusiasten schwören auf Holzkohle für den besten Geschmack. Gas- und Elektro-Smoker bieten zwar bessere Temperaturkontrolle, verlieren aber das Holzkohle-Aroma. Holzkohle erfordert ständiges Überwachen, Lüftungsregulierung und Nachjustieren. Ziel: Smoker autonom regeln lassen, während man entspannt auf der Couch sitzt.
Das Projekt
Ein Controller überwacht die Smoker-Temperatur per Thermistor und regelt die Luftzufuhr zum Holzkohlefeuer über ein Gebläse, um die Zieltemperatur zu halten. Zusätzlich können Smoker- und Fleischtemperaturen per Windows 10 App (Universal Windows App) remote überwacht werden. Basiert auf Arduino MKR1000 mit integriertem WiFi und LiPo-Lademöglichkeit.
Hardware
Temperaturmessung: 100 kΩ NTC-Thermistor in Spannungsteiler an Analogeingang A0 (kürzere Sonde auf dem Rost). Weitere Analogpins für Fleischfühler nutzbar. Vorwiderstand 10 kΩ (passend zu Thermistor-Widerstand bei ca. 225 °F / 107 °C). Messbereich ca. 10–150 °C mit guter Auflösung.
Luftregelung: Kleines Gebläse am Smoker-Luftschacht. Ein Edelstahlnapf (Hundefutternapf) deckt den Schacht ab, Gebläse bläst von unten hinein → thermische Isolation zum Smoker. Ansteuerung über N-Kanal MOSFET (IRF520N Modul). Gate an digitalen Pin des MKR1000.
Aufbau
Erster Prototyp auf Steckbrett. Thermistor-Spannungsteiler: 10 kΩ von VCC (3,3 V) zu Thermistor, anderer Anschluss an GND, Mitte an Analogpin. Sonde: Thermistor in dünnes Edelstahlrohr (¼″), ein Ende verpresst, andere Ende mit Schrumpfschlauch gesichert.
Gebläse-Seite: Motoranschlüsse an MOSFET-Ausgang (Polung beachten), LiPo-Akku (10.000 mAh für lange Laufzeit) an MOSFET-Eingang, JST-Stecker in MKR1000 Ladebuchse. Drei Jumper (VCC, GND, Steuerleitung) vom MOSFET-Modul zum MKR1000.
Zusätzlich auf Steckbrett: 10 kΩ Potentiometer zum Testen (Simulieren von Thermistor-Spannungen), LED mit 330 Ω an Pin 0 als Gebläse-Statusanzeige.
Software
Zwei Teile: Arduino-Sketch (Webserver) und Windows Universal App.
Sketch: Basiert auf WiFi-Server-Beispiel aus Simon Monks Buch „Programming Arduino Next Steps“. Festes IP-Setup. Loop: Client-Verbindungen prüfen, Webseite ausliefern (Temperaturen + Zieltemperatur-Eingabe). Zieltemperatur per URL-Parameter setzen. Temperaturmessung via Thermistor-Beta-Gleichung (Steinhart-Hart approximiert). Gebläse EIN wenn Ist < Soll, AUS wenn Ist > Soll.
Temperaturberechnung: Aus Analogwert → Spannung am Thermistor → Strom über Festwiderstand (Ohmsches Gesetz) → Thermistor-Widerstand → Beta-Gleichung: 1/T = 1/T0 + (1/Beta)*ln(R/R0). Temperaturen in Kelvin, Ausgabe in °F.
Webseite: Einfaches HTML mit Tabelle der Temperaturen (Smoker + bis zu 6 Fühler), Formular für Zieltemperatur.
Windows Universal App
Lädt periodisch die Webseite vom Smoker, parst Temperaturen, zeigt sie an, erlaubt Zieltemperatur-Einstellung. Screenshots im Projekt. Code für Sketch und App auf GitHub.
Code
Smoker Controller Sketch
// sketch_12_04_server_wifi
#include
#include
char ssid[] = "BeeBar2";
char pass[] = "9254582716";
WiFiServer server(80);
WiFiClient client;
const int numPins = 10;
int pins[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int pinState[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
char line1[100];
char buffer[100];
IPAddress server_IP(192,168,123,90);
float targetTemperature = 225;
float smokerTemperature = 225;
float v0;
void setup() {
Serial.begin(9600);
while (!Serial) {};
for (int i = 0; i < numPins; i++) {
pinMode(pins[i], OUTPUT);
}
analogReadResolution(12);
if (WiFi.begin(ssid, pass)) {
WiFi.config(server_IP);
printWifiStatus();
} else {
Serial.println("Could not connect to network");
}
server.begin();
}
void loop() {
client = server.available();
if (client) {
if (client.connected()) {
Serial.print("Request Received: ");
Serial.println(line1);
readHeader();
if (!pageNameIs("/")) {
Serial.print("Invalid Page Requested: ");
Serial.println(line1);
client.stop();
return;
}
readTargetTempParam();
client.println("HTTP/1.1 200 OK\nContent-Type: text/html\n");
sendBody();
delay(1);
client.stop();
} else {
Serial.println("No Client connected ");
}
}
int reading = analogRead(0);
v0 = (float)reading / 1241.0;
smokerTemperature = ThermisterTemp(v0, 100000, 10000, 3950, 25);
digitalWrite(0, smokerTemperature < targetTemperature);
}
void sendBody() {
client.println("");
sendAnalogReadings();
client.println("\n");
}
void sendAnalogReadings() {
client.println("Temperatures
\n");
Serial.print("Pin(");Serial.print(0);Serial.print("): V=");Serial.print(v0);Serial.print(" Temperature="); Serial.println(smokerTemperature);
client.print("Smoker ");
client.print(" ");
client.print(smokerTemperature);
client.println(" F ");
for (int i = 1; i < 7; i++) {
int reading = analogRead(i);
if (reading > 0) {
float v = (float)reading / 1241.0;
float T = ThermisterTemp(v, 100000, 10000, 3950, 25);
Serial.print("Pin(");Serial.print(i);Serial.print("): ");Serial.print(reading);Serial.print("V=");Serial.print(v);Serial.print(" Temperature="); Serial.println(T);
client.print("Probe ");
client.print(i);
client.print(" ");
client.print(T);
client.println(" F ");
}
}
client.println("
");
}
void readHeader() {
readRequestLine(line1);
while (readRequestLine(buffer) > 1 && buffer[0] != '\n') {}
}
int readRequestLine(char *line) {
char ch;
int i = 0;
while (ch != '\n' && i < 100 && client.available()) {
if (client.available()) {
ch = client.read();
line[i] = ch;
i++;
}
}
line[i] = '\0';
return i;
}
boolean pageNameIs(char* name) {
int i = 4;
char ch = line1[i];
while (ch != ' ' && ch != '\n' && ch != '?') {
if (name[i - 4] != line1[i]) { return false; }
i++; ch = line1[i];
}
return true;
}
float readTargetTempParam() {
Serial.println(line1);
int len = strlen(line1);
for (int i = 0; i < len; i++) {
if (line1[i] == 't' && line1[i + 1] == '=') {
float val = 0;
for (int j = i + 2; j < len; j++) {
if (isDigit(line1[j])) {
val *= 10;
val += (int)line1[j] - '0';
} else { break; }
}
targetTemperature = val;
Serial.println(val);
return val;
}
}
return -1;
}
void printWifiStatus() {
Serial.print("SSID: "); Serial.println(WiFi.SSID());
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: "); Serial.println(ip);
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):"); Serial.print(rssi); Serial.println(" dBm");
}
float ThermisterTemp(float Vtherm, int R0therm, int Rfixed, int Beta, int T0) {
double I = (3.3 - Vtherm) / Rfixed;
double Rtherm = Vtherm / I;
T0 += 273.15;
double T = 1.0 / ( (1.0 / ((double)Beta)) * log((Rtherm) / ((double)R0therm)) + (1.0 / ((double)T0)) );
return (float) ((9 * (T - 273.15)) / 5) + 32;
}
GitHub Repository (Sketch & Universal App): SmokerController
Schaltplan
Fritzing-Datei (Smoker.fzz) – MKR1000 durch Arduino Nano ersetzt (Fritzing hatte kein MKR1000-Teil). Schaltplanbild im Projekt enthalten.
Herstellungsprozess
- Arduino Digitaler Würfel: LCD-Würfel mit Zufallszahlen (1–6)
- Arduino Temperatur- & Feuchtelogger mit DHT11 & Ethernet Shield
- Arduino Iron Man bauen: Komponenten, Sensoren & Schritt-für-Schritt-Anleitung
- Find Me: Smarter Gegenstands-Finder mit Arduino und Bluetooth
- Funktionaler 3D-gedruckter Roboterarm mit Arduino – Schritt-für-Schritt-Anleitung
- DIY Arduino Luftbefeuchter-Steuerung mit Relais – Sichere Hochspannungs-Installation
- Berührungsloses Temperatur-Überwachungstor für schnelles Screening
- NeoPixel-Matrix Pong auf Arduino Nano: Neon-Pong selbst bauen
- DIY Arduino Lenkrad / Joystick für Rennspiele – USB-HID-Umbau
- Leistungsstarker FM-Radio-Empfänger mit Arduino & TEA5767