打印
[STM32U5]

【NUCLEO-U5A5ZJ-Q测评】温湿度信息检测仪表盘

[复制链接]
755|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
#申请原创#
在之前的文章中,分享了 【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的支持,上诉温湿度信息仪表盘显示的效果非常的好。
后面会继续尝试,连接更多的传感器,制作更丰富的呈现界面。

使用特权

评论回复
沙发
AloneKaven| | 2024-1-12 16:38 | 只看该作者
这个模块也带湿度检测吗

使用特权

评论回复
板凳
HonestQiao|  楼主 | 2024-2-1 15:19 | 只看该作者
AloneKaven 发表于 2024-1-12 16:38
这个模块也带湿度检测吗

不带啊,自备的

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

39

主题

96

帖子

2

粉丝