-
-
Save mKeRix/4fc553574af0a2d8682734695160b859 to your computer and use it in GitHub Desktop.
| #include "esphome.h" | |
| #include "math.h" | |
| using namespace esphome; | |
| #define I2C_ADDR_D6T 0x0a | |
| #define CMD 0x4c | |
| static const int SOBEL_X[3][3] = | |
| { { -1, 0, 1 }, | |
| { -2, 0, 2 }, | |
| { -1, 0, 1 } }; | |
| static const int SOBEL_Y[3][3] = | |
| { { -1, -2, -1 }, | |
| { 0, 0, 0 }, | |
| { 1, 2, 1 } }; | |
| static const float THRESHOLD = 4.0; | |
| class D6T44L06BinarySensor : public PollingComponent, public binary_sensor::BinarySensor { | |
| public: | |
| D6T44L06BinarySensor() : PollingComponent(500) {} | |
| void setup() override { | |
| Wire.begin(); | |
| } | |
| void update() override { | |
| float temps[4][4]; | |
| float gradients[4][4]; | |
| bool state; | |
| readTemps(temps); | |
| applySobel(temps, gradients); | |
| state = meetsThreshold(gradients); | |
| publish_state(state); | |
| } | |
| private: | |
| void readTemps(float temps[4][4]) { | |
| uint8_t buf[35]; | |
| int i = 0; | |
| Wire.beginTransmission(I2C_ADDR_D6T); | |
| Wire.write(CMD); | |
| Wire.endTransmission(); | |
| Wire.requestFrom(I2C_ADDR_D6T, 35); | |
| while (Wire.available() && i < 35){ | |
| buf[i++] = Wire.read(); | |
| } | |
| Wire.endTransmission(); | |
| for (int y = 0; y < 4; y++) { | |
| for (int x = 0; x < 4; x++) { | |
| i = x + (y * 4); | |
| temps[y][x] = (buf[(i * 2 + 2)] + (buf[(i * 2 + 3)] << 8)) * 0.1; | |
| } | |
| } | |
| } | |
| void applySobel(float temps[4][4], float gradients[4][4]) { | |
| for (int y = 0; y < 4; y++) { | |
| for (int x = 0; x < 4; x++) { | |
| float magX = 0; | |
| float magY = 0; | |
| float gradient = 0; | |
| for (int yk = 0; yk < 3; yk++) { | |
| for (int xk = 0; xk < 3; xk++) { | |
| magX += temps[clamp(y + yk - 1, 0, 3)][clamp(x + xk - 1, 0, 3)] * SOBEL_X[yk][xk]; | |
| magY += temps[clamp(y + yk - 1, 0, 3)][clamp(x + xk - 1, 0, 3)] * SOBEL_Y[yk][xk]; | |
| } | |
| } | |
| gradients[y][x] = sqrt(pow(magX, 2) + pow(magY, 2)); | |
| } | |
| } | |
| } | |
| bool meetsThreshold(float values[4][4]) { | |
| for (int y = 0; y < 4; y++){ | |
| for (int x = 0; x < 4; x++){ | |
| if (values[y][x] >= THRESHOLD) { | |
| return true; | |
| } | |
| } | |
| } | |
| return false; | |
| } | |
| int clamp(int d, int min, int max) { | |
| const int t = d < min ? min : d; | |
| return t > max ? max : t; | |
| } | |
| }; |
| esphome: | |
| includes: | |
| - d6t_44l_06.h | |
| name: d6t_sensor | |
| platform: ESP32 | |
| board: nodemcu-32s | |
| i2c: | |
| sda: 21 | |
| scl: 22 | |
| scan: False | |
| binary_sensor: | |
| - platform: custom | |
| lambda: |- | |
| auto d6t_sensor = new D6T44L06BinarySensor(); | |
| App.register_component(d6t_sensor); | |
| return {d6t_sensor}; | |
| binary_sensors: | |
| name: "D6T Sensor" | |
| device_class: occupancy |
I just matched the pins via the data sheet. I don't remember it exactly, but it's just power, ground and then the i2c pins on your board. In my case those were pins 21 and 22.
The D6T-1A-01 only has a single output, so you don't need most of the code above. You can probably reuse the connection logic (
readTemps), but would need to change the output format and read buffer size (Wire.requestFrom). The rest you can just skip: either you output the temperature directly as a sensor, or you apply some threshold to it.
Hi @mKeRix I'm not so well versed with the libraries. Is it possible to re-write this for D6T-1A? found this arduino code for d6t-1A, but not quite sure how to port it! https://github.com/hankha/d6t-ap-SeatOccupancy-arduino/blob/master/examples/d6t-1a/d6t-1a.ino
What about making it work with amg8833