2011年10月27日 星期四

v-usb for arduino USBKeyboard

USBKeyboard 是 V-USB for arduino 這個計畫所提供的一個範例,它實作了一個很簡單的 USB 鍵盤裝置。

這個範例名字其實取得不好,因為它並沒有真正做出一個 USB 鍵盤,事實上這個範例只用到一個按鈕,程式會在按鈕被按下時,送出 "hello world" 跟一個 Enter 的鍵盤訊息給電腦,所以也許應該把它稱作 USB Helloworld Button 比較恰當。先不管這個問題,我們還是繼續沿用 USBKeyboard 這個名字。

接下來,我們就來自製這個 USBKeyboard 吧。

硬體電路

首先,你必須為 Arduino 做個 USB Shield,底下是一個參考電路,由於 USB D+ 和 D- 用 3.3V 的電壓,因此在 D+ 和 D- 上使用稽納二極體 (Zener diodes)。你必須確保 D- 準位在 2.5V 與 3.6V 之間。

image_thumb135

做好 USB Shield 後,接著接一顆按鈕到 Arduino 的 pin 12 上。線路接法為: 把按鍵的一支接腳接到 pin 12,而另一支接腳接到 GND,這樣就行了,如下圖:

image
註:

本例會用到 Arduino 內部的提升電阻,所以按鈕是低態動作 (Active-LOW),在未按下時電壓是 HIGH,而按下時電壓是 LOW。這部份請參考「Arduino 的提升電阻」一文。

軟體下載與安裝

USBKeyboard 程式可以在底下的網址取得:

http://goo.gl/k5lq9

這是我修改過的版本,原始版本包在 V-USB for arduino 這個套件裏。我所做的只是整理工作,好讓程式碼看起來清楚易讀一些而已,沒做多少改變。

下載後,把 UsbKeyboard 複製到 Arduino Sketch Folder 的 libraries 或 arduino-00xx\libraries 資料夾下,這樣安裝程序就完成了。

韌體調整

接著韌體要做兩個調整:

  1. 修改 usbconfig.h:  定義所用的 D+ 和 D- data lines 腳位。必須根據你的硬體調整 USB_CFG_IOPORTNAME, USB_CFG_DMINUS_BIT 和 USB_CFG_DPLUS_BIT。其它不需要修改。 
  2. 這點很重要!由於 Arduino 的 timer0 ISR 執行時間太久,會影響 V-USB 的運作,所以你必須修改 Arduino-00xx\hardware\arduino\cores\arduino\wiring.c 的 Timer0 ISR,把 "sei();" 加到 ISR 的第一行,像這樣:

編譯與執行

打開 Arduino IDE,載入 UsbKeyboardDemo1 範例,把程式上傳到板子上。

參考下圖,在你把 USB Shield 放到 Arduino 板子上,將 USB cable 插到電腦後,「裝置管理員」視窗裏就會多出一個「USB 人性化介面裝置」:

image 

接著打開任何一個編輯器例如「記事本」,然後按下 Arduino 的按鈕,如果這時畫面上有出現 "hello world" 訊息的話,恭禧你!你已經完成了一個簡易的 USB Keyboard 了!

image

如下圖,假如你插上 USB Shield 後遇到「USB 裝置無法辨識」這個錯誤訊息,有幾個可能的原因,可能是你 USB Shield 線路沒做好,或是 usbconfig.h 沒有設定正確,或者是沒有把 "sei();" 指令加到 wiring.c ISR 的第一行。

image

主程式說明

底下是 USBKeyboard 的 Arduino 主程式 (USBKeyboardDemo.pde):

程式邏輯其實非常簡單,setup() 函式只是將 ledPin, buttonPin 腳位初始化。而在 loop() 函式中,程式會不斷的檢查 buttonPin 的狀態,檢查按鈕是否被按下,是的話就做兩件事,一個是打開 LED 指示燈,另一個是送出 "hello world" 跟著一個 Enter 的按鍵訊息給電腦端。當按鈕放開時,程式就把 LED 指示燈關掉。

希望藉由這個範例可以讓你知道,要自製一個 USB Keyboard 並非難事。這個 USB Keyboard 可以應用在什麼地方?接下來就是換你動腦發揮的時候了!^o^

延伸閱讀

6 意見:

提到...

您好! 請問一下,我的 arduino 板子是用
ATMega168V 晶片和 8MHz 的石英。
可是V-USB官網說:
Runs on any AVR microcontroller with at least 2 kB of Flash memory, 128 bytes RAM and a clock rate of at least 12 MHz.
請問要如何才能把板子改到12MHz以上呢?
(之前一直無法辨識裝置是因為這個原因嗎?)
謝謝您!

coopermaa 提到...

你手上的晶片是 ATMega168V ?
ATMega168V 速度最快只能跑到 10MHz,可能沒辦法跑 V-USB 喔。建議改用 ATMega168-20xx 系列的 MCU 並加一顆 16 Mhz Crystal

提到...

謝謝您,我用 ATMega8 做了一個 V-USB,
想請教您,像這種 V-USB 可不可以像
Arduino Uno Keyboard 的
Keyboard.print("hello world");
的這種輸出方式,因為如果用
sendKeyStroke(KEY_A);
沒設定好的話,它會變成打注音。
還有 V-USB 可以打出國字嗎?
(像這樣?Keyboard.print("您好");)
謝謝您!

coopermaa 提到...

你用 V-USB 做出來了嗎? 讚!

目前這個 Library 只提供 sendKeyStroke() function,如果想像 Arduino Uno 的提供 Keyboard.print() 這種輸出方式的話,可以參考我寫的 USBKeyboard Library 來改l http://coopermaa2nd.blogspot.com/2011/11/usbkeyboard-library.html

程式不難,不過我最近比較忙,抽不出時間弄,就先給你當作業好了,haha~~

USB keyboard 只能輸出標準鍵盤的 keystroke,所以要用 Keyboard.print("您好"); 輸出中文,如果是 USB-Serial 或許還有機會,用 USB Keyboard 的話,可能沒辦法喔。

提到...

嗚嗚~ 試了兩個晚上都沒成功,請求高手幫忙!
還有請問您什麼是USB-Serial呢?
謝謝您!

coopermaa 提到...

什麼沒試成功? 遇到什麼狀況?
USB-Serial 就是 USB 轉 Serial 的 Bridge 啊,根據轉出來的訊號,還可以分成 USB-TTL (即 UART),USB-RS232,USB-RS485.... 等幾種形式

USB-Serial 會實作 USB CDC 這份規格:
http://www.usb.org/developers/devclass_docs/usbcdc11.pdf