本帖最后由 hollyedward 于 2024-3-8 13:55 编辑
一、传感器介绍
D6T MEMS非接触温度传感器
主要特点:高精度,定向扫描,红外传感
一些应用场景:室内测温,人体感应检测(热释电),异常高温检测等等
官方网站:MEMS非接触温度传感器 D6T | OMRON电子部品网站 - China
欧姆龙D6T系列温度传感器,采用MEMS技术和ASIC芯片,精度高、灵敏度高、响应速度快,可用于工业、医疗、家用电器等领域。在工业领域,可用于生产线温度监测,确保产品质量;在医疗领域,可用于体温测量,提高医疗效率;在家用电器领域,可用于空调、冰箱等电器的温度控制,提升用户体验。D6T系列产品有多种型号,可根据不同应用需求进行选择。
一些传传感器原理图,最终可以通过MCU控制单元的I2C总线读取数据
测温范围
我使用的这款传感器的具体型号是D6T-44L-06H,可以测量一个4x4区域内的温度,大概是每个方块内的温度用一个值表示,精度越高测温的分辨率也越高
大概意思就是距离越近,测量格子内的范围就越小,温度就越可信。
二、传感器连接板卡
已经引出了四个接口,用板卡上的5V供电就可以
板卡的引脚上已经接入了上拉电阻
用一根GH1.25转杜邦线4p连接
对应的I2C总线读取
三、板卡烧录代码
开发板读取传感器信息,处理后输出至串口。电脑上位机读取串口数据,解析并且以一张4x4的温度分布图片显示。
开发板代码:
#include <Wire.h>
/* defines */
#define D6T_ADDR 0x0A // for I2C 7bit address
#define D6T_CMD 0x4C // for D6T-44L-06/06H, D6T-8L-09/09H, for D6T-1A-01/02
#define N_ROW 4
#define N_PIXEL (4 * 4)
#define N_READ ((N_PIXEL + 1) * 2 + 1)
uint8_t rbuf[N_READ];
double ptat;
double pix_data[N_PIXEL];
uint8_t calc_crc(uint8_t data) {
int index;
uint8_t temp;
for (index = 0; index < 8; index++) {
temp = data;
data <<= 1;
if (temp & 0x80) {data ^= 0x07;}
}
return data;
}
/** <!-- D6T_checkPEC {{{ 1--> D6T PEC(Packet Error Check) calculation.
* calculate the data sequence,
* from an I2C Read client address (8bit) to thermal data end.
*/
bool D6T_checkPEC(uint8_t buf[], int n) {
int i;
uint8_t crc = calc_crc((D6T_ADDR << 1) | 1); // I2C Read address (8bit)
for (i = 0; i < n; i++) {
crc = calc_crc(buf[i] ^ crc);
}
bool ret = crc != buf[n];
if (ret) {
Serial.print("PEC check failed:");
Serial.print(crc, HEX);
Serial.print("(cal) vs ");
Serial.print(buf[n], HEX);
Serial.println("(get)");
}
return ret;
}
/** <!-- conv8us_s16_le {{{1 --> convert a 16bit data from the byte stream.
*/
int16_t conv8us_s16_le(uint8_t* buf, int n) {
uint16_t ret;
ret = (uint16_t)buf[n];
ret += ((uint16_t)buf[n + 1]) << 8;
return (int16_t)ret; // and convert negative.
}
/** <!-- setup {{{1 -->
* 1. Initialize
- initialize a Serial port for output.
- initialize I2C.
*/
void setup() {
Serial.begin(115200); // Serial baudrate = 115200bps
Wire.begin(); // i2c master
delay(620);
}
/** <!-- loop - Thermal sensor {{{1 -->
* 2. read data.
*/
void loop() {
int i = 0;
int16_t itemp = 0;
// Read data via I2C
// I2C buffer of "Arduino MKR" is 256 buffer. (It is enough)
memset(rbuf, 0, N_READ);
Wire.beginTransmission(D6T_ADDR); // I2C slave address
Wire.write(D6T_CMD); // D6T register
Wire.endTransmission();
delay(1);
Wire.requestFrom(D6T_ADDR, N_READ);
while (Wire.available()) {
rbuf[i++] = Wire.read();
}
D6T_checkPEC(rbuf, N_READ - 1);
//Convert to temperature data (degC)
ptat = (double)conv8us_s16_le(rbuf, 0) / 10.0;
for (i = 0; i < N_PIXEL; i++) {
itemp = conv8us_s16_le(rbuf, 2 + 2*i);
pix_data[i] = (double)itemp / 10.0;
}
//Output results
Serial.print("PTAT:");
Serial.print(ptat, 1);
Serial.print(" [degC], Temperature: ");
for (i = 0; i < N_PIXEL; i++) {
Serial.print(pix_data[i], 1);
Serial.print(", ");
}
Serial.println(" [degC]");
delay(300);
}
电脑上位机代码
import serial
import time
import matplotlib.pyplot as plt
# 设置串口参数
port = serial.Serial('COM10', 115200, timeout=1)
# 图片保存路径
image_path = 'your_image.png'
def parse_serial_data(data):
# 提取PTAT和温度数据
ptat_start_index = data.find("PTAT:") + len("PTAT:")
ptat_end_index = data.find("[degC]")
ptat = float(data[ptat_start_index:ptat_end_index].strip())
temp_start_index = data.find("Temperature:") + len("Temperature:")
temp_end_index = data.find("[degC]", ptat_end_index + len("[degC]"))
temperature_data = data[temp_start_index:temp_end_index].strip().split(", ")
# 去除温度数据中的逗号
temperature_data = [temp.replace(',', '') for temp in temperature_data]
# 处理温度数据的转换错误
try:
temperature_data = [float(temp) for temp in temperature_data]
except ValueError:
# 温度数据转换错误,可以进行适当的处理
print("Invalid temperature data:", temperature_data)
temperature_data = []
return ptat, temperature_data
# 绘制温度数据图形并保存为图片
def draw_temperature_data(temperature_data):
tcolor = ['#400040', '#000080', '#006060', '#008000', '#C0C000', '#E0A000', '#F08080', '#E00000']
fig, ax = plt.subplots(4, 4, figsize=(8, 8))
plt.subplots_adjust(hspace=0.3)
for i, temp in enumerate(temperature_data):
row = i // 4
col = i % 4
if temp < 0:
color = tcolor[0]
elif temp < 5:
color = tcolor[1]
elif temp < 10:
color = tcolor[2]
elif temp < 15:
color = tcolor[3]
elif temp < 20:
color = tcolor[4]
elif temp < 25:
color = tcolor[5]
elif temp < 30:
color = tcolor[6]
else:
color = tcolor[7]
ax[row, col].axis('off')
ax[row, col].add_patch(plt.Rectangle((0, 0), 1, 1, color=color))
ax[row, col].text(0.5, 0.5, str(temp), fontsize=20, ha='center', va='center')
# 保存温度图片
plt.savefig(image_path)
# 显示温度图片
plt.pause(0.001) # 暂停一段时间,使得图形窗口能够更新
# 创建温度数据图形
fig, ax = plt.subplots(4, 4, figsize=(8, 8))
plt.subplots_adjust(hspace=0.3)
plt.ion() # 打开交互模式
# 主循环
while True:
# 从串口读取数据
if port.in_waiting > 0:
data = port.readline().decode('utf-8').strip()
ptat, temperature_data = parse_serial_data(data)
# 打印PTAT和温度数据
print("PTAT:", ptat)
print("Temperature:", temperature_data)
# 绘制温度数据图形并保存为图片
draw_temperature_data(temperature_data)
# 可以在这里添加其他的处理逻辑
time.sleep(0.1) # 延迟一段时间,避免频繁读取串口数据
四、输出结果
开发板串口输出结果
上位机根据串口数据,显示温度分布
一些地方初学难免有错误,望大佬不吝批评指正
reference:
MEMS非接触温度传感器 D6T | OMRON电子部品网站 - China
MEMS Thermal Sensors D6T User’s Manual (omron.com)
D6T MEMS非接触温度传感器 (omron.com)