Co2-Messung mit dem MH-Z19 und Anzeige auf dem 7735 TFT-Display 1,8 Zoll

7735 lcd displa mit mh-z21

Hier nun mal ein Sketch um die Werte live auf einem preiswerten TFT-Display anzuzeigen.

/*
  Arduino TFT text example

   http://www.arduino.cc/en/Tutorial/TFTDisplayText

 */

#include <TFT.h>  // Arduino LCD library
#include <SPI.h>

// pin definition for the Uno
#define cs   10
#define dc   9
#define rst  8

// pin definition for the Leonardo
// #define cs   7
// #define dc   0
// #define rst  1

// create an instance of the library
TFT TFTscreen = TFT(cs, dc, rst);

// char array to print to the screen
char sensorPrintout[6];

void setup() {

  // Put this line at the beginning of every sketch that uses the GLCD:
  TFTscreen.begin();

  // clear the screen with a black background
  TFTscreen.background(0, 0, 0);

  // write the static text to the screen
  // set the font color to white
  TFTscreen.stroke(255, 255, 255);
  // set the font size
  TFTscreen.setTextSize(2);
  // write the text to the top left corner of the screen
  TFTscreen.text("Sensor Value :\n ", 0, 0);
  // ste the font size very large for the loop
  TFTscreen.setTextSize(5);

  #define AIQ_SENSOR_ANALOG_PIN 5
}
void loop() {
  //CO2
  
  unsigned long duration = pulseIn(AIQ_SENSOR_ANALOG_PIN, HIGH, 2000000);
  
  //Serial.print(duration/1000); Serial.println(" ms ");
  //from datasheet
  //CO2 ppm = 2000 * (Th - 2ms) / (Th + Tl - 4ms)
  //  given Tl + Th = 1004
  //        Tl = 1004 - Th
  //        = 2000 * (Th - 2ms) / (Th + 1004 - Th -4ms)
  //        = 2000 * (Th - 2ms) / 1000 = 2 * (Th - 2ms)
 
  long co2ppm = 5 * ((duration/1000) - 2);
  Serial.print(co2ppm);

 
String sensorVal = String(co2ppm);
 sensorVal.toCharArray(sensorPrintout, 6);
  TFTscreen.stroke(255,255,255);
  TFTscreen.text(sensorPrintout, 20, 50);

  delay(1000);
  TFTscreen.stroke(0,0,0);
  TFTscreen.text(sensorPrintout, 20, 50);
}

 

4SensorenSketch V0.13 mit dem MH-Z19 für die CO2-Messung

Hier nun die Fortsetzung meines alten 4 Sensoren Sketches. Nun ist der MH-Z19 für die CO2 Messung integriert und ich habe außerdem noch eine Steuerung für eine LED-Warnung eingebaut. Der Sketch funktioniert genau so mit dem MH-Z21.

//Sens4Sketch (Motion, Temperature, Humidity, CO2)

//v0.13 LED blink co2
//v0.12 MH-Z19 integration
//v0.11 Motion corrected
//v0.10 ---- installation co2 value specification outside----under construction
//v0.9 Autoset r0 off, vaule < 400 possible!!!!
//v0.8 Corr. Lib von rstoica (set r0, correction) impl
//v0.7 set r0 to eeprom
//v0.6 SetR0-Button
//v0.5 Motion
//v0.4 autosetr0 if co2<400
//v0.3 api 2.0, redesign
//v0.2 CorrectedRZero basis for calculating r0
//G. Krocker K.-H. Wind et. al. ++++JH
//Caution: The Sketch erorder an amended mq135.h Library

#define MY_DEBUG    // Enables debug messages in the serial log
#define MY_RADIO_NRF24
//#define MY_REPEATER_FEATURE  // Enables repeater functionality for a radio node
#include <SPI.h>
#include <MySensors.h>
#include "DHT.h"
//----------------------------------------------------------------------------
// Timer
unsigned long SLEEP_TIME = 30*1000; // Sleep time between reads (in milliseconds)
//-----------------------------------------------------------------------------
//MOTION
#define DIGITAL_INPUT_SENSOR 3   // The digital input you attached your motion sensor.  (Only 2 and 3 generates interrupt!)
#define INTERRUPT DIGITAL_INPUT_SENSOR-3 // Usually the interrupt = pin -2 (on uno/nano anyway)
#define CHILD_ID_MOTION 16   // Id of the sensor child
MyMessage msgMotion(CHILD_ID_MOTION, V_TRIPPED);
//-----------------------------------------------------------------------------
// DHT22
#define CHILD_ID_HUM 0
#define CHILD_ID_TEMP 1
#define DHTPIN 4     // what digital pin we're connected to
//#define DHTTYPE DHT11   // DHT 11
#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
//#define DHTTYPE DHT21   // DHT 21 (AM2301)
DHT dht(DHTPIN, DHTTYPE);
float lastTemp;
float lastHum;
boolean metric = true; 
MyMessage msgHum(CHILD_ID_HUM, V_HUM);
MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
//-------------------------------------------------------------------------
#define CHILD_ID_AIQ 0
#define AIQ_SENSOR_ANALOG_PIN 5
float valAIQ =0.0;
float lastAIQ =0.0;
MyMessage msg(CHILD_ID_AIQ, V_LEVEL);
MyMessage msg2(CHILD_ID_AIQ, V_UNIT_PREFIX);
//-----------------------------------------------------------------------------

void setup() {
//--------------------------------------------------------------------- 
 dht.begin();
pinMode(DIGITAL_INPUT_SENSOR, INPUT);
pinMode(7, OUTPUT);
}
//-----------------------------------------------------------------------------
void presentation(){
sendSketchInfo("Sens4", "v0.13");
present(CHILD_ID_TEMP, S_TEMP);
present(CHILD_ID_HUM, S_HUM);
present(CHILD_ID_MOTION, S_MOTION);
present(CHILD_ID_AIQ, S_AIR_QUALITY);  
//--------------------------------------------------------------------
}

void loop(){



//-----------------------------------------------------------------------------
//TEMP_FEUCHTE 
  float temperature = dht.readTemperature();
   send(msgTemp.set(temperature, 1));
    Serial.print("T: ");
    Serial.println(temperature);
 
  float humidity = dht.readHumidity();

      send(msgHum.set(humidity, 1));
      Serial.print("H: ");
      Serial.println(humidity);
//-----------------------------------------------------------------------------  
//CO2
  
  unsigned long duration = pulseIn(AIQ_SENSOR_ANALOG_PIN, HIGH, 2000000);
  
  //Serial.print(duration/1000); Serial.println(" ms ");
  //from datasheet
  //CO2 ppm = 2000 * (Th - 2ms) / (Th + Tl - 4ms)
  //  given Tl + Th = 1004
  //        Tl = 1004 - Th
  //        = 2000 * (Th - 2ms) / (Th + 1004 - Th -4ms)
  //        = 2000 * (Th - 2ms) / 1000 = 2 * (Th - 2ms)
 
  long co2ppm = 5 * ((duration/1000) - 2);
  Serial.print(co2ppm);

    send(msg.set(co2ppm,1));
 
if (co2ppm>1000){
    digitalWrite(7, HIGH);   // turn the LED on (HIGH is the voltage level)
}
if (co2ppm<550) {
    digitalWrite(7, LOW);
}

//-----------------------------------------------------------------------------
//Read digital motion value
boolean tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH;
 Serial.print("Motion: ");
Serial.println(tripped);
send(msgMotion.set(tripped?"1":"0"));  
//-----------------------------------------------------------------------------
wait(SLEEP_TIME);
}
//---------------------------------------------------------------------------

 

Multi (5) Sensor für smarthome Arduino FHEM MYSENSORS

5sens Modul

Einleitung

Heute veröffentliche ich die Version 0.11. des Sensor-Sketches. Änderung ist die Korrektur des Sketchteils für den Bewegungssensors.

 Sensoren

HC-SR501 (Motion)

DHT-22 (Temperature/Humidity)

MQ135 (Airquality)

MH-Z19 (CO2) –> demnächst

 

Entscheidung MQ135 / MH-Z19(14)

Die Entscheidung welcher CO2 Wert verwendet wird ist für den MH-Z14(19) gefallen. Dieser liefert deutlich plausiblere Werte. So ist  eine Übereinstimmung beider Kurven ist grob gegeben. Aber der MQ135 reagiert eben dennoch auf eine Menge andere Gase, so dass ich ihn vorerst weiter verwende und im Sketch belasse. Zukünftig teste ich mit dem MH-Z14 der bei Lieferung durch den MH-Z19 ersetzt und auf die Platine integriert wird.

 

//Sens4Sketch (Motion, Temperature, Humidity, CO2)

//v0.xx MH-Z19 integration
//v0.11 Motion corrected
//v0.10 ---- installation co2 value specification outside----under construction
//v0.9 Autoset r0 off, vaule < 400 possible!!!!
//v0.8 Corr. Lib von rstoica (set r0, correction) impl
//v0.7 set r0 to eeprom
//v0.6 SetR0-Button
//v0.5 Motion
//v0.4 autosetr0 if co2<400
//v0.3 api 2.0, redesign
//v0.2 CorrectedRZero basis for calculating r0
//G. Krocker K.-H. Wind et. al. ++++JH
//Caution: The Sketch erorder an amended mq135.h Library

//#define MY_DEBUG    // Enables debug messages in the serial log
#define MY_RADIO_NRF24
#define MY_REPEATER_FEATURE  // Enables repeater functionality for a radio node
#include <SPI.h>
#include <MySensors.h>
#include <DHT.h>
#include <MQ135.h>
//----------------------------------------------------------------------------
// Timer
unsigned long SLEEP_TIME = 30*1000; // Sleep time between reads (in milliseconds)
//-----------------------------------------------------------------------------
//MOTION
#define DIGITAL_INPUT_SENSOR 3   // The digital input you attached your motion sensor.  (Only 2 and 3 generates interrupt!)
#define INTERRUPT DIGITAL_INPUT_SENSOR-3 // Usually the interrupt = pin -2 (on uno/nano anyway)
#define CHILD_ID_MOTION 16   // Id of the sensor child
MyMessage msgMotion(CHILD_ID_MOTION, V_TRIPPED);
//-----------------------------------------------------------------------------
// DHT22
#define CHILD_ID_HUM 0
#define CHILD_ID_TEMP 1
#define HUMIDITY_SENSOR_DIGITAL_PIN 4
DHT dht;
float lastTemp;
float lastHum;
boolean metric = true; 
MyMessage msgHum(CHILD_ID_HUM, V_HUM);
MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
//-----------------------------------------------------------------------------
// MQ135
#define CHILD_ID_CO2C 24
#define CHILD_ID_CO2 25
#define CHILD_ID_R0C 26
#define CHILD_ID_R0 27
#define EEPROM_R0C 0
int C02;
int CO2C;
float R0;
float R0C;
float R02;
MQ135 gasSensor = MQ135(0);//PIN0 
MyMessage msgCO2C(CHILD_ID_CO2C, V_VAR1);
MyMessage msgCO2(CHILD_ID_CO2, V_VAR1);
MyMessage msgR0C(CHILD_ID_R0C, V_VAR1);
MyMessage msgR0(CHILD_ID_R0, V_VAR1);
//-----------------------------------------------------------------------------
void setup() {
//--------------------------------------------------------------------- 
 //R0C aus EEPROM sonst 55
dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN);
pinMode(DIGITAL_INPUT_SENSOR, INPUT);
uint8_t R02 = loadState(EEPROM_R0C);
// get R0C from EEPROM
float R0C = R02 * 2;
if (R0C > 1.0 && R0C < 500.0)
{
Serial.print(F("Setting R0 from EEPROM: "));
}
else
{
Serial.print(F("Setting default R0C: "));
R0C = 50;
}
Serial.print(R0C);
Serial.println(F(""));
gasSensor.setRZero(R0C);
}
//-----------------------------------------------------------------------------
void presentation(){
sendSketchInfo("Sens4", "v0.7");
present(CHILD_ID_TEMP, S_TEMP);
present(CHILD_ID_HUM, S_HUM);
present(CHILD_ID_CO2C, S_CUSTOM);
present(CHILD_ID_CO2, S_CUSTOM);
present(CHILD_ID_R0C, S_CUSTOM);
present(CHILD_ID_R0, S_CUSTOM);
present(CHILD_ID_MOTION, S_MOTION);
}
//-----------------------------------------------------------------------------



void loop(){



//-----------------------------------------------------------------------------
//TEMP_FEUCHTE 

wait(dht.getMinimumSamplingPeriod());// TheoL
  float temperature = dht.getTemperature();
  if (isnan(temperature)) {
      Serial.println("Failed reading temperature from DHT");
  } else if (temperature != lastTemp) {
    lastTemp = temperature;
    if (!metric) {
      temperature = dht.toFahrenheit(temperature);
    }
   send(msgTemp.set(temperature, 1));
    Serial.print("T: ");
    Serial.println(temperature);
  }
  
  float humidity = dht.getHumidity();
  if (isnan(humidity)) {
      Serial.println("Failed reading humidity from DHT");
  } else if (humidity != lastHum) {
      lastHum = humidity;
      send(msgHum.set(humidity, 1));
      Serial.print("H: ");
      Serial.println(humidity);
  }
//-----------------------------------------------------------------------------  
//CO2
  float R0 = gasSensor.getRZero();
  float R0C = gasSensor.getCorrectedRZero(temperature, humidity);
  float CO2 = gasSensor.getPPM();
  float CO2C = gasSensor.getCorrectedPPM(temperature, humidity);
  
  Serial.print("R0: "); 
  Serial.println(R0);
  send(msgR0.set(R0,1));

  Serial.print("R0C: ");
  Serial.println(R0C);
  send(msgR0C.set(R0C,1));

  Serial.print("CO2: ");
  Serial.println(CO2);
  send(msgCO2.set(CO2,1));

  Serial.print("CO2C: ");
  Serial.println(CO2C);
  send(msgCO2C.set(CO2C,1));
  
  Serial.println();
//-----------------------------------------------------------------------------
//Read digital motion value
boolean tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH;
 Serial.print("Motion: ");
Serial.println(tripped);
send(msgMotion.set(tripped?"1":"0"));  
//-----------------------------------------------------------------------------
wait(SLEEP_TIME); //sleep/wait for: sleepTime // byTheo: Changed
}
//-----------------------------------------------------------------------------
//incomingMessage
void receive(const MyMessage& message){
 Serial.println(F("Incoming Message:"));

if (message.isAck())
{
Serial.println(F("This is an ack from gateway"));
}

uint8_t sensor = message.sensor;
if (sensor == CHILD_ID_R0C)
{
float R0C = message.getFloat();

Serial.print(F("Incoming R0C: "));
Serial.print(R0C);
Serial.println(F(""));

saveState(EEPROM_R0C, (uint8_t)(R0C/2));
gasSensor.setRZero(R0C);
send(msgR0.set(R0C, 2));
}
}
//-----------------------------------------------------------------------------

 

Gasverbrauch messen mit Arduino FHEM und MYSENSORS ohne Raspberry

Gaszähler mit Impulsgeber

Leider gibt es keine fertige Lösung obwohl es einfach scheint. Bisher habe ich nur Ergebnisse mit Firmata für Raspberry und Netzwerkschnittstelle gefunden. Das ist mir zu aufwändig. Es gibt für Arduino mysensors Sketche, die die Türkontakte (Reedkontakte) erkennen. Die Reedkontakte lassen sich am Zähler anbringen und reagieren auf den magnetischen Punkt am Zahlenrad. Das wäre der Hardware-Ansatz. Also muss ich mich bei Gelegenheit an die Software machen.

Smarthome Arduino MYSENSORS FHEM Sketch CO2 Bewegung Temperatur Feuchte

FHEM Abbildung Sensoren Feuchte Temp CO2 Bewegung

Allegmein

Der Sketch stammt von Karl-Heinz Wind und wurde von mir angepasst. Er enthält die Berechnung und Anzeige der Sensoren für CO2 (MQ135), Feuchte, Temperatur und Bewegung. Es wurden ausschließlich typische MYSENSORS-Bauteile verwendet. Sollten bestimmte Bibliotheken fehlen, kann ich die gerne noch bereitstellen.

 

Sketch

#include <SPI.h>
#include <MySensor.h>

#include <Wire.h>

#include <DHT.h>
#include <MQ135.h>

#include „Timer.h“

//—————————————————————————-
//unsigned long SLEEP_TIME = 10000; //Sleep time between reports (in milliseconds)
#define DIGITAL_INPUT_SENSOR 3   // The digital input you attached your motion sensor.  (Only 2 and 3 generates interrupt!)
#define INTERRUPT DIGITAL_INPUT_SENSOR-3 // Usually the interrupt = pin -2 (on uno/nano anyway)
#define CHILD_ID 1   // Id of the sensor child

//—————————————————————————–
// Timer
Timer timer;
#define TEMP_UPDATE_INTERVAL 30000

//—————————————————————————–
// DHT22
#define CHILD_ID_TEMP 2
#define CHILD_ID_HUM 3
#define HUMIDITY_SENSOR_DIGITAL_PIN 4

DHT dht;
float lastTemp;
float lastHum;
MyMessage msgHum(CHILD_ID_HUM, V_HUM);
MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);

//—————————————————————————–
// MQ135
#define CHILD_ID_CO2_CORRECTED 0
#define CHILD_ID_CO2 1
#define CHILD_ID_R0 4
#define CO2_SENSOR_ANALOG_PIN 0
#define CO2_SENSOR_BUFFER_SIZE 3

/// Calibration resistance at atmospheric CO2 level
// Buero 21Grad Regen
#define RZERO 300.0
#define EEPROM_R0 0

MQ135 gasSensor = MQ135(CO2_SENSOR_ANALOG_PIN, RZERO);
int lastC02;
int lastCO2Corrected;
float lastR0;

//RunningAverage lastCO2Values(CO2_SENSOR_BUFFER_SIZE);

//—————————————————————————–
// MySensor
MySensor gw;
MyMessage msgCO2Corrected(CHILD_ID_CO2_CORRECTED, V_VAR1);
MyMessage msgCO2(CHILD_ID_CO2, V_VAR1);
MyMessage msgR0(CHILD_ID_R0, V_VAR1);
MyMessage msg(CHILD_ID, V_TRIPPED);

//—————————————————————————–
void setup()
{
Serial.begin(115200);
dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN);

gw.begin(incomingMessage, AUTO, true);
gw.sendSketchInfo(„CO2 Sensor MQ-135“, „1.3“);
gw.present(CHILD_ID_CO2_CORRECTED, S_AIR_QUALITY);
gw.present(CHILD_ID_CO2, S_AIR_QUALITY);
gw.present(CHILD_ID_TEMP, S_TEMP);
gw.present(CHILD_ID_HUM, S_HUM);
gw.present(CHILD_ID_R0, S_CUSTOM);

gw.sendSketchInfo(„Motion Sensor“, „1.0“);
pinMode(DIGITAL_INPUT_SENSOR, INPUT);
gw.present(CHILD_ID, S_MOTION);

uint8_t R02 = gw.loadState(EEPROM_R0);

// get R0 from EEPROM
float R0 = R02 * 2;
if (R0 > 1.0 && R0 < 400.0)
{
Serial.print(F(„Setting R0 from EEPROM: „));
}
else
{
Serial.print(F(„Setting default R0: „));
R0 = RZERO;
}

Serial.print(R0);
Serial.println(F(„“));

gasSensor.setR0(R0);
//float ppm = gasSensor.getPPM();
//lastCO2Values.fillValue(ppm, CO2_SENSOR_BUFFER_SIZE);

//int tickEvent1 =
timer.every(TEMP_UPDATE_INTERVAL, timerHandler);

}

bool DHT22Changed(bool waitMinimumSamplingPeriod = true)
{
bool changed = false;

if (waitMinimumSamplingPeriod)
{
delay(dht.getMinimumSamplingPeriod());
}

float temperature = dht.getTemperature();
if (isnan(temperature))
{
Serial.println(F(„Failed reading temperature from DHT“));
}
else if (temperature != lastTemp)
{
lastTemp = temperature;
Serial.print(„T: „);
Serial.println(temperature);
changed = true;
}

float humidity = dht.getHumidity();
if (isnan(humidity))
{
Serial.println(F(„Failed reading humidity from DHT“));
}
else if (humidity != lastHum)
{
lastHum = humidity;
Serial.print(F(„H: „));
Serial.println(humidity);
changed = true;
}

return changed;
}

bool MQ135Changed(float t, float h)
{
bool changed = false;

lastR0 = gasSensor.getRZero();
Serial.print(F(„R0: „));
Serial.println(lastR0);

{
float ppm = gasSensor.getPPM();

Serial.print(F(„CO2 ppm: „));
Serial.print(ppm);

//lastCO2Values.addValue(ppm);
//ppm = lastCO2Values.getAverage();

//Serial.print(“ average: „);
//Serial.print(ppm);

int roundedPpm = (int)ppm;
Serial.print(F(“ –> „));
Serial.println(roundedPpm);

if (roundedPpm != lastC02)
{
lastC02 = roundedPpm;
changed = true;
}
}

{
float ppm = gasSensor.getCorrectedPPM(t, h);

Serial.print(F(„CO2 corrected ppm: „));
Serial.print(ppm);

int roundedPpm = (int)ppm;
Serial.print(F(“ –> „));
Serial.println(roundedPpm);

if (roundedPpm != lastCO2Corrected)
{
lastCO2Corrected = roundedPpm;
changed = true;
}
}
// Read digital motion value
boolean tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH;

Serial.println(tripped);
gw.send(msg.set(tripped?“1″:“0“));  // Send tripped value to gw

// Sleep until interrupt comes in on motion sensor. Send update every two minute.
//gw.sleep(INTERRUPT,CHANGE, SLEEP_TIME);

return changed;
}

void timerHandler()
{
bool humidityChanged = DHT22Changed(false);
bool airQualityChanged = MQ135Changed(lastTemp, lastHum);

if (humidityChanged || airQualityChanged)
{
gw.send(msgTemp.set(lastTemp, 1));
gw.send(msgHum.set(lastHum, 1));
gw.send(msgCO2Corrected.set(lastCO2Corrected));
gw.send(msgCO2.set(lastC02));
gw.send(msgR0.set(lastR0, 2));
}
}

void loop()
{
gw.process();

timer.update();

}

void incomingMessage(const MyMessage& message)
{
Serial.println(F(„Incoming Message:“));

if (message.isAck())
{
Serial.println(F(„This is an ack from gateway“));
}

uint8_t sensor = message.sensor;
if (sensor == CHILD_ID_R0)
{
float R0 = message.getFloat();

Serial.print(F(„Incoming R0: „));
Serial.print(R0);
Serial.println(F(„“));

gw.saveState(EEPROM_R0, (uint8_t)(R0/2));
gasSensor.setR0(R0);
gw.send(msgR0.set(R0, 2));
}
}