Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation about how to change from MH-Z19B to MH-Z14A module is missing #21

Open
StefanL38 opened this issue Feb 7, 2021 · 1 comment
Labels
good first issue Good for newcomers PR welcome help appreciated, feel free to submit a PR

Comments

@StefanL38
Copy link

StefanL38 commented Feb 7, 2021

tested this library with a MH-Z14A module.

comment about how to change from MZ-H19B to MH-Z14A module is missing.

delays hided away in a library are bad coding practice!!

To the author: If your library is even available through the arduino-library-manager you should add INTENSIVE DOCUMENTAION

and having done a lot of tests including all kinds of extraordinary circumstances to make your library HIGH-reliable

GRRRR!!!!

 It did not work reliable. After a few answers  no more responds from the module shown in the serial monitor

So I used this code for testing (pre-heating and calibrating are disabled through commenting out

Anyway this code is aber to display the answer of the module on eah request

I uploaded this code new to my ESP8266 nodeMCU for re-checking if the code is working directly before copy & pasting this code here. So there is a high chance that this code will work
`/***************************************************************************
Sample sketch for using a mh-z14a co2 with a ESP8266
for TESTING a MH_Z14A-sensor

Written by Erik Lemcke, combined out of the following samples:

https://www.letscontrolit.com/forum/viewtopic.php?f=2&t=1785&start=40, calibration sample by s3030150
https://www.home-assistant.io/blog/2015/10/11/measure-temperature-with-esp8266-and-report-to-mqtt/, home assistant mqqt by Paulus Schoutsen

modified by Stefan Ludwig (StefanL38)
wiring:
nodeMCU mh-z14a
D7(GPIO13)--> Rx
D6(GPIO12)<-- Tx
GND GND

use the nodeMCU-Vin pin to supply with 5V, the mh-z14a needs 5v
***************************************************************************/

#include <SoftwareSerial.h>
#include <SPI.h>
#include <Wire.h>

#define INTERVAL 5000

//Tx_pin of MH_Z is connected to nodeMCU-RX-pin D6 (GPIO12)
#define nodeMCU_D6_GPIO12 12
#define MH_Z14_TX nodeMCU_D6_GPIO12

//Rx_pin of MH_Z is connected to nodeMCU-TX-pin D7 (GPIO13)
#define nodeMCU_D7_GPIO13 13
#define MH_Z14_R_Pin nodeMCU_D7_GPIO13

byte mhzResp[9]; // 9 bytes bytes response
byte mhzCmdReadPPM[9] = {0xFF,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79};
byte mhzCmdCalibrateZero[9] = {0xFF,0x01,0x87,0x00,0x00,0x00,0x00,0x00,0x78};
byte mhzCmdABCEnable[9] = {0xFF,0x01,0x79,0xA0,0x00,0x00,0x00,0x00,0xE6};
byte mhzCmdABCDisable[9] = {0xFF,0x01,0x79,0x00,0x00,0x00,0x00,0x00,0x86};
byte mhzCmdReset[9] = {0xFF,0x01,0x8d,0x00,0x00,0x00,0x00,0x00,0x72};
byte mhzCmdMeasurementRange1000[9] = {0xFF,0x01,0x99,0x00,0x00,0x00,0x03,0xE8,0x7B};
byte mhzCmdMeasurementRange2000[9] = {0xFF,0x01,0x99,0x00,0x00,0x00,0x07,0xD0,0x8F};
byte mhzCmdMeasurementRange3000[9] = {0xFF,0x01,0x99,0x00,0x00,0x00,0x0B,0xB8,0xA3};
byte mhzCmdMeasurementRange5000[9] = {0xFF,0x01,0x99,0x00,0x00,0x00,0x13,0x88,0xCB};

int shifts = 0 ;
int co2ppm;

long previousMillis = 0;

// the softwareserial interface is defined from the view of the nodeMCU
// nodeMCUs Rx is MH_Zs Tx and vice versa nodeMCUs Tx is MH_Zs Rx

//basic definition of Software-serial is SoftwareSerial MySerial(Rx,Tx)

// from the nodeMCUs view using nodeMCU-pins
SoftwareSerial co2Serial(nodeMCU_D6_GPIO12, nodeMCU_D7_GPIO13); // define MH-Z14A

// from the MH_Zs view using the MH_Z-pins
//SoftwareSerial co2Serial(MH_Z14_TX, MH_Z14_R_Pin); // define MH-Z14A

byte checksum(byte response[9]){
byte crc = 0;
for (int i = 1; i < 8; i++) {
crc += response[i];
}
crc = 255 - crc + 1;
return crc;
}

void disableABC() {
co2Serial.write(mhzCmdABCDisable, 9);
}

void enableABC() {
co2Serial.write(mhzCmdABCEnable, 9);
}

void setRange5000() {
co2Serial.write(mhzCmdMeasurementRange5000, 9);
}

void calibrateZero(){
co2Serial.write(mhzCmdCalibrateZero, 9);
}

int readCO2() {
byte cmd[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
byte response[9];
co2Serial.write(cmd, 9);
// The serial stream can get out of sync. The response starts with 0xff, try to resync.
while (co2Serial.available() > 0 && (unsigned char)co2Serial.peek() != 0xFF) {
co2Serial.read();
yield();
shifts++;
}

memset(response, 0, 9);
co2Serial.readBytes(response, 9);

for (int i = 0; i < 9; i++) {
Serial.print(" 0x");
Serial.print(response[i], HEX);
}
Serial.println(" Response OK. Shifts=" + String(shifts));

if (response[1] != 0x86)
{
Serial.println(" Invalid response from co2 sensor!");
delay(1000);
return -1;
}

if (response[8] == checksum(response)) {
int responseHigh = (int) response[2];
int responseLow = (int) response[3];
int ppm = (256 * responseHigh) + responseLow;
return ppm;
} else {
Serial.println("CRC error!");
return -1;
}
}

void setup() {

Serial.begin(115200);
Serial.println("Startup");
co2Serial.begin(9600);
Serial.println("co2Serial.begin(9600);");

unsigned long previousMillis = millis();
delay(500);
/*
Serial.println("Disabling ABC");
disableABC();
/
Serial.println("Setting range to 5000");
setRange5000();
/

Serial.println("Waiting half an hour before calibrating zero");
delay(1800000);
calibrateZero();
Serial.println("Zero was calibrated");
*/
Serial.println("leaving Setup");

}

long lastMsg = 0;

void loop() {
unsigned long now = millis();
//send a meaage every minute
if (now - lastMsg > 5 * 1000) {
lastMsg = now;
unsigned long currentMillis = millis();
if (abs(currentMillis - previousMillis) > INTERVAL)
{
previousMillis = currentMillis;
Serial.print("Requesting CO2 concentration...");
co2ppm = -999;
co2ppm = readCO2();

  //If no proper co2 value is returned, try again
  while (co2ppm == -1){
    yield();
    Serial.print("re-Requesting CO2 concentration...");
    co2ppm = readCO2();  
  }
  
  Serial.println("  PPM = " + String(co2ppm));
}

}
}`

@tobiasschuerg
Copy link
Owner

Hi @StefanL38,

sorry to hear that it did not work for you out of the box. I have a sensor running with that code for months without problems (and others do as well).
With the missing documentation you are right. Howver my time is limited, so feel free to help - PRs are welcome!

some comments about commenting out, the preheat time:
the MHZ-141 has a preheat time of 3 minutes, see sensor specification:
https://www.winsen-sensor.com/d/files/infrared-gas-sensor/mh-z14a_co2-manual-v1_01.pdf
So this is nothing that needs to be customized as it will lead to false readings instead. Still it's clearly mentioned where all other constants are defined and can be edited

const int MHZ14A = 14;
const int MHZ19B = 19;
const int MHZ_2K = 1;
const int MHZ_5K = 2;
const int MHZ_10K = 3;
const unsigned long MHZ14A_PREHEATING_TIME = 3L * 60L * 1000L;
const unsigned long MHZ19B_PREHEATING_TIME = 3L * 60L * 1000L;
const unsigned long MHZ14A_RESPONSE_TIME = 60 * 1000;
const unsigned long MHZ19B_RESPONSE_TIME = 120 * 1000;
const int STATUS_NO_RESPONSE = -2;
const int STATUS_CHECKSUM_MISMATCH = -3;
const int STATUS_INCOMPLETE = -4;
const int STATUS_NOT_READY = -5;
const int STATUS_PWM_NOT_CONFIGURED = -6;
const int STATUS_SERIAL_NOT_CONFIGURED = -7;

Also notice that the sensor has a response time of T90 < 120s so you really need to wait between readings. In the beginning I also did just wait one or two seconds between readings, which led to the sensor stop to respond after a few days.

@tobiasschuerg tobiasschuerg changed the title Does not work reliable Documentation about how to change from MH-Z19B to MH-Z14A module is missing Feb 9, 2021
@tobiasschuerg tobiasschuerg added PR welcome help appreciated, feel free to submit a PR good first issue Good for newcomers labels Oct 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers PR welcome help appreciated, feel free to submit a PR
Projects
None yet
Development

No branches or pull requests

2 participants