2011年10月29日 星期六

利用 Dropbox 同步你的 Arduino Sketches

Dropbox 很簡單好用,所以大受歡迎。底下分享一個小技巧,這個技巧可以讓你在不同電腦或作業系統 (Mac, Linux 或 Windows) 之間同步你的 Arduino Sketches。

install_graphic
▲ 圖片來源: Dropbox 

方法很簡單,只要兩個步驟:

首先,把你的 Arduino Sketches 以及 Libraries 放到 Dropbox 資料夾:

image

接著到 Arduino Prefrences 視窗把 Sketchbook location 設定到這個資料夾:

image

這樣就完成了。之後你就可以在不同電腦或是不同作業系統上同步與使用你的 Arduino sketches。真是方便!

image
▲ Arduino Sketchbook

UsbKeypad for Arduino

上一篇中我們自製了一個 USBKeyboard,這次來自製一個 USB 數字鍵盤 (Numeric USB Keypad)。

image
▲ USBKeypad: 照片來源

準備材料

除了 Arduino 板子和 USB Shield 外,你還需要一個 Keypad:

image

關於 Keypad 的介紹與使用方法,請參考我寫的「Arduino 筆記 – Lab18 讀取 3x4 Keypad 的輸入」這篇筆記。

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

2011年10月24日 星期一

V-USB examples for Arduino

我把 V-USB 提供的 4 支範例程式 (custom-class, hid-mouse, hid-custom-rq, hid-data) 移植到 Arduino 上了,現在你只要用 Arduino IDE 就可以上傳這 4 支範例程式:

image

在你開始之前,我希望你已經看過「V-USB 簡介」一文,知道 V-USB 是什麼,而且也希望你看過底下這幾篇,因為這 4 支範例程式的使用方法都寫在這幾篇裏,在這我就不再重述了:

準備硬體

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

image_thumb135

實物照片:

image
▲ 圖片來源: galileo  的 USB Shield

下載與安裝範例程式

Arduino 版的 V-USB 範例程式可以在底下的鏈結中取得:

下載後把檔案解壓縮到 Arduino-00xx\libraries 資料夾下,或是放到 Arduino 速寫簿(Sketchbook)資料夾的 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 打開範例程式並且上傳到 Arduino 板子上執行。

就這樣!

希望你可以順利使用這四支範例程式。如果你遇到什麼困難,歡迎留言或寫信來詢問。

延伸閱讀

2011年10月21日 星期五

V-USB hid-data 範例解說

承上篇,這篇將摘要說明 V-USB hid-data 範例程式。

hid-data 分成韌體和指令列工具 (commandline) 兩個部份。

韌體

usbconfig.h

底下是 hid-data 對 usbconfig.h 所做的調整:

  • USB_CFG_IOPORTNAME, USB_CFG_DMINUS_BIT 與 USB_CFG_DPLUS_BIT

這些設定 USB bus D+ 和 D- 所用的接腳。預設是:

#define USB_CFG_IOPORTNAME      D
#define USB_CFG_DMINUS_BIT      4
#define USB_CFG_DPLUS_BIT       2

  • #define USB_CFG_HAVE_INTRIN_ENDPOINT    1

這個設定 interrupt-in endpoint 1,這是 HID device 的必要選項。

  • #define USB_CFG_INTR_POLL_INTERVAL      100

這個設定 interrupt-in endpoint 1 的 poll interval,單位為 miliseconds,不能小於 10 ms。

  • USB_CFG_VENDOR_ID 與 USB_CFG_DEVICE_ID

這些設定 VID 和 PID。預設是:

#define  USB_CFG_VENDOR_ID       0xc0, 0x16
#define  USB_CFG_DEVICE_ID       0xdf, 0x05

資料表示方式是 low byte first,VID 0x16c0 和 PID 0x05df 是 obdev 提供的共享 VID/PID。

  • USB_CFG_DEVICE_NAME and USB_CFG_DEVICE_NAME_LEN

這些設定 Device Name 和資料長度,hid-data 把 Device Name 設成 "DataStore",資料長度是 9:

#define USB_CFG_DEVICE_NAME     'D', 'a', 't', 'a', 'S', 't', 'o', 'r', 'e'
#define USB_CFG_DEVICE_NAME_LEN 9

  • USB_CFG_DEVICE_CLASS 與 USB_CFG_INTERFACE_CLASS

這些設定 Device Class 和 Interface Class。hid-mouse 的設定為:

#define USB_CFG_DEVICE_CLASS        0
#define USB_CFG_INTERFACE_CLASS     3

USB 有定義一些常用的 device class,可在 USB Class Codes 這個頁面中找到,0 代表由 interface 指定。而 interface class 定義 3 代表這個是 HID Class。

  • #define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH    22

這個設定 HID report descriptor 的資料長度。你必須在程式裏定義一個叫 usbHidReportDescriptor 的陣列,用來存放 report descriptor,而且陣列 size 要跟這個設定一致為 22 bytes 才行。

  • USB_CFG_IMPLEMENT_FN_READ 與 USB_CFG_IMPLEMENT_FN_WRITE  

這會設定呼叫 usbFunctionWrite() 來處理 control-out transfer,而用 usbFunctionRead() 來處理 control-in transfer:

#define USB_CFG_IMPLEMENT_FN_WRITE      1
#define USB_CFG_IMPLEMENT_FN_READ       1

main.c

主程式分成 main() 和 usbFunctionSetup() 兩個函式。關於 main() 和 usbFunctionSetup() 兩個函式的說明,請參考「V-USB custom-class 範例解說」一文。

在這個範例程式中,main loop 的工作很單純,只是不斷呼叫 usbPoll() 讓 driver 處理工作。根據 V-USB 的說明,usbPoll() 至少每 50 ms 要跑一次。

底下是 hid-data的 usbFunctionSetup():

程式的邏輯是透過 bRequestRequest 判斷是不是 class request,假如是,再依 bRequest 判斷是哪一種 class request (Get Report, Set Report, Get Idle, Set Idle, Get Protocol 或 Set Protocol)。hid-data 只處 Get Report 和 Set Report 兩個 requests。在這個範例中,Get Report 是傳回 feature report 給 Host,而 Set Report 則是接收來自 host 端的 feature report。因為只有一個 feature report,所以 Get/Set Reports 沒有進一步判斷 ReportType (wValue high byte) 和 Report ID (wValue low byte)。

當收到 Get Report 或 Set Report 的 request 時,usbFunctionSet() 並沒有馬上把資料傳給 Host,而是回傳 USB_NO_MSG 讓 V-USB Driver 呼叫 usbFunctionRead() 和 usbFunctionWrite() 來處理。

usbFunctionRead() 的實作如下:

只是單純從 eeprom 讀取一塊資料 (data chunk) 並放到 buffer 給 Driver 處理。

而 usbFunctionWrite() 的實作如下:

也只是單純把從 host 收到的一塊資料 (data chunk) 寫到 eeprom。

HID Report  Descriptor

底下是 hid-data 所定義的 HID Report Descriptor:

上列定義一個 Feature Report,資料長度為 128 bytes。

指令列工具 (commandline)

指令列工具包含 hiddata.c 和 hidtool.c。hid-data 把開啟 USB device 以及 Get Report 和 Set Report 的功能集中到 hiddata.c。

主程式 hidtool.c 只是間接呼叫 hiddata.c 中的 usbhidGetReport() 和 usbhidSetReport(),假如是 usbhidGetReport() 會將收到的資料以 hex format 印出,除此之外,沒有值得一提的地方。

hid-data 利用 usb_control_msg() 發送 control message,usb_control_msg() 的原型為:

int usb_control_msg(usb_dev_handle *dev, int requesttype, int request, int value, int index, char *bytes, int size, int timeout);

以 Get Feature Report 為例,呼叫方法為:

其中 USB_TYPE_CLASS 指定 Class request,USB_RECIP_DEVICE 指定接收者為 Device,而 USB_ENDPOINT_IN 則是指定 Control-IN transfer。USBRQ_HID_GET_REPORT 表示 Get Report 的 request,而 wValue 高位元組為 USB_HID_REPORT_TYPE_FEATURE 表示要取 Feature Report,而低元組是 report number,在此為 0。

而 Set Feature Report 的呼叫方法則為:

其中 USB_ENDPOINT_OUT 指定 Control-OUT transfer。

延伸閱讀

2011年10月20日 星期四

V-USB hid-custom-rq 範例解說

承上篇,這篇將摘要說明 V-USB hid-custom-rq 範例程式。

hid-customer-rq 分成兩個部份:韌體和 PC 端的指令列工具 (commandline)。

hid-custom-rq 的功能跟 custom-class 範例一樣,因此底下的內容大部份都跟 custom-class 雷同。hid-custom-rq 跟 custom-class 不一樣的地方,在於 hid-custom-rq 是宣告成 HID device。

韌體

usbconfig.h

底下是 hid-custom-rq 對 usbconfig.h 所做的調整:

  • USB_CFG_IOPORTNAME, USB_CFG_DMINUS_BIT 與 USB_CFG_DPLUS_BIT

這些設定 USB bus D+ 和 D- 所用的接腳。預設是:

#define USB_CFG_IOPORTNAME      D
#define USB_CFG_DMINUS_BIT      4
#define USB_CFG_DPLUS_BIT       2

  • #define USB_CFG_HAVE_INTRIN_ENDPOINT    1

這個設定 interrupt-in endpoint 1,這是 HID device 的必要選項。

  • #define USB_CFG_INTR_POLL_INTERVAL      100

這個設定 interrupt-in endpoint 1 的 poll interval,單位為 miliseconds,不能小於 10 ms。

  • USB_CFG_VENDOR_ID 與 USB_CFG_DEVICE_ID

這些設定 VID 和 PID。預設是:

#define  USB_CFG_VENDOR_ID       0xc0, 0x16
#define  USB_CFG_DEVICE_ID       0xdf, 0x05

資料表示方式是 low byte first,VID 0x16c0 和 PID 0x05df 是 obdev 提供的共享 VID/PID。

  • USB_CFG_DEVICE_NAME and USB_CFG_DEVICE_NAME_LEN

這些設定 Device Name 和資料長度,hid-custom-rq 把 Device Name 設成 "LEDCtlHID",資料長度是 9:

#define USB_CFG_DEVICE_NAME     'L', 'E', 'D', 'C', 't', 'l', 'H', 'I', 'D'
#define USB_CFG_DEVICE_NAME_LEN 9

  • USB_CFG_DEVICE_CLASS 與 USB_CFG_INTERFACE_CLASS

這些設定 Device Class 和 Interface Class。hid-custom-rq 的設定為:

#define USB_CFG_DEVICE_CLASS        0
#define USB_CFG_INTERFACE_CLASS     3

USB 有定義一些常用的 device class,可在 USB Class Codes 這個頁面中找到,0 代表由 interface 指定。而 interface class 定義 3 代表這個是 HID Class。

  • #define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH    22

這個設定 HID report descriptor 的資料長度。你必須在程式裏定義一個叫 usbHidReportDescriptor 的陣列,用來存放 report descriptor,而且陣列 size 要跟這個設定一致為 22 bytes 才行。

V-USB hid-mouse 範例解說

承上篇,這篇將摘說明 V-USB hid-mouse 範例程式。

usbconfig.h

底下是 hid-mouse 對 usbconfig.h 所做的調整:

  • USB_CFG_IOPORTNAME, USB_CFG_DMINUS_BIT 與 USB_CFG_DPLUS_BIT

這些設定 USB bus D+ 和 D- 所用的接腳。預設是:

#define USB_CFG_IOPORTNAME      D
#define USB_CFG_DMINUS_BIT      4
#define USB_CFG_DPLUS_BIT       2

  • #define USB_CFG_HAVE_INTRIN_ENDPOINT    1

這個設定 interrupt-in endpoint 1,這是 HID device 的必要選項。

  • #define USB_CFG_INTR_POLL_INTERVAL      100

這個設定 interrupt-in endpoint 1 的 poll interval,單位為 miliseconds,不能小於 10 ms。

  • USB_CFG_VENDOR_ID 與 USB_CFG_DEVICE_ID

這些設定 VID 和 PID。預設是:

#define  USB_CFG_VENDOR_ID       0xc0, 0x16
#define  USB_CFG_DEVICE_ID       0xe8, 0x03

資料表示方式是 low byte first,VID 0x16c0 和 PID 0x03e8 是 obdev 提供的共享 VID/PID。

  • USB_CFG_DEVICE_NAME and USB_CFG_DEVICE_NAME_LEN

這些設定 Device Name 和資料長度,hid-mouse 把 Device Name 設成 "Mouse",資料長度是 5:

#define USB_CFG_DEVICE_NAME     'M', 'o', 'u', 's', 'e'
#define USB_CFG_DEVICE_NAME_LEN 5

  • USB_CFG_DEVICE_CLASS 與 USB_CFG_INTERFACE_CLASS

這些設定 Device Class 和 Interface Class。hid-mouse 的設定為:

#define USB_CFG_DEVICE_CLASS        0
#define USB_CFG_INTERFACE_CLASS     3

USB 有定義一些常用的 device class,你可以在 USB Class Codes 這個頁面中找到,0 代表由 interface 指定。而 interface class 定義成 3 代表這個是 HID Class。

  • #define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH    52

這個設定 HID report descriptor 的資料長度。你必須在程式裏定義一個叫 usbHidReportDescriptor 的陣列,用來存放 report descriptor,而且陣列 size 要跟這個設定一致為 52 bytes 才行。

main.c

主程式分成 main() 和 usbFunctionSetup() 兩個函式。關於 main() 和 usbFunctionSetup() 兩個函式的說明,請參考「V-USB custom-class 範例解說」一文。

在這個範例程式中,main loop 利用 usbInterruptIsReady() 檢查 Interrupt-In endpoint 1 的 buffer 是否可用,假如可以,便呼叫 advanceCircleByFixedAngle() 計算新的滑鼠座標,接著再呼叫 usbSetInterrupt() 把 reportBuffer 傳給 Host:

底下是 hid-mouse 的 usbFunctionSetup():

程式的邏輯是透過 bRequestType 判斷是不是 class request,假如是就依 bRequest 判斷是哪一種 class request (Get Report, Set Report, Get Idle, Set Idle, Get Protocol 或 Set Protocol)。hid-mouse 只處理 Get Report, Get Idle 和 Set Idle 這三個 requests。除了 Get Report 是必要的外,其它兩個 requests 可以省略不寫。事實上因為 Host 端的 HID Driver 已經知道 report 的格式,所以其實 host 也不會發出這些 requests。

HID Report  Descriptor

底下是 hid-mouse 所定義的 HID Report Descriptor:

上列定義一個標準滑鼠,有三個按鈕,X 和 Y 軸的相對座標,以及一個滾輪 (wheel)。而 report 的資料結構如下:

底下簡單說明這個 Report Descriptor 的結構:

首先,必須先定義 Buttons,總共有 3 個 Button:

每個 Button 狀態不是 0 就是 1:

3 個 Button 總共是 3 個位元:

這 3 個位元是 INPUT report:

其它 5 個位元是填充位元 (padding bits):

最後定義 X, Y 和滾輪:

把它們全當成 1 byte 的 signed integer,值域為 -127  到 +127:

每個 8 位元,總共 3 個:

把它們宣告成 INPUT report:

最後告訴電腦這是一個滑鼠:

就這樣。關於 HID Report Descriptor,你也可以參考「HID Report Descriptor 教學」這幾篇文章。

延伸閱讀

2011年10月1日 星期六

Arduino 1.0 RC 簡報上線

應 Openlab Taipei 社群發起人鴻旗的邀請,今天下午 (10/1) 到寶藏巖分享玩 Arduino 的心得,主題是「Openlab Taipei 共玩 Co-Play #12 Arduino 1.0 分享」,很榮幸可以跟與會的朋友介紹 Arduino 1.0 的新特色,這次聚會認識了幾位朋友,Ben, David, 達達, rick, 阿航還有一位不知名的正妹等。非常感謝鴻旗的邀請。

簡報已上線,可以在底下取得: