-
-
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