【智能家居套件】温湿度计 精华
【智能家居套件】温湿度计
以后会更新些HiSpark WiFi-IoT 智能家居物联网开发套件做的一些小场景,这些虽然大部分都是有开源资料的,但是对于刚接触的小伙伴来说还是有困难的,所以我每期更新会从硬件的了解到功能的实现还有一些问题汇总都会总结到这里。
实现功能:通过温湿度传感器采集数据显示到OLED屏幕中。
本期介绍用到的是Code-2.0,下面看下功能实现都做了哪些准备.
简介
主控芯片
先来说一下开发板中使用的芯片:
Hi3861V100主要用到的主控芯片,它是一款高度集成的2.4GHz WiFi SoC芯片,这款芯片不支持蓝牙,需要的话可以选择Neptune开发板。芯片为32bit微处理器,内嵌了352KB SRAM和288KB ROM,并且有丰富的外设接口,SPI、UART、I2C、PWM、GPIO还有多路ADC,接口方面还是挺丰富的,基本可以满足智能家居大部分场景的。
熟悉硬件
HiSpark WiFi-IoT 智能家居物联网开发套件中有很多外设模块,本次需要用到的有:扩展板、3861主板、显示板、环境检测板,下面一个一个介绍。
1. 扩展板
扩展板,主要集成了电源外接电路模块和方便用户插接模块的接口
2. 显示板
显示板,上面是一块SSD1306 0.96寸的OLED显示屏幕,使用I2C的通信方式:
I2C(全称 Inter Integrated Circuit)总线是由 Philips 公司开发的一种简单、双向二线制同步串行总线。I2C 以主从方式工作,通常有一个主设备和一个或者多个从设备,主从设备通过 SDA(SerialData)串行数据线以及 SCL(SerialClock)串行时钟线两根线相连。
查看与主控板连接的方式,显示板与扩展板连接原理图:
扩展板与主控板连接原理图:
可以看到这连接过程是主控板 -> 扩展板 <- 显示板,所以对应关系为:
OLED | 主控板 | |
---|---|---|
SDA | SDA | GPIO13 |
SCL | SCL | GPIO14 |
3. 环境检测板
环境检测板,只使用板载AHT20温湿度芯片,也是通过I2C通讯方式
对应主控板:
可以看到OLED和AHT20都是连接到了主控芯片的GPIO13和GPIO14,可能有人会问,都是连接相同引脚,怎么判断是哪个设备啊。上面也对I2C大概介绍了一下,其实啊,I2C是通过总线连接,然后通讯使用寻址的方式操作各模块,当主设备需要和某一个从设备通信时,通过广播的方式,将从设备地址写到总线上,如果某个从设备符合此地址,将会发出应答信号,建立传输。
编写驱动
介绍完这些,相信大家已经对各模块间外设接口和通讯协议有了一定了解,下面继续说实现。
由于它们都是使用I2C的通讯方式所以写一个I2C读写即可:
static uint32_t I2C_ReadOrWirte(uint32_t rw, uint32_t id, uint16_t addr, uint8_t buffer, uint32_t bufLen) {
uint32_t retval = 0;
if (rw == DEVICE_I2C_READ) {
retval = IotI2cRead(id, addr, buffer, bufLen);
} else {
retval = IoTI2cWrite(id, addr, buffer, bufLen);
}
if (retval != IOT_SUCCESS) {
printf("I2C %s failed, err code: %X\n", retval);
return retval;
}
return IOT_SUCCESS;
}
其实code1.0中i2c读写使用的是hi_i2c_read,IotI2cRead只是对他们进行了二次封装,接口第三个参数结构体已经在IotI2cRead中定义了,当然也可以直接调用hi_i2c_read。
温湿度驱动程序
查看手册5.3章节中说到设备地址的定义、启动初始化、测量数据的说明
设备I2C地址定义
#define AHT20_DEVICE_ADDR 0x38 // 设备I2C地址,前七位为地址
#define AHT20_READ_ADDR ((0x38<<1)|0x1) // 第八位为读写位 110 1001
#define AHT20_WRITE_ADDR ((0x38<<1)|0x0) // 第八位为读写位 110 1000
再看如何测量数据的,手册5.4中这样说的:
// 发送 触发测量 命令,开始测量
uint32_t AHT20_StartMeasure(void)
{
uint8_t triggerCmd[] = {AHT20_TrigMeasure_REG, AHT20_TrigMeasure_REG_ARG0, AHT20_TrigMeasure_REG_ARG1};
return Aht20_I2c_Write(triggerCmd, sizeof(triggerCmd));
}
// 接收测量结果,拼接转换为标准值
uint32_t AHT20_GetMeasureResult(float *temp, float *humi)
{
uint32_t retval = 0, i = 0;
if (temp == NULL || humi == NULL) {
return IOT_FAILURE;
}
uint8_t buffer[AHT20_STATUS_RESPONSE_MAX] = { 0 };
memset(&buffer, 0x0, sizeof(buffer));
retval = I2C_ReadOrWirte(DEVICE_I2C_READ, AHT20_I2C_IDX, AHT20_READ_ADDR, buffer, sizeof(buffer)); // 读取一个字节状态值
if (retval != IOT_SUCCESS) {
return retval;
}
for (i = 0; AHT20_STATUS_BUSY(buffer[0]) && i < AHT20_MAX_RETRY; i++) {
usleep(AHT20_MEASURE_TIME);
retval = I2C_ReadOrWirte(DEVICE_I2C_READ, AHT20_I2C_IDX, AHT20_READ_ADDR, buffer, sizeof(buffer));
if (retval != IOT_SUCCESS) {
return retval;
}
}
if (i >= AHT20_MAX_RETRY) {
return IOT_FAILURE;
}
uint32_t humiRaw = buffer[1];
humiRaw = (humiRaw << 8) | buffer[2];
humiRaw = (humiRaw << 4) | ((buffer[3] & 0xF0) >> 4);
*humi = humiRaw / (float)AHT20_RESLUTION * 100;
uint32_t tempRaw = buffer[3] & 0x0F;
tempRaw = (tempRaw << 8) | buffer[4];
tempRaw = (tempRaw << 8) | buffer[5];
*temp = tempRaw / (float)AHT20_RESLUTION * 200 - 50;
return IOT_SUCCESS;
}
温度和湿度的转换公式为:
这样,温湿度的驱动基本完成了。
OLED屏幕驱动
官方也是提供有驱动的,这里直接使用官方驱动,不再叙述使用方法,有不懂的小伙伴可以留言,一起探讨。
具体应用
完成这些之后,就剩下如何使用这些驱动,把数据显示到屏幕中了,继续往下看。
static void EnvironmentTask(void *arg) // 创建一个任务
{
(void)arg;
uint32_t retval = 0;
float humidity = 0.0f;
float temperature = 0.0f;
static char line[32] = {0};
/*Oled驱动初始化*/
OledInit(); // 初始化OLED
OledFillScreen(0); // 以0填充屏幕,清空屏幕
while (IOT_SUCCESS != AHT20_Calibrate()) {
printf("AHT20 sensor init failed!\r\n");
usleep(1000);
}
while(1) {
/*开始测量*/
retval = AHT20_StartMeasure();
if (retval != IOT_SUCCESS) {
printf("trigger measure failed!\r\n");
}
/*获取温湿度*/
retval = AHT20_GetMeasureResult(&temperature, &humidity);
if (retval != IOT_SUCCESS) {
printf("get humidity data failed!\r\n");
}
printf("temp = %f, humi= %f\r\n", temperature, humidity);
/*Oled显示温度*/
sprintf(line, sizeof(line), "temp: %.2f", temperature);
OledShowString(0, 1, line, 1);
/*Oled显示湿度*/
sprintf(line, sizeof(line), "humi: %.2f", humidity);
OledShowString(0, 2, line, 1);
sleep(5);
}
}
上面的代码主要是定义了一个线程,在线程中分别初始化了两个I2C设备模块,然后进入到一个while(1)循环中,每隔五秒测量一次温湿度,然后把数值显示到OLED屏幕中。
总结
上面提供了一个简单的采集温湿度的小场景Demo,实际还是有一些其他场景可以研究的:
- 当温度值达到设定阈值时,可以联动别的设备运行,如,当温度过高,打开风扇;
- 上面那一点只限于本地运行,当然还可以通过wifi和手机互联,让用户可以通过手机查看实时数据。手机作为“超级终端”,通过温湿度联动更多的设备,这不更体现了鸿蒙系统的1+8+N的特点吗
- 目前是自己按照例程学习,通过深入学习,希望以后能做更多的东西。
遇到的问题
[OHOS ERROR] riscv32-unknown-elf-ld: ohos/libs/libhal_iothardware.a(libhal_iothardware.hal_iot_i2c.o): in function `IoTI2cWrite':
[OHOS ERROR] hal_iot_i2c.c:(.text.IoTI2cWrite+0x1a): undefined reference to `hi_i2c_write'
解决:这种问题是因为CONFIG_I2C_SUPPORT宏定义没打开导致的,以code-2.0为例(可能不同源码的位置不一致)需要在device\hisilicon\hispark_pegasus\sdk_liteos\build\config\usr_config.mk把# CONFIG_I2C_SUPPORT is not set改为CONFIG_I2C_SUPPORT=y
下面,我整理了一些实例代码和一些数据手册在这里与大家分享!
第一时间前排支持!
勇敢牛牛,冲冲冲!
支持,收藏再看
666666