楊東軒 劉 碩 王 嵩
(北京工商大學網絡中心 北京 100048)
目前在一些辦事大廳等場景廣泛使用排隊叫號系統(tǒng),不少系統(tǒng)仍采用紙質的叫號方式。這種紙質方式既不利于環(huán)境保護又在內容顯示上無法實時更新。有些手機APP的叫號方式又有許多使用的局限性,包括可能暴露客戶信息等情況[1,2]。本文結合物聯(lián)網技術和基于低功耗Wi-Fi的電子手持號牌設計,給出使用該電子手持號牌較為完整的叫號系統(tǒng)設計與實現(xiàn)方法。
系統(tǒng)主要由電子號牌和服務器兩部分組成,它們同處于一個無線局域網之中。電子號牌以低功耗Wi-Fi芯片CC3200為核心,接收來自服務器端的無線數(shù)據(jù),提醒用戶當前的業(yè)務信息。服務器端由Linux系統(tǒng)及相關軟件構成,負責控制電子號牌的發(fā)放、叫號信息的數(shù)據(jù)廣播以及與對外提供系統(tǒng)交互接口。系統(tǒng)架構如圖1所示。
圖1 系統(tǒng)架構圖
目前市場較為常見的電子號牌一般都采用315 MHz左右的較低頻率無線調頻技術,使用數(shù)碼管顯示號碼,一般只有一個信號發(fā)射端用來手工發(fā)號和叫號,不能更改號牌的號碼,也不提供二次開發(fā)的接口。它們的無線發(fā)射端和接收端不具備組網功能,且信號覆蓋范圍固定,僅適用于快餐業(yè)務領域的叫號使用。
本文實現(xiàn)的電子號牌在系統(tǒng)構成方面更加復雜、應用范圍也更為廣泛。號牌具有文本顯示能力,包括顯示業(yè)務類型、辦理進度、時間和電量等信息。而且還有震動功能提醒客戶。由于服務器端和客戶端是使用Wi-Fi進行通信的,因此系統(tǒng)的覆蓋范圍可以根據(jù)AP的安裝位置進行靈活擴展。
系統(tǒng)設計初期,將電子號牌的外觀尺寸限定在普通的銀行卡尺寸大小,這就對其內部的電路設計提出了很高的要求。在核心器件低功耗Wi-Fi芯片的選型上,選擇了德州儀器的CC3200芯片,與同一應用領域的其他廠家的芯片相比[3-4],它具有外設接口豐富、工作電壓范圍更寬、開發(fā)周期較短等優(yōu)點,如表1所示。
表1 同類低功耗Wi-Fi芯片對比
硬件電路包含CC3200最小運行系統(tǒng)、OLED點陣顯示屏、振子電機驅動、霍爾效應開關傳感器及充電管理模塊。CC3200最小系統(tǒng)包含了能使該芯片正常運行的最少電路設計以及能支持其無線通信的天線電路設計。由于該主控芯片集成了一個ARM-Cortex M4內核的處理器和一個Wi-Fi網絡處理器[5],因此在電路板的布局和走線方面要嚴格按照TI公司給出的設計手冊進行,其中電源部分和射頻鏈路部分的設計尤為重要。為了滿足芯片啟動、發(fā)射和接收數(shù)據(jù)時的電流需求,電源相關引腳的走線必須滿足表2中的條件。
表2 CC3200引腳通過電流
射頻部分的布局則會影響信號的輸出功率、誤差向量幅度以及頻譜掩模。在射頻電路中,天線起到了將PCB引線中的導波轉換為自由空間中電磁輻射的作用,因此在布局中要盡量把陶瓷天線器件放到PCB板的邊緣,確保沒有其他信號線穿過天線底部。由于射頻部分走線要滿足其在2.4 GHz頻段工作時的阻抗為50 Ω,因此需要選擇適合的傳輸模型。本文選用具有地面結構的共面波導CPW-G(Coplanar Waveguide With GND)模型,該模型結構如圖2所示,其中εr為相對介電常數(shù),W為間隙寬度,S為走線寬度,h為電解質厚度[6]。
圖2 CPW-G模型結構
在顯示功能方面,選用像素尺寸為128×64的OLED點陣顯示屏,該屏幕可以同時顯示32個漢字或者64個半角字符,足以容納叫號業(yè)務所需顯示的內容。相比目前流行的LCD、QLED和LPD顯示技術,OLED具有自發(fā)光、厚度極薄、響應時間快、低功耗等優(yōu)點[7]。該款屏幕在2.8 V供電情況下,全像素點亮時的電流為28 mA,休眠狀態(tài)時則為1 μA。屏幕與主控芯片之間采用SPI串行總線連接,電路原理如圖3所示。
圖3 OLED屏幕電路
振子即微型的震動電機,通過將電能轉換為機械能起到震動提醒作用,是整個電路系統(tǒng)中最為耗電的部分。號牌采用的振子最大電流為120 mA,為了讓CC3200的GPIO口足以驅動該電機,采用NPN型的三極管作為驅動開關。如圖4所示,將電機的正負輸入端分別接到系統(tǒng)電源與三極管的集電極之間,為了防止電機停止時產生的反電動勢對其他電子器件造成損壞,還需要在電機的兩端并入一個二極管以作保護。
圖4 振動電機驅動電路
電子號牌沒有任何可供用戶操作的輸入設備,因此需要設計一個激活裝置來將整個電路系統(tǒng)從關閉狀態(tài)激活為開啟狀態(tài)。采用A3212型的超靈敏霍爾效應開關傳感器,可以在不使用物理觸控的條件下,通過磁場變化就可以改變該傳感器的輸出電壓。將該傳感器布局在PCB的邊緣,有助于更加靈敏地受到磁鐵的感應。如圖5所示,OUTPUT輸出引腳通過上拉電阻連接到主控芯片的GPIO口,該IO口用于將冬眠狀態(tài)的處理器喚醒為運行狀態(tài)。當垂直通過該傳感器的磁感應強度大于37 T的時候,輸出為低電平。
圖5 霍爾開關傳感器電路
使用一塊容量為700 mAH的鋰離子電池作為整個電路的供電來源,采用USB Micro接口作為號牌的充電接口,充電管理芯片的型號為TP4056。如圖6所示,當電路系統(tǒng)接入5 V的USB充電線后,USB接口的VBUS電源引腳通過限流電阻使NPN三極管CE兩端導通,發(fā)射極觸發(fā)主控芯片的GPIO口從而通知系統(tǒng)已經接入充電線。充電管理芯片的STDBY引腳為電池充電狀態(tài),當電池充滿電后會內部下拉到低電平。
圖6 充電管理電路
設備的主要耗電器件是屏幕、震動電機以及主控芯片,由于前兩者在運行期間的功耗基本是恒定不變的,因此為主控芯片制定合適的低功耗策略是關鍵所在。對于理想化的計算機系統(tǒng)而言降低核心處理器CPU的電壓和頻率均可以起到降低功耗的作用[8],如果把CPU看作是一個基于電容器的系統(tǒng),那么它的功耗滿足如下物理關系式:
(1)
式中:E為芯片消耗的能量,T為消耗能量所需的時間,U為運行電壓,f為芯片的工作頻率。
對于CC3200而言,雖然它的工作電壓范圍在1.76 V至3.6 V之間,但是為了簡化硬件設計,通常采用恒定的穩(wěn)壓電源,因此只需要通過改變芯片的運行頻率就可以滿足功耗的調整了,其物理關系滿足下式:
(2)
式中:Ttask為單個任務運行的時間。
而芯片在不同的運行頻率下,所處的工作模式也不同。CC3200內部包含兩個獨立的系統(tǒng),分別是Cortex-M4應用處理器(MCU)子系統(tǒng)和網絡處理器(NWP)子系統(tǒng),每個子系統(tǒng)都有若干種工作模式。在號牌的軟件實現(xiàn)中,分別用到了MCU的激活模式、低功耗深度睡眠模式(LPDS)以及冬眠模式。在激活模式時,它將以80 MHz的頻率運行應用代碼,此時MCU的功耗最高;在LPDS模式時,只保留特定寄存器的配置,但可以從網絡事件中喚醒;在冬眠模式時,功耗最低且僅由頻率最低的實時時鐘驅動,僅能由時鐘定時器或外部事件觸發(fā)喚醒,喚醒后重新加載串行Flash中的應用代碼運行。NWP的工作模式由其自身根據(jù)當前的網絡狀態(tài)和MCU的電源策略自動控制,分別在激活模式、LPDS模式和冬眠模式中自主切換[9]。
在號牌的實際使用過程中,針對不同的工作場景切換不同的工作模式,在保障運行效率的情況下使芯片功耗降到最低。表3給出了所有工作場景下芯片對應的電源模式以及電路各主要部分的電流使用情況。在號牌未被發(fā)出時,處于冬眠狀態(tài),此時功耗最低;當號牌被發(fā)出時,需要從冬眠狀態(tài)被喚醒,由于喚醒時機不確定,因此只能使用外部IO作為喚醒源;號牌在用戶手中的大部分時間是保持屏幕畫面不變的狀態(tài),處于LPDS模式,但是當處于接收廣播消息、屏幕時間定時刷新等事件時,便會被喚醒;喚醒狀態(tài)的號牌處于激活模式,此時進行屏幕刷新、網絡數(shù)據(jù)處理等業(yè)務。
表3 電子號牌電源工作模式
電子號牌與服務器之間的通信方案采用無握手機制的UDP協(xié)議報文。軟件整體結構基于FreeRTOS嵌入式實時操作系統(tǒng),采用TI官方提供的SimpleLink組件庫來實現(xiàn)網絡方面的編程,調用內置于芯片ROM的外設驅動庫(DriverLib)來對SPI、GPIO、ADC和定時器等外設進行編程。軟件的主函數(shù)運行流程如圖7所示。首先對CC3200的外設及硬件資源進行初始化,如OLED屏幕、外部輸入IO等;然后開始SimpleLink的任務調度器,該任務管理主處理器和NWP之間的消息通信;最后創(chuàng)建并執(zhí)行分別用于事件處理、UDP服務器和UDP客戶端的子任務。
圖7 號牌軟件運行流程
大部分工作時間里號牌處于接收服務器發(fā)送UDP廣播數(shù)據(jù)的狀態(tài),因此它將主要扮演UDP 服務器的角色,僅在第一次連接到服務器的時候才需要作為UDP 客戶端來向服務器發(fā)送激活消息。根據(jù)發(fā)送和接收不同的UDP報文,來驅動號牌在不同狀態(tài)之間切換。這些狀態(tài)包括:設備復位狀態(tài)、等待業(yè)務編號狀態(tài)、等待叫號狀態(tài)、被叫號狀態(tài)、過號狀態(tài)以及充電狀態(tài)。在大部分狀態(tài)改變的同時,號牌接收UDP報文的端口號也會隨之改變,在等待叫號狀態(tài)中,不同業(yè)務類型的號牌所監(jiān)聽的UDP端口也不同。這樣就實現(xiàn)了以端口號劃分業(yè)務類型的目的,在服務器廣播指定端口的UDP報文的同時,其他業(yè)務類型的號牌則不會收到該端口的報文。不接收報文意味著硬件不會從LDPS模式中被喚醒,從而節(jié)約了不必要的功耗開支。UDP報文與號牌狀態(tài)之間切換的流程如圖8所示。
圖8 號牌狀態(tài)切換流程
號牌軟件系統(tǒng)中有三個主要的任務,分別是:Task_MainProcess()(主處理任務),負責系統(tǒng)初始化、外設控制以及網絡報文數(shù)據(jù)處理;Task_UDPServer()(UDP服務器任務),負責接收來自服務器發(fā)送的UDP報文;Task_UDPClient()(UDP客戶端任務),負責向服務器發(fā)送UDP報文。當系統(tǒng)成功連接到指定SSID的AP后,首先會向服務器發(fā)送激活消息的數(shù)據(jù)包。在本次發(fā)送的數(shù)據(jù)中,加入該號牌的MAC地址作為唯一身份識別,用sl_NetCfgGet()獲取設備自身的MAC地址。無論是發(fā)送還是接收UDP數(shù)據(jù)包,都需要首先調用sl_Socket()創(chuàng)建UDP套接字,之后通過sl_SendTo()將封裝好的數(shù)據(jù)包發(fā)送出去。為了防止網絡阻塞、信號不好等意外情況導致目標地址無法正常收到數(shù)據(jù),在發(fā)送每個UDP報文的時候都連續(xù)發(fā)送N次同樣的數(shù)據(jù),一旦接收到服務器返回的數(shù)據(jù),則停止發(fā)送并執(zhí)行下一步操作,當?shù)贜次還沒有收到應答數(shù)據(jù),則判斷其運行狀態(tài)異常,系統(tǒng)調用rn_setup_power_policy()進入冬眠模式以備回收處理。當服務器成功接收到號牌發(fā)送的激活消息后,會做出相應的回答。號牌系統(tǒng)通過sl_RecvFrom()接收UDP報文,并使用sl_Bind()綁定接收數(shù)據(jù)的端口。如前文所述,UDP客戶端任務根據(jù)接收到的報文類型來使號牌切換狀態(tài)同時改變接收報文的端口號,該任務的運行流程如圖9所示。
圖9 UDP客戶端任務流程
服務器端的軟件采用GO語言編寫并運行于Linux系統(tǒng)之上。該語言編寫的代碼在編譯后生成一個靜態(tài)可執(zhí)行文件,在服務器上部署時完全不需要關心應用所需的各種包和庫的依賴關系,大大減輕了維護的負擔。
系統(tǒng)中主要用到了XML數(shù)據(jù)模型和關系型數(shù)據(jù)模型,前者用來存儲電子號牌硬件相關的數(shù)據(jù),后者用來存儲業(yè)務相關的運行數(shù)據(jù)。將每個電子號牌的射頻標簽EPC編碼和MAC地址存儲在XML文件中,如果需要更換或新增電子號牌,只需要更新該XML文件即可,該文件的存儲格式如下:
F4:B8:5E:45:EB:82
使用如下代碼將XML數(shù)據(jù)讀入到程序內存中:
data, err:=ReadFile(CONFIG_XML)
err=xml.Unmarshal(data, &cardslice)
for _, v:=range cardslice.Item
cardmap[v.Epc]=v.Mac
業(yè)務數(shù)據(jù)存儲到MySQL數(shù)據(jù)庫中的“system”表中,該表僅存儲非冬眠狀態(tài)即正在使用中的電子號牌的業(yè)務數(shù)據(jù)。每當發(fā)出一張新的電子號牌,使用InsertDB()向表中插入一條新數(shù)據(jù),并寫入EPC、MAC地址等基礎數(shù)據(jù);當電子號牌狀態(tài)發(fā)生改變后通過UpdateDB()改變該記錄的數(shù)據(jù);當電子號牌使用完畢并進入冬眠狀態(tài)后,通過DeleteDB()銷毀對應號牌的記錄。數(shù)據(jù)表“system”的結構和描述如表4所示。
表4 系統(tǒng)數(shù)據(jù)表結構
服務器端軟件的業(yè)務對象主要面向手牌硬件客戶端和上層叫號應用的調用,前者通過UDP協(xié)議與服務器端通信,后者通過HTTP API控制服務器做出相關動作。軟件開始運行后,首先初始化HTTP和UDP等網絡相關的監(jiān)聽接口,并通過串口檢查硬件發(fā)卡設備是否工作正常。服務器端軟件的結構如圖10所示。
圖10 服務器端軟件結構
GO語言有眾多優(yōu)秀的Web框架[10],但是本系統(tǒng)的HTTP接口僅面向上層應用之間的調用,不需要復雜的路由配置和HTML模板引擎,因此只使用GO的標準庫接口便可以實現(xiàn)功能。使用http.HandleFunc()接口把一個URL路徑綁定給相應的函數(shù),然后通過http.ListenAndServe()接口監(jiān)聽8080端口的HTTP請求。當客戶的應用調用指定的URL訪問服務器后,服務器會調用相應的函數(shù)執(zhí)行業(yè)務功能,同時以JSON格式的數(shù)據(jù)返回給客戶應用。以號牌發(fā)放流程為例,當HTTP端口收到來自客戶應用的發(fā)卡請求后會立即返回結果,因為發(fā)放操作涉及硬件控制,所以處理結果需要以異步主動查詢的方式獲取。如果發(fā)號機為空閑狀態(tài),則通過ttyS設備控制串口做出發(fā)號操作,此時客戶的應用可以定期調用查詢接口以查詢操作是否成功。如果以上步驟成功,則號牌會自動激活并向服務器發(fā)送相關UDP報文來請求分配業(yè)務號碼。
服務器在監(jiān)聽號牌上報的UDP報文的同時,還要根據(jù)HTTP接口調用的叫號操作向指定業(yè)務類型的號牌發(fā)送UDP廣播報文。使用以下代碼開啟UDP服務器:
addr, err:=net.ResolveUDPAddr(″udp″, ″:″+port)
conn, err=net.ListenUDP(″udp″, addr)
其中port為UDP服務器需要監(jiān)聽的端口號,然后循環(huán)調用以下代碼監(jiān)聽并讀取客戶端發(fā)送上來的UDP報文:
n, remoteAddr, err:=conn.ReadFromUDP(data)
與接收UDP報文的操作不同,HTTP接口的并發(fā)調用可能會引起多個同時發(fā)送UDP報文的操作,為了防止多線程之間在同時發(fā)送UDP報文的時候占用發(fā)送通道而發(fā)生異常,需要定義一個*sync.Mutex類型的互斥鎖來保證同時只有一個線程在發(fā)送報文,代碼如下所示:
broadipport:=fmt.Sprintf(″%s:%s″, ″192.168.1.255″, cardPort)
addr, err:=net.ResolveUDPAddr(″udp″, broadipport)
locker.Lock()
//阻塞其他發(fā)送報文的線程
_, err:=conn.WriteToUDP(data, addr)
locker.Unlock()
//釋放阻塞
從代碼可以看出發(fā)送報文并未指定任何目的IP地址而是使用廣播地址和指定的端口號來發(fā)送,因為系統(tǒng)規(guī)定不同的號碼業(yè)務對應不同的端口號,所以每次的叫號操作并不是把報文發(fā)送給特定IP的號牌客戶端,而是以端口號為分組的廣播發(fā)送。
3.3.1 外部HTTP接口
本系統(tǒng)對于外部應用來說相當于一個黑箱,各種應用只需要調用服務器提供的HTTP接口便可以操作整個電子號牌系統(tǒng)。HTTP接口部分說明如表5所示。
表5 HTTP接口
3.3.2 內部UDP協(xié)議
服務器與號牌客戶端之間處于一個內部網絡環(huán)境,不需要對第三方提供服務,為了簡化通信,直接使用OSI分層中屬于傳輸層的UDP報文進行通信。自定義報文的格式共分為幀頭、類型和內容三個段。其中幀頭段固定為2個字節(jié)的0x55和0xAA;類型段為1個字節(jié),用來區(qū)分當前報文的功能,分別有“設置號碼業(yè)務”類型和“叫號操作”類型;內容段的長度根據(jù)類型段來確定,如果類型為設置號碼業(yè)務,則內容段共15字節(jié),包含需要開啟的端口號、業(yè)務代碼類型、需要設置的號碼、當前叫到的號碼以及當前的時間戳。如果是叫號操作類型,則內容段共12個字節(jié),包含當前叫到的號碼以及該號碼的服務窗口名稱。
本文介紹了一種基于低功耗Wi-Fi的電子號牌系統(tǒng)的設計和實現(xiàn)方法。通過系統(tǒng)對外提供便捷的HTTP操作接口,可以與大部分目前的排隊叫號場景進行對接。系統(tǒng)的電子號牌不僅體積小,還可以在極低功耗的狀態(tài)下長時間休眠,有較好的使用價值和用戶體驗。