樂萬德 王永輝 趙妮 李珂 程海洋
(西安航空學(xué)院 陜西省西安市 710077)
近年來,Arduino 作為一款便捷靈活、方便上手的開源電子原型平臺,受到了很多高校的青睞。陸澤華等對Arduino 單片機(jī)在信息技術(shù)教育中的應(yīng)用進(jìn)行了探究[1],李梅等設(shè)計了基于Arduino 家居安防智能報警電路[2],許金等設(shè)計了可見光濁度檢測創(chuàng)新實驗[3],耿麗娟等設(shè)計了基于Arduino 的智能防盜系統(tǒng)[4],Arduino 的應(yīng)用和研究非常廣泛,如何利用好Arduino 培養(yǎng)學(xué)生的創(chuàng)新創(chuàng)業(yè)能力成為研究熱點。本文旨在在這些研究成果的基礎(chǔ)上進(jìn)一步探索基于Arduino 平臺的創(chuàng)新創(chuàng)業(yè)教育方法及過程。
Arduino 平臺包含各種型號的Arduino 板和Arduino IDE 軟件。Arduino 創(chuàng)始人于2005年開始討論這個項目,僅用了3 天時間就實現(xiàn)了最初的創(chuàng)意開發(fā)板[5]。Arduino UNO 于2011年9月份正式發(fā)布,目前廣泛應(yīng)用的是Arduino UNO R3,即第三版。Arduino 平臺具有豐富的控制板序列及擴(kuò)展板序列,支持多種傳感器及外圍電路,如Proteus 等仿真平臺對Arduino 具有越來越完善的功能支持[6]。LED燈、蜂鳴器、按鍵這幾個元器件雖然簡單,但這也是最基本最常用的聲光及控制器件。Arduino 基礎(chǔ)的開發(fā)板及套件具有很高的性價比,我們鼓勵學(xué)生在接觸更廣泛的傳感器甚至虛擬開發(fā)平臺之前,認(rèn)真做好基礎(chǔ)元器件的熟悉及創(chuàng)新實踐,正所謂大道至簡,然后觸類旁通。這種強(qiáng)化實踐基礎(chǔ)的方法在教學(xué)實踐中證明非常有效。
面對LED、蜂鳴器和按鍵開關(guān)等基本元器件實驗項目,通過按鍵控制來控制LED 等的亮和滅、控制蜂鳴器的響和停等基本操作學(xué)生基本都能想到;進(jìn)一步需要引導(dǎo)學(xué)生通過按鍵的次數(shù)來控制LED 燈的亮度等級、蜂鳴器的頻率變化等,逐漸體現(xiàn)出創(chuàng)意設(shè)計的意味;最后引導(dǎo)學(xué)生通過這幾個簡單元器件設(shè)計出了一個非常有趣的聲光組合“眼疾手快”訓(xùn)練器。其基本設(shè)計思路如下:
(1)“眼疾手快”訓(xùn)練器的LED 燈根據(jù)設(shè)置的難度等級進(jìn)行隨機(jī)閃爍,每次閃爍亮燈與滅燈的時間間隔由隨機(jī)函數(shù)產(chǎn)生,難度等級越高,隨機(jī)時間間隔越短。
(2)LED 燈亮起后,玩家第一時間按下按鍵,從LED 燈亮燈開始計時,在規(guī)定的時間內(nèi)按下按鍵被定義為“擊中”并得分,超時按下按鍵則本次按鍵不得分。規(guī)定的時間也與難度等級有關(guān),難度也高,留給玩家按鍵的時間越短。
(3)游戲需防止玩家一直按著按鍵或者連續(xù)不斷進(jìn)行按鍵等漏洞。
圖1:系統(tǒng)外圍電路及與Arduino 的接口
圖2:系統(tǒng)的兩個并行任務(wù)
(4)擊中得分,蜂鳴器發(fā)出得分音樂聲音。
(5)為增加娛樂性,游戲開始時響起特殊的音樂,提醒玩家游戲即將開始。
(6)項目可拓展,硬件上可拓展為雙LED,雙按鍵,雙手控制等多種拓展玩法。軟件上可隨著后臺數(shù)據(jù)的積累做統(tǒng)計后對游戲難度參數(shù)及分級做進(jìn)一步優(yōu)化。
根據(jù)上述創(chuàng)意,基于Arduino UNO 控制板及其對應(yīng)芯片ATmega328,用Proteus 設(shè)計外圍電路仿真電路圖及其與Arduino UNO 的接口如圖1所示,Arduino UNO 電路板略。LED 燈經(jīng)過分壓電阻后接在Arduino UNO 數(shù)字口IO7 上,設(shè)置為輸出模式。buzzer 分別接在IO3,設(shè)置為輸出模式。注意根據(jù)選用buzzer 的電氣特性參數(shù),有的buzzer 可能需要外接電源。本實驗中,選用集成了分壓電路的LED 等和集成功能的buzzer。按鍵分別接在A0 口模擬輸入口上。
為了項目的需要,亮燈滅燈時間不能采用固定的時間間隔,而是采用隨機(jī)數(shù)生成時間間隔。一方面,Arduino 系統(tǒng)不斷地查詢時間,如果時間滿足了預(yù)先隨機(jī)數(shù)對應(yīng)的時間,則LED 等的亮燈滅燈狀態(tài)發(fā)生變化。另一方面,Arduino 還要不斷地查詢開關(guān)狀態(tài)的變化,以確定開關(guān)的按下事件,并記錄下按鍵的時間,與亮燈的時間比對,以判定此次按鍵是否符合要求并進(jìn)一步觸發(fā)計分、播放提示音等動作。這樣,監(jiān)聽時間以決定LED 燈的亮滅與監(jiān)聽開關(guān)的狀態(tài)就形成了兩個并行的任務(wù),如圖2所示。
Arduino 默認(rèn)沒有操作系統(tǒng),對于這樣的并行任務(wù)需要自行設(shè)計處理。對于閃燈,學(xué)生首先想到的是用delay( )函數(shù),但delay( )會獨占CPU,任何一個任務(wù)使用了delay( ),其它任務(wù)也就停下來了,不適合并行任務(wù)。對于開關(guān)的觸發(fā)事件,學(xué)生首先想到的是中斷,但是中斷發(fā)生時delay( )函數(shù)不會生效,millis( )函數(shù)的計時數(shù)值也不會持續(xù)增加[5]。計時及計算時間差是本項目的關(guān)鍵因素之一,中斷方案將會非常困難。因此本項目中最合適的解決方案是利用millis( )或者micros( )函數(shù)。本項目選用millis( )函數(shù),函數(shù)則僅僅是一個時間記錄者,在LED 閃燈任務(wù)里用millis( )函數(shù)來控制閃燈并不會讓其他任務(wù)停滯。通過不停地循環(huán)查詢并記錄下LED 燈的亮燈時間和開關(guān)按下的時間,就可以模擬多任務(wù)的并行運行。本項目中引入基于millis( )函數(shù)的狀態(tài)機(jī),狀態(tài)機(jī)是一種能解決多任務(wù)并發(fā)的有效方法[7]。定義兩個狀態(tài)機(jī),一個狀態(tài)機(jī)記錄LED 等的狀態(tài)并采用相應(yīng)的策略,一個狀態(tài)機(jī)記錄按鍵的狀態(tài)及時間。
據(jù)前述分析,LED 狀態(tài)機(jī)以給定的一組隨機(jī)數(shù)進(jìn)行閃燈,設(shè)計LED 狀態(tài)機(jī)類圖主要成員如圖3所示。為了項目的擴(kuò)展性,系統(tǒng)設(shè)計中使用了面向?qū)ο蟮乃枷脒M(jìn)行類的封裝。LED 狀態(tài)機(jī)的關(guān)鍵參數(shù)包括LED 當(dāng)前是亮的狀態(tài)還是滅的狀態(tài),用變量ledState 來表示,另外需要記錄當(dāng)前LED 燈狀態(tài)的時間,以決定是否需要改變LED燈的狀態(tài),用變量ledChangeTime 來記錄某次狀態(tài)的起始時間點。當(dāng)LED 等變?yōu)榱翢魻顟B(tài)時,用ledOnTime 記下該時間點,供按鍵狀態(tài)機(jī)checkButtonState( )函數(shù)使用。
其它成員變量還包括:ledPin 是連接LED 的Arduino 端口號,flashTimes 是LED 閃燈的次數(shù),這兩個參數(shù)通過構(gòu)造函數(shù)傳入。randomFlahsTime 為一個長度為flashTimes 的數(shù)組,數(shù)組長度為閃燈次數(shù),數(shù)組中的元素通過隨機(jī)數(shù)函數(shù)獲得。
通過updateLEDState 函數(shù)結(jié)合LED 燈當(dāng)前狀態(tài)及當(dāng)前狀態(tài)的持續(xù)時間,根據(jù)閃燈隨機(jī)數(shù)時間對LED 燈的狀態(tài)進(jìn)行更新。
按鍵狀態(tài)機(jī)類如圖4所示。
圖3:LED 狀態(tài)機(jī)
圖4:按鍵狀態(tài)機(jī)
圖5:基于Arduino的手指靈敏度訓(xùn)練器實驗裝置
圖6:實驗結(jié)果及后臺顯示
項目選用的是按壓式開關(guān),需要判定按壓開關(guān)時按下還是彈起兩種狀態(tài)。按鍵狀態(tài)機(jī)的關(guān)鍵參數(shù)是按鍵當(dāng)前的狀態(tài)及之前按鍵的狀態(tài),分別用變量buttonState 和previousButtonState 來表示,如果當(dāng)前開關(guān)為按下狀態(tài),并不能判定開關(guān)按下事件發(fā)生,只有當(dāng)當(dāng)前開關(guān)為按下狀態(tài)且之前的狀態(tài)為彈起狀態(tài),才能判定為開關(guān)按下事件發(fā)生。
其他參數(shù)包括記錄開關(guān)按下的時間buttonDownTime。buttonPin是連接button 的Arduino 端口號。buttonCount 記錄按鍵的次數(shù),如果按鍵次數(shù)達(dá)到預(yù)設(shè)值,則再按下按鍵無效,有效地避免了選手不停地按鍵的作弊行為。
checkButtonState( )函數(shù)執(zhí)行上述算法規(guī)則,包括判定按鍵按下,記錄按鍵按下的時間,與LED 狀態(tài)機(jī)中的ledOnTime 比對,滿足閾值要求判定為按鍵擊中。
以LED 所連接的IO 口ledPin 和閃燈次數(shù)flashTimes 做為clsLED 構(gòu)造函數(shù)的參數(shù),以按鍵pin 腳buttonPin 及按鍵次數(shù)buttonCount 作為clsButton 構(gòu)造函數(shù),分別在setup 函數(shù)和loop 函數(shù)外分別構(gòu)造clsLED 和clsButton 的對象。在loop 函數(shù)里分別調(diào)用clsLED 的成員函數(shù)updateLEDState 和clsButton 的成員函數(shù)checkButtonState,實現(xiàn)兩個狀態(tài)及之間的協(xié)同工作。
通過狀態(tài)機(jī)類的設(shè)計,很容易構(gòu)造出多個狀態(tài)機(jī)對象,比如可以構(gòu)造第二組LED 燈及按鍵,同時針對左右手,進(jìn)一步提高可玩性。
為了提高項目的可玩性,對蜂鳴器進(jìn)行了tone( )函數(shù)音樂編程,tone 函數(shù)的原理不難,但要編出悅耳的音樂需要一些音樂知識和編程技巧。本文按鍵擊中聲音采用了頻率按正弦規(guī)律變化的警報音,使玩家提高注意力。進(jìn)一步的Arduino tone 的使用及音樂編程課參考文獻(xiàn)[8,9]。
實驗裝置如圖5所示。Arduino UNO 板7 號數(shù)字口接LED 燈,3 號數(shù)字口接蜂鳴器,A0 口接按鍵。LED 燈、蜂鳴器和按鍵為集成元件模塊、簡單易用,所需電源由UNO 板引出。為了實驗的方便和可擴(kuò)展性,采用了面包板進(jìn)行了轉(zhuǎn)接。
實驗中定義了不同的難度等級,以LEVEL1 為例,QUICKNESS 是閃燈后按鍵按下的最晚時間,TIMES 是總的允許的按鍵次數(shù),MININTERVAL 與MAXINTERVAL 為隨機(jī)數(shù)產(chǎn)生的取值范圍:
圖6為選擇難度級別LEVEL1的某次測試通過串口顯示的結(jié)果,按鍵時間與LED 亮燈的時間差如果小于規(guī)定的500ms,則蜂鳴器發(fā)聲且提示soundHitted OK 并且將記分。最后根據(jù)擊中的次數(shù)與總的允許按鍵的次數(shù)取百分比得到總成績score.本次實驗中一次擊中距離亮燈時間664ms,超過500ms,擊中失敗,沒有擊中提示且不計分,其他9 次均小于設(shè)定的500ms,因此最終成績?yōu)?0 分。實驗結(jié)果符合設(shè)計預(yù)期。
本文是在輔導(dǎo)大學(xué)生創(chuàng)新訓(xùn)練過程中,引導(dǎo)學(xué)生用聲、光、按鍵等基本元器件,培養(yǎng)學(xué)生創(chuàng)新思維過程中形成的項目。項目原材料簡單,但創(chuàng)意有趣,引入了狀態(tài)機(jī)很好地解決了LED 閃燈與開關(guān)按鍵查詢并行任務(wù),并基于此開發(fā)了手指靈敏度訓(xùn)練器,項目設(shè)計過程中用面向?qū)ο蟮乃枷牒头椒▽顟B(tài)機(jī)進(jìn)行了類封裝,方便項目進(jìn)一步拓展。該項目在大學(xué)生基于Arduino 平臺進(jìn)行創(chuàng)新實踐訓(xùn)練初級階段中起到了良好的效果。