Skip to content

Instantly share code, notes, and snippets.

@diplix
Created February 3, 2018 19:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save diplix/9b06bb0853e04a34e70afd81ac6ab796 to your computer and use it in GitHub Desktop.
Save diplix/9b06bb0853e04a34e70afd81ac6ab796 to your computer and use it in GitHub Desktop.
/*
* The MySensors Arduino library handles the wireless radio link and protocol
* between your home built sensors/actuators and HA controller of choice.
* The sensors forms a self healing radio network with optional repeaters. Each
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
* network topology allowing messages to be routed to nodes.
*
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2015 Sensnology AB
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
*
* Documentation: http://www.mysensors.org
* Support Forum: http://forum.mysensors.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*******************************
*
* DESCRIPTION
*
* MH-Z19 CO2 sensor
*
* It communicates with your board over serial at 9600 speed.
*
*
*
*/
//------------------------------------------------------------------------------
// if you uncomment this, you can get test and debug updates about the sensor' wireless connection by using the serial monitor tool.
#define MY_DEBUG
// Enable and select radio type attached
#define MY_RADIO_NRF24 // A 2.4Ghz transmitter and receiver, often used with MySensors.
// #define MY_RF24_PA_LEVEL RF24_PA_MIN // This sets a low-power mode for the radio. Useful if you use the verison with the bigger antenna, but don't want to power that from a separate power source. It can also fix problems with fake Chinese versions of the radio.
// #define MY_RADIO_RFM69 // 433Mhz transmitter and reveiver.
// Choose if you want this sensor to also be a repeater.
// #define MY_REPEATER_FEATURE // Just remove the two slashes at the beginning of this line to also enable this sensor to act as a repeater for other sensors. If this node is on battery power, you probably shouldn't enable this.
#define MY_TRANSPORT_WAIT_READY_MS 3000
// Libraries
#include <MySensors.h>
#include <SoftwareSerial.h>
// This can be changed:
boolean switch_on = true;
#define RED_LED_PIN 6 // Arduino pin attached to MOSFET Gate pin
#define GREEN_LED_PIN 5 // Arduino pin attached to MOSFET Gate pin
long co2ppm = 400;
unsigned long co2MeasurementInterval = 30000; // Time to wait between reads (in milliseconds).
bool initialValueSent = false;
//SoftwareSerial mySerial(6, 7); // RX, TX . You can choose other pins if you prefer.
SoftwareSerial mySerial(2, 3); // RX, TX . You can choose other pins if you prefer.
//SoftwareSerial mySerial(2, 3, true); // RX, TX . You can choose other pins if you prefer.
// Mysensors settings
#define CHILD_ID_CO2 0 // The Co2 sensor' ID on this node.
#define CHILD_ID_SWITCH 1 // The Co2 sensor' ID on this node.
MyMessage msgCo2(CHILD_ID_CO2, V_LEVEL);
MyMessage msgCo2b(CHILD_ID_CO2, V_UNIT_PREFIX);
MyMessage switchMsg(CHILD_ID_SWITCH, V_STATUS);
void presentation()
{
// Send the sketch version information to the gateway and Controller
sendSketchInfo("AIQ Sensor CO2 MH-Z19", "1.2");
// Register attached sensor(s) to gateway
present(CHILD_ID_CO2, S_AIR_QUALITY);
send(msgCo2b.set("ppm"));
present(CHILD_ID_SWITCH, S_BINARY);
send(switchMsg.set(switch_on));
}
void setup()
{
pinMode(RED_LED_PIN, OUTPUT); // Tell Arduino that redLEDPin is an output pin
pinMode(GREEN_LED_PIN, OUTPUT); //Tell Arduino that yellowLEDPin is an output pin
analogWrite(GREEN_LED_PIN, 10);
analogWrite(RED_LED_PIN, 0);
delay(1000);
Serial.begin(115200);
delay(3000);
mySerial.begin(9600);
delay(3000);
while (mySerial.read()!=-1) {}; //clear Co2 buffer.
Serial.println("hello world, I am a sensor.");
}
void loop()
{
if (!initialValueSent) {
Serial.println("Sending initial value");
//send(msgCo2.set((long)ceil(400)));
send(msgCo2b.set("ppm"));
send(switchMsg.set(switch_on)); // send feedback, really?
initialValueSent = true;
}
// You should not change these variables:
static unsigned long previousCo2Millis = 0; // Used to remember the time of the last temperature measurement.
unsigned long currentMillis = millis(); // The time since the sensor started, counted in milliseconds. This script tries to avoid using the Sleep function, so that it could at the same time be a MySensors repeater.
if (currentMillis - previousCo2Millis >= co2MeasurementInterval) { // this only gets triggered when enough time has passed.
Serial.println("CO2 - Sending data request to sensor.");
previousCo2Millis = currentMillis;
//long co2ppm = readCO2();
co2ppm = readCO2();
Serial.println("Co2 - PPM = " + String(co2ppm));
if (co2ppm != -1) {
send(msgCo2.set((long)ceil(co2ppm)));
set_lights(co2ppm);
}
Serial.print("Co2 - zzzzZZZZzzzzZZZZzzzz\n");
}
}
// Main function that gets the Co2 data
int readCO2()
{
while (mySerial.read()!=-1) {}; //clear serial buffer
char response[9]; // for answer
byte cmd[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
//byte cmd[]={0xff,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79}; //Befehl zum Auslesen der CO2 Konzentration
// The serial stream can get out of sync. The response starts with 0xff, try to resync.
while (mySerial.available() > 0 && (unsigned char)mySerial.peek() != 0xFF) {
mySerial.read();
}
memset(response, 0, 9);
// command to ask for data
mySerial.write(cmd, 9); //request PPM CO2
mySerial.readBytes(response, 9);
Serial.print(" - ");
Serial.print(response[0], HEX);
Serial.print(" - ");
Serial.print(response[1], HEX);
Serial.print(" - ");
Serial.print(response[2], HEX);
Serial.print(" - ");
Serial.print(response[3], HEX);
Serial.print(" - ");
Serial.print(response[4], HEX);
Serial.print(" - ");
Serial.print(response[5], HEX);
Serial.print(" - ");
Serial.print(response[6], HEX);
Serial.print(" - ");
Serial.print(response[7], HEX);
Serial.print(" - ");
Serial.print(response[8], HEX);
Serial.println(" - END");
/*
Serial.print(" - ");
Serial.print(unsigned(response[0]), HEX);
Serial.print(" - ");
Serial.print(unsigned(response[1]), HEX);
Serial.print(" - ");
Serial.print(unsigned(response[2]), HEX);
Serial.print(" - ");
Serial.print(unsigned(response[3]), HEX);
Serial.print(" - ");
Serial.print(unsigned(response[4]), HEX);
Serial.print(" - ");
Serial.print(unsigned(response[5]), HEX);
Serial.print(" - ");
Serial.print(unsigned(response[6]), HEX);
Serial.print(" - ");
Serial.print(unsigned(response[7]), HEX);
Serial.print(" - ");
Serial.print(unsigned(response[8]), HEX);
Serial.println(" - END");
*/
if (response[0] != 0xFFFFFFFF)
{
Serial.println("Wrong starting byte from co2 sensor! (should be FF)");
return -1;
}
if (response[1] != 0xFFFFFF86)
{
Serial.println("Wrong command from co2 sensor! (should be 86)");
return -1;
}
int responseHigh = (int) response[2];
int responseLow = (int) response[3];
Serial.print("high: ");
Serial.print(responseHigh);
Serial.print(" low: ");
Serial.println(responseLow);
//if (responseLow >= 256) { int responseLow = responseLow - 256; }
if (responseLow < 0) { responseLow = responseLow + 256; }
if (responseLow == 0) { return -1; }
int ppm = (256 * responseHigh) + responseLow;
return ppm;
}
void receive(const MyMessage &message)
{
// We only expect one type of message from controller. But we better check anyway.
if (message.type==V_STATUS) {
switch_on = message.getBool();
set_lights(co2ppm);
// Store state in eeprom
//saveState(message.sensor, message.getBool());
// Write some debug info
Serial.print("Incoming change for sensor:");
Serial.print(message.sensor);
Serial.print(", New status: ");
Serial.println(message.getBool());
send(switchMsg.set(switch_on)); // send feedback, really?
}
}
void set_lights(int co2ppm)
{
if (switch_on) {
// do stuff to LEDs
/*
* < 1000 behaglich
* > 2000 deutlich unbehaglich
* 1500 grenzwert wohnräume
* > 5000 möglich
* < 1500 optimal
*/
if (co2ppm <= 1000) {
analogWrite(RED_LED_PIN, 0);
analogWrite(GREEN_LED_PIN, 10);
}
if (co2ppm > 1000 && co2ppm <= 1500) {
analogWrite(RED_LED_PIN, 3);
analogWrite(GREEN_LED_PIN, 3);
}
if (co2ppm > 1500) {
analogWrite(RED_LED_PIN, 10);
analogWrite(GREEN_LED_PIN, 0);
}
}
else {
// turn off LEDs
analogWrite(RED_LED_PIN, 0);
analogWrite(GREEN_LED_PIN, 0);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment