Набор для точного температурного контроля угляного коптильни: Arduino MKR1000 + WiFi
Компоненты и материалы
- Arduino MKR1000 — 1 шт. (встроенный WiFi, зарядка LiPo)
- 5V Brushless Blower (турбонадув) — 1 шт. (подача воздуха к углям)
- Модуль драйвера MOSFET IRF520N — 1 шт. (управление надувом)
- NTC-термистор 100 кОм — 1 шт. (датчик температуры)
- Плата для прототипирования (breadboard) — 1 шт.
- Провода-перемычки — 1 набор
- LiPo батарея 3.7В ≥ 700 мА·ч — 1 шт. (питание, заряжается через MKR1000)
- Резистор 10 кОм — 1 шт. (делитель напряжения для термистора)
Приложения и сервисы
- Arduino IDE
- Microsoft Visual Studio 2015 — для разработки Universal Windows App (UWP)
О проекте
Предыстория
Настоящие любители BBQ знают: лучший вкус дает уголь. Газовые и электрические коптильни лучше контролируют температуру, но лишают вкуса угля. Уголь капризен: нужно постоянно регулировать заслонки, следить за температурой каждые 30 минут. Хочется просто сидеть на диване с напитком и смотреть спорт, пока коптильня сама поддерживает температуру.
Проект
Создать контроллер, который:
- Мониторит температуру в коптильне.
- Регулирует подачу воздуха к углям через надув для поддержания заданной температуры.
- Позволяет удаленно следить за температурой коптильни и мяса (несколько зондов) через WiFi на любом Windows 10 устройстве.
Основа — Arduino MKR1000 с WiFi и поддержкой зарядки LiPo.
Аппаратная часть
Измерение температуры
NTC-термистор 100 кОм в делителе напряжения на аналоговый вход MKR1000. Выбран термистор от Prusa (3D-принтеры) — дешевый, доступный, часто уже на высокотемпературных силиконовых проводах. Термистор помещается в тонкую нержавеющую трубку (≤6 мм), один конец закатан, провода закреплены термоусадкой. Делитель: 10 кОм от VCC (3.3В MKR) к термистору, другой конец термистора на GND, середина — на аналоговый пин A0. Это дает хороший диапазон 10–150°C с приемлемым разрешением.
Дополнительные аналоговые пины (A1–A6) можно использовать для зондов в мясе.
Управление надувом
Маленький бесколлекторный надув (blower) крепится к вентиляционному отверстию коптильни. Автор использовал нержавеющую миску для собачьей еды над вентилем, надув в отверстии дна миски. Это:
- Полностью перекрывает вентиль при выключенном надуве.
- Обеспечивает теплоизоляцию между горячей коптильней и надувом.
Надув управляется N-канальным MOSFET (модуль IRF520N для удобства). Gate → цифровой пин Arduino (пин 0 в коде). Питание надува — от LiPo через MOSFET-модуль.
Сборка (на breadboard)
Все собрано на макетной плате для простоты. Добавлены:
- Подстроечный резистор 10 кОм для тестирования кода (переключение джампером между термистором и делителем).
- Светодиод + 330 Ом на пине 0 — индикация включения надува.
Программное обеспечение
Две части: скетч Arduino (Web-сервер) и Universal Windows App (UWP) для мониторинга.
Скетч Arduino
Основан на примере WiFi-сервера из книги Саймона مونка «Programming Arduino Next Steps».
- Инициализация: настройка WiFi, задание статического IP (192.168.123.90), пин 0 = OUTPUT.
- Loop: проверка клиентов, обслуживание HTTP-запросов. Если в URL есть параметр
t=XXX— обновление целевой температуры. - Измерение температуры термистором: чтение ADC (12 бит на MKR1000), расчет напряжения, тока через фиксированный резистор, сопротивления термистора, затем уравнение Бета:
1/T = 1/T0 + 1/Beta * ln(R/R0)(температуры в Кельвинах), перевод в Фаренгейты. - Управление: если текущая температура < целевой → вентилятор ВКЛ (пин 0 HIGH), иначе ВЫКЛ.
- Веб-страница: простая HTML-таблица с температурами зондов + форма ввода целевой температуры (кнопка Update).
// sketch_12_04_server_wifi
#include <SPI.h>
#include <WiFi101.h>
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; // °F
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); // MKR1000 имеет 12-битный ADC
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("/")) { client.stop(); return; }
readTargetTempParam();
client.println("HTTP/1.1 200 OK\nContent-Type: text/html\n");
sendBody();
delay(1);
client.stop();
}
}
// Измерение и управление вентилятором
int reading = analogRead(0);
v0 = (float)reading / 1241.0; // 3.3В / 4095 * reading? Уточнить константу
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(0): V="); Serial.print(v0); Serial.print(" Temperature="); Serial.println(smokerTemperature);
client.print("Smoker "); 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);
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() {
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;
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) {
// T0 в °C, Beta в K, R0therm в Омах при 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.0 * (T - 273.15)) / 5.0) + 32.0; // В Фаренгейты
}
Universal Windows App (UWP)
Периодически запрашивает веб-страницу коптильни, парсит температуры, отображает их, позволяет менять целевую температуру. Скриншоты интерфейса в оригинале. Код обоих проектов на GitHub: SmokerController.
Схемы
Fritzing-схема (MKR1000 заменен на Nano, так как в Fritzing не было MKR1000). Файлы: Smoker.fzz, фото сборки на breadboard.
Производственный процесс
- Цифровые кости на Arduino: генератор случайных чисел с LCD-дисплеем и кнопкой
- Логгер температуры и влажности на Arduino с DHT11 и Ethernet Shield
- Строим Iron Man на Arduino: компоненты, сенсоры и пошаговый гайд
- Find Me: Умный поисковик вещей на Arduino и Bluetooth
- Сборка функционального 3D-печатного манипулятора на Arduino: пошаговое руководство
- DIY-контроллер увлажнителя на Arduino с реле: безопасная работа с высоким напряжением
- Бесконтактный термометрический шлюз для быстрого и точного скрининга
- NeoPixel Matrix Pong на Arduino Nano: неоновая игра Pong на матрице 15×10
- Своё рулевое управление (джойстик) для игр на Arduino
- FM-радиоприемник на Arduino и модуле TEA5767