Компактный монитор домашнего воздуха (CO2, температура, влажность, давление) с Wi-Fi и мобильным интерфейсом

    image


    Про измерение CO2 и его важность на Geektimes было уже немало публикаций (ссылки в конце статьи). Здесь же хочу описать проект компактного монитора уровня CO2, а также температуры, влажности и давления с Wi-Fi, обновлением прошивки по воздуху и интерфейсом в мобильном приложении. Сердца системы модуль на базе esp8266, сенсор CO2 MH-Z19 и фреймворк esp8266-arduino. И так, включим устройство в USB-розетку:


    image


    Cперва оно попытается подключиться к сохраненной ранее сети и успешно выполнив подключение, начинает работу. Если же wifi сеть не обнаружится, то монитор загрузится в режиме ожидания настройки и поднимет точку доступа. Подключившись к ней и открыв в браузере http://192.168.4.1 можно указать данные реальной сети, а также ключ для подключения к серверу и имя устройства.


    image


    На сервере и для мобильного клиента использован открытый проект Blynk. Он уже упоминался пару раз на Geektimes. Это opensource сервер, который имеет библиотеки для разных встраиваемых систем и позволяет в несколько строчек подключить общение со сторонним сервисом. Можно установить его на свой сервер, например запустив docker-контейнер, a можно использовать и публичный сервер разработчика.


    Интерфейс для blynk строится из готовых кирпичиков в мобильном приложении доступном для iOS и Android. Web-интерфейса, к сожалению нет. Через него можно посмотреть историю измерения всех параметров, настроить нотификации или web hook на по условию (здесь — превышению уровня CO2), обновить прошивку и сброситься к настройкам по умолчанию.


    Blynk позволяет распространять приложения через внушительных размеров QR-код, в котором сохранена конфигурация всех модулей.


    QR-код приложения, просканируйте приложением Blynk

    image


    image


    Как собрать подобное устройство?


    Для начала нужно купить все необходимые модули, например, на aliexpress. Поскольку конкретные предложения и продавцы постоянно меняются, поэтому в таблице указаны лишь поисковые запросы, по которым найдется то, что нужно.


    Компонент Поисковая фраза Ориентировочная цена
    Esp-12 NodeMCU модуль* esp8266 nodemcu cp2102 $3.50
    Датчик CO2 mh-z19 mh-z19 $22
    Датчик давления**,*** bmp280 $1
    Датчик температуры и влажности**,*** gy-21 SI7021 i2c $2.2
    Экран 0.96" 128x64 i2c OLED blue $2.7
    Провода dupont female-female 10cm $1
    3д-печать корпуса - $8
    Итого: $40.4

    * — На китайском рынке существуют две версии модуля NodeMCU. Они отличаются в первую очередь USB-UART преобразователем cp2102 и ch340g, но и размером — версия с ch340g шире на 3 мм и уже не влезет в этот корпус. Также, версия с cp2102 может быть интереснее, потому что у этого преобразователя нет проблем с драйверами под любую операционку.
    ** — В текущей версии использовался bmp-085, который сейчас уже не купить. Но модули с bmp-280 имеют те же размеры и все, что нужно сделать, это заменить используемую библиотеку на https://github.com/adafruit/Adafruit_BMP280_Library — все методы у них одинаковые.
    *** — Вместо пары датчиков bmp280+si7021, можно использовать один bme280, который измеряет все три показателя: температуру, влажность и давление. На aliexpress его можно найти за $3.5


    Корпус


    Хотелось сделать с одной стороны устройство из готовых модулей, с другой не хотелось делать его размером с буханку хлеба. Для этого в Tinkercad был нарисован корпус пригодный для 3д-печати. Большая проблема tinkercad в том, что очень тяжело вносить изменения в уже готовые проекты. Если бы я начинал сейчас, то воспользовался бы openSCAD


    image


    Корпус получился действительно компактным, но провода внутри все равно занимают большую часть места и их пришлось сделать довольно короткими, чтобы коробочка закрылась.


    image


    Недостаток такой плотной компановки в том, что тепло от микроконтроллера и dc-dc преобразователя нагревают воздух внутри на ~3 градуса выше реальной температуры, это же вредит точности показаний влажности. С другой стороны это создает конвекцию, которая обновляет воздух в сенсоре CO2 быстрее.


    Отчасти эту проблему можно решить, поработав над потреблением микроконтроллера, например реже передавать данные по сети.


    Подключение


    Электрическая схема очень проста — датчик давления, датчик температуры и влажности и дисплей питаются от 3.3в и подключаются через двухпроводной интерфейс I2C. Он позволяет подключать все устройства параллельно: SDA каждого устройства к ножке D1 (GPIO5), а SCL — к ножке D2 (GPIO4)


    Датчик CO2 питается от 5в (в нашем случае Vin — питание от USB входа) и подключается через UART. Для этого используются ноги D7 (GPIO13) — RX (который подключается к TX сенсора) и D8 (GPIO15) — TX (который подключается к RX сенсора)


    image


    Программная часть


    Все файлы проекта были разработаны в среде разработки PlatformIO и лежат на Github-e.


    Код прошивки, чтобы не ходить на Github
    #include <FS.h>
    #include <Arduino.h>
    #include <ESP8266WiFi.h>          //https://github.com/esp8266/Arduino
    
    // Wifi Manager
    #include <DNSServer.h>
    #include <ESP8266WebServer.h>
    #include <WiFiManager.h>         //https://github.com/tzapu/WiFiManager
    
    // HTTP requests
    #include <ESP8266HTTPClient.h>
    
    // OTA updates
    #include <ESP8266httpUpdate.h>
    // Blynk
    #include <BlynkSimpleEsp8266.h>
    
    // JSON
    #include <ArduinoJson.h>          //https://github.com/bblanchon/ArduinoJson
    
    // GPIO Defines
    #define I2C_SDA 5 // D1 Orange
    #define I2C_SCL 4 // D2 Yellow
    
    // Humidity/Temperature SI7021
    #include <SI7021.h>
    SI7021 si7021;
    
    #include <Wire.h>
    
    // Pressure and Temperature
    #include <Adafruit_BMP085.h>
    
    // Use U8g2 for i2c OLED Lib
    #include <SPI.h>
    #include <U8g2lib.h>
    U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, I2C_SCL, I2C_SDA, U8X8_PIN_NONE);
    byte x {0};
    byte y {0};
    
    // Handy timers
    #include <SimpleTimer.h>
    
    // CO2 SERIAL
    #define DEBUG_SERIAL Serial1
    #define SENSOR_SERIAL Serial
    
    byte cmd[9] = {0xFF,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79};
    unsigned char response[7];
    
    // Pressure and temperature
    Adafruit_BMP085 bme;
    
    // Blynk token
    char blynk_token[33] {"Blynk token"};
    char blynk_server[64] {"blynk-cloud.com"};
    const uint16_t blynk_port {8442};
    
    // Device Id
    char device_id[17] = "Device ID";
    const char fw_ver[17] = "0.1.0";
    
    // Handy timer
    SimpleTimer timer;
    
    // Setup Wifi connection
    WiFiManager wifiManager;
    
    // Network credentials
    String ssid { "ku_" +  String(ESP.getChipId())};
    String pass {"ku_" + String(ESP.getFlashChipId()) };
    
    //flag for saving data
    bool shouldSaveConfig = false;
    
    // Sensors data
    int t {-100};
    int p {-1};
    int h {-1};
    int co2 {-1};
    
    char loader[4] {'.'};
    
    //callback notifying the need to save config
    void saveConfigCallback() {
            DEBUG_SERIAL.println("Should save config");
            shouldSaveConfig = true;
    }
    
    void factoryReset() {
            wifiManager.resetSettings();
            SPIFFS.format();
            ESP.reset();
    }
    
    void printString(String str) {
            DEBUG_SERIAL.println(str);
    }
    
    void readCO2() {
            // CO2
            bool header_found {false};
            char tries {0};
    
            SENSOR_SERIAL.write(cmd, 9);
            memset(response, 0, 7);
    
            // Looking for packet start
            while(SENSOR_SERIAL.available() && (!header_found)) {
                    if(SENSOR_SERIAL.read() == 0xff ) {
                            if(SENSOR_SERIAL.read() == 0x86 ) header_found = true;
                    }
            }
    
            if (header_found) {
                    SENSOR_SERIAL.readBytes(response, 7);
    
                    byte crc = 0x86;
                    for (char i = 0; i < 6; i++) {
                            crc+=response[i];
                    }
                    crc = 0xff - crc;
                    crc++;
    
                    if ( !(response[6] == crc) ) {
                            DEBUG_SERIAL.println("CO2: CRC error: " + String(crc) + " / "+ String(response[6]));
                    } else {
                            unsigned int responseHigh = (unsigned int) response[0];
                            unsigned int responseLow = (unsigned int) response[1];
                            unsigned int ppm = (256*responseHigh) + responseLow;
                            co2 = ppm;
                            DEBUG_SERIAL.println("CO2:" + String(co2));
                    }
            } else {
                    DEBUG_SERIAL.println("CO2: Header not found");
            }
    
    }
    
    void sendMeasurements() {
            // Read data
            // Temperature
            float tf = si7021.getCelsiusHundredths() / 100.0;
            float t2f =bme.readTemperature();
            t = static_cast<int>((tf + t2f) / 2);
    
            // Humidity
            h = si7021.getHumidityPercent();
    
            // Pressure (in mmHg)
            p = static_cast<int>(bme.readPressure() * 760.0 / 101325);
    
            // CO2
            readCO2();
    
            // Send to server
            Blynk.virtualWrite(V1, t);
            Blynk.virtualWrite(V2, h);
            Blynk.virtualWrite(V4, p);
            Blynk.virtualWrite(V5, co2);
    
            // Write to debug console
            printString("H: " + String(h) + "%");
            printString("T: " + String(t) + "C");
            printString("P: " + String(p) + "mmHg");
            printString("CO2: " + String(co2) + "ppm");
    }
    
    void loading() {
            long unsigned int count {(millis() / 500) % 4};
            memset(loader, '.', count);
            memset(&loader[count], 0, 1);
    }
    
    void draw() {
            u8g2.clearBuffer();
    
            // CO2
            if (co2 > -1) {
                    char co2a [5];
                    sprintf (co2a, "%i", co2);
    
                    u8g2.setFont(u8g2_font_inb19_mf);
                    x = (128 - u8g2.getStrWidth(co2a))/2;
                    y = u8g2.getAscent() - u8g2.getDescent();
                    u8g2.drawStr(x, y, co2a);
    
                    const char ppm[] {"ppm CO2"};
                    u8g2.setFont(u8g2_font_6x12_mf);
                    x = (128 - u8g2.getStrWidth(ppm)) / 2;
                    y = y + 2 + u8g2.getAscent() - u8g2.getDescent();
                    u8g2.drawStr(x, y, ppm);
            } else {
                    loading();
                    u8g2.setFont(u8g2_font_inb19_mf);
                    x = (128 - u8g2.getStrWidth(loader)) / 2;
                    y = u8g2.getAscent() - u8g2.getDescent();
                    u8g2.drawStr(x, y, loader);
            }
    
            // Cycle other meauserments
            String measurement {"..."};
            const char degree {176};
    
            // Switch every 3 seconds
            switch((millis() / 3000) % 3) {
            case 0:
                    if (t > -100) { measurement = "T: " + String(t) + degree + "C"; }
                    break;
            case 1:
                    if (h > -1) { measurement = "H: " + String(h) + "%"; }
                    break;
            default:
                    if (p > -1) { measurement =  "P: " + String(p) + " mmHg"; }
            }
    
            char measurementa [12];
            measurement.toCharArray(measurementa, 12);
    
            u8g2.setFont(u8g2_font_9x18_mf);
            x = (128 - u8g2.getStrWidth(measurementa))/2;
            y = 64 + u8g2.getDescent();
            u8g2.drawStr(x, y, measurementa);
    
            u8g2.sendBuffer();
    }
    
    void drawBoot(String msg = "Loading...") {
            u8g2.clearBuffer();
            u8g2.setFont(u8g2_font_9x18_mf);
            x = (128 - u8g2.getStrWidth(msg.c_str())) / 2;
            y = 32 + u8g2.getAscent() / 2;
            u8g2.drawStr(x, y, msg.c_str());
            u8g2.sendBuffer();
    }
    
    void drawConnectionDetails(String ssid, String pass, String url) {
            String msg {""};
            u8g2.clearBuffer();
    
            msg = "Connect to WiFi:";
            u8g2.setFont(u8g2_font_7x13_mf);
            x = (128 - u8g2.getStrWidth(msg.c_str())) / 2;
            y = u8g2.getAscent() - u8g2.getDescent();
            u8g2.drawStr(x, y, msg.c_str());
    
            msg = "net: " + ssid;
            x = (128 - u8g2.getStrWidth(msg.c_str())) / 2;
            y = y + 1 + u8g2.getAscent() - u8g2.getDescent();
            u8g2.drawStr(x, y, msg.c_str());
    
            msg = "pw: "+ pass;
            x = (128 - u8g2.getStrWidth(msg.c_str())) / 2;
            y = y + 1 + u8g2.getAscent() - u8g2.getDescent();
            u8g2.drawStr(x, y, msg.c_str());
    
            msg = "Open browser:";
            x = (128 - u8g2.getStrWidth(msg.c_str())) / 2;
            y = y + 1 + u8g2.getAscent() - u8g2.getDescent();
            u8g2.drawStr(x, y, msg.c_str());
    
            // URL
            // u8g2.setFont(u8g2_font_6x12_mf);
            x = (128 - u8g2.getStrWidth(url.c_str())) / 2;
            y = y + 1 + u8g2.getAscent() - u8g2.getDescent();
            u8g2.drawStr(x, y, url.c_str());
    
            u8g2.sendBuffer();
    }
    
    bool loadConfig() {
            File configFile = SPIFFS.open("/config.json", "r");
            if (!configFile) {
                    DEBUG_SERIAL.println("Failed to open config file");
                    return false;
            }
    
            size_t size = configFile.size();
            if (size > 1024) {
                    DEBUG_SERIAL.println("Config file size is too large");
                    return false;
            }
    
            // Allocate a buffer to store contents of the file.
            std::unique_ptr<char[]> buf(new char[size]);
    
            // We don't use String here because ArduinoJson library requires the input
            // buffer to be mutable. If you don't use ArduinoJson, you may as well
            // use configFile.readString instead.
            configFile.readBytes(buf.get(), size);
    
            StaticJsonBuffer<200> jsonBuffer;
            JsonObject &json = jsonBuffer.parseObject(buf.get());
    
            if (!json.success()) {
                    DEBUG_SERIAL.println("Failed to parse config file");
                    return false;
            }
    
            // Save parameters
            strcpy(device_id, json["device_id"]);
            strcpy(blynk_token, json["blynk_token"]);
    }
    
    void configModeCallback (WiFiManager *wifiManager) {
            String url {"http://192.168.4.1"};
            printString("Connect to WiFi:");
            printString("net: " + ssid);
            printString("pw: "+ pass);
            printString("Open browser:");
            printString(url);
            printString("to setup device");
    
            drawConnectionDetails(ssid, pass, url);
    }
    
    void setupWiFi() {
            //set config save notify callback
            wifiManager.setSaveConfigCallback(saveConfigCallback);
    
            // Custom parameters
            WiFiManagerParameter custom_device_id("device_id", "Device name", device_id, 16);
            WiFiManagerParameter custom_blynk_server("blynk_server", "Blynk server", blynk_server, 64);
            WiFiManagerParameter custom_blynk_token("blynk_token", "Blynk token", blynk_token, 34);
            wifiManager.addParameter(&custom_blynk_server);
            wifiManager.addParameter(&custom_blynk_token);
            wifiManager.addParameter(&custom_device_id);
    
            // wifiManager.setTimeout(180);
            wifiManager.setAPCallback(configModeCallback);
    
            if (!wifiManager.autoConnect(ssid.c_str(), pass.c_str())) {
                    DEBUG_SERIAL.println("failed to connect and hit timeout");
            }
    
            //save the custom parameters to FS
            if (shouldSaveConfig) {
                    DEBUG_SERIAL.println("saving config");
                    DynamicJsonBuffer jsonBuffer;
                    JsonObject &json = jsonBuffer.createObject();
                    json["device_id"] = custom_device_id.getValue();
                    json["blynk_server"] = custom_blynk_server.getValue();
                    json["blynk_token"] = custom_blynk_token.getValue();
    
                    File configFile = SPIFFS.open("/config.json", "w");
                    if (!configFile) {
                            DEBUG_SERIAL.println("failed to open config file for writing");
                    }
    
                    json.printTo(DEBUG_SERIAL);
                    json.printTo(configFile);
                    configFile.close();
                    //end save
            }
    
            //if you get here you have connected to the WiFi
            DEBUG_SERIAL.println("WiFi connected");
    
            DEBUG_SERIAL.print("IP address: ");
            DEBUG_SERIAL.println(WiFi.localIP());
    }
    
    // Virtual pin update FW
    BLYNK_WRITE(V22) {
            if (param.asInt() == 1) {
                    DEBUG_SERIAL.println("Got a FW update request");
    
                    char full_version[34] {""};
                    strcat(full_version, device_id);
                    strcat(full_version, "::");
                    strcat(full_version, fw_ver);
    
                    t_httpUpdate_return ret = ESPhttpUpdate.update("http://romfrom.space/get", full_version);
                    switch (ret) {
                    case HTTP_UPDATE_FAILED:
                            DEBUG_SERIAL.println("[update] Update failed.");
                            break;
                    case HTTP_UPDATE_NO_UPDATES:
                            DEBUG_SERIAL.println("[update] Update no Update.");
                            break;
                    case HTTP_UPDATE_OK:
                            DEBUG_SERIAL.println("[update] Update ok.");
                            break;
                    }
    
            }
    }
    
    // Virtual pin reset settings
    BLYNK_WRITE(V23) {
            factoryReset();
    }
    
    void setup() {
            // Init serial ports
            DEBUG_SERIAL.begin(115200);
    
            SENSOR_SERIAL.begin(9600);
            SENSOR_SERIAL.swap();  // GPIO15 (TX) and GPIO13 (RX)
    
            // Init I2C interface
            Wire.begin(I2C_SDA, I2C_SCL);
    
            // Init display
            u8g2.begin();
            drawBoot();
    
            // Init Humidity/Temperature sensor
            si7021.begin(I2C_SDA, I2C_SCL);
    
            // Init Pressure/Temperature sensor
            if (!bme.begin()) {
                    DEBUG_SERIAL.println("Could not find a valid BMP085 sensor, check wiring!");
            }
    
            // Init filesystem
            if (!SPIFFS.begin()) {
                    DEBUG_SERIAL.println("Failed to mount file system");
                    ESP.reset();
            }
    
            // Setup WiFi
            setupWiFi();
    
            // Load config
            drawBoot();
            if (!loadConfig()) {
                    DEBUG_SERIAL.println("Failed to load config");
                    factoryReset();
            } else {
                    DEBUG_SERIAL.println("Config loaded");
            }
    
            // Start blynk
            Blynk.config(blynk_token, blynk_server, blynk_port);
    
            // Setup a function to be called every 10 second
            timer.setInterval(10000L, sendMeasurements);
    
            sendMeasurements();
    }
    
    void loop() {
            Blynk.run();
            timer.run();
            draw();
    }

    Разработка сильно упростилась благодаря наличию хороших примеров и наличию функциональных библиотек:



    Для работы с CO2 датчиком был использован чутка улучшенный пример из datasheet-а.


    Что можно сделать лучше?


    Здесь есть еще над чем поработать:
    1) Решить проблему избыточного тепла в корусе
    2) Сделать его еще компактнее — разведя плату и избавившись от проводов
    3) Сделать работу в offline режиме


    Что еще можно сделать? Какие у вас идеи? Если кто-то соберется сделать что-то подобное буду рад помочь и ответить на вопросы.


    Существующие статьи на тему на Geektimes:


    1. Измеряем концентрацию CO2 в квартире с помощью MH-Z19
    2. Обзор инфракрасного датчика CO2 MH-Z19
    3. Wi-Fi измеритель CO2 на ESP8266 + K-30
    Поделиться публикацией
    Никаких подозрительных скриптов, только релевантные баннеры. Не релевантные? Пиши на: adv@tmtm.ru с темой «Полундра»

    Зачем оно вам?
    Реклама
    Комментарии 138
    • 0
      Весьма забавно. Возможно ли использовать другие дачтики CO2? А то больно дорого 20уе отдавать.
      • +7
        Датчик, конечно можно другой, но этот самый дешевый из доступных на рынке. Традиционно более дешевые электро-химические датчики стоят сравнимые деньги, при этом требуют сильно больше энергии (т.к. рабочая температура ~300С), обладают меньшей точностью и избирательностью (реагируют на другие газы)
        • +2
          Это еще дешево. Готовые устройства с такими датчиками еще дороже

          Цена постоянно обсуждается в комментариях к таким статьям. Например
          https://geektimes.ru/company/dadget/blog/253084/#comment_8436346
          Ну я и написал — «хорошие датчики стоят 70+ баксов».
        • +1
          gy-21 SI7021 i2c

          Ух ты, отдельное спасибо за упоминание! Не знал, что такие бывают.
          • +2
            Это не лучший экран для постоянной индикации — он выцветает чрезвычайно быстро — буквально за год-два потеряет 50% яркости.
            • +1
              Спасибо, не знал что проблема у подобных OLED экранов стоит так остро.
              • +1
                Просто сам столкнулся с этой проблемой. Обожаю эти экранчики — слишком уж они милые, но эх…
                • +1
                  Есть у меня старый мобильник — филипс ксениум с внешним экраном как раз таки ОЛЕД.
                  Последнее время стоял все время на зарядке как будильник, в этом режиме экран постоянно горел.
                  ЗА примерно 3 года выцвел в ноль.
                  • 0
                    А если подключить HC-SR501 (датчик движения) и включать экранчик когда есть движение рядом? Давно об этом думал… Мой OLED пока едет с китая.
                    • +1
                      Тогда уж лучше датчик приближения, подобно тому что ставят в мобильники.

                      Не знаю как вас, а меня злил бы этот маяк, который мигал бы каждый раз как я по комнате прохожу.
                • 0
                  выцветает от наработки или от внешнего воздействия?
                • +2
                  Как раз нахожусь в процессе конструирования/подбора компонентов для устройства с почти таким же функционалом.
                  Единственное что хочу у себя добавить — это небольшой литиевый аккумулятор, который будет заряжаться при питании от USB. Так появится еще и автономность.
                  Вместо bmp280+gy-21 планирую попробовать BME280, он измеряет давление, температуру и влажность сам в одном флаконе. Или может по нему есть какие-то нарекания?
                  Ну, и поглядываю на Wemos D1 mini, можно еще места сэкономить…
                  • 0
                    небольшой литиевый аккумулятор
                    Датчики углекислого газа потребляют достаточно большую мощность. И прогреваются при этом несколько минут, импульсами включать не получится.
                    Так что придётся или аккумулятор делать уровня 18650, или хватать будет на несколько часов работы.
                    • 0
                      ИК датчики СО2 (в примере как раз один из таких) потребляют немного — типовой уровень 10-30 мА. И на рабочий режим выходят за 20-30 секунд
                      • 0
                        По даташиту, MH-Z19 должна 5 минут прогреваться, ЕМНИП. А 10-30 мА – это достаточно много, пальчиковые батарейки будут садиться примерно за неделю, BL-4 («аккумулятор от Нокии») – дня за три.
                        • 0
                          По даташиту у него 3 минуты. Но это как понимаю это для выхода на паспортную точность.

                          Те пару ИК датчиков что мне попадались начинали выдавать показания уже через 20-30 секунд и более-менее адекватные показания, а не случайные значения от балды. Проверить эталона нет, но по крайней мере показания не сильно менялись после выжидания нескольких дополнительных минут. В пределах 5-15% и тут сложно сказать сколько из этого плавающая точность датчика, а сколько реальные изменения концентрации в воздухе от моего собственного присутствия и движения воздуха в помещении.

                          Да, только на несколько дней заряда хватит. Но не несколько часов. Как основной(единственный) источник для постоянной работы поэтому подходит плохо, но как дополнительный — вполне нормально.
                    • +1
                      Да, bme280 хорош, его планировал использовать. Но единственный доступный мне экземпляр оказался бракованным. Я обновил статью указав эту возможность.

                      Питание от аккумулятора возможно, но тогда стоит использовать другой дисплей, вводить esp8266 в спящий режим, и подключаться к WiFi периодически.
                      а вот сэкономить на питании mh-z19 сложнее. Его лучше держать включенным постоянно. Он потребляет ток около 18ma, а значит система с аккумулятором на 700ma, как у маленькой нокии, сможет продержаться 1,5 суток.
                      • 0
                        Под автономностью я имел в виду не пожизненную работу в автономном режиме, а просто чуть большую мобильность. Чтобы можно было пройтись по разным помещения и посмотреть сколько надышали тут, сколько надышали там, нормально ли проветривается вот здесь.
                        Чтобы не искать свободные usb в каждом помещении или не таскать какой-нибудь PowerBank. А просто достал, включил — работает. Естественно не вечно.
                        Даже сутки работы для таких целей более чем достаточно, можно и неплохую динамику заснять, если потребуется.
                      • 0
                        Пример реализации с использованием Wemos D1 mini и стандартного корпуса для Arduino
                        <img src="" alt=«image»/>
                      • +3
                        Почему не bme280? В нем 3 в одном — влажность, температура, давление.
                        • +4
                          Да, bme280 хороший вариант, изначально планировал использовать именно его, но с aliexpress приехал неработающий экземпляр, поэтому использовал то, что было. А когда писал статью забыл про существование bme280. Спасибо за напоминание!
                          • +2
                            Есть два bme280, показания влажности отличаются на 4 единицы, при том что давление и температура совпадает. Смотрел raw-данные они отличаются, но и поправочные коэффициенты разные.
                            • 0
                              Аналогичная проблема — есть несколько датчиков, dht-22/bme-280/sht-21 — все показывают значения близкие, но не одинаковые. Даже в рамках одного датчика из разных партий.
                              Увы, нет одинаковых, купленных пачкой — чтобы сравнить их показания, все покупались поштучно.
                              Интересно было бы увидеть статистику по разбросу, точности и т.п. по самым популярным датчикам.
                              • +2
                                По дому раскидано несколько bmP280, bmE280, DS18B20 и одинокий DHT22 (AM2302).

                                По году-полутора наблюдений могу сказать, что разброс bmp/bme в пределах 0.5..1С и 0.5..1.6 мм.рт.ст. при том, что высота установки примерно одинакова (±0.5м). С влажностью сложнее, но BME280 по ощущениям гораздо адекватнее DHT22, особенно при высокой влажности, где DHT «промокает» и держит 99.9% довольно долго. Разность по влажности DHT BME была порядка 5-7.

                                Есть три рядом стоящих датчика — BMP на плате с «мозгами» на ESP8266, BME+DS18B20 на выносном датчике в паре метров рядом. Давление различается на 0.5мм, стабильно за всё время наблюдений. А вот температура 18B20+BME гораздо непредсказуемей. во-первых, BME _гораздо_ лучше ловит отраженное тепло (коррекция -2.2С по сравнению с 18B20), во-вторых у них сильно разная инерционность и расхождение гуляет до пары-тройки градусов (особенно, когда сосед снизу окно открывает ;) ) Что, в общем-то, логично, т.к. BMx250 позиционируются в том числе для навигации в помещениях.

                                ЗЫ: где-то мелькал совет по вымачиванию DHT22 полчаса в спирте с последующей сушкой несколько часов — вроде как перестаёт откровенно левые показания давать и выравнивается между датчиками. Не пробовал…
                                • 0
                                  есть небольшая статейка по этой теме: https://goo.gl/vn6yio (url сократил потому, что слишком длинный)
                          • +1
                            Дополнительно можно установить microSD слот и писать накарту все показания с привязкой по времени. Это позволит работать в оффлайне, при необходимости брать карту памяти с файлом и кидать её содержимое в комп, ну и вообще с картой памяти всё становится лучше как и с Bluetooth Wifi
                            • +1

                              Собирал на arduino pro micro этот же датчик + датчик температуры + microsd, ethernet, RTC ии… скажем для дисплея доступных 29кб прошивки уже не хватает

                              • 0
                                я когда осваивал этот OLED дисплей и библиотеку для него для Ethernet-сервачка на Уно — тоже поначалу приуныл. Потом обнаружил, что необязательно тащить весь набор символов в память и, вообще, объём занимаемой памяти сильно зависит от размера шрифта. Мож вам тоже хватило бы памяти при использовании шрифта небольшого размера и только цифровых символов? :)
                                • 0
                                  Дело в том, что сейчас без дисплея занято 99% от доступной памяти. А «убирать ненужное» из библиотек для работы с сетью/sd-картой не очень хочется.
                            • +3
                              Забавно, делал недавно подобный девайс, только экран предпочел TFT цветной.
                              Корпус — напечатаная надстройка над телефонной розеткой (сами джеки для подключения питания и внешнего термодатчика)
                              картинка
                              image
                              • 0
                                И я тоже! image
                                • 0
                                  Там не спросил — сдержался, спрошу здесь
                                  ssid и ip-шник-то зачем??? :)

                                  Можете сколько угодно хаить едакий девайс, но
                                  светотофорный дизайн
                                  /
                                  тут более чем уместнен
                                  • 0
                                    ssid для того чтобы видеть куда станция пытается подключиться (или уже подключена). При отсутствии подключения там пишется имя временной точки доступа для изменения настроек сети. Кстати имя сети выбрано мной неслучайно. Это чтобы не палиться на работе))))
                                    ip-шник (он внутренний за роутером c DHCP) для того чтобы можно было зайти на внутренний веб-сервер esp8266 и посмотреть показания датчиков.
                                    Это первый вариант устройства. Главные на мой взгляд недостатки это питание от usb. Надо переходить на батареи, монохромный дисплей и использование спящего режима.
                                    Веб сервер оказался никому не нужен. Самые удобные «показометры» это экранчик и отправка данных куда-нить на сервер по get(php) или mqtt (чтобы народ мог посмотреть с телефона например).
                                    P.S. Для программирования использовал среду arduino
                                  • 0
                                    А что за дисплей был использован и как «присобачили»? :)
                                    • 0
                                      Дисплей самый дешевый на чипе ili9341 с али.
                                      картинка страшный вид сзади
                                      image

                                      Я старался максимально доступное все брать. Как в плане цены так и в плане библиотек под ардуино.
                                  • 0
                                    Прелесть какая
                                  • 0
                                    А про датчики CO и мелких частиц в воздухе не думали? Вроде такого https://www.sparkfun.com/products/9689. Они, правда, крупные по размеру.
                                    • +2
                                      Можно подключить без проблем. В моих условиях надобности в них нет, квартира без газа, поэтому СО опасаться не стоит, район без промышленности, поэтому пыли опасаться тоже не стоит.
                                      Хотя мой друг, живущий в Шанхае, активно использует подобную систему с датчиком пыли.
                                      • 0
                                        Игрался с датчиком пыли GP2Y1010AU0F, к сожалению не удалось получить сколько ни будь правдоподобные показания. и в инете на тот момент не много было описаний успешного опыта использования.
                                        • +2
                                          Подключил в свою поделку датчик пыли GP2Y1010AU0F.
                                          Достаточно точный. Реагирует на пайку, открытие корпуса компа, уборку в комнате.
                                          Как калибровать только непонятно.
                                          image
                                          • 0
                                            мне кажется удачно модно откалибровать где нибудь в лесу, в поле и желательно зимой. Видел статью в интернете не могу ни как найти извините.
                                            • +1
                                              Как вариант осадить пыль паром.
                                              Удобно в ванной комнате.
                                              • 0
                                                Главное не посыпать перхотью датчик, после парилки, во время калибровки ))
                                                • 0

                                                  Если заморачиваться с чистотой, то перед всеми действиями необходимо помыться, тотально и глобально.
                                                  Полиэтиленовую шапочку и топлесс :) или что-то типа медицинского халата.


                                                  И настоятельно рекомендую потренироваться без пациента :)

                                                  • 0
                                                    Да вот тоже думаю для своих поделок заказать такой датчик… не знал о необходимости калибровки, видимо придется вместе с датчиком заказать еще и костюмчик для использования в гермозонах)))
                                        • 0
                                          Извиняюсь, а что и с чем соединять где-нибудь описано? Так сказать аппаратная часть, или вопрос на самом деле ламерский и на самом деле «и так всё ясно, не перепутаешь?»
                                        • 0
                                          Интересует, насколько стабильно работает устройство? Случаются ли зависания?
                                          • 0
                                            Зависания случались только в режиме точки доступа. В рабочем режиме не наблюдал. Есть подозрения, что были спонтанные перезагрузки, но специально я это не отслеживал. Для бытового устройства работает весьма стабильно.
                                          • 0

                                            А кто-нибудь может посоветовать аналогичный готовый девайс?
                                            Можно даже без экранчика, главное чтоб по сети данные можно было смотреть, без облаков и прочих удалённых сервисов (либо они должны быть опциональны).

                                            • 0
                                              Вот готовое решение.
                                              http://mybroadlink.ru/catalog/meteostanciya-e-air/
                                              на али стоит 2400р.
                                              Только вместо CO2 показывает «качество воздуха» а это может быть что угодно.
                                              • 0
                                                Эта штука CO2 не меряет.
                                              • 0
                                                https://masterkit.ru/shop/others/dadget/2122569

                                                у китайцев цены примерно такие же и выше.
                                                • 0

                                                  Она же USBшная, а не сетевая. Плюс требует дополнительный софт для работы.

                                                  • 0
                                                    И кто Вам мешает использовать любой БП с USB-разъемом?
                                                    Софт использовать можно, но совсем не обязательно, все данные выводятся на экран.
                                                    • 0

                                                      Не уверен, что блок питания поможет передавать данные по сети… Как я и написал изначально, мне экран не нужен, а нужна возможность получения данных по вайфаю.

                                                • 0
                                                  Вот мне этот чувак сделал — http://forum.ixbt.com/topic.cgi?id=47:11005:1720#1720 — как раз то, что вам нужно, только там датчиков больше (но, наверно, он может сделать и только со2)
                                                • 0
                                                  Можно заказать уже готовый и настроенный?

                                                  Сколько будет стоить?
                                                  • 0
                                                    Не думаю, что буду доводить это устройство до мелкой серии
                                                    но что если делать, то нужно сделать печатную плату, чтобы упростить монтаж и сделать еще чуть компактнее.
                                                    Да и качество 3д-печатного корпуса не дотягивает до ожиданий от купленного устройства.
                                                    • 0
                                                      Выше отписал, я взял у этого парня — http://forum.ixbt.com/topic.cgi?id=47:11005:1720#1720 — работает норм.
                                                    • +1
                                                      Чтобы избавиться от внутреннего тепла — мне пришлось вынести датчик за пределы корпуса. Неэстетично, зато правдиво — температура упала сразу на 2 градуса.
                                                      • +1
                                                        Так в мануалах датчиков пишут и рисуют как правильно устанавливать: если датчик на общей плате распаян, то вокруг датчика делают фрезеровку, чтобы через текстолит не проходило тепло и в корпусе закрывают датчик в своей проветриваемой камере.
                                                        • 0
                                                          Не поможет тут фрезеровка, тепло все равно будет нагревать датчик. Только выносить или делать термобокс небольшой.
                                                      • +1
                                                        Спасибо! Как раз собирался сотворить подобное именно в таком сочетании комплектующих и софта. Возьму Ваш девайс за основу :)

                                                        Если же wifi сеть не обнаружится, то монитор загрузится в режиме ожидания настройки и поднимет точку доступа.
                                                        Имхо, кнопка предпочтительнее тем более, что кнопка для прошивки все равно нужна:
                                                        зажатая кнопка + включение питания — переход в режим прошивки
                                                        включение питания + надпись на экране на пару секунд «Press button to enter setup» + нажимаем кнопку — переход в режим конфигурирования

                                                        PlatformIO
                                                        Уже можно пользоваться? Когда пробовал был очень сырой продукт, но явно амбициозный :)

                                                        Корпус
                                                        3D печать это здорово и модно, но все ж таки несколько аляповато получилось.

                                                        но провода внутри все равно занимают большую часть места
                                                        С учетом коннекторов — чудо, что вообще влезло )

                                                        Ну, то все мелкие придирки, за исходники отдельное спасибо!
                                                        • 0
                                                          PlatformIO лично мне очень нравится. В связке с Atom. Бывает, правда, плагин Atom Beatify подглючивает (сижу на Linux).
                                                          • 0
                                                            PlatformIO можно пользоваться, работает весьма стабильно и активно поддерживается и разрабатывается.
                                                            Кнопка, по моему мнению, не нужна.
                                                            Всего одна строчка в коде `wifiManager.setTimeout(180);` позволяет не входить в режим настройки навечно — если проблема с сетью временная.
                                                            Прошивка по воздуху активируется через мобильное приложение, для прошивки через провод, кнопка тоже не нужна.
                                                            • 0
                                                              Ну, я в этом плане параноик :) Щелкнул пакетником в щетке, прошил по воздуху и вот уже в вашей домашней сети устройство которое делает то что нужно мне…
                                                              • +1
                                                                Тут дырки в безопасности нет. Чтобы подключиться к устройству в режиме настройки, нужно знать пароль доступа к точке, который отображается на экране. Полагаю, что лестичной клети экрана не видно.
                                                                Обновление по воздуху работает по другой схеме. URL с которого нужно загрузить новую прошивку содержится в текущей прошивке, а не передается по воздуху. По воздуху отправляется лишь команда «проверить обновления прошивки»
                                                                К слову здесь используется простой http, но проблем с https (в том числе с tls 1.2) быть не должно
                                                                • +1
                                                                  Неплохой ответ, но

                                                                  Внутренний параноик:
                                                                  — это еще надо посмотреть как генерятся эти логин и пароль.

                                                                  Внутренний параноик (про TLS):
                                                                  — да, кстати, не припомню об реальном использовании ssl на девайсах с esp8266

                                                                  Внутренний параноик (вообще):
                                                                  — знать бы еще что эти китайцы в реализацию ip-стека засунули…

                                                                  :)
                                                                  • +2
                                                                    — логин и пароль это серийники чипа и flash-a
                                                                    — ssl работает
                                                                    — Китайца зовут Иван https://github.com/esp8266/Arduino/issues/2537
                                                              • 0
                                                                Можно про прошивку подробнее? Какая технология обновления прошивки?
                                                                Можно ссылкой…
                                                          • 0
                                                            А как вы справляетесь с тем, что и MH-Z19, и OLED экран в общем-то существенно нагревают воздух внутри корпуса, искажая показания термодатчика?
                                                            • +1
                                                              Нагревает в основном esp866 и dc-dc преобразователь, но я никак с этим не справляюсь
                                                              • 0
                                                                А пробовали измерить вносимую погрешность?
                                                                • 0
                                                                  3-4 градуса цельсия, она примерно постоянна и достигается через 15 минут работы устройства, наверное можно внести программную коррекцию.
                                                                  • 0
                                                                    Осталось убедиться, что она константна (что 99% не так)
                                                                    • 0
                                                                      Она, конечно, не константа. Но проградуировать, думаю, можно
                                                                  • +1
                                                                    Она не постоянна.
                                                                    Собрано два девайса 1. Макетка (датчики немного разнесены) — ESP8266 + MH-Z19 + SHT10 + BMP280. 2. «Готовое изделие» ESP8266 + MH-Z19 + DHT22 (датчик температуры вынесен на корпус).
                                                                    При «стоячем воздухе» разница в показаниях до 3'C, при проветривании (с учетом что стол стоит в углу) снижается до 1'C.
                                                                    Нагрев от понижаюки и самого еспешки довольна существенный.
                                                              • 0
                                                                Лучшее, что здесь можно улучшить — отказаться от вороха коробочек в доме (подозреваю что цель этого проекта реальная, а не proof of concept).

                                                                Пусть ваши датчики шлют данные в RAW на сервер (возможно даже по WiFi), а уже сервер их парсит. Вы сможете использовать эти данные для электромеханических устройств (PPM опустилось -> включился кулер вентиляции), вы сможете использовать их вдали от дома, вы сможете их просматривать со смартфона, вы сможете повесить себе рядом с входной дверью планшет или RPI-шку с TFT, и смотреть эти показания не отходя от кассы. Вы даже сможете находить закономерность между временем суток, освещению вашего окна солнцем, и падением уровня O2, или даже между PPM и вашей сонливостью.
                                                                • 0
                                                                  данные и шлются на сервер в сыром виде, более того сервер позволяет легко настроить web hook-и для каких-то дополнительных действий.
                                                                  • 0

                                                                    да я тут реализовал сие наконец тоже и в 10 минут прикрутил к thingspeak (сервер из статьи как-то непонятно как сейчас работает, и вдобавок поставить приблуду из QR кода стоило $4, как настраивать ее неясно..)

                                                                  • +2
                                                                    Я тут тоже MH-Z19 приобрёл и выяснил кое-какие недокументированные возможности. Для поста маловато, так что продублирую свой камент в другом посте:

                                                                    упомянутый MH-Z19 может ещё и температуру говорить, хотя в даташите это не указано. Однако указано, что градусник там есть, что и побудило меня порыться в интернете на эту тему.

                                                                    https://revspace.nl/MHZ19#Command_0x86_.28read_concentration.29

                                                                    Байт сразу после СО2 — температура плюс некоторая константа (по-хорошему надо её калибровать). Хотя здесь ложка дёгтя — для генерации дальнего ИК используется лампочка Ильича, каковая дополнительно нагревает датчик. Но это опять же мерять надо, насколько она его греет.

                                                                    Следующий байт — судя по всему, символизирует точность, достигаемую прибором на настоящий момент. А оная точность время от времени ухудшается — когда датчик тревожат, открывают дверь, либо вовсе без видимых причин (быть может, калибруется?), и тогда на графике мы видим пляски святого Витта. Коли всё хорошо — то байт равен 64, а когда плохо — то падает до 4. Например, это может пригодиться, ежели мы чем-то управляем на основании измерения СО2 — коли мы видим, что байт упал ниже 64, мы не рвёмся сразу переключать реле, а ждём, пока снова не станет 64, и показаниям снова можно будет доверять (ну или просто усредняем усерднее).

                                                                    Далее там ещё два байта — а вот что они значат, одному аллаху ведомо. Но, видимо, ничего, что бы относилось к параметрам окружающей среды. Автор упомянутой статьи высказывает предположение, что это давление, но вряд ли давление будет час стоять на одном месте с абсолютной точностью, затем несколько минут падать, а затем столь же незыблемо сохранять своё значение.

                                                                    Конец цитаты.

                                                                    Вот график: https://hsto.org/files/80c/0d2/20e/80c0d220e601462391b20c35ac9a7f13.png

                                                                    Когда температура падает (приблизительно до 8 градусов) — это я окно открыл.

                                                                    Собственно, видно, что когда показания СО2 колбасит, красная линия уходит вниз. И видно, что датчик довольно нежный — малейший ветерок — и показания скачут (быть может, это мой экземпляр такой?).

                                                                    А также видно, что чуть раньше 24 часов она внезапно волевым решением приравнивает концентрацию СО2 к 400 ппм. Говорят, что она таким образом автоматически калибруется — видит минимальную концентрацию за сутки и считает, что это 400 ппм. Лично на мой взгляд это довольно подлое поведение — калиброваться без спроса, к тому же тогда, когда нет никакой уверенности, что перед тобой эталон. Вполне может быть, что окна вовсе за сутки не будут открываться, да и с открытыми окнами нет гарантии, что у нас именно 400 — быть может, мы в Москве или, чего доброго, в Шанхае? Про график Килинга я и вовсе не говорю — надо очень долго ждать, чтобы изменение глобальной концентрации СО2 превысило заявленную погрешность прибора.
                                                                    • +3
                                                                      У меня ощущение, что он калибруется несколько хитрее. Я тоже замечал эти скачки раз в сутки. Но у меня после месяца непрерывной работы скачки показаний раз в сутки сильно уменьшились.

                                                                      Я пытался калибровать его в атмосфере чистого азота (купил жидкий азот для этого), толку ноль.

                                                                      Реально этот датчик подходит для примерной оценки, не более.
                                                                      • +1
                                                                        У меня, похоже, он докалибровался. Раньше, когда я заходил в комнату и закрывал дверь/окно, показания росли приблизительно на 800 ппм в час. А сейчас — чуть более 200. И подозрительно много времени проводит около 400 — это даже не объяснить тем, что минимальный уровень за 400 принимает. Похоже на то, он «хочет» намерять меньше 400 (а то и вовсе меньше нуля), но какие-то «моральные принципы» ему мешают.

                                                                        Этот случай как нельзя лучше раскрывает всё паскудство «интеллектуальной» автоматической калибровки. Выдавай он «сырые» значения — можно было бы самому вытаскивать из ни концентрацию (или хотя бы понять, сошёл датчик с ума или нет). Быть может, оные значения выдаются какой-либо командой из тех, что не проверены в упомянутой статье.

                                                                        Правда, в описанном происшествии есть некоторая доля моей «вины». Вначале я подсоединил датчик к +5 вольтам ардуины (а её к УСБ через трёхметровый удлинитель). Так она двое суток поработала. А потом подсоединил к +3,3 вольтам той же ардуины, а они там берутся из крена на 160 мА. И, видимо, этих мА ему не хватает, что выражается в визуально более долгом времени горения лампочки внутре и повышению температуры на 2 — 3 градуса. Тем не менее даже при таком раскладе он выдавал значения от 400 и до чуть более 2000, правда, норовя выдать 400 либо 1755. А ещё через сутки я подключил оный датчик к аккумулятору, чтобы ему точно тока хватило. И вот здесь-то и произошло описанное событие, как в том анекдоте про японский станок и суровых русских мужиков. Тем не менее вины с датчика это не снимает — коли ты такой умный, то мог бы догадаться, что не надо калиброваться, коли тебе питания не хватает. Или по крайней мере не распространять эту калибровку на тот случай, когда питания хватает.

                                                                        И похоже, что я таки понял, что символизирует неведомое число в конце вывода датчика. А символизирует оно время работы лампочки (ну или энергию, затраченную на оную работу). При питании от 5 вольт было чуть более 10 тысяч, а от крена на 3,3 В — уже более 15 тысяч (то бишь больше, чем при старте датчика). А от аккумулятора — сейчас рисует 9676.

                                                                        Теперь следующий шаг — надо вогнать ему в питание 1 ом и записывать график напряжения на таковом. И посмотреть корреляцию с неведомой величиной. А затем потестировать различные недокументированные команды — быть может, какой-то из них можно управлять зажиганием/измерением непосредственно.

                                                                        > Но у меня после месяца непрерывной работы скачки показаний раз в сутки сильно уменьшились.

                                                                        А после перезагрузки сохраняется калибровка или слетает?
                                                                        • 0
                                                                          У меня показание CO2 считывается посредством прошивки с wifi-iot и льется в zabbix.
                                                                          На графике видны почти ежедневные ступеньки на 50-100 ppm, около 11 утра
                                                                          image

                                                                          По графику хорошо можно оценить насколько точная у датчика на данный момент калибровка 400ppm — ведь по идее падение к 400 должно быть плавным, если в комнате не открыто окно, а открыто в другом месте.Плюс у меня датчик стоит в почти закрытой коробке, таким образом убираются случайные пики.
                                                                          Так вот падение к 400 иногда прямо очень плавное, а иногда — совсем нет.

                                                                          Сегодня находился в комнате 10кв. метров, с датчиком 2.5 часа. Дверь закрыта. Показание выросло линейно с 500 до 1500ppm. После открытия двери за две минуты упало до 900ppm, дальше еще за 12 минут — 700ppm. Выглядит адекватно.

                                                                          А вот на день раньше днем — полка 400ppm при том, что в комнате был человек (это видно по графику датчика движения) и в соседней комнате было чуть приоткрыто окно (это видно по температуре, гг). Мне кажется это странным.

                                                                          Похоже, что перезагрузка датчика не изменила калибровку. Скачков на 200-300 ppm нет.

                                                                          Я у своего датчика вызывал калибровку, замыкая какие-то пины (в документации описано). И не заметил разницы между калибровкой в азоте и на воздухе.
                                                                      • 0
                                                                        Сверял эту выдаваемую температуру — десятки не выдает, целые совпадают.
                                                                        Датчики стояли на макетке.
                                                                      • –4

                                                                        Кстати, на Алиэкспресе можно получать кэшбек до 10% процентов с почти мгновенным выводом. Пишите в личку, расскажу как.

                                                                        • +2

                                                                          Не думал что тема еще актуальна так как в свое время собирал схожий девайс о котором я хотел написать еще год назад, но все никак не нашел свободного времени. Принцип работы немного отличается от того что собрал автор. У моей метеостанции на месте мозгов стоит Atmega328, а ESP8266 играет роль модема. Так-же имеется "протокол" для подключения беспроводных мини-модулей к которым можно понацеплять кучу датчиков, и все это добро отправлять на сайт народмониторинга. На данный момент из сенсоров стоят счетчик гейгера, СО2 (MH-Z19), BME280х2 и фоторезистор. В планах было присобачить датчики влажности почвы для напоминаний о поливе растений, но не свершилось, так как у меня больше нет растений в доме :) беспроводные модули кстати запитаны от CR2032. К чему про все это — если кто работает над схожим проектом или просто имеются вопросы, то можете мне написать. Постараюсь помочь чем смогу, так как думаю до написания статьи уже наверняка дело не дойдет.


                                                                          image

                                                                          • 0
                                                                            А можно посмотреть на код работы с nrf24l01? на обеих сторонах?
                                                                            • 0

                                                                              "Протокол" — это было громко сказано, поэтому и обернул это слово в кавычки. На самом деле все до безобразия просто. Используются нативные библиотеки <nRF24L01.h> и <RF24.h> а данные перед отсылкой пакуются в одну строчку разделенную запятыми, где первый параметр это ID датчика а все остальные параметры это собственно показания разных датчиков. Т.е когда "базовая станция" получает данные с удаленного датчика, первым делом она их распаковывает и сверяет ID, после чего уже точно знает какого рода данные полученные, сколько параметров и как их правильно разбить. Ко всему этому я добавил low power команды, чтобы после отправки данных, удаленный датчик засыпал и переводил NRF в энергосберегающий режим до следующего просыпания по истечению n-ного количества времени. Соответственно, как вы уже наверное догадались, все коммуникации работают в одностороннем порядке. Пишу развернутый ответ так как одновременно хотел ответить пользователю slgeo .


                                                                              Код относящийся именно к передаче и получению данных выглядят так (заранее извиняюсь за английский в комментариях — мне так было проще):


                                                                              Передатчик

                                                                              в setup:
                                                                              radio.begin(); //radio.setPayloadSize(8); //reduce payload to 8 (32 max) radio.setDataRate(RF24_250KBPS); //Pay attention to transfer speed radio.setRetries(15, 15); radio.openWritingPipe(rxAddr); radio.stopListening();


                                                                              в loop:
                                                                              radio.powerUp();`
                                                                              sprintf(msg, "%d,%d,%d,%d,%d,%d", sensorID, temp1002, hum1002, pres1002, lux1002, bat1002);


                                                                              radio.write( &msg, sizeof(msg)); //Send data to 'Receiver'
                                                                              radio.powerDown();
                                                                              `


                                                                              Приемник

                                                                              в define:
                                                                              `//****Data received via NRF24***
                                                                              char msg[32];
                                                                              int sensorID;
                                                                              int data1;
                                                                              int data2;
                                                                              int data3;
                                                                              int data4;
                                                                              int data5;


                                                                              //****sensor ID1001 — Base Station. No protocol — continous polling
                                                                              float temp1001;
                                                                              int hum1001;
                                                                              float pres1001;
                                                                              float avgcpm; //CPM for geiger events
                                                                              float uSv; // uSv converted from CPM
                                                                              float uRh; // Microroentgen= uSv
                                                                              100
                                                                              int COppm;


                                                                              //*****sensor ID1002 — Outside weather. Protocol ID:Temp:Hum:Pres:Lux:Bat
                                                                              float temp1002; //apply formula (float)data/100-50
                                                                              int hum1002;
                                                                              float pres1002; //apply formula (float)data/100
                                                                              int lux1002;
                                                                              float bat1002; //apply formula (float)data/100


                                                                              //*****sensor ID1003 — Hygrometer plant1. Protocol ID:Hygr:Bat
                                                                              int hygr1003;
                                                                              float bat1003; //apply formula (float)data/100


                                                                              //**sensor ID1004 — Hygrometer plant2. Protocol ID:Hygr:Bat
                                                                              int hygr1004;
                                                                              float bat1004; //apply formula (float)data/100


                                                                              в Setup-e обычная инициализация NRF24l01 radio.begin();
                                                                              radio.setDataRate(RF24_250KBPS);
                                                                              radio.openReadingPipe(0, rxAddr);
                                                                              radio.startListening();`


                                                                              в loop:
                                                                              `//check radio actively for updates
                                                                              while (radio.available())
                                                                              {
                                                                              digitalWrite(ledpin, HIGH);
                                                                              radio.read(&msg, sizeof(msg));
                                                                              sscanf(msg, "%d,%d,%d,%d,%d,%d", &sensorID, &data1, &data2, &data3, &data4, &data5);


                                                                              if (sensorID == 1002) {
                                                                                //structure read data for ID1002 - outside weather
                                                                                temp1002 = ((float)data1 / 100) - 50;      //apply formula (float)data/100-50
                                                                                hum1002 = data2;
                                                                                pres1002 = (float)data3 / 10;             //apply formula (float)data/100
                                                                                lux1002 = data4;
                                                                                bat1002 = (float)data5 / 100;
                                                                              }
                                                                              
                                                                              else if (sensorID == 1003) {
                                                                                //structure data for ID1003 - plant 1
                                                                                hygr1003 = data1;
                                                                                bat1003 = (float)data2 / 100;
                                                                              }
                                                                              
                                                                              else if (sensorID == 1004) {
                                                                                //structure data for ID1004 - plant 2
                                                                                hygr1004 = data1;
                                                                                bat1004 = (float)data2 / 100;
                                                                              }
                                                                              
                                                                              else if (sensorID == 1005) {
                                                                                //structure data for ID1005 - reserved for future sensor
                                                                              }

                                                                              `

                                                                            • 0
                                                                              офф а где Гейгер установлен? Есть в мыслях поставить у входной двери чтобы контролировать самое грязное — дорожную пыль.
                                                                              • 0

                                                                                Счетчик Гейгера установлен в центре квартиры там где и база метеостанции. Идеально было бы его поставить за окно или на балкон, но в моем случае это нереализуемо. Думаю ставить его у входа в квартиру не имеет особого смысла если только кто-то из домашних не работает в шахтах и случайно может занести кусок урановой руды в ботинке.

                                                                                • 0
                                                                                  Тоже так думал до прочтения книги
                                                                                  Виноградов Ю.А. Ионизирующая радиация обнаружение, контроль, защита

                                                                                  Вероятность куда то вступить выше, вероятности найти это же на высоте Н-цатого этажа.
                                                                              • 0
                                                                                А протокол на основе MySensors или собственный?
                                                                                • 0

                                                                                  Ответил в предыдущем комментарии про передачу данных.

                                                                                • 0
                                                                                  Как долго живут датчики с автономным питанием? Можете привести схему беспроводного датчика — там используется nRF24L01 и Atmega328, правильно я понял?
                                                                                  • 0

                                                                                    Все правильно Аtmega328 + nRF24L01 + BME280 + фоторезистор + светодиод. Так же стоят пару электролитических конденсаторов на линиях питания. Схемы к сожалению не составлял, но там все предельно просто. CR2032 по моим подсчетам должно хватить на более года работы (в идеальных условиях) если передавать данные каждые 10 минут или 250 дней если передавать данные каждые 5 минут. Дальнобойность проверял в пределах 10 метров через стены — все работало. В спящем режиме такой набор потребляет порядка 6-7 микроампер (если верить дешевому китайскому мультиметру). Самая главная фишка, это подобрать адекватный модуль nRF24L01+ и правильно его настроить, так как даже из одной партии разные модули имеют разный ток потребления. По паспорту, там должно быть что-то около 2 микроампер. + 4 микроампер потребляет Atmega328 в глубоком сне. На данный момент беспроводной датчик уже проработал 4 месяца без замены батареи.

                                                                                • +1
                                                                                  Добавьте в статью, пожалуйста, схему устройства.
                                                                                • 0
                                                                                  Как-то оборвано предложение
                                                                                  Cперва оно попытается подключиться к сохраненной ранее сети и успешно выполнив
                                                                                  • 0
                                                                                    Спасибо, поправил. В следующий раз лучше в личку.
                                                                                • +1
                                                                                  Круто, запишу идеи. А я всё никак не соберусь доделать похожую штуку, но на своей плате и с AVR. И с MQ-135 для углекислого газа.
                                                                                  • НЛО прилетело и опубликовало эту надпись здесь
                                                                                    • 0
                                                                                      Можно, но без Blynk. С blynk тоже можно, но с промежуточным сервером. В этом случае и статичный IP не нужен.
                                                                                      • 0
                                                                                        Посмотрите https://wifi-iot.com, там очень широкий функционал, код писать не нужно.
                                                                                        Если на роутере есть рут, можно попробовать телеграм-бот поднять и без белого ip, но для этого вероятно надо будет писать код.

                                                                                        • 0

                                                                                          Можете посмотреть в сторону narodmon но не знаю как у них с удаленным управлением.

                                                                                        • 0
                                                                                          А CO эта штука может измерять?
                                                                                          • 0

                                                                                            Эта нет, для CO есть недорогой (~$1.3) датчик MQ-7. Он имеет массу недостатков, но задачу решать должен. Он был упомянут в статье на гиктаймс

                                                                                            • 0
                                                                                              Благодрю! CO намертво связывает гемоглобин до его утилизации в селезенке, это может произойти и через 2-3 месяца. Так-что если что и мониторить в первую очередь, так это СО. Т.е. человек может иметь высокий гемоглобин, и, при этом, страдать от гипоксии, причем ущерб получают все органы и системы при недостатке кислорода идут сложные цепные реакции, некоторые потом весьма труднообратимые.
                                                                                              • +1

                                                                                                Да, но СО имеет смысл мониторить только там, где может быть его повышенная концентрация, в гаражах, в квартирах — если есть газовый водогрей или газовая плита. В отсутствии возможных продуктов горения, смысла в мониторинге особо нет. СО2 же есть везде, и при высоких концентрациях продуктивность и комфорт может сильно падать

                                                                                                • 0
                                                                                                  В малоэтажных домах частенько встречаются газовые плиты. Так же СО выделяется при курении, и даже при дыхании. Так-что его стоит мониторить и там, где есть сложности с вентиляцией на фоне повышенного скопления людей, например в душных офисах.
                                                                                                  • 0

                                                                                                    При курении — да. При дыхании нет. В душных офисах — нет, в них как раз стоит контролировать содержание CO2, которое легко может превысить 2000 ppm.

                                                                                                    • 0
                                                                                                      В организм окись углерода поступает через органы дыхания. Моноксид углерода способен соединяться с гемоглобином в 200 раз быстрее, чем кислород с образованием карбоксигемоглобина (HbCO). Период его полураспада — 4-6 часов. Расщепление карбоксигемоглобина на гемоглобин (Hb) и монооксид углерода (CO) происходит в 10 000 раз медленнее, чем расщепление оксигемоглобина на Hb и O2. Поэтому при наличии во вдыхаемом воздухе CO кислород постепенно вытесняется из гемоглобина. Уже при концентрации 0,1% CO в воздухе больше половины гемоглобина крови превращается в карбоксигемоглобин; в результате нарушается перенос кислорода от лёгких к тканям и развивается так называемое угарное отравление. Карбоксигемоглобин не способен переносить кислород к тканям организма, поэтому при отравлении окисью углерода у человека может быстро наступить смерть. Хроническая экспозиция низких концентраций СО может привести к возникновению таких симптомов, как головная боль, усталость, головокружение, ощущение биения сердца, боли в груди, тошнота, рвота и абдоминальные боли.



                                                                                                      Результаты исследования уровня монооксида углерода в выдыхаемом воздухе.

                                                                                                      Исследование взрослых не курящих лиц показало, что концентрация СО у них определялась в интервале от 0 до 1 ррm. У эпизодически курящих лиц в возрасте от 25 до 62 лет концентрация монооксида углерода определялась от 0 до 3 ррm. У лиц, выкуривающих более 10 сигарет в день концентрация СО определялась от 16 до 21 ррm.

                                                                                                      Так, у лиц, выкуривающих в день более 12 сигарет в день, по сравнению с теми, кто выкуривал до 5 сигарет в день, наблюдалось резкое повышение уровня СО. Связано это, по-видимому, с тем, что в организме курильщика накапливается монооксид углерода в бронхолегочной системе, который не успевает вывестись, поскольку при интенсивном курении (более 10 сигарет в день) курильщик, как правило, курит каждые 1-2 часа в день, а период полураспада карбоксигемоглобина составляет 4-6 часов, что и обусловливает высокое содержание СО в организме.



                                                                                                      Так как концентрация угарного газа в бронхах и легких повышается при длительных поездках на велосипеде по автострадах, нахождении в задымленном помещение, при чрезмерном вдыхании выхлопных газов и т. п.



                                                                                                      Источник: http://www.hintfox.com/article/soderzhanie-ygarnogo-gaza-v-vidihaemom-vozdyhe-kak-indikator-tabakokyrenija-podrostkov.html

                                                                                                      В общем не совсем понятна эта история, но я так думаю что если в душном офисе соберутся активные курильщики, а это не редкость, то накочегарят они там что мама не горюй…
                                                                                                      • 0
                                                                                                        Ну и вот до кучи, не знаю насколько достоверно, но задуматься заставит http://zdravclub.ru/news/162-prebyvanie-v-neprovetrivaemom-pomeshhenii.html
                                                                                          • 0
                                                                                            Есть ещё вроде модуль mg-811 пример (https://ru.aliexpress.com/cp/mg811-co2-sensor-online-shopping.html) его можно использовать!?
                                                                                            • 0

                                                                                              Можно, но mg-811 менее точный, с худшей избирательностью, большим энергопотреблением и дороже.

                                                                                            • 0
                                                                                              По вебке — любую бесплатную вебку можно подлючить через вебхуки в Blynk. На локальном сервере можно даже убрать лимит в 1 вебхук в секунду на 1 пин (если надо чаще).
                                                                                              • 0

                                                                                                А что такое "вебка" в данном контексте?

                                                                                                • +1
                                                                                                  Веб интерфейс.
                                                                                                  • 0
                                                                                                    При чем работает в обе стороны. Можно слать из блинка в вебку и можно из вебки слдать в блинк (в апку и в железо)
                                                                                                • +1
                                                                                                  Спасибо за публикацию. «Заразно» это все наверное, вот прототип подобной конструкции. В качестве анализатора воздуха мечтаю использовать MQ-135.
                                                                                                  image
                                                                                                  • 0

                                                                                                    Китайская Itead Studio делает вот такую штуку за $20:
                                                                                                    image


                                                                                                    Как всегда у Itead, устройство очень хакабельно, open hardware и open software, и тов. Tinkerman написал прошивку, которая отдаёт данные через MQTT на вашу любимую систему мониторинга или автоматизации. Он же обнаружил пару свободных GPIO, так что можно подключить MH-Z19 или экранчик.

                                                                                                    • 0
                                                                                                      Собрал прибор, очень интересный концепт с platformio и blynk. Только вот приложение для blinky из статьи дороговатое (много всяких графиков), требует 2 бакса. Стоило, наверное, специально для статьи сделать вариант попроще, чтоб уложиться в 2000 бесплатных баллов. Автору большое спасибо!

                                                                                                      kumekay подскажите пожалуйста, нет ли проблемы с выгоранием дисплея при работе 24х7? Может стоит сделать режим снижения яркости\выключение?

                                                                                                      ps: я использовал стандартный корпус для поделок с ebay, получилось довольно компакнтно и бюджетно…
                                                                                                      image
                                                                                                      • 0

                                                                                                        Рад, что статья оказалась полезной.
                                                                                                        Для блинк-а я использую свой сервер, развернутый при помощи https://github.com/kumekay/blynk-server,
                                                                                                        поэтому даже не задумывался о ресурсах.
                                                                                                        К слову можно развернуть его на scaleway.com за 2.99 евро и не задумываться о потреблении.


                                                                                                        Что касается времени жизни дисплея, то пока никаких проблем нет, с другой стороны сенсор включен у меня далеко не постоянно. Я довольно много где использую подобные дисплеи, но везде они отображают не постоянно, поэтому даже спустя полтора года сложно сказать. Может проблема и не так серьезна.


                                                                                                        К слову, компоновка как у меня в статье (и как у вас) не очень удачная, тепло от esp8266 может искажать показания датчика.

                                                                                                        • 0
                                                                                                          Плюсую. Сначала попробовал отсканировать куаркод, не хватило токенов. Чуть подофигел от такой наглости)) Пришлось разбираться с Блинком по хелпу и настраивать самому)) благо дружелюбная штука получилась. Токенов хватает на 1 виджет точно. Дальше нужно спонсировать.

                                                                                                        • 0
                                                                                                          «Недостаток такой плотной компановки в том, что тепло от микроконтроллера и dc-dc преобразователя нагревают воздух внутри на ~3 градуса выше реальной температуры»
                                                                                                          — Что мешает сделать разъём, для подключения внешних первичников (датчиков)?
                                                                                                          Это, заодно, и позволит использовать девайс не только как измеритель
                                                                                                          параметров среды (внутри устройства),
                                                                                                          но и замерить где-либо ещё (например, за окном).

                                                                                                          «но провода внутри все равно занимают большую часть места»
                                                                                                          — Их не обязательно брать такими толстыми. Это-же не силовая схема.

                                                                                                          Спасибо за эту публикацию.
                                                                                                          • +1
                                                                                                            Все клево, но код не рабочий. Какие-то траблы с подключением к блинку.

                                                                                                            Экранчик работает, все ок!

                                                                                                            Переделал под себя по быстрому — подключение к блинк-серверу по хелпу, все остальное функциями из кода выше.

                                                                                                            Еще раз спасибо! Теперь я подключу таки в умный дом датчики со2!!!

                                                                                                            ПЫСЫ И да, напиши что блин таки платный. Считывание куар кода стоит конкретно денег. Я зажмотился и разобрался за вечерок во всем, но не все поймут прикол же.

                                                                                                            ПЫПЫСЫ Что там за сайт с которого должна ообновляться прошивка? Лежит мертвый.

                                                                                                            ПЫПЫПЫСЫ Я так и не смог понять как работает PlatformIO, но я не прораммист, это так, хобби. Все зашил через ардуину, не все библиотеки есть по умолчанию в ардуино иде, написал бы как-что ставить.
                                                                                                            image
                                                                                                            Короче, материал огонь! Но новички сломают ноги. А людям вроде меня было по кайфу собрать датчик углекислого газа в дополнение к умному дому))
                                                                                                            • 0

                                                                                                              да, тоже реализовал проект вот сейчсас и обнаружил все это. Блунк содрал четыре доллара и неясно как там эту прилагу настраивать. Ардуина ИДЕ рулит.
                                                                                                              Кстати на гитхабе автора форк для другого датчика плохо работает с поднятием точки доступа, если одна сетка уже зашита. Не поднимает. Ну, может, это из за того, что у меня почему-то работает со2 и не работают другие датчики.

                                                                                                              • 0
                                                                                                                настроить блинк на смарте просто — начни с уроков блинка, я вьехал через пару часов))

                                                                                                                по повод остального — я хз. если что-то не работает — сделай сам)) я взял части кода и сваял под себя, использовал части из помощи блинка. все заработало, все ок. правда сетку вайфай зашил намертво, все лишнее поубирал.

                                                                                                                хватило бесплатного блинка))) но у меня темпер и влажность уже измеряются, мне только со2 нужен.
                                                                                                                • 0

                                                                                                                  А я за 10 мин вписал thingSpeak туда. мне особо не надо на телефоне. Да, блинк приятнее, но тут быстрее. )

                                                                                                            • 0

                                                                                                              Вопрос дилетанта, если пока едет из Китая датчик температуры, давления и экранчик, можно подключить только esp и датчик со2, (уже прикупил) и мониторить через андроид?

                                                                                                              • 0

                                                                                                                Можно, но может нужно будет что-нибудь в коде поправить.
                                                                                                                Если что, справишайте в issues на гитхабе: https://github.com/kumekay/kuhomon

                                                                                                                • 0

                                                                                                                  image


                                                                                                                  И попробуйте вот этот qr код проекта, он должен влезать в бесплатный лимит на blynk — если нет напишите, я еще подрежу что-нибудь

                                                                                                                  • 0
                                                                                                                    Ок, благодарю, потестю в ближайшее время

                                                                                                                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.