Автоматическое проветривание помещений на Arduino UNO MH-Z19B и DHT11. Контроль уровня CO2 и влажности.

Здравствуйте!

Поступил заказ изготовить прибор, для контроля уровня углекислого газа (CO2) в четырех помещениях, а также контроля уровня влажности в одном помещении (в ванной). Чтобы была возможность получать данные о содержании углекислого газа со всех датчиков MH-Z19B, и возможность принудительного включения проветривания.

Рабочая модель без подключенных вентиляторов, представлена на фото которое ниже.

Контроль уровня углекислого газа (CO2) на Arduino UNO MH-Z19B, а также влажности при помощи DHT11

В данном проекте используется:

Плата Arduino Uno

4 датчика MH-Z19B

4 сервомотора

Двухканальный модуль с твердотельными реле G3MB-202P

Bluetooth модуль HC-06, но можно и HC-05

Датчик влажности и температуры DHT11

Провода разъемы и кусок платы, к которой все припаял

Ниже представлен код проекта. Как он работает я рассказывал в видео, ссылку на которое найдете в конце этой статьи.

Данный проект можем работать самостоятельно, то есть без использования Bluetooth модуля HC-06 и Android устройства. Но если проветривание будет слишком частым, то в 47 строке кода можете повысить лимиты для срабатывания по датчикам.

Строка выглядит следующим образом limit_1s = 800, limit_2s = 800, limit_3s = 800, limit_4s = 800; .

На пример переменная limit_1s равна 800, значение 800 это и есть предел для срабатывания по первому датчику.



Можете скопировать, и загрузить этот код на плату Arduino.


//Начало скетча

#include "EEPROM.h"
#include "Servo.h"
#include "SimpleDHT.h"
#define DHT_Sensor 6    //контакт для подключения датчика DHT11
SimpleDHT11 dht11(DHT_Sensor);
int temperature_ = 0, humidity_ = 0;

Servo myservo_1;
Servo myservo_2;
Servo myservo_3;
Servo myservo_4;

//контакты к которым подключены сервомоторы
#define servo_1 2
#define servo_2 3
#define servo_3 4
#define servo_4 5

//значения углов в открытом и закрытом состоянии
#define angle_open_1 90
#define angle_close_1 0

#define angle_open_2 90
#define angle_close_2 0

#define angle_open_3 90
#define angle_close_3 0

#define angle_open_4 90
#define angle_close_4 0

boolean flag_1 = 0, flag_2 = 0, flag_3 = 0, flag_4 = 0, flag_1p = 0, flag_2p = 0, flag_3p = 0, flag_4p = 0;
boolean flags_1234 = 0, flags_1234p = 0;

#define kuller_general 18  //подписан на плате как A4
#define kuller_bathroom 19 //подписан на плате как A5

int time_ = 5; //периодичность опроса датчиков в секундах (оптимально от 5 до 120 секунд)
int SensorPins[4][4] = { 
            {A0, A1, A2, A3}, //A0, A1, A2, A3 контакты для подключения датчиков MH-Z19B
            { 0,  0,  0,  0},
            { 0,  0,  0,  0},
            { 0,  0,  0,  0},
            };

String sost1, sost2, sost3, sost4, vannaya;
int limit_1, limit_2, limit_3, limit_4, limit_1s = 800, limit_2s = 800, limit_3s = 800, limit_4s = 800;
int addres_0 = 23, addres_1 = 25, addres_2 = 28, addres_3 = 30, addres_4 = 32, flag_start = 4, flag_st;
int count = 0, scan_count = 1, ppm_BUF = 0, result = 0, while_count = 0;
long ppm, timing1 = 0;

void setup() {
  Serial.begin(9600);
  //чтение из энергонезависимой памяти
  EEPROM.get(addres_0, flag_st);
  
  //однократная запись первоначальных настроек при первом запуске после прошивки
  if (flag_st != flag_start){
    EEPROM.put(addres_0, flag_start);
    EEPROM.put(addres_1, limit_1s);
    EEPROM.put(addres_2, limit_2s);
    EEPROM.put(addres_3, limit_3s);
    EEPROM.put(addres_4, limit_4s);
  }
  //чтение из энергонезависимой памяти
  EEPROM.get(addres_1, limit_1); 
  EEPROM.get(addres_2, limit_2);
  EEPROM.get(addres_3, limit_3);
  EEPROM.get(addres_4, limit_4);
  //подключение сервомоторов
  myservo_1.attach(servo_1);
  myservo_2.attach(servo_2);
  myservo_3.attach(servo_3);
  myservo_4.attach(servo_4);
  //установка валов сервомоторов в закрытое состояние заслонок
  myservo_1.write(angle_close_1);
  myservo_2.write(angle_close_2);
  myservo_3.write(angle_close_3);
  myservo_4.write(angle_close_4);

  pinMode(kuller_general, OUTPUT); digitalWrite(kuller_general, HIGH);
  pinMode(kuller_bathroom, OUTPUT); digitalWrite(kuller_bathroom, HIGH);
}    

void loop() {
 //------- Проверка концентрации CO2 по 4 датчикам MH-Z19B  ---------
 
  if (millis() - timing1 > time_ * 1000){ 
    timing1 = millis();

    while(while_count < 20){
      int Val = analogRead(SensorPins[0][count]);
      ppm = map(Val, 18, 650, 650, 2000); 
      
      if(scan_count > 1 && (ppm > ppm_BUF - 8 && ppm < ppm_BUF + 8)){
        ppm_BUF = ppm; SensorPins[scan_count][count] = ppm;
        scan_count++;
        if(scan_count > 3){
    
          scan_count = 1; count++; if(count > 3){ count = 0;}
        }
      }else{  scan_count = 1;}
    
      if(scan_count == 1){  SensorPins[scan_count][count] = ppm; ppm_BUF = ppm; 
        scan_count++;
      }
      while_count++;
    }
    while_count = 0;

   //------------- Проверка влажности по датчику DHT11 ----------------
      byte temperature = 0;
      byte humidity = 0;
      dht11.read(&temperature, &humidity, NULL);
      temperature_ = (int)temperature; humidity_ = (int)humidity;
      if(humidity_ > 70){digitalWrite(kuller_bathroom, LOW);  vannaya = "    ON";
      }else{digitalWrite(kuller_bathroom, HIGH);              vannaya = "    OFF";}
  }//millis() - timing1 > 5000

   //------------- Настройка лимитов для датчика MH-Z19B --------------- 

  if (Serial.available()) {
    char c = Serial.read();
    if (c == 'A') {
      limit_1 += 5; EEPROM.put(addres_1, limit_1);
      Serial.print(F("Gostinaya +5    LIMIT = ")); Serial.println(limit_1); 
    } 
    if (c == 'a') {
      limit_1 -= 5; EEPROM.put(addres_1, limit_1);
      Serial.print(F("Gostinaya -5    LIMIT = ")); Serial.println(limit_1);
    }
    if (c == 'B') {
      limit_2 += 5; EEPROM.put(addres_2, limit_2);
      Serial.print(F("Detskaya +5     LIMIT = ")); Serial.println(limit_2);
    } 
    if (c == 'b') {
      limit_2 -= 5; EEPROM.put(addres_2, limit_2);
      Serial.print(F("Detskaya -5     LIMIT = ")); Serial.println(limit_2);
    }
    if (c == 'C') {
      limit_3 += 5; EEPROM.put(addres_3, limit_3);
      Serial.print(F("Spalnya +5      LIMIT = ")); Serial.println(limit_3);
    } 
    if (c == 'c') {
      limit_3 -= 5; EEPROM.put(addres_3, limit_3);
      Serial.print(F("Spalnya -5      LIMIT = ")); Serial.println(limit_3);
    }       
    if (c == 'D') {
      limit_4 += 5; EEPROM.put(addres_4, limit_4);
      Serial.print(F("Kabinet +5      LIMIT = ")); Serial.println(limit_4);
    } 
    if (c == 'd') {
      limit_4 -= 5; EEPROM.put(addres_4, limit_4);
      Serial.print(F("Kabinet -5      LIMIT = ")); Serial.println(limit_4);
    }

 //------ Запрос данных состояния датчиков MH-Z19B, DHT11 и лимитов -----

    if (c == 'E') {
      Serial.print(F("Gostinaya  = ")); Serial.print(SensorPins[3][0]);
      Serial.print(F("   LIMIT = "));   Serial.print(limit_1);
      Serial.print(F("    "));          Serial.println(sost1);
      
      Serial.print(F("Detskaya   = ")); Serial.print(SensorPins[3][1]);
      Serial.print(F("   LIMIT = "));   Serial.print(limit_2);
      Serial.print(F("    "));          Serial.println(sost2);
      
      Serial.print(F("Spalnya    = ")); Serial.print(SensorPins[3][2]);
      Serial.print(F("   LIMIT = "));   Serial.print(limit_3);
      Serial.print(F("    "));          Serial.println(sost3);
      
      Serial.print(F("Kabinet    = ")); Serial.print(SensorPins[3][3]);
      Serial.print(F("   LIMIT = "));   Serial.print(limit_4);
      Serial.print(F("    "));          Serial.println(sost4);

      Serial.print(F("Temperatura= ")); Serial.print(temperature_); Serial.println(F("*C"));
      Serial.print(F("Vlagnoct   = ")); Serial.print(humidity_);    Serial.print(F("%"));
      Serial.println(vannaya);
    }
    
    //------- Принудительное управление сервомоторами и сентилятором -------
 
    if (c == 'F') {Serial.println(F("Gostinaya ON"));  flag_1p = 1;} 
    if (c == 'f') {Serial.println(F("Gostinaya OFF")); flag_1p = 0;}               
    if (c == 'G') {Serial.println(F("Detskaya ON"));   flag_2p = 1;} 
    if (c == 'g') {Serial.println(F("Detskaya OFF"));  flag_2p = 0;}
    if (c == 'H') {Serial.println(F("Spalnya ON"));    flag_3p = 1;} 
    if (c == 'h') {Serial.println(F("Spalnya OFF"));   flag_3p = 0;}
    if (c == 'I') {Serial.println(F("Kabinet ON"));    flag_4p = 1;} 
    if (c == 'i') {Serial.println(F("Kabinet OFF"));   flag_4p = 0;}
    
  }//Serial.available

  //------ алгоритмы для автоматической работы по датчикам MH-Z19B ------- 

  if(SensorPins[3][0] > limit_1 + 5){flag_1 = 1;}
  if(SensorPins[3][0] < limit_1 - 5){flag_1 = 0;}
  if(SensorPins[3][1] > limit_2 + 5){flag_2 = 1;}
  if(SensorPins[3][1] < limit_2 - 5){flag_2 = 0;}
  if(SensorPins[3][2] > limit_3 + 5){flag_3 = 1;}
  if(SensorPins[3][2] < limit_3 - 5){flag_3 = 0;}
  if(SensorPins[3][3] > limit_4 + 5){flag_4 = 1;}
  if(SensorPins[3][3] < limit_4 - 5){flag_4 = 0;}
    
  //------------- алгоритмы для включения сервомоторов -------------

  if(flag_1 == 1 || flag_1p == 1){myservo_1.write(angle_open_1); sost1 = "ON";}
    else{myservo_1.write(angle_close_1); sost1 = "OFF";}

  if(flag_2 == 1 || flag_2p == 1){myservo_2.write(angle_open_2); sost2 = "ON";}
    else{myservo_2.write(angle_close_2); sost2 = "OFF";}

  if(flag_3 == 1 || flag_3p == 1){myservo_3.write(angle_open_3); sost3 = "ON";}
    else{myservo_3.write(angle_close_3); sost3 = "OFF";}

  if(flag_4 == 1 || flag_4p == 1){myservo_4.write(angle_open_4); sost4 = "ON";}
    else{myservo_4.write(angle_close_4); sost4 = "OFF";}

  //------------- алгоритмы для включения общего вентилятора -------------

  if (flag_1 == 1 || flag_2 == 1 || flag_3 == 1 || flag_4 == 1){
    flags_1234 = 1;}else{flags_1234 = 0;}
  
  if (flag_1p == 1 || flag_2p == 1 || flag_3p == 1 || flag_4p == 1){
    flags_1234p = 1;}else{flags_1234p = 0;}

  if (flags_1234 == 1 || flags_1234p == 1){
    digitalWrite(kuller_general, LOW);
    }else{ digitalWrite(kuller_general, HIGH);}
   
}//void loop

//Конец скетча




После загрузки скетча на плату Arduino, соберите все как показано на этой схеме

Схема для сборки контроллера углекислого газа (CO2) на Arduino UNO MH-Z19B и DHT11 с управлением по Bluetooth, при помощи Android устройства

После сборки убедитесь что все верно, и можно подключать питание.



Для управления прибором при помощи Android устройства необходимо настроить Bluetooth модуль HC-06, а также скачать и настроить приложение. Ссылка на информацию по данной теме появится здесь в ближайшее время!



Подробное видео “Автоматическое проветривание помещений на Arduino UNO MH-Z19B и DHT11. Контроль уровня CO2 и влажности.”


Автоматическое проветривание помещений на Arduino UNO MH-Z19B и DHT11. Контроль уровня CO2 и влажности.