WifWaf / MH-Z19

For Arduino Boards (&ESP32). Additional Examples/Commands., Hardware/Software Serial
GNU Lesser General Public License v3.0
196 stars 41 forks source link

Serial communication - MH-Z19b + ESP-01S together or Arduino #14

Closed Eldenroot closed 4 years ago

Eldenroot commented 4 years ago

Hi,

is possible to get these two modules working side by side over serial communication with Arduino UNO?

I get this error: image

My part of the code: `

include

include // ESP-01S Wifi modul AT - serial komunikace

include "Adafruit_BME280.h" // Bosch BME280 I2C (T+RH+P)

include "MHZ19.h" // MH-Z19B (CO2)

define MHZ19B_RX 10 // MH-Z19B - RX PIN (CO2 modul RX pin -> Arduino)

define MHZ19B_TX 11 // MH-Z19B - TX PIN (CO2 modul TX pin -> Arduino)

define ESP01S_RX 2 // ESP-01S - RX PIN (Wifi modul TX pin -> Arduino)

define ESP01S_TX 3 // ESP-01S - RX PIN (Wifi modul RX pin -> Arduino)

int CO2ppm; // koncentrace CO2 (ppm) unsigned long getDataTimer = 0; // MHZ19B timer

// ESP-01S Wifi modul - konfigurace zapojeni PINu - RX/TX SoftwareSerial espSerial(ESP01S_RX,ESP01S_TX);

// MH-Z19B CO2 senzor - konfigurace zapojeni PINu - RX/TX (UART zapojeni) MHZ19 myMHZ19; // knihovna SoftwareSerial mhz19bSerial(MHZ19B_RX,MHZ19B_TX);

void setup() {

// Arduino - komunikace
Serial.begin(9600); // Komunikace Arduino - 9600 baudrate

// Inicializace senzoru + modulu // Bosch BME280 senzor (T+RH+P) Serial.println("Inicializace..."); Serial.println("Detekce BME280 sensoru..."); if(!bme.begin(0x76)) // IC2 adresa pro komunikaci nastavena na 0x76 { Serial.println("BME280 senzor nebyl detekovan. Zkontrolujte vase zapojení a/nebo IC2 adresu!"); while(1); } Serial.println("BME280 senzor uspesne nacten!");

  // MH-Z19B CO2 senzor
  mhz19bSerial.begin(9600); // Komunikace s CO2 modulem - 9600 baudrate
  myMHZ19.begin(mhz19bSerial); // Definovat seriovou komunikaci
  myMHZ19.autoCalibration(false); // Vypnout auto-kalibraci CO2

// ESP-01S - komunikace  
  espSerial.begin(115200); // Komunikace s Wifi modulem - 115200 baudrate
  espSerial.flush(); // Vymazat serial monitor
  espData("AT+RST", 1000, DEBUG); // Reset ESP-01S modulu
  espData("AT+CWMODE=1", 1000, DEBUG); // Nastavit rezim ESP-01S na "station mode"
  espData("AT+CWJAP=\""+ AP_SSID +"\",\""+ AP_PASSWORD +"\"", 1000, DEBUG); // Pripojit k Wifi siti
  delay(1000);

}

void readSensors(void) {

// MH-Z19B - koncentrace CO2 (ppm) if (millis() - getDataTimer >= 2000) { CO2ppm = myMHZ19.getCO2(); // Hodnota koncentrace CO2 (ppm) getDataTimer = millis(); } ...

`

WifWaf commented 4 years ago

If they are accessing different pins I think it should be fine.

Have you confirmed the sensor works okay on the current pins, without the ESP connected to the UNO?

Eldenroot commented 4 years ago

One question - I have JST version (with 7 pin connector) - is there nay of these 7 pins the PWM pin or do I need to solder extra wire into to board?

Eldenroot commented 4 years ago

Is that the yellow one on the left side?

Eldenroot commented 4 years ago

Ok, nevermind, works fine with another library... I dont know why but it works out of the box

https://github.com/crisap94/MHZ19

WifWaf commented 4 years ago

No problem. I'm honestly not sure why it's happening, but if I happen to pick up an esp8266 variant, I will give it a try.

Eldenroot commented 4 years ago

I will use your library in the next proejct which is in my TODO list. I will have different wiring and ESP8266 from wemos.

Anyway, I know that it is not related to your library, but I am stuck with this (I am a newbie with Arduino)...

https://github.com/crisap94/MHZ19/issues/11

I would be grateful if you can give me a hint :) I would like ot use data from CO2 sensor in other parts of my code but I cannot get it to make a "int or float" value which would be possible to use... thx

WifWaf commented 4 years ago

No problem :). I'm not entirely sure what you mean, but I think you're asking how to convert between an integer and float?

So if you're calling the function "m.co2_ppm". You can see in the header file on line 72 it returns a value in the format of "uint8_t" - this stands for "unsigned integer of 8 bits type" (it can get confusing as there are different naming conventions, and often they can mean the same or similar. For example, 'uint8_t' is the same as 'char').

So, to avoid confusion you can convert between two variable types by using a 'cast'. So to go from 'uint8_t' to a 'float', you would write:

float ppm_f = (float)m.co2_ppm;

Where "ppm_f" is the variable which holds the value from the 'm.co2_ppm' and "(float)" is the 'cast' action.

Obviously, this won't increase the accuracy of the returned value as it's limited by the function, but it allows you to be sure it's returned to the correct variable format and stops error messages.

Hopefully, I've interpreted the issue correctly...

Eldenroot commented 4 years ago

Thx for reply, so "ppm_f" will hold the value from measurement and I can use this in other parts of code. I will try and let you know.

EDIT: My question was about a variable, because I cannot use m.com2_ppm (it can be used only in serial.print), so now I will try with your hint. Thank you buddy!

Eldenroot commented 4 years ago

OK, I got this error :(

image

in header I added float ppm_f = (float)m.co2_ppm;

Eldenroot commented 4 years ago

Before I send a reply here I had tried something similar... but the "m." in is meesing with me :(

WifWaf commented 4 years ago

Ah, 'm' was just an example taken from crisap94's library you linked above.

The 'm' refers to the library instance at the top of your code.

The cast needs to be called in your code, not the library header (this was just an example of where you can find which value the library function is using).

Can you post the full Arduino code that's causing the problem?

WifWaf commented 4 years ago

I think I understand your question. You need to declare a variable in your code to hold the returned value from the function in a format that best meets its purpose.

If you send me the code I'll provide an example.

Eldenroot commented 4 years ago

Yeah I know, I need to convert uint8_t to float, but I dont have any idea how... (newbie :()

Do you have Discord? Or IRC? Or something like that?

WifWaf commented 4 years ago

Unfortunately not, but if you send the code, I'll add an example.

What's your aim with the ppm value, is it just to be stored or sent to the ESP?

Eldenroot commented 4 years ago

I think I understand your question. You need to declare a variable in your code to hold the returned value from the function in a format that best meets its purpose.

If you send me the code I'll provide an example.

Exactly, I need a variable which I could use in other parts of my code... with m.co2_ppm it is not possible because it is not working (and contains ".").

Here is my code, WIP (a little bit messy but will be improved).

https://pastebin.com/eQ1PpcND

I just need to store the value into the variable and then I will use it for (LED color RGB for CO2 ppm level; alarm etc.)

WifWaf commented 4 years ago

I see - so at the top;

float ppm_f = (float)m.co2_ppm;

Change this too;

int CO2 = 0; int MHZ19_temp = 0;

Then when you read the sensor here:

// MH-Z19B - koncentrace CO2 (ppm) measurement_t m = mhz19_uart->getMeasurement(); // Hodnota koncentrace CO2 (ppm) + T sensoru Serial.print("co2: "); Serial.println(m.co2_ppm); Serial.print("temp: "); Serial.println(m.temperature); Serial.print("co2 int: "); Serial.println(ppm_f);

Instead, write:

// MH-Z19B - koncentrace CO2 (ppm) measurement_t m = mhz19_uart->getMeasurement(); // Hodnota koncentrace CO2 (ppm) + T sensoru

CO2 = (int)m.co2_ppm; MHZ19_temp = (int)m.temperature;

Serial.print("co2: "); Serial.println(CO2); Serial.print("temp: "); Serial.println(MHZ19_temp);

The values will be stored in the global variable CO2 and MHZ19_temp of the type integer.

Unfortunately, I can't test it right now, so you'll have to let me know if it works.

WifWaf commented 4 years ago

Corrected a mistake above.

Eldenroot commented 4 years ago

OK, works fine but last issue - it displays "?" at line: #236 (I use "CO2" for print:

Serial.print(" || CO2: ");
Serial.println(CO2, 0);
WifWaf commented 4 years ago

I changed the value from a float to an int. So you can remove the 0 decimal place notation.

Are you specifically looking for a float variable?

Eldenroot commented 4 years ago

Ohh, I missed that. Yeah I removed the O decimal place notation and now it works fine!

I think "int" is enough :)

Thank you so much!

One more question - do you have any experience with BME280 sensors? Just my question - if yes, have you ever noticed wrong atmosferic pressure measurement? Temperature and humidity is correct, pressure is about 50 hPa lower (maybe defective sensor?).

WifWaf commented 4 years ago

No worries.

I have used them. There can be some deviation, but it shouldn't be much, they are generally accurate. You could try using an offset (I.e adding 50 hPa to the value) and seeing if it still reports other pressure changes correctly (I.e whether it's readings remain linear).

I used the library here with the official Bosh drivers, so it might be a bit different if you are using Adafruits library.

I might be worth comparing it against another BME280 with the same library.

WifWaf commented 4 years ago

Nothing is ever simple though, despite what Arduino tell you :)

Eldenroot commented 4 years ago

OK, I will try this library: https://github.com/finitespace/BME280

Do you use default setting or do you use any special settings (filter, mode, ...)? I will use it in a weather station (at home)

WifWaf commented 4 years ago

Ah, - weather stations are great. I recently bought a 2.5 um particulate matter recording. a few studies showed it's pretty good for a cheap sensor.

Looks like the library owner recommends to keep the filter off for Weather Monitoring:

forced mode, 1 sample/minute pressure ×1, temperature ×1, humidity ×1, filter off Current Consumption = 0.16 μA RMS Noise = 3.3 Pa/30 cm, 0.07 %RH Data Output Rate 1/60 Hz

Going by code I left it on, so should probably change that.