Прошла неделя стабильной работы. Время выхода на нормальный режим больше 30 минут, целенаправленно не засекал, редко выключается между компьютером и блоком питания. Работает практически 24/7.
Датчик CCS811 оказался интереснее чем просто CO2, и по началу это меня вводило заблуждение. Один день наблюдал показания ppm > 5000, ожидая что датчик умрет, но это был нарезанный неподалеку лук.
Долгое проветривание помещения может уменьшить показания ppm до 400 и TVOC до 0 (это минимум для датчик), но 3 человека для 1 комнатной квартиры это много и уже 2500 ppm через час.
Не всем знают какая норма для проветриваемого помещения. Поэтому был добавлен мигающий светодиод (LED), который напрямую подключен к выводу D0 ESP8266 а другим выводом к GND. В код добавлена простая логика включения при показаниях ppm >= 2200 или TVOC >= 250. Отключение LED произойдет если уровень упадет <= 1000 и <= 150 соответственно.
В шапке темы схема включения и прошивка именно под этот случай и она основная v1.0 как самая простая и достаточная для большинства пользователей.
Время показало что включать LED лучше при ppm >= 1200 и TVOC >= 220 и отключать при ppm <= 500 и TVOC <= 11, это увеличит качество проветривания помещения.
Telegram уведомления и управление.
Бесплатно расширяем функционал и будем слать сообщения в телеграм через бота
Telegram bot.
Оф. API для разработчиков:
Telegram Bot API.
ВНИМАНИЕ!!!
Официально telegram заблокирован на территории РФ, но всегда есть способы обхода. Я рекомендую проверить, будет ли это работать у вас. Для этого в браузере компьютера или телефона подключенный к этому же Wi-Fi что и предполагаемый модуль и перейти по ссылке:
https://api.telegram.org/bot123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11/getMe
Если в открытой странице:
Код: Выделить всё
{"ok":false,"error_code":401,"description":"Unauthorized"}
Отлично! Вы можете смело работать с Telegram. А если не грузится или доступ закрыт, значит ваш провайдер заблокировал.
Обход блокировки
Для обхода использую роутре ASUS, другого у меня нет, поднимаю на нем VPN клиент, есть бесплатный OpneVPN
здесь файл конфигурации:
https://www.vpngate.net/en/
Я использую Японию, скорость нам не важна, как и время отклика. Создаю правило для IP модуля ESP8266, что бы не замедлять другие устройства в сети и подключать их напрямую без VPN.
Для тестирования телеграмм бота использую готовый код:
Код: Выделить всё
#include "Adafruit_CCS811.h"
#include "TM1637.h"
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>
#define CLK 13 // D7 ESP8266
#define DIO 12 // D6 ESP8266
#define ledPin 16 // D0 ESP8266
int ledStatus = 0;
int i = 0;
bool alarm = true;
bool sms = true; // false or true
bool co2triger = true;
bool tvoctriger = true;
int pause = 5;
int pausestatus = 0;
TM1637 disp(CLK, DIO);
Adafruit_CCS811 ccs;
const char* ssid = "xxxxxxx";
const char* password = "xxxxxxx";
// инициализация бота Telegram
const char BotToken[] = "xxxxxxxxxx:xxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);
int Bot_mtbs = 1000; //mean time between scan messages
long Bot_lasttime; //last time messages' scan has been done
bool Start = false;
// управление Telegram
void handleNewMessages(int numNewMessages) {
Serial.println("handleNewMessages");
Serial.println(String(numNewMessages));
for (int i=0; i<numNewMessages; i++) {
String chat_id = String(bot.messages[i].chat_id);
String text = bot.messages[i].text;
String from_name = bot.messages[i].from_name;
if (from_name == "") from_name = "Guest";
if (text == "/pause") { // задаем количество циклов пропуска для чтения сообщения Telegram
if (pause == 5){
pause = 10;
bot.sendMessage(chat_id, "Twix 10sec.", "");
}
else if (pause == 10){
pause = 15;
bot.sendMessage(chat_id, "Twix 15sec.", "");
}
else {
pause = 5;
bot.sendMessage(chat_id, "Twix 5sec.", "");
}
}
if (text == "/sms") {
sms = !sms;
if(sms){
bot.sendMessage(chat_id, "SMS ON", "");
} else {
bot.sendMessage(chat_id, "SMS OFF", "");
}
}
if (text == "/alarm") {
alarm = !alarm;
if(alarm){
bot.sendMessage(chat_id, "Alarm ON", "");
} else {
bot.sendMessage(chat_id, "Alarm OFF", "");
}
}
if (text == "/start" || text == "/info") {
String welcome = "\xd0\xaf \xd0\xb1\xd0\xbe\xd1\x82 \xd0\xba\xd0\xb0\xd1\x87\xd0\xb5\xd1\x81\xd1\x82\xd0\xb2\xd0\xb0 \xd0\xb2\xd0\xbe\xd0\xb7\xd0\xb4\xd1\x83\xd1\x85\xd0\xb0. \xd0\x9e\xd1\x82\xd0\xb2\xd0\xb5\xd1\x87\xd0\xb0\xd1\x8e \xd0\xbd\xd0\xb0 \xd0\xba\xd0\xbe\xd0\xbc\xd0\xb0\xd0\xbd\xd0\xb4\xd1\x8b\x3a\x0d\x0a\n";
welcome += "/alarm : to switch the Led ON\n";
welcome += "/sms : to switch the Led OFF\n";
welcome += "/pause : Returns current status of LED\n\n";
if(alarm){
welcome += "Alarm ON & ";
} else {
welcome += "Alarm OFF & ";
}
if(sms){
welcome += "SMS ON & ";
//bot.sendMessage(chat_id, "SMS ON", "");
} else {
welcome += "SMS OFF & ";
}
if(pause == 5){
welcome += "5sec\n\n";
} else if (pause == 10){
welcome += "10sec\n\n";
}
else {
welcome += "15sec\n\n";
}
welcome += "eCO2=";
welcome += ccs.geteCO2();
welcome += "ppm & TVOC=";
welcome += ccs.getTVOC();
welcome += "ppb\n\n";
welcome += "\xd0\x9c\xd0\xbe\xd0\xb9 \xd1\x81\xd0\xbe\xd0\xb7\xd0\xb4\xd0\xb0\xd1\x82\xd0\xb5\xd0\xbb\xd1\x8c\x3a llirikks\x40mail.ru.\x0d\x0a\n\n"; // Мой создатель: llirikks@mail.ru.
bot.sendMessage(chat_id, welcome, "Markdown");
}
}
}
void setup() {
pinMode(ledPin, OUTPUT); // выход под LED
disp.init(); // инициализация
disp.set(1); // яркость, 0 - 7 (минимум - максимум)
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(100);
WiFi.begin(ssid, password);
// если датчик не исправен выводим "----"
if(!ccs.begin()){
disp.displayByte(_dash, _dash, _dash, _dash);
delay(500);
disp.clearDisplay(); // очистка дисплея
delay(500);
while(1);
}
//calibrate temperature sensor
while(!ccs.available());
float temp = ccs.calculateTemperature();
ccs.setTempOffset(temp - 25.0);
// подключение Wi-Fi
while (WiFi.status() != WL_CONNECTED) { //|| i != 10
disp.displayByte(_dash, _empty, _empty, _empty);
delay(200);
disp.displayByte(_dash, _dash, _empty, _empty);
delay(200);
disp.displayByte(_dash, _dash, _dash, _empty);
delay(200);
disp.displayByte(_dash, _dash, _dash, _dash);
delay(200);
disp.clearDisplay();
delay(300);
//i++;
}
// если подключение есть, на дисплее 1111
if(WiFi.status() == WL_CONNECTED) {
disp.displayInt(1111);
delay(300);
}
if(WiFi.status() == WL_CONNECTED) { bot.sendMessage(String(272561288), "\xd0\x97\xd0\xb0\xd0\xbf\xd1\x83\xd1\x89\xd0\xb5\xd0\xbd \xd0\xb1\xd0\xbe\xd1\x82 CSS811." , ""); } // Запущен бот CSS811.
}
void loop() {
/* Считываем данные с датчика и выводим на экран по очереди на 2 сек */
if(ccs.available()){
float temp = ccs.calculateTemperature();
if(!ccs.readData()){
disp.clearDisplay();
disp.displayInt(ccs.geteCO2());
delay(2000);
disp.clearDisplay();
disp.displayInt(ccs.getTVOC());
delay(2000);
// управление LED и сообщениями
if(alarm) { // если alarm ON разрешаем LED и SMS
if(ccs.geteCO2() >= 1200 || ccs.getTVOC() >= 220) { // если порог превышен
if(co2triger == true) { // выполняем первое SMS и вкл. LED
digitalWrite(ledPin, HIGH);
if(WiFi.status() == WL_CONNECTED && sms ) { bot.sendMessage(String(272561288), "\xE2\x9A\xA0 \xd0\x9f\xd1\x80\xd0\xbe\xd0\xb2\xd0\xb5\xd1\x82\xd1\x80\xd0\xb8\xd1\x82\xd1\x8c! " + String(ccs.geteCO2()) + "ppm & " + String(ccs.getTVOC()) + "ppb", ""); }
co2triger = false; // запрещаем повторять SMS о превышении
tvoctriger = true; // разрешаем SMS о снижении
}
}
else if(ccs.geteCO2() <= 500 || ccs.getTVOC() <= 11 && tvoctriger == true) { // если показания в норме
if(tvoctriger == true) { // выполняем первое SMS и выкл. LED
digitalWrite(ledPin, LOW);
if(WiFi.status() == WL_CONNECTED && sms ) { bot.sendMessage(String(272561288), "\xF0\x9F\x8D\x80 \xd0\xa5\xd0\xbe\xd1\x80\xd0\xbe\xd1\x88\xd0\xbe " + String(ccs.geteCO2()) + "ppm & " + String(ccs.getTVOC()) + "ppb", ""); }
tvoctriger = false; // запрещаем повторять SMS о превышении
co2triger = true; // разрешаем SMS о снижении
}
}
}
else { // если alarm OFF отключаем LED
digitalWrite(ledPin, LOW); //выкл LED
}
pausestatus++;
if(pause == pausestatus && WiFi.status() == WL_CONNECTED) { // если есть подключение и кол-во циклов = паузе
pausestatus = 0;
// чтение новых сообщений Telegramm;
if (millis() > Bot_lasttime + Bot_mtbs) {
int numNewMessages = bot.getUpdates(bot.last_message_received + 1);
while(numNewMessages) {
Serial.println("got response");
handleNewMessages(numNewMessages);
numNewMessages = bot.getUpdates(bot.last_message_received + 1);
}
Bot_lasttime = millis();
}
}
}
}
else{
disp.displayByte(_E, _r, _r, _empty);
while(1);
}
}
Для работы нужна библиотека
ArduinoJson и
Universal Arduino Telegram Bot.
Для русских символах в сообщениях Telegram использую
Кодер/Декодер Url. Для примера пишем
Привет и получаем
%cf%f0%e8%e2%e5%f2, с помощью блокнота меняем % на \x, так же знак + меняем на пробел. В итоге получается:
/xcf/xf0/xe8/xe2/xe5/xf2.