Add support for DFRobot HCHO Formaldehyde Sensor (SEN0231)

This commit is contained in:
Christian Witting 2023-12-15 19:29:21 +01:00
parent 23a9a704f3
commit 8aef1514d2
6 changed files with 136 additions and 0 deletions

View File

@ -280,6 +280,7 @@ esphome/components/sdm_meter/* @jesserockz @polyfaces
esphome/components/sdp3x/* @Azimath
esphome/components/selec_meter/* @sourabhjaiswal
esphome/components/select/* @esphome/core
esphome/components/sen0231/* @cwitting
esphome/components/sen0321/* @notjj
esphome/components/sen21231/* @shreyaskarnik
esphome/components/sen5x/* @martgras

View File

@ -0,0 +1 @@
CODEOWNERS = ["@cwitting"]

View File

@ -0,0 +1,66 @@
#include "sen0231.h"
#include "esphome/core/log.h"
#include "esphome/core/hal.h"
namespace esphome {
namespace sen0231_sensor {
static const char *const TAG = "sen0231_sensor.sensor";
static constexpr uint8_t START_BYTE = 0;
static constexpr uint8_t NAME_BYTE = 1;
static constexpr uint8_t UNIT_BYTE = 2;
static constexpr uint8_t NUM_DECIMAL_BYTE = 3;
static constexpr uint8_t CONCENTRATION_HIGH_BYTE = 4;
static constexpr uint8_t CONCENTRATION_LOW_BYTE = 5;
static constexpr uint8_t FULL_RANGE_HIGH_BYTE = 6;
static constexpr uint8_t FULL_RANGE_LOW_BYTE = 7;
static constexpr uint8_t CHECKSUM_BYTE = 8;
static constexpr uint8_t NUM_BYTES = 9;
void Sen0231Sensor::setup() { ESP_LOGCONFIG(TAG, "Setting up sen0231..."); }
void Sen0231Sensor::update() { this->read_data_(); }
void Sen0231Sensor::dump_config() {
ESP_LOGCONFIG(TAG, "DF Robot Formaldehyde Sensor sen0231:");
LOG_UPDATE_INTERVAL(this);
}
uint8_t check_sum(const uint8_t array[], uint8_t length) {
uint8_t sum = 0;
for (int i = 1; i < length - 1; i++) {
sum += array[i];
}
sum = (~sum) + 1;
return sum;
}
void Sen0231Sensor::read_data_() {
uint8_t buffer[NUM_BYTES] = {0};
// Read the full buffer, but we are only interested in the last frame
while (available() > 0) {
for (uint8_t i = 0; i < NUM_BYTES - 1; i++) {
// Shift buffer
buffer[i] = buffer[i + 1];
}
// Fill into last element
buffer[NUM_BYTES - 1] = read();
}
uint8_t check_val = check_sum(buffer, NUM_BYTES);
if ((buffer[START_BYTE] != 0xFF) || (buffer[NAME_BYTE] != 0x17) || (buffer[UNIT_BYTE] != 0x04) ||
(buffer[CHECKSUM_BYTE] != check_val)) {
ESP_LOGE(TAG, "Error in received data %d, %d, %d, %d", buffer[START_BYTE], buffer[NAME_BYTE], buffer[UNIT_BYTE],
buffer[CHECKSUM_BYTE]);
return;
}
float val = ((uint16_t) (buffer[CONCENTRATION_HIGH_BYTE] << 8) + buffer[CONCENTRATION_LOW_BYTE]) / 1000.0;
this->publish_state(val);
}
} // namespace sen0231_sensor
} // namespace esphome

View File

@ -0,0 +1,24 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/uart/uart.h"
// ref:
// https://wiki.dfrobot.com/Gravity__HCHO_Sensor_SKU__SEN0231
namespace esphome {
namespace sen0231_sensor {
class Sen0231Sensor : public sensor::Sensor, public PollingComponent, public uart::UARTDevice {
public:
void update() override;
void dump_config() override;
void setup() override;
protected:
void read_data_();
};
} // namespace sen0231_sensor
} // namespace esphome

View File

@ -0,0 +1,34 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import uart, sensor
from esphome.const import (
ICON_CHEMICAL_WEAPON,
UNIT_PARTS_PER_MILLION,
STATE_CLASS_MEASUREMENT,
)
CODEOWNERS = ["@cwitting"]
DEPENDENCIES = ["uart"]
sen0231_sensor_ns = cg.esphome_ns.namespace("sen0231_sensor")
Sen0231Sensor = sen0231_sensor_ns.class_(
"Sen0231Sensor", cg.PollingComponent, uart.UARTDevice
)
CONFIG_SCHEMA = (
sensor.sensor_schema(
Sen0231Sensor,
unit_of_measurement=UNIT_PARTS_PER_MILLION,
icon=ICON_CHEMICAL_WEAPON,
accuracy_decimals=3,
state_class=STATE_CLASS_MEASUREMENT,
)
.extend(cv.polling_component_schema("60s"))
.extend(uart.UART_DEVICE_SCHEMA)
)
async def to_code(config):
var = await sensor.new_sensor(config)
await cg.register_component(var, config)
await uart.register_uart_device(var, config)

View File

@ -263,6 +263,11 @@ uart:
rx_pin: GPIO10
parity: EVEN
baud_rate: 9600
- id: sen0231_uart
rx_pin:
allow_other_uses: true
number: 27
baud_rate: 9600
ota:
safe_mode: true
@ -1326,6 +1331,11 @@ sensor:
id: sen0321_ozone
update_interval: 10s
i2c_id: i2c_bus
- platform: sen0231
name: Workshop Formaldehyde Sensor
id: sen0231_formaldehyde
update_interval: 10s
uart_id: sen0231_uart
- platform: sgp30
eco2:
name: Workshop eCO2