ESPHome 2026.6.0-dev
Loading...
Searching...
No Matches
bl0939.h
Go to the documentation of this file.
1#pragma once
7namespace esphome::bl0939 {
9// https://datasheet.lcsc.com/lcsc/2108071830_BL-Shanghai-Belling-BL0939_C2841044.pdf
10// (unfortunately chinese, but the formulas can be easily understood)
11// Sonoff Dual R3 V2 has the exact same resistor values for the current shunts (RL=1miliOhm)
12// and for the voltage divider (R1=0.51kOhm, R2=5*390kOhm)
13// as in the manufacturer's reference circuit, so the same formulas were used here (Vref=1.218V)
14static const float BL0939_IREF = 324004 * 1 / 1.218;
15static const float BL0939_UREF = 79931 * 0.51 * 1000 / (1.218 * (5 * 390 + 0.51));
16static const float BL0939_PREF = 4046 * 1 * 0.51 * 1000 / (1.218 * 1.218 * (5 * 390 + 0.51));
17static const float BL0939_EREF = 3.6e6 * 4046 * 1 * 0.51 * 1000 / (1638.4 * 256 * 1.218 * 1.218 * (5 * 390 + 0.51));
18
19struct ube24_t { // NOLINT(readability-identifier-naming,altera-struct-pack-align)
20 uint8_t l;
21 uint8_t m;
22 uint8_t h;
23} __attribute__((packed));
24
25struct ube16_t { // NOLINT(readability-identifier-naming,altera-struct-pack-align)
26 uint8_t l;
27 uint8_t h;
28} __attribute__((packed));
29
30struct sbe24_t { // NOLINT(readability-identifier-naming,altera-struct-pack-align)
31 uint8_t l;
32 uint8_t m;
33 int8_t h;
34} __attribute__((packed));
35
36// Caveat: All these values are big endian (low - middle - high)
37
38union DataPacket { // NOLINT(altera-struct-pack-align)
39 uint8_t raw[35];
40 struct {
41 uint8_t frame_header; // 0x55 according to docs
52 uint8_t RESERVED1; // value of 0x00
54 uint8_t RESERVED2; // value of 0x00
55 uint8_t checksum; // checksum
56 };
57} __attribute__((packed));
58
60 public:
61 void set_voltage_sensor(sensor::Sensor *voltage_sensor) { voltage_sensor_ = voltage_sensor; }
62 void set_current_sensor_1(sensor::Sensor *current_sensor_1) { current_sensor_1_ = current_sensor_1; }
63 void set_current_sensor_2(sensor::Sensor *current_sensor_2) { current_sensor_2_ = current_sensor_2; }
64 void set_power_sensor_1(sensor::Sensor *power_sensor_1) { power_sensor_1_ = power_sensor_1; }
65 void set_power_sensor_2(sensor::Sensor *power_sensor_2) { power_sensor_2_ = power_sensor_2; }
66 void set_energy_sensor_1(sensor::Sensor *energy_sensor_1) { energy_sensor_1_ = energy_sensor_1; }
67 void set_energy_sensor_2(sensor::Sensor *energy_sensor_2) { energy_sensor_2_ = energy_sensor_2; }
68 void set_energy_sensor_sum(sensor::Sensor *energy_sensor_sum) { energy_sensor_sum_ = energy_sensor_sum; }
69
70 void loop() override;
71
72 void update() override;
73 void setup() override;
74 void dump_config() override;
75
76 protected:
80 // NB This may be negative as the circuits is seemingly able to measure
81 // power in both directions
87
88 // Divide by this to turn into Watt
89 float power_reference_ = BL0939_PREF;
90 // Divide by this to turn into Volt
91 float voltage_reference_ = BL0939_UREF;
92 // Divide by this to turn into Ampere
93 float current_reference_ = BL0939_IREF;
94 // Divide by this to turn into kWh
95 float energy_reference_ = BL0939_EREF;
96
97 static uint32_t to_uint32_t(ube24_t input);
98
99 static int32_t to_int32_t(sbe24_t input);
100
101 static bool validate_checksum(const DataPacket *data);
102
103 void received_package_(const DataPacket *data) const;
105} // namespace esphome::bl0939
This class simplifies creating components that periodically check a state.
Definition component.h:585
void update() override
Definition bl0939.cpp:66
void set_power_sensor_2(sensor::Sensor *power_sensor_2)
Definition bl0939.h:65
void set_current_sensor_2(sensor::Sensor *current_sensor_2)
Definition bl0939.h:63
void set_energy_sensor_1(sensor::Sensor *energy_sensor_1)
Definition bl0939.h:66
static int32_t to_int32_t(sbe24_t input)
Definition bl0939.cpp:142
void setup() override
Definition bl0939.cpp:72
void loop() override
Definition bl0939.cpp:37
void set_power_sensor_1(sensor::Sensor *power_sensor_1)
Definition bl0939.h:64
void set_energy_sensor_2(sensor::Sensor *energy_sensor_2)
Definition bl0939.h:67
sensor::Sensor * energy_sensor_sum_
Definition bl0939.h:86
sensor::Sensor * voltage_sensor_
Definition bl0939.h:77
static bool validate_checksum(const DataPacket *data)
Definition bl0939.cpp:53
sensor::Sensor * current_sensor_2_
Definition bl0939.h:79
sensor::Sensor * energy_sensor_2_
Definition bl0939.h:85
void set_voltage_sensor(sensor::Sensor *voltage_sensor)
Definition bl0939.h:61
sensor::Sensor * power_sensor_1_
Definition bl0939.h:82
static uint32_t to_uint32_t(ube24_t input)
Definition bl0939.cpp:140
void received_package_(const DataPacket *data) const
Definition bl0939.cpp:80
void set_energy_sensor_sum(sensor::Sensor *energy_sensor_sum)
Definition bl0939.h:68
sensor::Sensor * energy_sensor_1_
Definition bl0939.h:84
void dump_config() override
Definition bl0939.cpp:128
void set_current_sensor_1(sensor::Sensor *current_sensor_1)
Definition bl0939.h:62
sensor::Sensor * power_sensor_2_
Definition bl0939.h:83
sensor::Sensor * current_sensor_1_
Definition bl0939.h:78
Base-class for all sensors.
Definition sensor.h:47
esphome::bl0939::BL0939 __attribute__
static void uint32_t