Из рубрики «Не жизнь, а сказка». Теперь я парюсь с Алисой, а моя жена совсем не против
Краткая история о том как менеджер самого среднего звена умную сауну делал.
Понимаете, каждый год 31 декабря мы с друзьями ходим в баню. Это у нас такая традиция.
Год 2020 выдался необычный, поэтому может уже пора самоизолироваться в своей парилке и с друзьями всем дружно в зуме поддать парку? Правило в конференц-парилке: “В случае запотевания протрите сначала камеру, потом экран, потом стакан“.
Если Вам интересно как сделать своими руками сауну с голосовым управлением прошу под кат.
— Алиса, выключи вентиляцию, включи свет парилку на 95 градусов. А мы начинаем!
Вентиляция
Баня без пара, что щи без навара.
Для быстрого удаления пара после использования сауны была сделана принудительная вентиляция. Вентиляционный канал теплоизолирован и выведен в отдельный канал в стене.
В стене вентилятор-улитка. Канальный не подходит из-за температуры и влажности. Доступ для обслуживания вентилятора сделан из другого помещения.
Чтобы жар не уходил в вентиляционный канал во время таинства сделан электрический клапан, который открывает заслонку. Клапан включается одновременно с мотором от 220В. Когда питание выключается возвратная пружина возвращает клапан в закрытое положение.
При закреплении привода клапан должен быть закрыт. Приток воздуха из щели под дверью.
Пол
В бане мыться, заново родиться.
В полу сделан сухой клапан как аналог гидрозатвора. Половина пола сауны сделана с уклоном в сторону слива. На пол уложен керамогранит.
Печь
Банька – не нянька, а хоть кого ублажит.
Помещение для сауны находится в цокольном этаже дома. Поэтому между дровяной и электрической печью явно выигрывал электрический вариант. Печь я купил заранее. Бренд финский, печь для сауны цилиндрическая. Печь 7кВт обошлась в 15.500 руб.
Первоначально я хотел расположить печь в полке́. Затем, понял проект из соображений безопасности. Когда печь отдельно до нее сложнее случайно прикоснуться.
Стены
Поддай парок да лезь на полок.
Сделано отверстие в стене из щитка в предбаннике для введения силовых проводов, проводов для освещения и термопары.
Провода все выбираю в термостойкой оплетке. К стене прибивает бруски из сосны 50х50мм. Усиливаем места, делаем закладные под места крепления полков.
Между брусков закладываем утеплитель для саун. Я выбрал вариант фольгированного утеплителя для сауны фольгой к стене и дополнительно фольгу 100мкм со стороны сауны.
Провода устанавливаем в металлической гофре.
Сверху укладываем фольгу и заклеиваем места стыков фольгированным скотчем. Далее делаем контробрешетку.
Монтируем вагонку из липы.
Собираем полки́, а не по́лки. Никогда не понимал, почему именно так. Все собираем на уголки с креплением на саморезы снизу, чтобы сверху не было шляпок, лежать будет очень не удобно.
Потолок
Пар костей не ломит.
Особое внимание нужно уделить теплоизоляции потолка, можно использовать 100-200мм теплоизоляции. В целом высоту сауны не стоит делать больше 220см. из-за большого теплового градиента по высоте.
Освещение
Баня парит, баня правит.
Для освещения я выбрал комбинированный вариант. Лампа над дверью и под полками. Светодиодная лента за гималайской солью под потолком. Ленту обязательно брать термостойкую.
Отдельный разговор про гималайскую соль. Лечит тело и душу. Стоять будет до 100 лет, депрессию снимает как рукой. Больше никакого сглаза. Говорят, даже шестое кольцо Таноса сделано из гималайской соли.
Вот я и решил рядами ее выложить. Лучшее лечение — это профилактика.
Термостат
Который день паришься, тот день не старишься.
Печь, которую я выбрал можно купить в 3 вариантах:
— Без управления. Т.е. просто контакты на три фазы, ноль и землю за 15.500 руб.
— С термостатом на печи за 21.000 руб.
— С электрической выносной панелью(Стоимость панели в 25.000 руб.) дороже самой печи, Карл!
Быстрый поиск вариантов на Али показал, что есть панели, которые с доставкой обойдутся в 11.000 руб. Я у мамы инженер, поэтому с такой мировой несправедливостью решил бороться решительно. Я у мамы инженегр! Контроллер решил сделать из проверенного трехфазного контактора за 3.500 руб. и недорогого настраиваемого электронного термостата за 200 руб. Термостат можно поставить даже механический с газовой трубкой и на этом регулятор будет готов.
Все это собралось и работало, но в этом не было души.
Как я Алису в сауну поселил
Здесь и начинается мой рассказ, по сути. Мне захотелось сделать голосовое управление для включение сауны под настроение, знаете когда такое тонкое чувство… наитие, что ли.
Для этого я использовал простейший скрипт web-сервера на lolin nodemcu. По сути, это несколько GET-запросов, обращаясь к которым можно включать и выключать реле, которые связаны с пинами nodemcu. Это не совсем кошерно, можно запустить москито на RPi и сделать локального брокера, можно статичный IP и перебросить порты. Согласен, но нет!
#include <ESP8266WiFi.h>
const char* ssid = "";//type your ssid
const char* password = "";//type your password
int ledPin = 2;
WiFiServer server(80);//Service Port
void setup() {
Serial.begin(115200);
delay(10);
pinMode(16, OUTPUT);
pinMode(5, OUTPUT);
pinMode(4, OUTPUT);
pinMode(0, OUTPUT);
pinMode(2, OUTPUT);
digitalWrite(16, LOW);
digitalWrite(5, LOW);
digitalWrite(4, LOW);
digitalWrite(0, LOW);
digitalWrite(2, LOW);
// Connect to WiFi network
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
// Start the server
server.begin();
Serial.println("Server started");
// Print the IP address
Serial.print("Use this URL to connect: ");
Serial.print("http://");
Serial.print(WiFi.localIP());
Serial.println("/");
}
void loop() {
// Check if a client has connected
WiFiClient client = server.available();
if (!client) {
return;
}
// Wait until the client sends some data
Serial.println("new client");
while(!client.available()){
delay(1);
}
// Read the first line of the request
String request = client.readStringUntil('r');
Serial.println(request);
client.flush();
// Match the request
int value = LOW;
if (request.indexOf("/LED1=ON") != -1) {
digitalWrite(16, HIGH);
value = HIGH;
}
if (request.indexOf("/LED1=OFF") != -1){
digitalWrite(16, LOW);
value = LOW;
}
if (request.indexOf("/LED2=ON") != -1) {
digitalWrite(5, HIGH);
value = HIGH;
}
if (request.indexOf("/LED2=OFF") != -1){
digitalWrite(5, LOW);
value = LOW;
}
if (request.indexOf("/LED3=ON") != -1) {
digitalWrite(4, HIGH);
value = HIGH;
}
if (request.indexOf("/LED13=OFF") != -1){
digitalWrite(4, LOW);
value = LOW;
}
if (request.indexOf("/LED4=ON") != -1) {
digitalWrite(0, HIGH);
value = HIGH;
}
if (request.indexOf("/LED4=OFF") != -1){
digitalWrite(0, LOW);
value = LOW;
}
if (request.indexOf("/LED5=ON") != -1) {
digitalWrite(2, HIGH);
value = HIGH;
}
if (request.indexOf("/LED5=OFF") != -1){
digitalWrite(2, LOW);
value = LOW;
}
//Set ledPin according to the request
//digitalWrite(ledPin, value);
// Return the response
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println(""); // do not forget this one
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.print("Led pin is now: ");
if(value == HIGH) {
client.print("On");
} else {
client.print("Off");
}
client.println("<br><br>");
client.println("Click <a href="/LED1=ON">here</a> turn the LED1 ON<br>");
client.println("Click <a href="/LED1=OFF">here</a> turn the LED1 OFF<br><br>");
client.println("Click <a href="/LED2=ON">here</a> turn the LED2 ON<br>");
client.println("Click <a href="/LED2=OFF">here</a> turn the LED2 OFF<br><br>");
client.println("Click <a href="/LED3=ON">here</a> turn the LED3 ON<br>");
client.println("Click <a href="/LED3=OFF">here</a> turn the LED3 OFF<br><br>");
client.println("Click <a href="/LED4=ON">here</a> turn the LED4 ON<br>");
client.println("Click <a href="/LED4=OFF">here</a> turn the LED4 OFF<br><br>");
client.println("Click <a href="/LED5=ON">here</a> turn the LED5 ON<br>");
client.println("Click <a href="/LED5=OFF">here</a> turn the LED5 OFF<br>");
client.println("</html>");
delay(1);
Serial.println("Client disconnected");
Serial.println("");
}
Вариант рабочий. Алису можно научить работать с таким простейшим управлением, но у Вас не будет возможности включить сауну по дороге с работы.
Яндекс.Алису в баню!
Для возможности удаленного управления можно воспользоваться online серверами mqtt и совершать запросы к данным серверам. Сервер MQTT, который был хороший потому что бесплатный стал плохим, потому что полностью платный. И в целом, хотелось попробовать другой вариант, что-то новое.
Аппаратная часть
Для управления нагрузками используется блок на 8реле. Для проверки температуры используется термопара на max6675. Тип K диапазон температур 0-1024 градусов. Рабочее напряжение: 3. 0 ~ 5. 5 В. Разрешение температуры: 0. 25 градусов; Диапазон компенсации холодного соединения: — 20 ~ + 80 градусов. Использование SPI.
Модуль nodemcu соединяется по wifi с роутером, в случаем обрыва связи происходит повторное соединение, все это уже готово в библиотеке BlynkSimpleEsp8266.
Конечно, это не образец сборки щитка, но все соединено крепко, сечение с запасом. ESP и блок реле запитывается от блока питания на 5В на DIN-рейке, блок включается отдельным автоматом. Так же в щитке блок питания на 24В для светодиодной ленты. Все нагрузки включаются как с помощью реле, так и байпасом каждое через свой автомат. При желании автоматику можно отключить и включать все олдскульно.
Скрипт
Подключаем lolin к usb. Подробнее о загрузке скетча.
#define BLYNK_PRINT Serial
#include "max6675.h"
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
char auth[] = ""; // blynk token
char ssid[] = ""; //ssid
char pass[] = ""; //pass
int heaterpin=16;
uint32_t heatertimer=0;
uint32_t heatermax=1440000000;//Таймер на 4 часа максимальную работу печи сауны
int needtemp=0,curtemp=0,heateron=0,hysteresis=3,workhysteresis=1;
BlynkTimer timer;
int thermoDO = 13;
int thermoCS = 15;
int thermoCLK = 14;
MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);
BLYNK_WRITE(V1)
{
needtemp = param.asInt();
Serial.print("needtemp=");
Serial.println(needtemp);
}
BLYNK_WRITE(V3)
{
heateron = param.asInt();
Serial.print("heateron=");
Serial.println(heateron);
if(heateron==0){
heatertimer = micros();
}
}
void myTimerEvent()
{
Blynk.virtualWrite(2,curtemp);
Serial.print("curtemp=");
Serial.print(curtemp);
Serial.print("t needtemp=");
Serial.print(needtemp);
Serial.print("t workhysteresis=");
Serial.println(workhysteresis);
curtemp=round(thermocouple.readCelsius());
if(micros()-heatermax>heatertimer and heateron==1 and curtemp<needtemp+hysteresis and workhysteresis==1){
digitalWrite(heaterpin, LOW);
Serial.println("PECH ON!!!!");
}else if(heateron==1 and curtemp>needtemp+hysteresis){
workhysteresis=0;
digitalWrite(heaterpin, HIGH);
}
if(heateron==0){
digitalWrite(heaterpin, HIGH);
workhysteresis=1;
}
if(curtemp<needtemp-hysteresis){
workhysteresis=1;
}
}
void setup()
{
Serial.begin(115200);
Blynk.begin(auth, ssid, pass);
digitalWrite(heaterpin, HIGH);
digitalWrite(5, HIGH);
digitalWrite(4, HIGH);
pinMode(heaterpin, OUTPUT);
pinMode(5, OUTPUT);
pinMode(4, OUTPUT);
timer.setInterval(500L, myTimerEvent);
}
void loop()
{
Blynk.run();
timer.run();
}
Скачиваем приложение Blynk. Добавляете устройство и получаете токен на email.
В приложении добавляем необходимые кнопки и привязываем их к состоянию цифровых или виртуальных пинов.
Добавляем слайдер для удобного изменения температуры. При каждом изменении будет вызываться функция на nodemcu.
BLYNK_WRITE(V1)
{
needtemp = param.asInt();
Serial.print("needtemp=");
Serial.println(needtemp);
}
Добавляем вывод данных о текущей температуре, выводим информацию из виртуального пина, который будем обновлять из скрипта.
Blynk.virtualWrite(2,curtemp);
Чтобы не спамить запросами сервер Blynk, они же просят не делать более 10Гц я запустил таймер, который измеряет и отправляет данные два раза в секунду. Можно и намного реже, так система очень инертная.
Отлично, теперь у нас есть удаленное управление. Мы можем включить парилку, свет, вентиляцию, задать целевую и узнать текущую температуру, но в этом все еще нет души.
Чтобы управлять Blynk из вне есть API
Чтобы что-то написать в пин(цифровой, налоговый или виртуальный)
http://blynk-cloud.com/auth_token/update/pin?value=value
Чтобы прочитать состояние или получить значение
http://blynk-cloud.com/auth_token/get/pin
Подставляем вместо auth_token Ваш токен и теперь отправляя этот GET запрос Вы можете управлять устройством вне приложения.
Самое время научить этому Алису. Делается это через навыки. Навык можно написать свой, это не так сложно. Для наших целей подойдет готовый навык Домовенок Кузя.
1. Авторизуемся на сайте https://alexstar.ru/ под тем же аккаунтом что и привязана Алиса к нашей станции или смартфону.
2. Нажимаем Добавить правило GET
3. Для каждого правила вписываем запросы к API Blynk
4. Переходим во вкладку Виртуальные устройства и создаем устройства типа Лампа, т.е. (вкл/выкл) для вентиляции и света. Устройство типа кондиционер для печи парилки.
5. Указываем соответствующие правила для устройств
Теперь на смартфоне устанавливаем Яндекс.браузер с Алисой.
1. Авторизуйтесь.
2. Перейдите во вкладку устройства — Добавить.
3. Выберите навык Домовенок Кузя и добавьте его.
4. Нажмите обновить устройства.
Готово, теперь в проекте есть душа! Так Алиса стала хозяйничать в моей сауне, теперь сможет управлять и твоей.
Результат
В конце я говорю:
-Алиса, выключи все в сауне.
-Алиса, включи вентиляцию на 30минут.
Очень удобно, не жизнь, а смазка!
Конкурс
Год выдался непростым, оптимисты знают, что следующий будет лучше, пессимисты боятся, как-бы не был хуже. Все проходит, и это пройдет…
Призом будет размещение Вашего творчества в данной статье до ката, признание друзей и сообщества, получение звания удалого молодца, замечательного настроения, увеличение количества антител, увеличение производительности и защиту от прокрастинации на весь год. Если Вы материалист — то получите еще и просто замечательную банную шляпу. Сам заказывал покрой в Баварском стиле и надпись. Отдельно можете попытаться угадать какая надпись. Шляпы, пока едут с производства, но вот вот и…
Напишите четверостишие, частушку, хокку, хайку, памфлет, белый стих, пословицу, житейскую мудрость или анекдот от соседа. В нем обязательно должно быть событие из этого непростого года или намек на 2021 и слово Хабр. Победителя выберет Boomburum, максимально субъективно, никаких псевдо-случайных чисел. Что-бы был эффект низкой базы я покажу пример:
Крыса уходит
Пар от камней
На Хабре статья!
…
Год уходит
И приходит новый затем
Читаю Хабр!
…
Банька от короны всех избавляет, даже хабрый царь в парной корону снимает долой!
Всем пара, мира, добра и Хабра! С Наступающим Новым Годом и Рождеством!
P.S.
Ребята из Яндекс могут найти все. BarakAdama, если Вы найдете Деда Мороза передайте ему, что я хочу получить на Новый Год Яндекс.Станцию Макс. Обещаю вести себя хорошо и придумать много интересного с новым домом для Алисы. Какой же там звук….4К видео… многофункциональный дисплей… мечта, а не девайс!
Если Вы хотите увидеть продолжение циклов «Я у мамы инженегр!», «Не жизнь, а смазка» — погладьте своего кота.
Все публикации в потоке Дизайн