#申请原创#
在之前的文章中,分享了 【NUCLEO-U5A5ZJ-Q测评】驱动DFRobot高清彩屏使用lvgl显示动态仪表盘,这篇文章在此基础上,获取SHT3x温湿度传感器的信息,然后使用仪表盘显示温湿度信息。
一、硬件连接
1. 1.47 英寸 172×320 IPS LCD 高清显示屏,参考上述 【NUCLEO-U5A5ZJ-Q测评】驱动DFRobot高清彩屏使用lvgl显示动态仪表盘 连接即可:
2. SHT3x温湿度传感器
我使用的SHT3x是维特智能SHT30传感器模块:
这个温湿度传感器,支持串口通讯,也支持IIC接口通讯。
在之前分享的 【NUCLEO-U5A5ZJ-Q测评】无需移植使用lvgl驱动SSD1306 OLED显示中英文和绘图中,使用过IIC接口,那么这里,也急需使用IIC接口,来存SHT30读取数据。
参考之前的连接方式:
将SHT30的IIC接口和NUCLEO-U5A5ZJ-Q开发板上Arduino兼容接口的IIC接口连接即可。
供电部分,注意使用的SHT30需要的供电电压。我使用的这个是3.3v、5V通用的。
二、驱动处理
1. 显示驱动
显示部分,在 【NUCLEO-U5A5ZJ-Q测评】驱动DFRobot高清彩屏使用lvgl显示动态仪表盘 已经详细说明过。
2. SHT30驱动
因为使用的是Arduino兼容接口,Zephyr本身已经有SHT30的驱动,我们只需要做一个NUCLEO-U5A5ZJ-Q开发板对应的 overlay 定义即可。
具体文件:samples/sensor/sht3xd/boards/nucleo_u5a5zj_q.overlay
#include <zephyr/dt-bindings/led/led.h>
&arduino_i2c {
sht3xd: sht3xd@44 {
compatible = "sensirion,sht3xd";
reg = <0x44>;
alert-gpios = <&gpioa 9 GPIO_ACTIVE_HIGH>;
};
};
/ {
aliases {
sht3xd = &sht3xd;
};
};
这个定义的含义,是指 定义了一个 sht3xd 设备,使用预定义的 arduino_i2c 接口,设备IIC地址为 0x44
三、基础测试
上述overlay处理好以后,就可以直接使用 samples/sensor/sht3xd 实例了。
代码中,读取温湿度信息的核心代码如下:
rc = sensor_sample_fetch(sht3x_dev);
if (rc == 0) {
rc = sensor_channel_get(sht3x_dev, SENSOR_CHAN_AMBIENT_TEMP,
&temp);
}
if (rc == 0) {
rc = sensor_channel_get(sht3x_dev, SENSOR_CHAN_HUMIDITY,
&hum);
}
if (rc != 0) {
printf("SHT3XD: failed: %d\n", rc);
continue;
}
printf("SHT3XD: %.2f Cel ; %0.2f %%RH\n",
sensor_value_to_double(&temp),
sensor_value_to_double(&hum));
其逻辑较为简单,具体如下:
- 使用 sensor_sample_fetch 通知sht30进行数据采样
- 使用 sensor_channel_get 获取温度信息
- 使用 sensor_channel_get 获取湿度信息
- 打印出来
现在,编译上述实例进行测试,编译命令如下:
west build -b nucleo_u5a5zj_q samples/sensor/sht3xd
编译通过后,下载到 NUCLEO-U5A5ZJ-Q开发板 开发板,然后使用串口工具连接到开发板挂接的串口,就能看到温湿度信息的输出了:
四、在屏幕上显示两个仪表盘
因为需要同时显示温度和湿度信息,我们需要在屏幕上,显示两个仪表盘,在 【NUCLEO-U5A5ZJ-Q测评】驱动DFRobot高清彩屏使用lvgl显示动态仪表盘 的基础上,我们只需要做如下的处理即可:
1. 生成中文字体文件:
lv_font_conv --no-compress --format lvgl --font $ttf_path -o opposans_m_16_sht3x.c --bpp 4 --size 16 -r 0x20-0x7F --symbols "温度湿度"
2. 预定义:
LV_FONT_DECLARE(opposans_m_16_sht3x);
static lv_obj_t * meter;
static lv_obj_t * meter2;
static lv_meter_indicator_t * indic;
static lv_meter_indicator_t * indic2;
static lv_style_t label_style_cn;
上述代码定义了使用的字体文件,以及两个仪表盘,以及仪表盘对应的指示器。
3. 温度仪表盘
void lv_example_sht3x_temp(void)
{
meter = lv_meter_create(lv_scr_act());
lv_obj_align(meter, LV_ALIGN_CENTER, 0, -80);
lv_obj_set_size(meter, 150, 150);
/*Add a scale first*/
lv_meter_scale_t * scale = lv_meter_add_scale(meter);
lv_meter_set_scale_ticks(meter, scale, 41, 2, 10, lv_palette_main(LV_PALETTE_GREY));
lv_meter_set_scale_major_ticks(meter, scale, 8, 4, 15, lv_color_black(), 10);
// lv_meter_indicator_t * indic;
lv_meter_set_scale_range(meter, scale, -40, 60, 270, 90);
/*零下*/
indic = lv_meter_add_arc(meter, scale, 3, lv_palette_main(LV_PALETTE_BLUE), 0);
lv_meter_set_indicator_start_value(meter, indic, -40);
lv_meter_set_indicator_end_value(meter, indic, -10);
/*Make the tick lines blue at the start of the scale*/
indic = lv_meter_add_scale_lines(meter, scale, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_BLUE),
false, 0);
lv_meter_set_indicator_start_value(meter, indic, -40);
lv_meter_set_indicator_end_value(meter, indic, -10);
// /*零上*/
// indic = lv_meter_add_arc(meter, scale, 3, lv_palette_main(LV_PALETTE_YELLOW), 0);
// lv_meter_set_indicator_start_value(meter, indic, 0);
// lv_meter_set_indicator_end_value(meter, indic, 18);
// /*Make the tick lines blue at the start of the scale*/
// indic = lv_meter_add_scale_lines(meter, scale, lv_palette_main(LV_PALETTE_YELLOW), lv_palette_main(LV_PALETTE_YELLOW),
// false, 0);
// lv_meter_set_indicator_start_value(meter, indic, 0);
// lv_meter_set_indicator_end_value(meter, indic, 18);
/*舒适*/
indic = lv_meter_add_arc(meter, scale, 3, lv_palette_main(LV_PALETTE_GREEN), 0);
lv_meter_set_indicator_start_value(meter, indic, 17);
lv_meter_set_indicator_end_value(meter, indic, 27);
/*Make the tick lines blue at the start of the scale*/
indic = lv_meter_add_scale_lines(meter, scale, lv_palette_main(LV_PALETTE_GREEN), lv_palette_main(LV_PALETTE_GREEN),
false, 0);
lv_meter_set_indicator_start_value(meter, indic, 17);
lv_meter_set_indicator_end_value(meter, indic, 27);
/*高温*/
indic = lv_meter_add_arc(meter, scale, 3, lv_palette_main(LV_PALETTE_RED), 0);
lv_meter_set_indicator_start_value(meter, indic, 35);
lv_meter_set_indicator_end_value(meter, indic, 60);
/*Make the tick lines red at the end of the scale*/
indic = lv_meter_add_scale_lines(meter, scale, lv_palette_main(LV_PALETTE_RED), lv_palette_main(LV_PALETTE_RED), false,
0);
lv_meter_set_indicator_start_value(meter, indic, 35);
lv_meter_set_indicator_end_value(meter, indic, 60);
/*Add a needle line indicator*/
indic = lv_meter_add_needle_line(meter, scale, 4, lv_palette_main(LV_PALETTE_GREY), -10);
lv_obj_t *temp_label;
temp_label = lv_label_create(lv_scr_act());
lv_label_set_text(temp_label, "温度");
lv_obj_align(temp_label, LV_ALIGN_CENTER, 40, -50);
lv_obj_add_style(temp_label, &label_style_cn, LV_PART_MAIN); // 应用效果风格
}
在温度仪表盘中:
- 定义了从零下40度到零上60度的范围
- 零下40度到零下10度,为蓝色超冷区域
- 零上17度到27度,为绿色合适温度区域
- 零上35度到60度,为红色超热温度区域
- 合适的区域显示“温度”标签
4. 湿度仪表盘
void lv_example_sht3x_humi(void)
{
meter2 = lv_meter_create(lv_scr_act());
lv_obj_align(meter2, LV_ALIGN_CENTER, 0, 80);
lv_obj_set_size(meter2, 150, 150);
/*Add a scale first*/
lv_meter_scale_t * scale = lv_meter_add_scale(meter2);
lv_meter_set_scale_ticks(meter2, scale, 41, 2, 10, lv_palette_main(LV_PALETTE_GREY));
lv_meter_set_scale_major_ticks(meter2, scale, 8, 4, 15, lv_color_black(), 10);
// lv_meter_indicator_t * indic2;
lv_meter_set_scale_range(meter2, scale, 0, 100, 270, 90);
/*较低*/
indic2 = lv_meter_add_arc(meter2, scale, 3, lv_palette_main(LV_PALETTE_BLUE), 0);
lv_meter_set_indicator_start_value(meter2, indic2, 0);
lv_meter_set_indicator_end_value(meter2, indic2, 20);
/*Make the tick lines blue at the start of the scale*/
indic2 = lv_meter_add_scale_lines(meter2, scale, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_BLUE),
false, 0);
lv_meter_set_indicator_start_value(meter2, indic2, 0);
lv_meter_set_indicator_end_value(meter2, indic2, 20);
/*合适*/
indic2 = lv_meter_add_arc(meter2, scale, 3, lv_palette_main(LV_PALETTE_GREEN), 0);
lv_meter_set_indicator_start_value(meter2, indic2, 40);
lv_meter_set_indicator_end_value(meter2, indic2, 60);
/*Make the tick lines blue at the start of the scale*/
indic2 = lv_meter_add_scale_lines(meter2, scale, lv_palette_main(LV_PALETTE_GREEN), lv_palette_main(LV_PALETTE_GREEN),
false, 0);
lv_meter_set_indicator_start_value(meter2, indic2, 40);
lv_meter_set_indicator_end_value(meter2, indic2, 60);
/*高温较高*/
indic2 = lv_meter_add_arc(meter2, scale, 3, lv_palette_main(LV_PALETTE_RED), 0);
lv_meter_set_indicator_start_value(meter2, indic2, 80);
lv_meter_set_indicator_end_value(meter2, indic2, 100);
/*Make the tick lines red at the end of the scale*/
indic2 = lv_meter_add_scale_lines(meter2, scale, lv_palette_main(LV_PALETTE_RED), lv_palette_main(LV_PALETTE_RED), false,
0);
lv_meter_set_indicator_start_value(meter2, indic2, 80);
lv_meter_set_indicator_end_value(meter2, indic2, 100);
/*Add a needle line indicator*/
indic2 = lv_meter_add_needle_line(meter2, scale, 4, lv_palette_main(LV_PALETTE_GREY), -10);
lv_obj_t *humi_label;
humi_label = lv_label_create(lv_scr_act());
lv_label_set_text(humi_label, "湿度");
lv_obj_align(humi_label, LV_ALIGN_CENTER, 40, 110);
lv_obj_add_style(humi_label, &label_style_cn, LV_PART_MAIN); // 应用效果风格
}
在湿度仪表盘中:
- 定义了从0到100的范围
- 0到20,为蓝色干燥区域
- 40到60,为绿色合适湿度区域
- 80~100,为红色超湿温度区域
- 合适的区域显示“湿度”标签
然后,在主代码中,使用下面的代码,来绘制上述两个仪表盘:
lv_obj_clean(lv_scr_act());
lv_example_sht3x_temp();
lv_example_sht3x_humi();
while(1) {
lv_task_handler();
k_sleep(K_MSEC(5000));
}
最终的实际效果如下:
五、结合温湿度传感器的数据,更新到仪表盘
上面已经显示了两个仪表盘,下一步,把温湿度信息给整合进来即可。
1. prj.conf处理
首先,需要在prj.conf中添加sht3x的配置:
# sht3x
CONFIG_I2C=y
CONFIG_SENSOR=y
CONFIG_CBPRINTF_FP_SUPPORT=y
2. main.c代码处理
头文件调用部分添加:
#include <zephyr/drivers/sensor.h>
main()部分设备初始化检查:
const struct device *const sht3x_dev = DEVICE_DT_GET_ONE(sensirion_sht3xd);
int rc;
if (!device_is_ready(sht3x_dev)) {
printf("Device %s is not ready\n", sht3x_dev->name);
return 0;
}
while循环部分读取温湿度信息,并更新到仪表盘:
struct sensor_value temp, hum;
while(1) {
rc = sensor_sample_fetch(sht3x_dev);
if (rc == 0) {
rc = sensor_channel_get(sht3x_dev, SENSOR_CHAN_AMBIENT_TEMP,
&temp);
}
if (rc == 0) {
rc = sensor_channel_get(sht3x_dev, SENSOR_CHAN_HUMIDITY,
&hum);
}
if (rc != 0) {
printf("SHT3XD: failed: %d\n", rc);
continue;
}
printf("SHT3XD: %.2f Cel ; %0.2f %%RH\n",
sensor_value_to_double(&temp),
sensor_value_to_double(&hum));
lv_meter_set_indicator_value(meter, indic, sensor_value_to_double(&temp));
lv_meter_set_indicator_value(meter2, indic2, sensor_value_to_double(&hum));
lv_task_handler();
k_sleep(K_MSEC(5000));
}
在上述代码中,参考sht3xd实例读取出来温湿度数据,然后使用 lv_meter_set_indicator_value 更新仪表盘的value即可。
在室内环境的情况下,具体呈现结果:
对着SHT30哈气后,湿度上升:
六、总结
感觉在NUCLEO-U5A5ZJ-Q开发板上进行相关的开发,真是的太方便了。
得益于良好的结构设计,以及Zephyr的支持,上诉温湿度信息仪表盘显示的效果非常的好。
后面会继续尝试,连接更多的传感器,制作更丰富的呈现界面。
|
此文章已获得独家原创/原创奖标签,著作权归21ic所有,未经允许禁止转载。
|