Select your language

Miks on vahel halb uni, kas liialt umbne ruum või kõrge temperatuur, otsime vastuseid. 
Kui CO2 (süsihappegaasi) sisaldus õhus on kõrge siis ei ole hea olla.
Mõõtühik ppm - miljondikosa (tähis ppm, ingliskeelsest fraasist parts per million) on ühik, mis väljendab arvulist suhet üks miljondik tervikust.
* 250-400ppm Normaalne taustkontsentratsioon välisõhus
* 400–1000 ppm hea õhuvahetusega hõivatud siseruumidele omased kontsentratsioonid
* 1000–2000 ppm Kaebused unisuse ja halva õhu kohta.
* 2000–5000 ppm Peavalud, unisus ja seisak, seisnud, kinnine õhk. Samuti võib esineda halb kontsentratsioon, tähelepanu kaotus, südame löögisageduse suurenemine ja kerge iiveldus.
* 5000 kokkupuute piirmäär töökohal (8-tunnise TWA-na) enamikus jurisdiktsioonides.
* > 40 000 ppm Kokkupuude võib põhjustada tõsist hapnikuvaegust, mille tagajärjeks on püsivad ajukahjustused, kooma ja isegi surm​

Piisavalt usaldusväärne (ja hinnalt mitte tappev) andur mis suudab suhelda mõne ESP kontrolleriga on MZ-H19B.
Info edastamiseks kasutasin juba tuttavat Wemos D1 mini millel on kõik vajalik (ja ülearugi) olemas.
Wemos Vin 5V    -> MZH19B +
Wemos Vin GND -> MZH19B -
Wemos Vin GPI12 -> MZH19B RX
Wemos Vin GND13 -> MZH19B TX

(proovisin ka PWN -i aga ei saanud kohe käima ning hiljem ei viitsinud kah)

Samuti pookisin külge temperatuure mõõtmiseks Dalllas 18B20 anduri ning konstruktsiooniliselt viisin selle törts kaugemale, et Wemose töötemperatuur ei mõjutaks nõnna palju lugemit.
(MZ-H19B annab väljundis ka temperatuuri (ilma kümnendik kohata) kuid pelgasin taas, et Wemos paiknemine samas kestas hakkab tulemit väänama).

Kogu Wemose väljapritsitud info korjab kokku Raspberry PI (MQTT -> Node Red) ja saadab  Blynk-i vahendusel telefoni milleses on juba mõnus SuperChart widget-i vaadata CO2 / T taseme graafikuid. 
Et süsteem ei jääks pelgalt vaatlemise tasemele käivitab Raspberry (Node Red -> MQTT -> ESP01/Relee (või SONOFF)) ventilaatori (sõltuvalt CO2 ja/või temperatuuri) tasemest ruumis.

// Wemos Mini D1 <-> MH-Z19B
//               <-> D18B20
// Client = "MHZ19B";
// 

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <SoftwareSerial.h>
SoftwareSerial co2Serial(12, 13); // define MH-Z19 RX TX
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 4 // gpiO4
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

bool ps = false;            // ps=client.publish()
int i = 0;
int timerv = 1;             // read/publish timer
uint32_t tim;               // timer

const char* ssid = "xxx";
const char* password = "passw";
const char* mqtt_server = "xxx.xxx.xxx.xxx";

const char* idr = "MHZ19B";
const char* idv = "MHZ19B.v";
const char* idq = "timerq";
const char* idv1 = "MHZ19BT.v";
const char* idv2 = "D18B20.v";
WiFiClient MHZ19B;
PubSubClient client(MHZ19B);

void setup_wifi() {
  delay(10);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.hostname(idr);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("WiFi connected - ESP IP address: ");
  Serial.println(WiFi.localIP());
  Serial.print(F("Hostname: "));
  Serial.println(WiFi.hostname());
}

void reconnect() {
  while (!client.connected()) {
    if (client.connect("MHZ19B")) {
      client.subscribe("vent/timer");
    } else {
      delay(5000);
    }
  }
}

void setup() {
  Serial.begin(9600);
  co2Serial.begin(9600);
  sensors.begin();
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  //pinMode(Sensor, INPUT);
  Serial.println("Preheat start 3 min.");
  delay(3 * 60 * 1000); // sensor preheating 3 min
  Serial.println("GO ...");
  uhenda();
  do { // küsi timerit
    ps = client.publish(idq, String(1).c_str());
  } while (!ps);
}

void callback(String topic, byte* message, unsigned int length) {
  String msg;
  for (int i = 0; i < length; i++) {
    msg += (char)message[i];
  }

  if (topic == "vent/timer") {
    timerv = msg.toInt();
    do {
      ps = client.publish("vent/timer.v", String(timerv).c_str());
    } while (!ps);
  }
}

int readCO2UART() {

  int ppm_uart = 0;
  char cmd[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
  char response[9]; // for answer
  //Serial.println("Sending CO2 request...");
  co2Serial.write(cmd, 9); //request PPM CO2

  // clear the buffer
  memset(response, 0, 9);
  int i = 0;
  while (co2Serial.available() == 0) {
    delay(1000);
    i++;
  }
  if (co2Serial.available() > 0) {
    co2Serial.readBytes(response, 9);
  }
  //print out the response in hexa
  for (int i = 0; i < 9; i++) {
    //Serial.print(String(response[i], HEX));
    //Serial.print("   ");
  }
  //Serial.println("");

  // checksum
  char check = getCheckSum(response);
  if (response[8] != check) {
    //Serial.println("Checksum error");
    //Serial.print("Received: ");
    //Serial.println(response[8]);
    //Serial.print("Should be: ");
    //Serial.println(check);
  } else {
    byte status = response[5];
    if (status != 0) {
      //Serial.println("Status error");
    } else {
      // ppm
      ppm_uart = 256 * (int)response[2] + response[3];
      //Serial.print("********* CO2: ");
      //Serial.println(ppm_uart);
      return ppm_uart;
      // temp
      //byte temp1_uart = response[4]    - 40;
      //Serial.print("Temp ");
      //Serial.println(temp1_uart);
      //return temp1_uart;
    }
  }
}

byte getCheckSum(char *packet) {
  byte i;
  unsigned char checksum = 0;
  for (i = 1; i < 8; i++) {
    checksum += packet[i];
  }
  checksum = 0xff - checksum;
  checksum += 1;
  return checksum;
}

float dallas_temp () {
  sensors.requestTemperatures();
  delay(100);
  float temp2 = sensors.getTempCByIndex(0);
  //Serial.print("********* Dallas Temp: ");
  //Serial.println(temp2);
  return temp2;
}

void uhenda () {
  if (!client.connected()) {
    reconnect();
  }
  if (!client.loop())
    client.connect("MHZ19B");
}

void loop() {
  uhenda();

  if ((millis() > tim) ) {
    tim = millis() + timerv * 60 * 1000;

    //Serial.println("Start ppm");
    int ppm = readCO2UART();
    do {
      ps = client.publish(idv, String(ppm).c_str());
    } while (!ps);
    
    //Serial.println("Start temp");
    float temp = dallas_temp();
    do {
      ps = client.publish(idv2, String(temp).c_str());
    } while (!ps);
  }
}

äima ning hiljem ei viitsinud kah)

Samuti pookisin külge temperatuure mõõtmiseks Dalllas 18B20 anduri nin konstruktsiooniliselt viisin selle törts kaugemale, et Wemose töötemperatuur ei mõjutaks nõnna palju lugemit.
(MZ-H19B annab väljundis ka temperatuuri (ilma kümnendik kohata) kuid pelgasin taas, et Wemos paiknemine samas kestas hakkab tulemit väänama).

Kogu Wemose väljapritsitud info korjab kokku Raspberry PI (MQTT -> Node Red) ja saadab  Blynk-i vahendusel telefoni milleses on juba mõnus SuperChart widget-i vaadata CO2 taseme graafikut.