概述:
這是一個(gè)數(shù)據(jù)采集的裝置,本身沒有什么亮點(diǎn)。主要是基于RT-Thread操作系統(tǒng),驅(qū)動(dòng)NB模塊-BC26來實(shí)現(xiàn)數(shù)據(jù)的發(fā)送。值得一說的是RT-Thread本身有BC-26的驅(qū)動(dòng)包。不過這里并沒有使用,而是使用at-device軟件包來驅(qū)動(dòng)的BC26。因此稍微改一改內(nèi)部的代碼,就能驅(qū)動(dòng)其他的AT設(shè)備。話回正題,我使用at-thread的目的就是驅(qū)動(dòng)BC26建立TCP或UDP連接,使得板卡采集得到的數(shù)據(jù)能發(fā)送到我電腦上的TCP Server。當(dāng)然,除了數(shù)據(jù)上傳之外,也能實(shí)現(xiàn)上位機(jī)控制板卡。還有則是在代碼中發(fā)現(xiàn)利用郵箱+消息隊(duì)列來進(jìn)行數(shù)據(jù)傳輸和通信真的很爽。
開發(fā)環(huán)境:
- 硬件部分
- ART-Pi (主控)
- BC-26 (NB-IOT模塊)
- BHT11 (溫濕度傳感器)
- RT-Thread版本
- RT-Thread V4.0.2
- 開發(fā)工具及版本
- RT-Thread Studio V2.0.0 :RT-thread推出的IDE,免費(fèi)。
- Putty V0.73:開源免費(fèi)的一款工具,我純把他當(dāng)成串口助手使用
- 花生殼 V5 :內(nèi)網(wǎng)穿透工具。
- 網(wǎng)絡(luò)調(diào)試助手(MetAssist V4.3.13):網(wǎng)上下的,應(yīng)該比較出名。
RT-Thread使用情況描述:
- 內(nèi)核部分
- 調(diào)度器
- 消息隊(duì)列
- 郵箱
- 組件部分
- at_device
- UART
硬件框架描述
先附圖一張:
很簡單的一個(gè)框架,總共只有主控,傳感器,執(zhí)行器,以及比較重要的云平臺(tái),這四大部分。傳感器可以是任意傳感器,只要發(fā)送的數(shù)值種類不一次性超出兩種即可。執(zhí)行器我在這里使用了板載的LED燈充當(dāng)。云平臺(tái)則是利用網(wǎng)絡(luò)調(diào)試助手搭了一個(gè)TCP Server來充當(dāng)。由于我個(gè)人沒有固定外網(wǎng)IP,所以我如果直接使用網(wǎng)絡(luò)助手,是無法將ART采集得到的數(shù)據(jù)傳輸?shù)轿业碾娔X上的。因此我利用花生殼將我的IP映射到了外網(wǎng),使得板卡能連接到我創(chuàng)建的TCP Server上。
軟件框架說明
流程圖如下:
本人并不是很會(huì)畫流程圖,所以辛苦大家看一看介紹吧。
其實(shí)在這個(gè)板卡中是要燒兩套程序的,一套是bootloader負(fù)責(zé)初始化QSPI并且運(yùn)行QSPI內(nèi)的程序。所以這份程序是下載到片內(nèi)Flash的。另一份則是具體的功能添加的比較多的程序。他是運(yùn)行在QSPI中的。這兩個(gè)程序必須先運(yùn)行BootLoader否則QSPI中的程序是無法運(yùn)行的。而由于BootLoader的職責(zé)是讓程序從 0x08000000
跳轉(zhuǎn)到0x90000000
運(yùn)行所以,如果QSPI中沒有其他程序的話,Bootloader只會(huì)運(yùn)行一次,表現(xiàn)的現(xiàn)象就是只打印一個(gè)LOGO。
其實(shí)在RT-Thread中其實(shí)有BC26的驅(qū)動(dòng)包,可以直接拿來用,不需要自己再對(duì)BC26進(jìn)行初始化,但是我這里使用的是at_device驅(qū)動(dòng)包,所以自己要寫一部分的代碼,進(jìn)行初始化。創(chuàng)建郵箱和消息隊(duì)列則是為了兩者相互配合一起實(shí)現(xiàn)發(fā)送同步消息的功能。
數(shù)據(jù)采集線程和數(shù)據(jù)發(fā)送線程之間使用消息隊(duì)列+郵箱的方式實(shí)現(xiàn)消息同步,在這里數(shù)據(jù)采集線程可以有多個(gè),而數(shù)據(jù)發(fā)送線程我這設(shè)立了一個(gè)。發(fā)送線程會(huì)將接收到的信息都發(fā)送到云平臺(tái)中。
數(shù)據(jù)接收則是利用at_device中的代碼實(shí)現(xiàn)的。利用內(nèi)部的代碼還可實(shí)現(xiàn)云平臺(tái)發(fā)送消息控制板卡上的LED燈或者其他執(zhí)行器。
軟件模塊說明
- 消息隊(duì)列+郵箱的消息同步方式
在使用消息隊(duì)列+郵箱的方式來進(jìn)行線程間消息同步的話需要先創(chuàng)建一個(gè)結(jié)構(gòu)體,一個(gè)動(dòng)態(tài)郵箱,一個(gè)消息隊(duì)列。然后對(duì)結(jié)構(gòu)體進(jìn)行填充后利用消息隊(duì)列發(fā)送出去,具體請(qǐng)看以下代碼示例:
//創(chuàng)建結(jié)構(gòu)體部分
struct msg //消息隊(duì)列發(fā)送此結(jié)構(gòu)體的地址來實(shí)現(xiàn)線程間的同步
{
char *str;
int vol;
float data1;
int data2;
struct rt_mailbox* ack;
};//創(chuàng)建動(dòng)態(tài)郵箱部分
rt_mailbox_t mail_box1 = RT_NULL; //創(chuàng)建二氧化氮線程應(yīng)答郵箱控制塊
rt_mailbox_t mail_box2 = RT_NULL; //創(chuàng)建二氧化硫線程應(yīng)答郵箱控制塊
rt_mailbox_t mail_box3 = RT_NULL; //創(chuàng)建粉塵數(shù)據(jù)線程應(yīng)答郵箱控制塊
rt_mailbox_t mail_box4 = RT_NULL; //創(chuàng)建備用線程郵箱控制塊/**************創(chuàng)建多個(gè)應(yīng)答郵箱******************/
int move_mail_box_sample(void)
{
mail_box1 = rt_mb_create("mail_box1", 1, RT_IPC_FLAG_FIFO); //創(chuàng)建動(dòng)態(tài)郵箱1
mail_box2 = rt_mb_create("mail_box2", 4, RT_IPC_FLAG_FIFO); //創(chuàng)建動(dòng)態(tài)郵箱1
mail_box3 = rt_mb_create("mail_box3", 4, RT_IPC_FLAG_FIFO); //創(chuàng)建動(dòng)態(tài)郵箱1
mail_box4 = rt_mb_create("mail_box1", 4, RT_IPC_FLAG_FIFO); //創(chuàng)建動(dòng)態(tài)郵箱1
}//填充發(fā)送
struct msg msage;
msage.str = "NO2";
msage.data1 = data1;
msage.ack = mail_box1;result = rt_mq_send(&mq,&msage, sizeof(struct msg)); //發(fā)送消息隊(duì)列
if(result != RT_EOK)
{
rt_kprintf("消息發(fā)送失敗rn");
}//接收處理
LOG_I("準(zhǔn)備接收各個(gè)數(shù)據(jù)rn");
data_send = at_create_resp(128, 0, rt_tick_from_millisecond(5000)); //分配內(nèi)存,并設(shè)定超時(shí)接收時(shí)間.準(zhǔn)備接收消息隊(duì)列
if (data_send == RT_NULL)
LOG_E("響應(yīng)結(jié)構(gòu)沒有內(nèi)存!");if(rt_mq_recv(&mq, &msage, sizeof(struct msg), RT_WAITING_FOREVER) == RT_EOK) /**接收消息隊(duì)列**/
{
rt_kprintf("收到信息:%srn",msage.str);
linshi = (int)msage.data1 *10;
rt_kprintf("收到發(fā)送的消息%drn",linshi);
抱歉,第一次寫,不知道重點(diǎn)在哪,先這樣吧。
演示效果
- 圖片
- 視頻
比賽感悟
首先非常感謝舉辦方舉辦的這場比賽,這也是我第一次參加這樣的比賽,也正是此次比賽讓我認(rèn)識(shí)到了和同齡人的差距,也讓我感受到了這么多的奇思妙想。很多參賽者的構(gòu)思和實(shí)力令我嘆為觀止。我個(gè)人是沒有做過什么項(xiàng)目的,也沒進(jìn)行過系統(tǒng)的學(xué)習(xí),RT-thread對(duì)我來講也是一個(gè)接觸沒多久的新事物。我對(duì)其也只是會(huì)使用一些皮毛。從大一到現(xiàn)在也只是接觸一些PLC和電動(dòng)機(jī)。對(duì)于ARM都是憑著一份愛好去做。一直以來沒有什么眼界和想法。通過這次比賽我發(fā)現(xiàn),它的能力超出了我的想象。對(duì)我指明了一點(diǎn)前進(jìn)的方向。并且在使用RT-Thread的過程中,我發(fā)現(xiàn)編程并不像以前那么復(fù)雜了。在使用RT-Thread的時(shí)候我可以不再考慮怎樣實(shí)現(xiàn)一個(gè)模塊的驅(qū)動(dòng),而是將重點(diǎn)放到了邏輯上,這對(duì)來講還是比較新奇的。最后其實(shí)是想對(duì)官方人員道個(gè)歉的,畢竟這款作品由于時(shí)間的原因,并沒有進(jìn)行細(xì)改,而是一個(gè)趕出來的作品。沒有擺正心態(tài),真的很抱歉。