用Arduino做一個手柄及UI設計
這個東西其實是一年前做的,主要工作歸功於Dr. Adrian Daerr,我只是設計了UI寫了代碼,今天突然和人聊天想起來,細節已經忘得差不多了照片也沒留存,還是趁完全遺忘之前留存下來吧。
主要的材料是按鈕若干,一塊PCB板(或麵包板),一塊Arduino板,一塊Arduino支持的LCD屏幕。電阻電線焊錫什麼的自不必說。
Arduino實際上是一種單片機,可以看作是微型的計算機。它沒有多少內部存儲空間,也沒有操作系統。我們使用的方式通常是在Arduino提供的IDE(Arduino - Home可免費下載)中寫類似c語言的代碼,然後編譯上傳給Arduino板,Arduino會反覆執行這段程序。Arduino有十幾個針腳,可以用作數字或模擬信號的輸入和輸出,這些針腳可以被程序控制。與電源接通後Arduino可以提供5V或3.3V的電平,不過電流並不大,不能用作驅動高功率(>1W)的LED。Arduino很靈活很好玩,特別推薦給小朋友們當玩具。
Arduino的程序沒有main()函數,它有兩個基本的函數:setup()和loop()。setup()在Arduino通電或者按按鈕(圖中右上角)重啟時執行,只執行一次,通常用於初始化內部變數和Arduino的介面狀態。loop()則會被反覆執行,斷電或重啟之前都不會停止工作。
按鈕我們可以用這種(Omron Electronics Inc-EMC Div)
它的四個針腳兩兩一組,是接通的,而按鈕實際上是這兩組針腳之間的開關。首先我們把5-6個按鍵在PCB板上排成手柄的形狀,然後把它們其中一組針腳全部接起來,引出一根線作為地線。每一個按鍵的另一組針腳引出一根線,用作按鈕的控制輸入。大致的工作原理是正常情況下,控制線的電平被Arduino維持在高態,當相應的按鍵被按下時,接地短路使得控制線電平變為0.
然後我們可以把手柄的地線接在Arduino的地線口,控制線接在任意的介面(比如,1-6口)。我們在setup()函數中使用
pinMode(1, INPUT_PULLUP);n
將1號口設為輸入口,並讓Arduino將1號口與高電平相連,使其維持在高電平狀態。按鍵按下時,1號口的變為低電平,Arduino可以讀取這個值並發現按鍵被按下。
設計好手柄,我們就可以用它來控制設備的運作。一塊屏幕可以幫助我們知道我們的操作具體是幹了什麼,因此需要一定的UI設計。這裡屏幕我們使用Arduino LCD Screen,Arduino提供了庫函數來操縱這個屏幕。我們可以使用TFTscreen.text(char* string,int xoffset,int yoffset)函數來寫字,字元串的位置以字元串左上角為準,需要通過設定的字型大小和屏幕的解析度來計算像素,這是個蛋疼的活。
我們只使用了五個按鍵:上、下、左、右和確認,分別接在KP_Up,KP_Down,KP_Left,KP_Right和KP_OK口。一個比較直觀的設計是通過左右鍵選擇功能,通過上下鍵設定參數,確認鍵啟動設備。為此我們設計了3個畫面,放在setup()函數中。第一個畫面用於提示用戶設備已啟動,沒有特別的功能。
代碼中我們使用digitalRead函數來監視輸入信號,在輸入之前通過死循環來暫停程序運作。
while(digitalRead(KP_OK)) //Waiting to continuen {n }n
第二個畫面我們畫了箭頭來引導用戶切換功能和設置參數:
思路是使用變數cScreen作為當前屏幕的tag,在畫好屏幕之後等待用戶輸入,檢測到輸入後執行相應功能。左右鍵使cScreen減增1,同時使用取余來循環屏幕。上下鍵調整數值。居中對齊的相關計算很蛋疼。另外一個微小的輸入延遲有助於提升手感。注意每個參數的調整都設置了上下限。
偽代碼實現
don {n switch(cScreen)n {n case 0:n TFTscreen.text("Screen 1n", 33 , 14);n break;n n case 1:n TFTscreen.text("Screen 2n", 33 , 14);n break;n n ……//More screensn }n while(digitalRead(KP_OK) && digitalRead(KP_Up) &&n digitalRead(KP_Down) && digitalRead(KP_Left) &&n digitalRead(KP_Right))n {n }n if(!digitalRead(KP_OK))n {n break; //Exiting this modulen }n if(!digitalRead(KP_Left))n {n delay(200);n TFTscreen.stroke(0,0,0); //Set font color to blackn TFTscreen.rect(11,0,140,60);n TFTscreen.rect(11,74,140,40); //Draw something black to erasen TFTscreen.stroke(255,255,255); //Set font color to whiten cScreen=(cScreen-1+ScreenNum)%ScreenNum;n }n else if(!digitalRead(KP_Right))n {n ……//Similar with aboven }n elsen {n switch(cScreen)n {n case 0:n if(!digitalRead(KP_Up) && PhotoIntv_min<99)n {n delay(100);n ++PhotoIntv_min;n }n else if(!digitalRead(KP_Down) && PhotoIntv_min>1)n {n delay(100);n --PhotoIntv_min;n }n TFTscreen.stroke(0,0,0);n TFTscreen.rect(11,74,140,40);n TFTscreen.stroke(255,255,255);n break;n n case 1:n ……//Similar with aboven break;nn ………………//More screensn }n }n }while(1);n
第三個畫面只是展示了系統的工作狀態。
這樣一個使用手柄操控的實驗裝置就完成啦。
推薦閱讀:
※科幻片里的「暗物質 」,其實源自於宇宙觀測中的一次靈異事件
※物理系的人是怎樣學狹義和廣義相對論的?
※工程力學和經典力學有什麼異同?
※我很喜歡物理,為什麼還是學不好。?
※光有沒有慣性?