基于RT-Thread的战舰开发板连接Onenent云平台(学习笔记)
摘要:本文主要是我在使用正点原子开发板在rt_thread框架下连接onenet云平台的学习笔记。此文主要介绍配置步骤和开发过程中遇到的问题,写本文的主要目的是为了强化自己的学习过程,第一次发文,希望对他人有所帮助,也希望大佬勿喷。
配置用的硬件主要是正点原子战舰开发板、正点原子ESP8266模块、DHT11温湿度传感器。通过运行rt_thread并加入相关的软件包连接云平台。软件有MDK5、MobaXterm串口调试助手。
准备工作:将ESP266WiFi模块连接到串口3、DHT11使用单总线通信数据传输,模块与开发板连接如下图
一、登录Onenet云平台创建产品和设备产品的联网方式为WIFI
设备接入协议为MQTT
在产品下创建设备,按照要求填写即可。
二、使用ENV工具添加软件包,需要添加的软件包主要有三个分别为:ESP8266软件包、DHT11软件包、onenet软件包,建议全部开启软件包示例sample,这样方便根据示例代码编写自己的工程
device id :为设备ID
auth info: 为鉴权信息
api key : API秘钥
product id :产品ID
master/product key:产品秘钥
以上信息按照你创建的产品和设备的信息如实填写,保证准确,当然你也可以在配置完成后在工程中的rtconfig.h中修改相关信息。
在AT DEVICE中使能ESP8266,并开启Enable sample
同理,还需要打开DHT11软件包,并Enable sample。
还需要打开串口3因为DHT11连接到了串口3上。
****注意:在rtconfig.h中修改软件包相关参数会在下次更新软件包时,自动更新为软件包配置时的参数,所以建议在ENV中修改软件包相关参数。
退出ENV配置,输入scons --target=mdk5生成新的工程。
三、代码的修改
1、如果你没有在ENV中配置软件包参数则可以在rtconfig.h中修改
#define PKG_USING_AT_DEVICE
#define AT_DEVICE_USING_ESP8266
#define AT_DEVICE_ESP8266_SAMPLE
#define ESP8266_SAMPLE_WIFI_SSID "WiFi账号"
#define ESP8266_SAMPLE_WIFI_PASSWORD "WiFi密码"
#define ESP8266_SAMPLE_CLIENT_NAME "uart3"
#define ESP8266_SAMPLE_RECV_BUFF_LEN 512
#define PKG_USING_AT_DEVICE_V202
#define PKG_AT_DEVICE_VER_NUM 0x20002
/* IoT Cloud */
#define PKG_USING_ONENET
#define PKG_USING_ONENET_SAMPLE
#define ONENET_USING_MQTT
#define ONENET_INFO_DEVID "设备ID"
#define ONENET_INFO_AUTH "鉴权信息"
#define ONENET_INFO_APIKEY "设备的APIkey"
#define ONENET_INFO_PROID "产品ID"
#define ONENET_MASTER_APIKEY "产品APIkey"
#define PKG_USING_ONENET_LATEST_VERSION
/* On-chip Peripheral Drivers */
#define BSP_USING_GPIO
#define BSP_USING_UART
#define BSP_USING_UART1
#define BSP_UART1_RX_USING_DMA
#define BSP_USING_UART3
2、在宏定义中打开串口3,编译工程下载后可能会导致死机,原因可能是没有在硬件层打开串口3导致系统初始化失败,下面是我修改的代码,仅供参考
该函数在是stm32f1xx_hal_msp.c中
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(huart->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspInit 0 */
/* USER CODE END USART1_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN USART1_MspInit 1 */
/* USER CODE END USART1_MspInit 1 */
}
if(huart->Instance==USART3)
{
/* USER CODE BEGIN USART3_MspInit 0 */
/* USER CODE END USART3_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_USART3_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**USART3 GPIO Configuration
PB10 ------> USART3_TX
PB11 ------> USART3_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USER CODE BEGIN USART3_MspInit 1 */
/* USER CODE END USART3_MspInit 1 */
}
}
修改完成后,可以尝试编译代码,并下载到开发板中,输入相关命令检查硬件是否能够正常工作。
打开MobaXterm串口调试助手(由于正点原子开发板带有一键下载电路,建议先重启开发板在打开串口,否则可能会导致串口打开失败)
输入命令dht11_read_temp_sample查看串口1是否打印DHT11温湿度数据。
3、完成上述过程后添加温湿度数据到MQTT协议中准备上传给Onenet云平台
首先,注释掉dht11_sample.c 中的DHT11温湿度读取线程,修改代码到onenet_sample.c中读取温湿度数据。
#include
#include
#include "sensor.h"
#include "sensor_dallas_dht11.h"
#include "drv_gpio.h"
/* Modify this pin according to the actual wiring situation */
#define DHT11_DATA_PIN GET_PIN(G, 11)
/*DHT11的数据读取在onenet_sample中完成*/
#if 0
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)
{
uint8_t temp = (sensor_data.data.temp & 0xffff) >> 0; // get temp
uint8_t humi = (sensor_data.data.temp & 0xffff0000) >> 16; // get humi
rt_kprintf("temp:%d, humi:%d\n" ,temp, humi);
}
}
rt_thread_delay(1000);
}
}
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;
}
MSH_CMD_EXPORT(dht11_read_temp_sample,sample);
#endif
/*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);
注意:DHT11的引脚需要修改为PG11
其次,修改onenet_sample.c中的代码
数据上传函数为onenet_mqtt_upload_digit()
#include
/*DHT11相关头文件*/
#include "sensor.h"
#include "sensor_dallas_dht11.h"
#include "drv_gpio.h"
#include
#define DBG_ENABLE
#define DBG_COLOR
#define DBG_SECTION_NAME "onenet.sample"
#if ONENET_DEBUG
#define DBG_LEVEL DBG_LOG
#else
#define DBG_LEVEL DBG_INFO
#endif /* ONENET_DEBUG */
#include
#ifdef FINSH_USING_MSH
#include
/* upload random value to temperature*/
static void onenet_upload_entry(void *parameter)
{
/*DHT11相关参数定义*/
rt_device_t dev = RT_NULL;
struct rt_sensor_data sensor_data;
rt_size_t res;
rt_uint8_t get_data_freq = 1; /* 1Hz */
uint8_t temp;
uint8_t humi;
/*DHT11设备查找并打开*/
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 = (sensor_data.data.temp & 0xffff) >> 0; // get temp
humi = (sensor_data.data.temp & 0xffff0000) >> 16; // get humi
/*上传温度*/
if (onenet_mqtt_upload_digit("temperature", temp) < 0)
{
LOG_E("upload has an error, stop uploading");
break;
}
else
{
LOG_D("buffer : {\"temperature\":%d}", temp);
}
/*延时,为湿度上传提供时间*/
rt_thread_mdelay(100);
/*上传湿度*/
if (onenet_mqtt_upload_digit("humidity", humi) < 0)
{
LOG_E("upload has an error, stop uploading");
break;
}
else
{
LOG_D("buffer : {\"humidity\":%d}", humi);
}
}
}
rt_thread_delay(rt_tick_from_millisecond(5 * 1000));
}
}
int onenet_upload_cycle(void)
{
rt_thread_t tid;
tid = rt_thread_create("onenet_send",
onenet_upload_entry,
RT_NULL,
2 * 1024,
RT_THREAD_PRIORITY_MAX / 3 - 1,
5);
if (tid)
{
rt_thread_startup(tid);
}
return 0;
}
MSH_CMD_EXPORT(onenet_upload_cycle, send data to OneNET cloud cycle);
int onenet_publish_digit(int argc, char **argv)
{
if (argc != 3)
{
LOG_E("onenet_publish [datastream_id] [value] - mqtt pulish digit data to OneNET.");
return -1;
}
if (onenet_mqtt_upload_digit(argv[1], atoi(argv[2])) < 0)
{
LOG_E("upload digit data has an error!\n");
}
return 0;
}
MSH_CMD_EXPORT_ALIAS(onenet_publish_digit, onenet_mqtt_publish_digit, send digit data to onenet cloud);
int onenet_publish_string(int argc, char **argv)
{
if (argc != 3)
{
LOG_E("onenet_publish [datastream_id] [string] - mqtt pulish string data to OneNET.");
return -1;
}
if (onenet_mqtt_upload_string(argv[1], argv[2]) < 0)
{
LOG_E("upload string has an error!\n");
}
return 0;
}
MSH_CMD_EXPORT_ALIAS(onenet_publish_string, onenet_mqtt_publish_string, send string data to onenet cloud);
/* onenet mqtt command response callback function */
static void onenet_cmd_rsp_cb(uint8_t *recv_data, size_t recv_size, uint8_t **resp_data, size_t *resp_size)
{
char res_buf[] = { "cmd is received!\n" };
LOG_D("recv data is %.*s\n", recv_size, recv_data);
/* user have to malloc memory for response data */
*resp_data = (uint8_t *) ONENET_MALLOC(strlen(res_buf));
strncpy((char *)*resp_data, res_buf, strlen(res_buf));
*resp_size = strlen(res_buf);
}
/* set the onenet mqtt command response callback function */
int onenet_set_cmd_rsp(int argc, char **argv)
{
onenet_set_cmd_rsp_cb(onenet_cmd_rsp_cb);
return 0;
}
MSH_CMD_EXPORT(onenet_set_cmd_rsp, set cmd response function);
#endif /* FINSH_USING_MSH */
注意:在上传温度和湿度的中间需要加入延时函数,因为数据时不断循环上传的,如果不加延时会导致湿度数据来不及上传。
四、运行调试
编译工程下载到开发板
输入命令onenet_mqtt_init进行MQTT初始化
输入命令onenet_upload_cycle进行温湿度循环上报
WiFi连接超时时间到达前请耐心等待开发板连接WiFi
查看云平台数据和上报数据是否一致,数据正常上报则说明实验成功。
**总结:**配置过程参考了rt_thread的官方文档说明
RT-Thread Onenet软件包配置文档
只是对软件包部分代码进行了修改。详情参考官方文档。