mirror of https://github.com/esphome/esphome.git
Add support for DFRobot HCHO Formaldehyde Sensor (SEN0231)
This commit is contained in:
parent
23a9a704f3
commit
8aef1514d2
|
@ -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
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
CODEOWNERS = ["@cwitting"]
|
|
@ -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
|
|
@ -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
|
|
@ -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)
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue