CO sensor - MICS-5524 or MICS-6814

Hi,

Has someone already integrated this kind of sensors?

I’m looking for a smaller form factor carbon monoxide sensors then the mq-7.

Thanks

2 Likes

Push this question up

If you have the MQ-7 or the MQ-2 up and running on an ESP32 for ESPHome, would you mind sharing that code?
And a follow-up Q; If I need to calibrate these components, do you might have some advice for me as to where to find such code too?

MQ sensors are VERY bad ones. Forget it.

What sensor do you recommend to an ESP32 and ESPHome?

1 Like

Why are MQ7 “so bad”? I mean - in what way? Accuracy? I just installed one in my basement where i have my pellets stove for central heating. I don’t need accuracy there, i just need to know if i’ll “die or stay alive”… :rofl:

I successfully integrated the MICS 5524 sensor. As it gives an analog output, we can use the Analog To Digital Sensor, it’s just a bit tricky to figure out the conversion from analog voltage to CO level.

Here's how I got the conversion from the datasheet

Converting Sensor Voltage to CO level

This relation is not straight up given in the datasheet, but there is a diagram that shows the change in resistance relative to the CO-level. There will probably be significant deviations from this graph from sensor to sensor, but this is all we have to get an estimate.

Resistance Rs to CO

Datasheet shows line in log-log scale, so that means that y = a * x^k, and in our case CO = a * (Rs/R0)^k.

To determine our constants we will take two measurements in the diagram:

  1. CO = 10 ppm @ Rs/R0 = 0.5

  2. CO = 1000 ppm @ Rs/R0 = 0.01

This gives us the following solution:

  • a = 6.3

  • k = -1.1

And thus CO = 6.3 * (Rs/R0)^-1.1

Rs is the measured sensing resistance and R0 is its resistance in normal air (at apparently 4.5 ppm CO). The datasheet states that it is somewhere between 100 kΩ and 1500 kΩ, so I assumed R0 = 700 kΩ.

Measuring Rs

On the usual PCB-Modules, the sensor is typically set up to form a voltage divider with a 10 kΩ resistor to ground. This means that the voltage on the Aout pin is determined by:

Aout = 5V * (10 kΩ) / (Rs + 10 kΩ).

Now, to determine our CO level with our handy formula, we need to calculate the current resistance of Rs, so we rearrange to get this:

Rs = (5V * (10 kΩ) / Aout) - 10 kΩ

Final Formula

Now we can just combine everything into one final formula, to get the CO level of the measured Aout voltage:

CO = 6.3 * (((5V * (10 kΩ) / Aout) - 10 kΩ)/(700 kΩ))^-1.1

Anyways, you’re probably just interested in the configuration, so here it is.

Warning: This sensor is not suitable to get accurate measurements, this configuration will only indicate a rough estimate! Individual sensors may vary significantly in offset and sensitivity, a low reading can not be trusted!

Note: The normal ESP32 can’t read voltages below 0.075V, which results in a minimum measuered CO level of 7 ppm.

sensor:
  - platform: adc
    pin: GPIOXX
    name: "CO"
    update_interval: 30s
    attenuation: auto
    unit_of_measurement: "ppm"
    accuracy_decimals: 0
    filters:
      - lambda: return 6.3f * pow(((5.0f * 10.0f / x) - 10.0f) / 700.0f, -1.1f);

I can confirm that it reacts to alcohol, but I don’t have the means to test and verify that it actually produces semi-accurate CO level readings, so use with caution!

Hi guys, thanks @JensKolb for all your pre-work! I typed in your formula into: Desmos | Graphing Calculator and found your formula did not align with the Grid on the datasheet, so I did a bit of trial and error on the above website to find a formula that is a bit closer to the chart from the MiCS 5524 datasheet.:
3.5 * (Rs)-0.85 or in code terms:

sensor:
  - platform: adc
    pin: GPIO32
    id: volt
    update_interval: 1s
    attenuation: auto
    internal: False
    name: "Volt"
    unit_of_measurement: "V"
    accuracy_decimals: 5
  - platform: template
    id: RsR0
    name: Rs/R0
    internal: False
    update_interval: 1s
    #unit_of_measurement: "ppm"
    accuracy_decimals: 5
    lambda: |-
      return (((5.0f * 10.0f / id(volt).state) - 10.0f) / 700.0F);
  - platform: template
    id: CO
    name: Carbon Monoxide
    internal: False
    update_interval: 1s
    unit_of_measurement: "ppm"
    accuracy_decimals: 0
    lambda: |-
      float co = 3.5f * pow(id(RsR0).state, -0.85f);
      if(co < 7) co = 0.0;
      if(co > 10000.0) co = 10000.0;
      return co;

If somebody have the time to align the other gases, this is how to set up the graph, you just have to play around with the 3.5 and -0.85 to change the graph, it actually is pretty easy now:

Thanks for the heads-up! I quietly switched x and y of the formula (CO and Rs/R0) for simpler transformation.
To recreate the graph in the datasheet, the exact formula would be
(RS/R0) = 3.53553*CO-0.849485.

But we need it the other way around: CO = a*(RS/R0)^k, and that’s what I tried to calculate.
However, I apparently did an error, because the correct values would be a=4.42214, k=-1.17718