esphome / feature-requests

ESPHome Feature Request Tracker
https://esphome.io/
415 stars 26 forks source link

Support for AGS02MA (Air Quality Sensor) #1800

Open zevs44 opened 2 years ago

zevs44 commented 2 years ago

Describe the problem you have/What new integration you would like It would be nice to include support for AGS02MA sensor as it relatively cheap way to measure TVOC. https://asairsensors.com/product/ags02ma-tvoc-gas-sensor/

Please describe your use case for this integration and alternatives you've tried: To measure TVOC concentration in environment.

Additional context Library for Arduino: https://github.com/RobTillaart/AGS02MA

zevs44 commented 2 years ago

Add support thought custom sensor.

YAML 1) Add includes and libraries in esphome section

esphome:
  name: $devicename
  comment: $devicecomment
  platform: $platform
  board: $board
  includes:
    - AGS02MACust.h
  libraries:
    - "Wire"
    - "robtillaart/AGS02MA@^0.3.0"

2) Setup frequency i2c

i2c:
  sda: GPIO12
  scl: GPIO14
  scan: true
  frequency: 30kHz
  id: bus_i2c

3) Add custom sensor

  - platform: custom
    lambda: |-
      auto my_AGS02MA = new AGS02MACust();
      App.register_component(my_AGS02MA);
      return {my_AGS02MA};
    sensors:
      name: "1.AGS02MA-TVOC"
      id: ags02ma_tvoc
      accuracy_decimals: 0
      filters:
        - delta: 1
      retain: true
      unit_of_measurement: "ppb"
      icon: "mdi:radiator"
      device_class: "carbon_dioxide"
      state_class: "measurement"

AGS02MACust.h Place file AGS02MACust.h to /config folder


#include "esphome.h"
#include "AGS02MA.h"
#include "Wire.h"

static const char *TAG = "AGS02MA.sensor";

// measure every 20 seconds = 3 times per minute
#define UPDATE_INTERVAL 20000 // update interval in ms

class AGS02MACust : public PollingComponent, public Sensor {
 public:
    AGS02MA AGS;
    AGS02MACust() : PollingComponent(UPDATE_INTERVAL) { }
    float get_setup_priority() const override { return esphome::setup_priority::BUS; }

    void setup() override
    {
    //ESP_LOGD(TAG, "AGS02MA: Setting up sensor...");
    AGS.begin();
    AGS.setPPBMode();
    }

    void update() override
    {
    ESP_LOGD(TAG, "AGS02MA: version=%d; mode (0 = PPB, 1 = UGm3, 255 = not set)=%d", AGS.getSensorVersion(), AGS.getMode());
    ESP_LOGI(TAG, "AGS02MA: last error=%d; RDY bit (from last read)=%d; last read=%u", AGS.lastError(), AGS.dataReady(), AGS.lastRead());
    publish_state(AGS.readPPB()); // publish
    }
};
mak-42 commented 9 months ago

The solution still work, but causes warnings in logs like that:

[16:14:40][W][component:214]: Component <unknown> took a long time for an operation (0.08 s).
[16:14:40][W][component:215]: Components should block for at most 20-30ms.
mak-42 commented 9 months ago

I managed to make it to use second i2c bus for ESP32. I updated the library version to ""robtillaart/AGS02MA@0.4.1" and modified the code for it:

#include "esphome.h"
#include "AGS02MA.h"
#include "Wire.h"

static const char *TAG = "AGS02MA.sensor";

// measure every 20 seconds = 3 times per minute
#define UPDATE_INTERVAL 20000 // update interval in ms

class AGS02MACust : public PollingComponent, public Sensor {
 public:
    AGS02MA AGS = AGS02MA(26,&Wire1);  // creates with second i2c bus.
    AGS02MACust() : PollingComponent(UPDATE_INTERVAL) { }
    float get_setup_priority() const override { return esphome::setup_priority::BUS; }

    void setup() override
    {
    //ESP_LOGD(TAG, "AGS02MA: Setting up sensor...");
    Wire1.begin(<sda pin number>,<scl pin number>,30000);
    AGS.begin();
    AGS.setPPBMode();
    }

    void update() override
    {
    ESP_LOGD(TAG, "AGS02MA: version=%d; mode (0 = PPB, 1 = UGm3, 255 = not set)=%d", AGS.getSensorVersion(), AGS.getMode());
    ESP_LOGI(TAG, "AGS02MA: last error=%d; RDY bit (from last read)=%d; last read=%u", AGS.lastError(), AGS.dataReady(), AGS.lastRead());
    publish_state(AGS.readPPB()); // publish
    }
};

And you should not configure second i2c bus in ESPHome config, because I2C Bus component uses creates its own objects for buses except for the first one (code).