<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

利用RT-Thread與MQTT實現智慧班車管理系統的設計

冬至子 ? 來源:Agony_L ? 作者:Agony_L ? 2023-10-09 10:55 ? 次閱讀

項目硬件開發總結
下面從開發者的角度對本項目進行總結:(因為不是寫paper所以比較隨意哈~)
項目采用的IoT架構,底層是STM32L475VET6潘多拉開發板+RT-Thread,對于RT-Thread的資源使用情況在論文中也有提到,這里直接截個圖:

1.jpg

RT-Thread使用情況詳情
內核層的信號量、郵箱、消息隊列等機制是用于線程同步以及線程通信的,中斷一開始是用于檢測PIN設備的IRQ,但是后來去掉了,原因是不好用,確實是用中斷的時候自己懶得調試了,程序運行會出現很多問題,所以直接開了個線程,這個后面會講到。

設備與驅動層中I/O設備模型是最基本的設備Model,所以不再贅述。UART設備是值得一提的哈。因為這個項目需要用到三個串口,即串口1用于Finsh組件調試,串口2用于NB-IoT通信,串口3用于GPS數據的URC解析,但是官方給的BSP中沒有添加串口3設備,所以需要自己添加UART設備。

添加UART設備
在RT-Thread文檔中心已經給出了詳細的添加步驟,所在路徑如下:

1.jpg

首先,需要本地安裝Cubemx,然后打開裁剪過的BSP目錄中的board文件夾
【關于BSP的裁剪工作可以通過ENV工具,使用scons—dist完成】
然后找到該文件夾

1.jpg

打開完成后如果Cube版本與官方制作BSP使用的Cube版本不同時會彈出如下提示框:

1.jpg

找到UART3選項,設置為異步模式

1.jpg

2.jpg

同時,需要注意的是USART3默認使用的端口,潘多拉開發板并沒有引出,所以需要到引出的PB10和PB11單獨設置端口的模式:

1.jpg

2.jpg

3.jpg

最后,需要打開board文件夾中的Kconfig文件,添加UART3選項:【建議使用Notepad打開,這樣打開的文件格式對稱,便于復制】

1.jpg

添加完成后,打開ENV工具輸入menuconfig命令,依次進入Hardware Drivers Config—->On-chip Peripheral Drivers—->Enable UART就可以看到新添加的UART3選項:

1.jpg

選中后重新生成工程,打開后記得重新編譯。這樣,UART3設備驅動已經添加成功。

適配軟件包
回顧一下本項目需要完成的功能,這里直接貼出了論文截圖:(懶了~)

1.jpg

AHT10軟件包的使用
將AHT10軟件包添加后,只需要關心應用層的邏輯即可。
我的應用層線程初始化都是在main線程中完成的,有關于AHT10數據采集線程的初始化如下:

1.jpg

線程入口函數如下:

static void aht10_thread_entry()
{
rt_device_t dev_temp = RT_NULL;
rt_device_t dev_humi = RT_NULL;
struct tmp_msg msg;
struct rt_sensor_data sensor_data;
rt_size_t res_temp,res_humi;
rt_err_t res;
res = rt_sem_take(send_AHT_sem, RT_WAITING_FOREVER);
if(res != RT_EOK)
{
rt_kprintf("getGps_thread take a nb semaphore, failed.n");
return;
}
dev_temp = rt_device_find("temp_aht");
dev_humi = rt_device_find("humi_aht");
if (dev_temp == RT_NULL)
{
rt_kprintf("Can't find device:dev_tempn");
return;
}
if (rt_device_open(dev_temp, RT_DEVICE_FLAG_RDWR) != RT_EOK)
{
rt_kprintf("open device dev_temp failed!n");
return;
}
if (dev_humi == RT_NULL)
{
rt_kprintf("Can't find dev_humi devicen");
return;
}
if (rt_device_open(dev_humi, RT_DEVICE_FLAG_RDWR) != RT_EOK)
{
rt_kprintf("open device dev_humi failed!n");
return;
}
while(1)
{
res_temp = rt_device_read(dev_temp, 0, &sensor_data, 1);
if (res_temp != 1)
{
rt_kprintf("read temp data failed!");
rt_device_close(dev_temp);
return;
}
else
{
// rt_kprintf("temp:%3dCn",abs(sensor_data.data.temp)/10);
msg.temp_value=(abs(sensor_data.data.temp)/10);
}
rt_thread_mdelay(10);
res_humi = rt_device_read(dev_humi, 0, &sensor_data, 1);
if (res_humi != 1)
{
rt_kprintf("read humi data failed!n");
rt_device_close(dev_humi);
return;
}
else
{
// rt_kprintf("hum:%2d%, timestamp:%5dn",abs(sensor_data.data.humi)/10);
msg.humi_value=abs(sensor_data.data.humi)/10;
}
rt_mq_send(tmp_msg_mq, &msg,sizeof(msg));
// rt_kprintf("======aht10-Thread Send a mq,msg.tem:%d,msg.hum:%d======rn",msg.temp_value,msg.humi_value);
rt_thread_mdelay(300);
}
}
在上述代碼中首先是獲取NB初始化完成后release的信號量;獲取成功后,再獲取注冊到Sensor框架中的溫濕度傳感器(注意:這里的溫濕度傳感器是分開的,可以通過list_device在Finshi終端查看);然后是打開設備并讀取溫濕度信息;最后將采集到的數據以郵箱機制發送到NB發送線程。這是整個AHT10軟件包的添加和數據的讀取工作(需要注意:AHT10是通過I2C進行通信的,所以需要開啟I2C設備框架)

lwgps軟件包的使用
lwgps軟件包是一個輕量級的gps的URC解析包,支持NEMA格式。在使用軟件包的時候也遇到過不少的坑哈,但是慶幸的是都已經解決了

可以直接使用該作者提供的驅動框架。特別需要注意的是:這里有一個小坑,可能很多人會忽略,軟件包已經使用了INIT_APP_EXPORT(lwgps2rtt_init);添加了lwgps的初始化,因此不需要在應用層調用,如果調用會出現我之前出現的報錯信息

1.jpg

2.jpg

線程入口函數如下:

static void getGps_thread_entry()
{
lwgps_t gps_info;
struct gps_msg gpsmsg;
float lati , longi;
rt_err_t res;
// res = rt_sem_take(send_Gps_sem, RT_WAITING_FOREVER);
// if(res != RT_EOK)
// {
// rt_kprintf("getGps_thread take a nb semaphore, failed.n");
// return;
// }
while(1)
{
lwgps2rtt_get_gps_info(&gps_info);
gpsmsg.lati_value=(gps_info.latitude);
gpsmsg.longi_value=(gps_info.longitude);
gpsmsg.hour=(gps_info.hours);
// rt_kprintf("GPS-Data:hour-->%drn",gpsmsg.hour);
rt_mq_send(gps_msg_mq,&gpsmsg,sizeof(gpsmsg));
rt_thread_delay(500);
}
}
使用PIN設備——MQ2數據采集
關于MQ2的數據讀取,并沒有使用到ADC設備,因為我想縮短開發周期趕論文┭┮﹏┭┮。我選用的是MQ2的DO輸出模式,通過調整電位器設置閾值,實現原理比較簡單哈,不再贅述。同時,它的軟件讀取工作也比較簡單。但是由于項目實時性要求,上行數據流是采用JSON封裝的,方便小程序端解析,所以需要持續發送采集數據,因此無論是檢測到可燃氣體還是沒有檢測到都要發送消息隊列。
詳細代碼如下:

static void test_thread_entry()
{
char TR_ARRAY[]="true";
char FA_ARRAY[]="false";
struct mq_msg mq2_msg;
while(1)
{
// rt_kprintf("testrn");
if(rt_pin_read(MQ2_PIN_NUM)==PIN_LOW)
{
memcpy(mq2_msg.msg,TR_ARRAY,sizeof(TR_ARRAY));
rt_mq_send(mq2_msg_mq,&mq2_msg,sizeof(mq2_msg));
rt_pin_write(BEEP_PIN_NUM, PIN_HIGH);
rt_thread_mdelay(500);
rt_pin_write(BEEP_PIN_NUM, PIN_LOW);
}
else{
memcpy(mq2_msg.msg,FA_ARRAY,sizeof(FA_ARRAY));
rt_mq_send(mq2_msg_mq,&mq2_msg,sizeof(mq2_msg));
}
rt_thread_mdelay(200);
}
}
使用PIN設備——紅外對射數據采集
紅外模塊采用的“消抖”操作,因為有可能車門位置經過的人會一直停留,所以按照按鍵消抖處理的,詳細的流程不再說明,直接上代碼了:

/* 紅外檢測線程入口函數*/
static void hw_thread_entry(void parameter)
{
static rt_uint8_t hw_up = 1; /
無人標志 /
/
初始化紅外對射模塊 /
rt_pin_mode(PIN_NUM_ADD, PIN_MODE_INPUT);
rt_pin_mode(PIN_NUM_SUB, PIN_MODE_INPUT);
rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
tmp_msg_mb = rt_mb_create("temp_mb0", MB_LEN, RT_IPC_FLAG_FIFO);
while (1)
{
/
檢測無人標志 /
if (hw_up && ((rt_pin_read(PIN_NUM_ADD) == PIN_LOW) ||
(rt_pin_read(PIN_NUM_SUB) == PIN_LOW)))
{
rt_thread_mdelay(50); /
延時消抖*/
hw_up = 0;
if (rt_pin_read(PIN_NUM_SUB) == PIN_LOW)
{
rt_kprintf("Having person-SUB!n");
rt_pin_write(LED0_PIN, PIN_HIGH);
if(people_num<=0)
{
rt_kprintf("The number of people is emptyn");
continue;
}
else{
people_num--;
rt_kprintf("The num of people is %drn",people_num);
//rt_mb_send(tmp_msg_mb,people_num);
// rt_mb_send(tmp_msg_mb,people_num);
}
}
else if (rt_pin_read(PIN_NUM_ADD) == PIN_LOW)
{
rt_kprintf("Having person-ADD!n");
rt_pin_write(LED0_PIN, PIN_LOW);//點亮
if(people_num>=30)
{
rt_kprintf("The number of people is full!n");
continue;
}
else{
people_num++;
rt_kprintf("The num of people is %drn",people_num);
// rt_mb_send(tmp_msg_mb,people_num);
}
}
}
else if((rt_pin_read(PIN_NUM_ADD) == PIN_HIGH) &&
(rt_pin_read(PIN_NUM_SUB) == PIN_HIGH))
{
hw_up = 1; /*無人標志 */
// rt_mb_send(tmp_msg_mb,people_num);
}
rt_mb_send(tmp_msg_mb,people_num);
rt_thread_mdelay(100);
}
}
使用AT設備——NB模塊初始化與NB模塊數據發送
首先需要在項目中添加AT組件,同時添加M5311軟件包,添加完成后,在應用層main線程中開啟NB初始化以及NB訂閱和發送線程(采用MQTT協議)

1.jpg

初始化線程入口函數如下:

//NB初始化線程:新建MQTT機制+連接MQTT服務器
static void NB_mqtt_thread_entery()
{
nb_client = at_client_get("uart2");
nb_resp = at_create_resp(1024, 0, rt_tick_from_millisecond(300));
if(at_obj_exec_cmd(nb_client,nb_resp,arv)!=RT_EOK)
{
LOG_E("The MQTT haven't inited successrn");
}
else{
LOG_E("MQTT HAVE INITED SUCCESSrn");
if(at_obj_exec_cmd(nb_client,nb_resp,"AT+MQTTOPEN=1,1,0,0,0,'',''")!=RT_EOK)
{
LOG_E("The MQTT haven't inited successrn");
}
else{//真正完成了新建MQTT機制和連接服務器
LOG_E("The MQTT haven inited successrn");
rt_pin_write(BEEP_PIN_NUM, PIN_HIGH);
rt_thread_mdelay(500);
rt_pin_write(BEEP_PIN_NUM, PIN_LOW);
rt_sem_release(nb_sem);//釋放信號量
rt_sem_release(send_Gps_sem);
rt_sem_release(send_AHT_sem);
}
}
rt_thread_mdelay(1000);
}
訂閱和發送線程入口函數如下:

static void NB_mqtt_send_thread_entery()
{
struct tmp_msg msg;
struct gps_msg GPS;
struct mq_msg mq2msg;
static rt_err_t result;
int pep_num=0;
result = rt_sem_take(nb_sem, RT_WAITING_FOREVER);
if(result != RT_EOK)
{
rt_kprintf("NB_mqtt_send_thread take a nb semaphore, failed.n");
return;
}else{
for(;;)
{
if(at_obj_exec_cmd(nb_client,nb_resp,"AT+MQTTSUB="pyr",1")==RT_EOK)//訂閱主題
{
rt_kprintf("The NB-IoT have subscribed the pyr topicrn");
break;
}
}
while(1)
{
if((rt_mq_recv(gps_msg_mq,&GPS,sizeof(GPS),RT_WAITING_FOREVER)==RT_EOK)&&
(rt_mq_recv(tmp_msg_mq, &msg, sizeof(msg), RT_WAITING_FOREVER)==RT_EOK)&&
(rt_mq_recv(mq2_msg_mq, &mq2msg, sizeof(mq2msg), RT_WAITING_FOREVER)==RT_EOK)&&
(rt_mb_recv(tmp_msg_mb,(int*)&pep_num,RT_WAITING_FOREVER)==RT_EOK))
{
rt_kprintf("---------->NB Send Thread Receive the data-hour:%d,tmp:%d,mq2:%s,pep_num:%drn",GPS.hour,msg.temp_value,mq2msg.msg,pep_num);
if(at_obj_exec_cmd(nb_client,nb_resp,"AT+MQTTPUB="pyr",1,1,0,0,"{"temp":%d,"hum":%d,"lati":%f,"longi":%f,"mq2":%s,"pep_num":%d}"",msg.temp_value,msg.humi_value,GPS.lati_value,GPS.longi_value,mq2msg.msg,pep_num)!=RT_EOK)
{
LOG_E("Send the MEssage of the MQTT failedrn");
}
// if(at_obj_exec_cmd(nb_client,nb_resp,"AT+MQTTPUB="pyr",1,1,0,0,"{"latitude":37.3862770000,"longitude":117.9898270000,"temp":23,"humi":60,"person":15,"smoke":false}"")!=RT_EOK)
// {
// LOG_E("Send the MEssage of the MQTT failedrn");
// }
}
rt_thread_mdelay(500);
// rt_thread_mdelay(1000); 有延時,所以采用0.5S-Debug測出來的
}
}
}

項目軟件開發總結
項目的應用軟件使用的是微信小程序,涉及到的內容包括:小程序適配MQTT客戶端連接服務器以及訂閱和發布消息、小程序云開發模式Serverless、小程序使用Map組件、小程序使用騰訊云SMS服務(個人版)、小程序實現左滑刪除樣式等內容… …另外,MQTT服務器使用的是EMQ搭建的免費版MQTT服務器。

這是使用的MQTT地址,目前仍然可以使用:EMQ服務器IP地址 ,支持端口號18083、8083、8084、18084訪問,同時提供匿名訪問.

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • PIN管
    +關注

    關注

    0

    文章

    36

    瀏覽量

    6235
  • UART接口
    +關注

    關注

    0

    文章

    124

    瀏覽量

    15085
  • RT-Thread
    +關注

    關注

    31

    文章

    1175

    瀏覽量

    38987
  • STM32L4
    +關注

    關注

    1

    文章

    42

    瀏覽量

    9287
  • MQTT協議
    +關注

    關注

    0

    文章

    91

    瀏覽量

    5253
收藏 人收藏

    評論

    相關推薦

    如何對RT-Thread內核有基本的了解?

    RT-Thread 的時鐘管理以時鐘節拍為基礎,時鐘節拍是 RT-Thread 操作系統中最小的時鐘單位。
    的頭像 發表于 07-19 10:12 ?6834次閱讀
     如何對<b class='flag-5'>RT-Thread</b>內核有基本的了解?

    如何利用RT-Thread開發的PahoMQTT軟件包與MQTT服務器進行通信?

    本教程就是介紹如何利用 RT-Thread 開發的 Paho MQTT 軟件包與 MQTT 服務器進行通信的。
    發表于 03-30 08:09

    RT-Thread編程指南

    RT-Thread編程指南——RT-Thread開發組(2015-03-31)。RT-Thread做為國內有較大影響力的開源實時操作系統,本文是RT
    發表于 11-26 16:06 ?0次下載

    RT-thread】如何將RT-thread系統移植到stm32

    設備,RT-Thread 又能使用在線的軟件包管理工具,配合系統配置工具實現直觀快速的模塊化裁剪,無縫地
    發表于 12-08 11:06 ?20次下載
    【<b class='flag-5'>RT-thread</b>】如何將<b class='flag-5'>RT-thread</b><b class='flag-5'>系統</b>移植到stm32

    RT-Thread AI kit開源:輕松實現一鍵部署AI模型至 RT-Thread

    RT-AK 是 RT-Thread 團隊為 RT-Thread 實時操作系統所開發的 AI 套件,能夠一鍵將 AI 模型部署到 RT-Thread
    發表于 01-25 18:18 ?3次下載
    <b class='flag-5'>RT-Thread</b> AI kit開源:輕松<b class='flag-5'>實現</b>一鍵部署AI模型至 <b class='flag-5'>RT-Thread</b>

    RT-Thread開源作品秀】基于RT-Thread的星務平臺研究

    本作品為了驗證星務軟件在RT-Thread系統運行的可行性,底層是否能夠驅動星務軟件,同時擴展RT-Thread應用范圍。ART-Pi作為衛星下位機,...
    發表于 01-25 18:26 ?5次下載
    【<b class='flag-5'>RT-Thread</b>開源作品秀】基于<b class='flag-5'>RT-Thread</b>的星務平臺研究

    RT-Thread全球技術大會:RT-Thread電源管理的意義

    RT-Thread全球技術大會:RT-Thread電源管理的意義是為了滿足用戶對性能需求,盡可能降低系統能耗以延長設備待機時間。 ? ? ? ? ? 審核編輯:彭靜
    的頭像 發表于 05-27 15:01 ?901次閱讀
    <b class='flag-5'>RT-Thread</b>全球技術大會:<b class='flag-5'>RT-Thread</b>電源<b class='flag-5'>管理</b>的意義

    RT-Thread全球技術大會:RT-Thread對POSIX的實現情況介紹

    RT-Thread全球技術大會:RT-Thread對POSIX的實現情況介紹 ? ? ? ? ? ? 審核編輯:彭靜
    的頭像 發表于 05-27 16:52 ?1592次閱讀
    <b class='flag-5'>RT-Thread</b>全球技術大會:<b class='flag-5'>RT-Thread</b>對POSIX的<b class='flag-5'>實現</b>情況介紹

    RT-Thread學習筆記 RT-Thread的架構概述

    的種種優越之處。RT-Thread 是一款完全由國內團隊開發維護的嵌入式實時操作系統(RTOS),具有完全的自主知識產權。經過 16 個年頭的沉淀,伴隨著物聯網的興起,它正演變成一個功能強大、組件豐富
    的頭像 發表于 07-09 11:27 ?4054次閱讀
    <b class='flag-5'>RT-Thread</b>學習筆記 <b class='flag-5'>RT-Thread</b>的架構概述

    RT-Thread文檔_RT-Thread 簡介

    RT-Thread文檔_RT-Thread 簡介
    發表于 02-22 18:22 ?5次下載
    <b class='flag-5'>RT-Thread</b>文檔_<b class='flag-5'>RT-Thread</b> 簡介

    RT-Thread文檔_線程管理

    RT-Thread文檔_線程管理
    發表于 02-22 18:28 ?0次下載
    <b class='flag-5'>RT-Thread</b>文檔_線程<b class='flag-5'>管理</b>

    RT-Thread文檔_時鐘管理

    RT-Thread文檔_時鐘管理
    發表于 02-22 18:28 ?0次下載
    <b class='flag-5'>RT-Thread</b>文檔_時鐘<b class='flag-5'>管理</b>

    RT-Thread文檔_內存管理

    RT-Thread文檔_內存管理
    發表于 02-22 18:30 ?0次下載
    <b class='flag-5'>RT-Thread</b>文檔_內存<b class='flag-5'>管理</b>

    RT-Thread文檔_中斷管理

    RT-Thread文檔_中斷管理
    發表于 02-22 18:30 ?1次下載
    <b class='flag-5'>RT-Thread</b>文檔_中斷<b class='flag-5'>管理</b>

    RT-Thread文檔_RT-Thread SMP 介紹與移植

    RT-Thread文檔_RT-Thread SMP 介紹與移植
    發表于 02-22 18:31 ?8次下載
    <b class='flag-5'>RT-Thread</b>文檔_<b class='flag-5'>RT-Thread</b> SMP 介紹與移植
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>