文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

OpenHarmony设备开发(六)-红外温度传感器

2024-12-01 14:23

关注

​想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com​

前言

最近的一个项目需要用到红外温度传感器,便想着能不能在Hi3861上开发这个外设,经过摸索了一阵子,终于把红外温度传感器简单的开起来了,后面还会追加对传感器的使用。

本次使用开发板:HiSpark_WiFi_IoT。

红外温度传感器

介绍

红外温度传感器应用广泛,在疫情期间可做体温测量,在汽车上可做空调控制、防雾应用,在家庭中可做家电温度控制等等。

MLX90614是一款红外非接触温度计(下文多以gy906简称)。TO-39金属封装里同时集成了红外感应热电堆探测器芯片和信号处理专用集成芯片。用以阻碍可见光和近红外光辐射的光学滤波器(可传播长波)集成在封装内提供对环境和日光的免疫。需注意的是封装内部的温差会影响温度计测量的精度,需要尽量将传感器和环境隔离。

协议

查阅文档时,发现这个红外温度传感器是使用SMBus通信协议或者PWM(默认SMBus输出格式),其中SMBus协议需要IO口设置为开漏输出,在Hi3861的IO口模式选择中并未发现有开漏输出选项,因此暂时不选择SMBus协议。

通过摸索了一大阵子得知,SMbus 规格是由 I2C 简化而来。两条信号线为 SMBCLK 和 SMBDATA. 这和 I2C 上的 Clock(SCL) 和 Data(SDA) 是一样的。SMBus的读取数据格式与I2C协议大差不差,差别只在于电平认定。

两者协议的电平认定虽有不同,但也有部分交集。

I2C协议中有两者电平认定:相对认定和绝对认定,其中的相对认定是依据Vdd的电压来决定,高电平为0.7 Vdd,低电平低于0.3 Vdd即可。

再看一看红外温度传感器上的SMBus协议(如下图),高电平需要高于Vdd-0.1,和I2C协议符合。而低电平最大只能0.6V,这里就只能希望Hi3861的I2C能将低电平拉得到0.6V以下了。但巧合了,经过验证Hi3861可以使用!

准备

本次使用到的是MLX90614BCC版本,该型号的供电是3V,注意不要不要插到5V的供电。!

接线:

VIN->3V3,GND->GND,SLK->SLK,SDA->SDA。

既然已经使用到了I2C,那么便需要知道该设备的地址,查阅了挺久的,发现了该设置的默认地址为0X00或者是0XB4,其中0x00是单个I2C设备连接时默认都能访问到。并且可以修改EEPROM,对其进行修改I2C地址。如果不小心修改了地址,又忘记了地址,便可以把传感器单独插上去,读0X0E的数值便可以得到设备的地址。

传感器将温度数据存在RAM里面的Tojb1,而ram里面Tobj1的地址为0x07,则得知读取温度的指令则为0x07,向该设备发送0x07,便可读取到温度数据。

代码编写

IO口初始化

老步骤,第一步先IO口初始化。

流程:

#define GPIO_SDA 13
#define GPIO_SCL 14
#define GY906_I2C 0
void gy906_init(void)
{
IoTGpioInit(GPIO_SDA);
IoTGpioInit(GPIO_SCL);
hi_io_set_func(GPIO_SDA, HI_IO_FUNC_GPIO_13_I2C0_SDA);
hi_io_set_func(GPIO_SCL, HI_IO_FUNC_GPIO_14_I2C0_SCL);
hi_i2c_init(GY906_I2C, 400000);
}

主函数及线程

查询相关文档,gy906反馈的信息有三个,第一个是低位数据,第二个是高位数据,第三个是校验位.将高位数据和低位数据拼接,再通过公式计算即可得出温度数据。

流程:

  1. 初始化I2c传输数据。
  2. 接收传感器反馈回来的数据。
  3. 判断数据的正确性。
  4. 对数据做拼接计算,即可得出温度数据。
#define GY906_I2C 0
#define GY906_addr 0x00 // 0x00 or 0xB4
//获取温度数值
void gy906_get(void)
{
hi_i2c_data gy_data = {0}; //I2C数据结构
uint8_t recv_data[3] = {0}; //接收数据缓存
uint8_t send_data[1] = {0x07}; //读取温度的指令
//初始化gy_data
gy_data.send_buf = send_data;
gy_data.send_len = 1;
gy_data.receive_buf = recv_data;
gy_data.receive_len = 3;
//I2C读写操作
hi_i2c_writeread(GY906_I2C, (GY906_addr << 1) | 0x01, &gy_data);
//进行校验位判断
uint8_t addr[6] = {0, 0, 0, 0x01, 0x07, 0x00};
addr[1] = recv_data[1]; //高位
addr[2] = recv_data[0]; //低位
uint8_t PY_CRC1 = PEC_Calculation(addr);
//如果校验位正确
if (PY_CRC1 == recv_data[2])
{
printf("temperture correct!\n");
}
//如果校验位错误,返回全部数值
else
{
printf("temperature false!\n");
printf("recv_data:low:%x high:%x CRC:%x\n", recv_data[0], recv_data[1], recv_data[2]);
printf("CRC1:%x\n", PY_CRC1);
}
//打印温度 T= (DataH:DataL)*0.02-273.15
float temperature_f = (((float)((recv_data[1] << 8) | recv_data[0])) * 2 - 27315) / 100;
printf("temperature:%.2f\n", temperature_f);
}
//主函数
void gy906_demo(void)
{
//IO口初始化
gy906_init();
while (1)
{
gy906_get();
sleep(1);
}
}
//线程创建
void gy_demo(void)
{
osThreadAttr_t attr;

attr.name = "gy_demo";
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = 10240;
attr.priority = 25;

if (osThreadNew((osThreadFunc_t)gy906_demo, NULL, &attr) == NULL)
{
printf("[gy_demo] Falied to create gy_demo!\n");
}
}

SYS_RUN(gy_demo);

校验算法

算法的代码如下(部分介绍打在注释上:

uint8_t PEC_Calculation(uint8_t pec[])
{
uint8_t crc[6]; //存放多项式
uint8_t BitPosition = 47; //存放所有数据最高位,6*8=48 最高位就是47位
uint8_t shift;
uint8_t i;
uint8_t j;
uint8_t temp;
do
{

crc[5] = 0;
crc[4] = 0;
crc[3] = 0;
crc[2] = 0;
crc[1] = 0x01;
crc[0] = 0x07;
//设置最大位位位置为47,记录位位置
BitPosition = 47;

shift = 0;

i = 5;
j = 0;
//0x80 -> 1000 0000,一位一位地找第一个"1"
while ((pec[i] & (0x80 >> j)) == 0 && i > 0)
{
//位位置-1
BitPosition--;
if (j < 7)
{
j++;
}
else
{
j = 0x00;
i--;
}
}

shift = BitPosition - 8;

//循环次数为:shift
while (shift)
{
for (i = 5; i < 0xFF; i--) //i<0xff即是i>0,遍历crc数组
{
//以下操作即是把一个八位的数据整体向左移一位,最高位移到最低位,例:1001 1000 ->0011 0001
if ((crc[i - 1] & 0x80) && (i > 0))
{
temp = 1;
}
else
{
temp = 0;
}
crc[i] <<= 1; //左移一位
crc[i] += temp;
}
shift--;
}

//将已经操作过的位 置0
for (i = 0; i <= 5; i++)
{
pec[i] ^= crc[i];
}
} while (BitPosition > 8);

return pec[0];
}

编译脚本BUILD.gn

static_library("my_gy906_demo") {
sources = [
"gy906.c",
]
include_dirs = [
"//utils/native/lite/include",
"//kernel/liteos_m/components/cmsis/2.0",
"//base/iot_hardware/peripheral/interfaces/kits",
"//device/soc/hisilicon/hi3861v100/sdk_liteos/include",
]
}

效果

 

文章相关附件可以点击下面的原文链接前往下载:

https://ost.51cto.com/resource/2302。

​想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com​​。

来源:51CTO开源基础软件社区内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯