STM32+ESP8266+RT Thread Studio+阿里云IoT实现手机显示温湿度(三)

  此部分在前面说明的基础上,介绍在RT-Thread Studio中使用相关组件,并进行代码修改,以实现整个项目的功能。首先创建RT-Thread项目,因在本示例中采用的正点原子MiniSTM32开发板其MCU是STM32F103RC,所以在创建项目时,选择“基于芯片”,芯片型号选择STM32F103RC,控制台串口保持默认的UART1。完成项目的创建后,打开applications下面的main.c,把LOG_D(“Hello RT-Thread!”)给注释掉,或移到while()循环上面,以免在程序运行时不停在串口控制台打印"Hello RT-Thread!"影响调试。
  添加DHT11温湿度组件。在RT-Thread Settings的软件包中心中查找dht11并添加,保存配置。因dht11组件比较简单,不需要进一步进行详细的配置。打开位于packages/dht11-latest目录下的dht11_sample.c文件,以下面的代码整体替换原来的代码:

#include <rtthread.h>
#include <rtdevice.h>
#include "sensor.h"
#include "sensor_dallas_dht11.h"
#include "drv_common.h"

#define DHT11_DATA_PIN    GET_PIN(C, 1) //PC1脚接DHT11的单总线
uint8_t temp_dht11 = 0; //记录温度的全局变量,被阿里云IoT线程读取并上传
uint8_t humi_dht11 = 0; //记录湿度的全局变量,被阿里云IoT线程读取并上传

//温湿度读取线程入口函数,每秒读取一次温湿度
static void read_temp_entry(void *parameter)
{
    rt_device_t dev = RT_NULL;
    struct rt_sensor_data sensor_data;
    rt_size_t res;
    rt_uint8_t get_data_freq = 1; /* 1Hz */

    dev = rt_device_find("temp_dht11");
    if (dev == RT_NULL)
    {
        return;
    }

    if (rt_device_open(dev, RT_DEVICE_FLAG_RDWR) != RT_EOK)
    {
        rt_kprintf("open device failed!\n");
        return;
    }

    rt_device_control(dev, RT_SENSOR_CTRL_SET_ODR, (void *)(&get_data_freq));

    while (1)
    {
        res = rt_device_read(dev, 0, &sensor_data, 1);

        if (res != 1)
        {
            rt_kprintf("read data failed! result is %d\n", res);
            rt_device_close(dev);
            return;
        }
        else
        {
            if (sensor_data.data.temp >= 0)
            {
                temp_dht11 = (sensor_data.data.temp & 0xffff) >> 0;      // 获取温度
                humi_dht11 = (sensor_data.data.temp & 0xffff0000) >> 16; // 获取湿度
                rt_kprintf("temp:%d, humi:%d\n" ,temp_dht11, humi_dht11);
            }
        }

        rt_thread_delay(2000);
    }
}
//创建并启动温湿度读取线程
static int dht11_read_temp_sample(void)
{
    rt_thread_t dht11_thread;

    dht11_thread = rt_thread_create("dht_tem",
                                     read_temp_entry,
                                     RT_NULL,
                                     1024,
                                     RT_THREAD_PRIORITY_MAX / 2,
                                     20);
    if (dht11_thread != RT_NULL)
    {
        rt_thread_startup(dht11_thread);
    }

    return RT_EOK;
}
INIT_APP_EXPORT(dht11_read_temp_sample); //加入应用自动初始化

//DHT11传感器设备初始化
static int rt_hw_dht11_port(void)
{
    struct rt_sensor_config cfg;
    
    cfg.intf.user_data = (void *)DHT11_DATA_PIN;
    rt_hw_dht11_init("dht11", &cfg);

    return RT_EOK;
}
INIT_COMPONENT_EXPORT(rt_hw_dht11_port);//加入组件自动初始化

  编译下载后,用串口调试工具连接,可在Finsh控制台中看见每秒打印出温湿度值。在控制台中执行list_device命令,可看到设备信息“temp_dht Sensor Device”,执行ps命令时,应该能看到“dht_tem"线程,如果温湿度不能正常打印,看不到“dht_tem"线程,很有可能是DHT11接线错误或模块损坏。在“dht_tem"线程启动时,会调用dht11_check()对DHT11模块进行检测,如不正常,则退出线程。
  添加ESP8266驱动相关组件。在RT-Thread Settings中添加at_device(AT客户端也会被自动添加,之间存在依赖关系),并开启libc库(默认开启的时minilibc库)。打开drivers目录下的board.h,在串口1宏定义下面添加如下代码:

#define BSP_USING_UART3
#define BSP_UART3_TX_PIN       "PB10"
#define BSP_UART3_RX_PIN       "PB11"

在at_device的详细配置中,启用“乐鑫ESP8266”,并在“使能示例”中设置WIFI密码和SSID,修改使用的串口为:uart3(MiniSTM32开发板的uart2引脚被用作存储设备的片选,所以串口2不能使用),其配置见下图:
在这里插入图片描述

图1 ESP8266 WiFi配置
保存配置后下载运行,可通过控制台看到ESP8266连接网络的过程,执行ifconfig命令应能看到ESP8266获取到的IP地址,ping www.baidu.com能正常ping通的话,说明模块运行正常,否自要检查接线或查看wifi信号是否太弱。

在这里插入图片描述

图2 网络连通性检查

  添加阿里云IoT软件包。在RT-Thread Settings中搜索“ali-iotkit”并添加,添加该组件时,因存在依赖关系,cjson、SAL等组件也被自动添加。进入该组件的详细配置界面,配置IoT产品和设备参数:

在这里插入图片描述

图3 RT-Thread中阿里云组件的配置
在第二部分阿里云IoT的的介绍中,要保存产品的ProductKey、ProductSecret,产品下设备的DeviceName、DeviceSecret四个参数,用这四个参数填入到RT-Thread的ali-iotkit组件对应的栏目中,注意要勾选该选项下面的Samples,并使"Enable MQTT sample"被选中,保存配置,可看到项目中的packages目下的ali-iotkit-v3.0.1被添加进来了,打开ali-iotkit-v3.0.1/mqtt目录下的mqtt-example.c,复制下面的代码进行整体替换:
#include "rtthread.h"
#include "dev_sign_api.h"
#include "mqtt_api.h"

char DEMO_PRODUCT_KEY[IOTX_PRODUCT_KEY_LEN + 1] = {0};
char DEMO_DEVICE_NAME[IOTX_DEVICE_NAME_LEN + 1] = {0};
char DEMO_DEVICE_SECRET[IOTX_DEVICE_SECRET_LEN + 1] = {0};

extern uint8_t temp_dht11; //在dht11_sample.c中定义,为采集到的温度数值
extern uint8_t humi_dht11; //在dht11_sample.c中定义,为采集到的湿度数值

void *HAL_Malloc(uint32_t size);
void HAL_Free(void *ptr);
void HAL_Printf(const char *fmt, ...);
int HAL_GetProductKey(char product_key[IOTX_PRODUCT_KEY_LEN + 1]);
int HAL_GetDeviceName(char device_name[IOTX_DEVICE_NAME_LEN + 1]);
int HAL_GetDeviceSecret(char device_secret[IOTX_DEVICE_SECRET_LEN]);
uint64_t HAL_UptimeMs(void);
int HAL_Snprintf(char *str, const int len, const char *fmt, ...);

#define EXAMPLE_TRACE(fmt, ...)  \
    do { \
        HAL_Printf("%s|%03d :: ", __func__, __LINE__); \
        HAL_Printf(fmt, ##__VA_ARGS__); \
        HAL_Printf("%s", "\r\n"); \
    } while(0)

static void example_message_arrive(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg)
{
    iotx_mqtt_topic_info_t     *topic_info = (iotx_mqtt_topic_info_pt) msg->msg;

    switch (msg->event_type) {
        case IOTX_MQTT_EVENT_PUBLISH_RECEIVED:
            /* print topic name and topic message */
            EXAMPLE_TRACE("Message Arrived:");
            EXAMPLE_TRACE("Topic  : %.*s", topic_info->topic_len, topic_info->ptopic);
            EXAMPLE_TRACE("Payload: %.*s", topic_info->payload_len, topic_info->payload);
            EXAMPLE_TRACE("\n");
            break;
        default:
            break;
    }
}

static int example_subscribe(void *handle) //Topic主题订阅函数
{
    int res = 0;
    const char *fmt = "/sys/%s/%s/thing/event/property/post";
    char *topic = NULL;
    int topic_len = 0;

    topic_len = strlen(fmt) + strlen(DEMO_PRODUCT_KEY) + strlen(DEMO_DEVICE_NAME) + 1;
    topic = HAL_Malloc(topic_len);
    if (topic == NULL) {
        EXAMPLE_TRACE("memory not enough");
        return -1;
    }
    memset(topic, 0, topic_len);
    HAL_Snprintf(topic, topic_len, fmt, DEMO_PRODUCT_KEY, DEMO_DEVICE_NAME);

    res = IOT_MQTT_Subscribe(handle, topic, IOTX_MQTT_QOS0, example_message_arrive, NULL);
    if (res < 0) {
        EXAMPLE_TRACE("subscribe failed");
        HAL_Free(topic);
        return -1;
    }

    HAL_Free(topic);
    return 0;
}

static int example_publish(void *handle) //向Topic主题发布属性函数
{
    int             res = 0;
    const char     *fmt = "/sys/%s/%s/thing/event/property/post";
    const char     *fmt_payload = "{\"params\" : { \"wendu\":%d,\"shidu\":%d } }";
    char           *topic = NULL;
    int             topic_len = 0;
    int             payload_len = 0;
    char           *payload = NULL;
    payload_len = strlen(fmt_payload)+4;
    payload = HAL_Malloc(payload_len);
        if (payload == NULL) {
            EXAMPLE_TRACE("memory not enough");
            return -1;
        }
        memset(payload, 0, payload_len);
    HAL_Snprintf(payload,payload_len,fmt_payload,temp_dht11,humi_dht11);

    topic_len = strlen(fmt) + strlen(DEMO_PRODUCT_KEY) + strlen(DEMO_DEVICE_NAME) + 1;
    topic = HAL_Malloc(topic_len);
    if (topic == NULL) {
        EXAMPLE_TRACE("memory not enough");
        return -1;
    }
    memset(topic, 0, topic_len);
    HAL_Snprintf(topic, topic_len, fmt, DEMO_PRODUCT_KEY, DEMO_DEVICE_NAME);


    res = IOT_MQTT_Publish_Simple(0, topic, IOTX_MQTT_QOS0, payload, strlen(payload));
    if (res < 0) {
        EXAMPLE_TRACE("publish failed, res = %d", res);
        HAL_Free(topic);
        HAL_Free(payload);
        return -1;
    }

    HAL_Free(topic);
    HAL_Free(payload);
    return 0;
}

static void example_event_handle(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg)
{
    EXAMPLE_TRACE("msg->event_type : %d", msg->event_type);
}

static void mqtt_example_main(void *parameter) //mqtt线程主入口函数
{
    void                   *pclient = NULL;
    int                     res = 0;
    iotx_mqtt_param_t       mqtt_params;

    HAL_GetProductKey(DEMO_PRODUCT_KEY);
    HAL_GetDeviceName(DEMO_DEVICE_NAME);
    HAL_GetDeviceSecret(DEMO_DEVICE_SECRET);

    EXAMPLE_TRACE("mqtt example");

    memset(&mqtt_params, 0x0, sizeof(mqtt_params));

    mqtt_params.handle_event.h_fp = example_event_handle;

    pclient = IOT_MQTT_Construct(&mqtt_params);
    if (NULL == pclient) {
        EXAMPLE_TRACE("MQTT construct failed");
        return;
    }

    res = example_subscribe(pclient);
    if (res < 0) {
        IOT_MQTT_Destroy(&pclient);
        return;
    }

    while (1) {
        example_publish(pclient);
        rt_thread_delay(3000);
        IOT_MQTT_Yield(pclient, 200);
    }
    return;
}

static rt_thread_t tid1 = RT_NULL;
int mqtt_thread(void) //创建mqtt线程
{
    tid1 = rt_thread_create("mqtt_thd", mqtt_example_main, RT_NULL, 4096, 14, 10);
    if (tid1 != RT_NULL)
        rt_thread_startup(tid1);
    return 0;
}
//#ifdef FINSH_USING_MSH
//MSH_CMD_EXPORT(mqtt_thread,mqtt thread);
//#endif
INIT_APP_EXPORT(mqtt_thread); //加入应用自动初始化

此部分代码的主要作用是建立一个"mqtt_thd"线程,该线程定时读取温湿度数据,再以json格式{“params” : { “wendu”:xx,“shidu”:xx } }"通过ESP8266上报到阿里云IoT平台中对应设备esp8266-dev1的属性Topic中(/sys/a1iMUSvxKOL/esp8266-dev1/thing/event/property/post),然后由阿里云平台再转发用户应用中。
  编译下载运行后,可在控制台中看到"mqtt_thd"线程定时打印出温湿度数值,用手机扫描在第二部分介绍的移动应用二维码,就可以在手机上实时看到上报的温湿度信息。本文介绍的物联网平台是阿里云的企业物联网平台,在该平台目前还不能以app方式提供手机应用,但阿里云的生活物联网平台(飞燕平台)支持生成手机app,有兴趣的可以试试。

### 回答1: 要让STM32ESP8266连接到阿里云,需要先了解阿里云物联网平台和相关的API接口。然后根据具体的应用场景需求,选择合适的协议和通信方式进行连接。具体可以采用MQTT或者HTTP协议进行连接,由此实现双向的数据传输。 首先,在STM32ESP8266中需要增加ESP8266的AT指令,将其作为WiFi模块使用,然后在此基础上进行网络配置和连接,获取SSID和密码信息等。然后基于MQTT或者HTTP协议进行连接,这两种协议都可以在阿里云IoT平台上实现。 使用MQTT协议进行连接,需要在STM32ESP8266中进行配置,包括服务器地址,端口号,客户端ID等信息。然后建立连接,发布或者订阅主题消息即可。 使用HTTP协议进行连接,需要在STM32ESP8266上进行HTTP请求,获取授权信息和TOKEN,然后调用阿里云提供的API接口来实现信息的发送和接收。 以上是STM32ESP8266连接阿里云的一些关键思路和步骤,具体还需要根据具体的需求进行详细的实现和调试。 ### 回答2: STM32是一款低功耗高性能的单片微控制器,而ESP8266是一款低成本的Wi-Fi模组,它们可以联合使用来连接到阿里云。 首先,你需要准备一台带有Wi-Fi模块供应商的STM32开发板,例如STMicroelectronics提供的Nucleo-F401RE,以及一台ESP8266 Wi-Fi模组。你还需要在阿里云上创建一个IoT Hub实例并为其生成证书。 接下来,你需要下载阿里云的SDK,该SDK支持C语言和STM32平台。将SDK包中的文件添加到您的工程中,并包含其头文件。 然后,在您的工程中设置Wi-Fi连接信息,包括SSID和密码。根据您的需求,您可以选择使用TCP或UDP协议,以及MQTT客户端进行连接和通信。 在向阿里云发送消息之前,您需要先使用证书验证自己的身份,并将证书和密钥文件添加到您的工程中。然后,您可以使用阿里云提供的API来发送和接收MQTT消息。 当您成功连接到阿里云IoT Hub并成功发送消息时,您可以在控制台中查看数据并将其用于您的应用程序。 在整个过程中,您需要确保您的代码按照阿里云SDK的指导进行编写,并且正确设置了Wi-Fi连接信息和证书。这将帮助您在不久的将来轻松地实现自己的IoT应用程序。 ### 回答3: STM32ESP8266作为微控制器和Wi-Fi模块组合,可以联合运作并连接到阿里云。概括地说,需要进行以下几步: 1. 准备硬件 网上购买STM32ESP8266开发板,将它们连接在一起。需要确保它们之间的连接是准确的,例如使用串行通信,确保引脚连接正确。 2. 搭建开发环境 需要安装ST-Link/V2驱动、Keil或者IAR等开发环境。ESP8266可以使用AT指令模式进行编程,也可以使用Lua语言进行编程。 3. 实现连接阿里云 (1)首先,注册阿里云账号并创建物联网实例。 (2)在阿里云后台创建设备,并获得设备的元组信息(Device Name、ProductKey、Device Secret)。 (3)在STM32ESP8266中,添加连接阿里云云平台所需要的支持代码,例如接入SDK等。 (4)编写代码,将STM32ESP8266连接到Wi-Fi网络并连接到阿里云云平台。具体步骤包括: a. 将ESP8266设置为STA模式或AP模式,分别连接到Wi-Fi网络或者创建一个Wi-Fi热点。 b. 设置阿里云物联网平台的API密钥。 c. 在STM32中,编写代码将设备信息(Device Name、ProductKey、Device Secret)从芯片里读取出来。 d. 在ESP8266中编写代码将元组信息加入MQTT连接参数,并连接到云端。 4. 通过阿里云平台进行消息传递 连接成功后,STM32ESP8266可以通过阿里云平台来进行双向数据传递。例如,STM32可以向阿里云发送传感器数据,阿里云会将数据转发给ESP8266ESP8266再将数据发送到远程设备或者APP上。 这就是STM32ESP8266连接到阿里云的主要流程。由于每个项目的要求不同,需要根据实际环境和需求来优化代码。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东南e匠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值