MQ7 Carbon Monoxide Sensor done the right way!

Many tutorials explain how to use the MQ7 sensor but they all get it wrong in the required power cycling of the sensor
Sep 22, 2023 — 5 mins read — Home Assistant

MQ7 Carbon Monoxide Sensor done the right way!

There are a ton of tutorials on how to use the MQ7 Carbon Monoxide sensor with Arduino, Raspberry Pis, and other microcontrollers but they are all making a big mistake.

Based on the sensor datasheet, it should always be preheated for a certain amount of time and most importantly, in order for it to be precise and release any CO buildup, it needs to be powered in cycles with 5V and 1.4V.

The cycle requires that the sensor is operated at 5V for 60 seconds, and then at 1.4V for 90 seconds. Only then, at the end of the 1.4V cycle, we can properly measure the CO levels, just before starting the operation again.

The commonly available modules are all basically ignoring this and they apply 5V constantly to the sensor and that really makes the reading useless in most cases. The only article that I found that does it properly is from the ESPHome website where they explain how to modify the module to remove the digital output from it and replace it with a digital control pin to control the voltage on the heater.

I attempted this modification myself and I got it to work but not without challenges, and you can see more about those challenges in the video below.

The original code can be found at the ESPHome website but below is what I ended up using myself in my setup with the addition of the DHT11 sensor.

substitutions:
  mq7_name: "MQ7"
  mq7_id: "mq7"
  # Both pins are 3.3V compatible and can be directly connected to the ESP if you followed the heater mod tutorial
  mq7_heater_pin: D2
  mq7_analog_pin: A0
  # Voltage divider values
  mq7_low_side_resistor: "1000"
  mq7_high_side_resistor: "470"
  mq7_supply_voltage: "5.0V"
  # Temperature / Humidity Compensation
  # replace "temperature" with the id of your temperature sensor (celsius) and "humidity" with the id of your humidity sensor
  temperature_sensor_id: "temperature"
  humidity_sensor_id: "humidity"
  # Calibration: place the sensor in clean air (outdoor) for a few hours and use the value of mq7_compensated_resistance
  mq7_clean_air_compensated_resistance: "203747"


output:
  - platform: gpio
    pin: ${mq7_heater_pin}
    id: ${mq7_id}_heater_pin


switch:
  - platform: output
    name: "${mq7_name} Heater"
    icon: mdi:fire
    entity_category: diagnostic
    disabled_by_default: True
    id: ${mq7_id}_heater
    output: ${mq7_id}_heater_pin


interval:
  - interval: 150s
    then:
      - switch.turn_on: ${mq7_id}_heater
      - logger.log: "${mq7_name}: The sensor is heating!"
      - delay: 55s
      - switch.turn_off: ${mq7_id}_heater
      - logger.log: "${mq7_name}: The sensor is measuring!"
      - delay: 90s
      - if:
          condition:
            - switch.is_off: ${mq7_id}_heater
          then:
            - component.update: ${mq7_id}_raw
            - logger.log: "${mq7_name}: Done"
            - switch.turn_on: ${mq7_id}_heater
            - delay: 5s


sensor:
  # Replace with your own temperature / humidity sensor, located near the MQ-7
  # - platform: homeassistant
  #   id: ${temperature_sensor_id}
  #   entity_id: sensor.temperature
  # - platform: homeassistant
  #   id: ${humidity_sensor_id}
  #   entity_id: sensor.humidity
  - platform: dht
    pin: D0
    temperature:
      id: "temperature"
      name: "Temperature"
    humidity:
      id: "humidity"
      name: "Humidity"
    update_interval: 60s
  - platform: adc
    id: ${mq7_id}_raw
    name: "${mq7_name} Voltage"
    entity_category: diagnostic
    disabled_by_default: True
    pin: ${mq7_analog_pin}
    #attenuation: auto
    update_interval: never
  - platform: resistance
    id: ${mq7_id}_resistance
    name: "${mq7_name} Resistance"
    icon: mdi:omega
    entity_category: diagnostic
    disabled_by_default: True
    sensor: ${mq7_id}_raw
    configuration: UPSTREAM
    resistor: ${mq7_low_side_resistor}
    reference_voltage: ${mq7_supply_voltage}
    filters:
      - lambda: return (x - ${mq7_high_side_resistor});
    on_value:
      then:
        - component.update: ${mq7_id}_compensated_resistance
  - platform: template
    id: ${mq7_id}_compensated_resistance
    name: "${mq7_name} Compensated Resistance"
    icon: mdi:omega
    entity_category: diagnostic
    unit_of_measurement: Ω
    lambda: |-
      return (id(${mq7_id}_resistance).state / ( -0.01223333 * id(${temperature_sensor_id}).state -0.00609615 * id(${humidity_sensor_id}).state + 1.70860897));
    update_interval: never
    on_value:
      then:
        - component.update: ${mq7_id}_ratio
  - platform: template
    id: ${mq7_id}_ratio
    name: "${mq7_name} Ratio"
    icon: mdi:percent
    entity_category: diagnostic
    disabled_by_default: True
    unit_of_measurement: "%"
    lambda: |-
        return 100.0 * (id(${mq7_id}_compensated_resistance).state / ${mq7_clean_air_compensated_resistance});
    update_interval: never
    on_value:
      then:
        - component.update: ${mq7_id}_co
  - platform: template
    id: ${mq7_id}_co
    name: "${mq7_name} Carbon Monoxide"
    unit_of_measurement: "ppm"
    device_class: carbon_monoxide
    lambda: |-
      auto ratio_ln = log(id(${mq7_id}_ratio).state / 100.0);
      return exp(-0.685204 - 2.67936 * ratio_ln - 0.488075 * ratio_ln * ratio_ln - 0.07818 * ratio_ln * ratio_ln * ratio_ln);
    update_interval: never

By buying through the links below, you support the channel at no extra cost!

Tools and materials used in the video:



mq7 sensor nodemcu home assistant smart home
Read next

Home Assistant Notifications with WhatsApp - Dumpster Reminder

In some of my previous projects and videos, I mentioned that they can be combined with notifications in Home Assistant and since I haven't s...

You might also enojy this

Backing up IR remote codes - IR Receiver

I got my surround system, used, about 13 years ago and I must say that I'm very pleased with it and I have been using it ever since. However...