这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【e起DIY】低功耗蓝牙温湿度计成果贴-驱动DHT11并将结果以蓝牙方式发出

共1条 1/1 1 跳转至

【e起DIY】低功耗蓝牙温湿度计成果贴-驱动DHT11并将结果以蓝牙方式发出

专家
2026-05-27 13:04:15     打赏

序言

本次活动,收获是真的很大。跟着刘工及一众大佬初步学会了如何在实时开源操作系统Zephyr下开发单片机应用程序,以及开发蓝牙应用的一些知识。

一、项目介绍

使用恩智浦 FRDM-MCXW71 开发板在  Zephyr开发环境下实现即时读取温湿度传感器DHT11的数据,并通过板载蓝牙设备将数据发送出去,供上位机接收、显示。

二、系统构成

1、软件环境

·Win10

·Python 3.14.5

·CMake 4.3.2

·West 1.5.0

·Ninja 1.13.2

·Git 2.54.0

·VSCode 1.120.0(非必须,为了编程方便)

2、硬件构成

·恩智浦 FRDM-MCXW71 开发板

 图片1.png

MCXW71是NXP推出的一款低功耗、高安全系数、面向无线连接的MCU,它的最大主频有96MHz,内核为Cortex-M33,片上集成1MB flash和128KB SRAM;FRDM-MCXW71是一款紧凑且可扩展的开发板,支持BLE、Zigbee、Thread和Matter多种无线协议。该板包括一个板载MCU-Link调试器、一个加速度传感器、一个光传感器和一个外接SPI闪存。

·DHT11温湿度传感器

图片2.png

DHT11是一款含有已校准数字信号输出的温湿度复合传感器,采用了集成式数字温湿度元件,应用专用的数字模块采集技术和温湿度传感技术,具有极高的可靠性与卓越的长期稳定性。DHT11传感器内包含一个温湿度测量元件和一个高性能MCU。

3、电路构成框图

 图片3.png

 三、功能设计

1、使用C语言以Zephyr方式建立工程

2、工作流程

图片4.png

 

3、关键代码

1)系统配置

A. DHT11用接口PA16(文件:frdm_mcxw71.overlay)

 {
        aliases {
                dht11 = &dht11_node;
                ledg = &ledg_node;
        };
 
        dht11_node: dht11 {
                compatible = "aosong,dht";
                dio-gpios = <&gpioa 16 GPIO_ACTIVE_HIGH>;
                status = "okay";
        };
        ledg_node: ledg {
                compatible = "gpio-leds";
                gpios = <&gpioa 19 GPIO_ACTIVE_HIGH>;
                status = "okay";
        };
};
/* Enable gpioa for DHT11 (PTA16) */
&gpioa {
        status = "okay";
};

B. 蓝牙模块(文件:prj.conf)

 
# Bluetooth configuration  
CONFIG_BT=y  
CONFIG_BT_PERIPHERAL=y  
CONFIG_BT_SMP=y  
CONFIG_BT_MAX_CONN=3  
CONFIG_BT_DEVICE_NAME="DHT11_MCXW71"  
CONFIG_BT_DIS=n  
CONFIG_BT_BAS=n  
CONFIG_BT_HRS=n


2) DHT11-初始化及读取温湿度数据

int dht11_init(const struct device *gpio_dev, int pin)
{
    if (!gpio_dev || !device_is_ready(gpio_dev)) {
        return -ENODEV;
    }
 
    int ret = gpio_pin_configure(gpio_dev, pin, GPIO_INPUT | GPIO_PULL_UP);
    if (ret < 0) {
        return ret;
    }
    return 0;
}
 
int dht11_read(const struct device *gpio_dev, int pin, uint8_t *humidity, uint8_t *temperature) {
    uint8_t data[5] = {0};
    int ret;
    if (!gpio_dev || !humidity || !temperature) {
        return -EINVAL;
    }
    /* Send start signal: output low for 18ms */
    ret = gpio_pin_configure(gpio_dev, pin, GPIO_OUTPUT_INACTIVE);
    if (ret < 0) {
        return ret;
    }
    dwt_delay_us(18000);  /* 18ms */
    /* Release bus: input with pull-up */
    ret = gpio_pin_configure(gpio_dev, pin, GPIO_INPUT | GPIO_PULL_UP);
    if (ret < 0) {
        return ret;
    }
    /* Wait for DHT ACK low (~80us low) */
    int ack_low = wait_and_measure_us(gpio_dev, pin, 0);
    if (ack_low >= 1000) {
        return -ETIMEDOUT;  /* No response */
    }
    /* Wait for DHT ACK high (~80us high) */
    int ack_high = wait_and_measure_us(gpio_dev, pin, 1);
    if (ack_high >= 1000) {
        return -ETIMEDOUT;
    }
    /* Read 40 bits */
    for (int i = 0; i < 40; i++) {
        /* Wait for bit start (low) */
        int low_dur = wait_and_measure_us(gpio_dev, pin, 0);
        if (low_dur >= 1000) {
            return -EIO;
        }
        /* Measure high duration to determine bit value */
        int high_dur = wait_and_measure_us(gpio_dev, pin, 1);
        /* Store bit: 0 bit ~30us, 1 bit ~70us */
        int byte_idx = i / 8;
        int bit_idx = 7 - (i % 8);
        if (high_dur > 40) {
            data[byte_idx] |= (1 << bit_idx);
        }
    }
    /* Verify checksum */
    uint8_t sum = data[0] + data[1] + data[2] + data[3];
    if (sum != data[4]) {
        return -EIO;  /* Checksum error */
    }
    *humidity = data[0];
    *temperature = data[2];
    return 0;
}


 

3)蓝牙初始化及发送数据

int btDevice_init(void)  {  
    int err;  
  
    err = bt_enable(NULL);  
    if (err) {  
        printf("BLE: bt_enable failed (err %d)\n", err);  
        return err;  
    }  
    printf("BLE: Bluetooth initialized\n");  
  
    err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));  
    if (err) {  
        printf("BLE: Advertising failed (err %d)\n", err);  
        return err;  
    }  
    printf("BLE: Advertising started\n");  
  
    return 0;  
}
 
void btDevice_notify(uint8_t temp, uint8_t hum)  {  
    int err; 
    unsigned char info[32]; 
  
    /* Convert sensor_value to uint16_t */  
    sensor_data.temp = (uint16_t)temp;  
    sensor_data.hum = (uint16_t)hum;  
 
    int len = snprintf(info, sizeof(info), "T=%d°C, H=%d%%\r\n", temp, hum);
    err = bt_gatt_notify(NULL, &dht11_svc.attrs[5], info, len);  
    if (err) {  
        printf("send info ng(%d)!\r\n", err);
    }  
 }


3) 主程序

int main(void) {
    int ret;
    uint8_t humidity, temperature;
 
    printk("DHT11 Test starting...\n");
    const struct device *gpio_dev = DEVICE_DT_GET(DT_NODELABEL(gpioa));
    ret = dht11_init(gpio_dev, DHT11_PIN);
    if (ret < 0) {
        printk("DHT11 init failed: %d\n", ret);
        return 0;
    }
    printk("DHT11 initialized\n");
    
    ret = gpio_pin_configure(gpio_dev, LED_PIN, GPIO_OUTPUT_INACTIVE );
    if (ret < 0) {
         printk("LED init failed: %d\n", ret);
        return ret;
    }
    
    /* Initialize BLE and start advertising */  
    ret = btDevice_init();  
    if (ret != 0) {  
        printf("BLE init failed: %d\n", ret);  
    }
    
    while (1) {
        led_state = !led_state;
        gpio_pin_configure(gpio_dev, LED_PIN,  led_state ?GPIO_OUTPUT_ACTIVE: GPIO_OUTPUT_INACTIVE );
         
        ret = dht11_read(gpio_dev, DHT11_PIN, &humidity, &temperature);
        if (ret == 0) {
            printk("H=%d%% T=%dC OK\n", humidity, temperature);
        } else {
            printk("Read failed: %d\n", ret);
        }
        /* Send sensor data via BLE notifications */  
        btDevice_notify(temperature, humidity);          
         
        k_sleep(K_SECONDS(3));
    }
    return 0;
}


四、运行效果

1、串口接收端

图片5.png

 注:手机端蓝牙没有连接场合,出现的“send info ng(-128)!”信息是正常的。连接成功后,不会再出现。

2、蓝牙接收端(使用微信小程序:蓝牙串口)

图片6.png

五、演示视频

<iframe src="//player.bilibili.com/player.html?isOutside=true&aid=116644735160806&bvid=BV1cDGk6pELJ&cid=38643368343&p=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"></iframe>

六、总结

这是首次使用Zephyr开发,在配置开发环境时遇到麻烦。使用软件自动安装的方式,花了两天时间也没有成功。不得已手动下载用到的软件,解压到对应的环境中。这个过程如果没有刘工的帖子的指导,根本不可能成功。在建立点灯工程、蓝牙工程时,依旧是早刘工及其他网友的帖子的帮助下,完成了最终的成果。

从整个开发过程来看,Zephyr有其方便之处。只需要做一些简单的配置,就可以省去底层代码的处理。这一点与Arduino的第三方库支持有些相似,虽然在使用便捷度上不如Arduino,但比Keil下的开发方便多了。另一面,Zephyr的学习成本相对要高一些,比如在如何制作配置文件上,且底层函数不能像STM32的HAL库那样可见,有一定难度。这些都需要花时间去学习。

通过这个活动,能了解、学习Zephyr开发是最大的收获。再次特别感谢刘工无私的付出!

 

 

 



共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]