Skip to content

Instantly share code, notes, and snippets.

@mKeRix
Last active March 12, 2023 09:34
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mKeRix/4fc553574af0a2d8682734695160b859 to your computer and use it in GitHub Desktop.
Save mKeRix/4fc553574af0a2d8682734695160b859 to your computer and use it in GitHub Desktop.
ESPHome D6T Custom Component
#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
@coolbombom
Copy link

Hi mKeRix

Which pins on the nodemcu-32s did you wire your sensor to? and would it ba as simple as changing temps[4][4] and etc... to temps[1][1] to make it work with D6T-1A-01?

kind regards
c_bb

@mKeRix
Copy link
Author

mKeRix commented Feb 1, 2020

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.

@bidyutper
Copy link

Hi @coolbombom did you make it work on 1A I have d6t-1a-02 trying to figure out how to do.

@bidyutper
Copy link

Hi @mKeRix can you please guide

@mKeRix
Copy link
Author

mKeRix commented Jun 9, 2020

What I wrote above also applies to the D6T-1A-02, you can rework the code to match the 1A protocol and only return one temperature. The D6T white paper has a specific code snippet for that which you need to convert to the Wire library. You can get rid of the Sobel and thresholding code, as there is nothing to filter on one temperature. And then either apply a threshold to make it a binary sensor or update the class to a complete sensor and output the temperature (see the ESPHome docs for that).

@shubness
Copy link

shubness commented Jul 7, 2021

ASNy updates on this thread - really keen to get this sensor working smoothly with ESPHome

@stress1ner
Copy link

What about making it work with amg8833

@soubhik-khan
Copy link

soubhik-khan commented Jul 30, 2022

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment