最早期的Arduino板子使用序列埠與電腦溝通,但現今一般電腦上已經找不到序列埠了(9針或25針),後來Arduino的板子採用FTDI公司的USB轉序列埠的晶片,讓電腦的USB埠化身變成虛擬序列埠;而Uno板改用Atmega8U2或Atmega16U2(R3),其實它就是一顆具有USB功能的微控制器,只不過在出廠時它預先燒錄具有「USB轉序列埠」功能的韌體,於是可作為電腦USB埠與Arduino板微控制器序列埠之間的中介橋樑。但我們可以讓8U2/16U2進入DFU(Device Firmware Update)模式,便可更新韌體,燒錄別的功能,譬如變成USB鍵盤,從Arduino板子傳送「按鍵」給電腦。
所謂DFU是USB規格的其中一項標準,讓USB裝置韌體更新的功能予以標準化,在Atmega8U2/Atmega16U2裡已含有DFU bootloader,我們從電腦將韌體傳給DFU bootloader,進行燒錄動作。
我的環境:電腦是Windows XP、開發板是Arduino Uno R3、Arduino軟體開發環境是1.0.5版。底下提到「韌體」時,若無特別註明,皆指8U2/16U2的韌體。
下圖紅圈處便是Uno R3的Atmega16U2,旁邊2x3針腳是它的ICSP接頭。
我們要做的事情有:
- 下載並安裝電腦端的DFU燒錄軟體,Atmel Flip。
- 讓Arduino Uno進入DFU模式,安裝它的DFU模式驅動程式。
- 燒錄「不斷送出hello world按鍵」的草稿碼到板子的微控制器晶片裡。
- 燒錄8U2/16U2的新韌體,變成USB鍵盤。
- 在電腦上看到從Arduino Uno不斷傳來的「hello world」。
然後請連接Arduino板電腦,可在裝置管理員裡找到代表板子的連接埠。下圖顯示出我的板子Arduino Uno R3。
要進入DFU模式,需重置8U2/16U2,作法是讓下圖的兩個腳位接觸一下(只需一下即可),其中一個是GND接地,另一個是RESET腳位,接觸一下即可重置。
若是R2以前的Uno板,必須在下圖這個位置焊接10K歐姆的電阻,我手上沒有這種板子,所以沒實際試過。
重置後,Windows XP電腦端就會發現硬體。
請選「從清單或特定位置安裝(進階)」。
然後選擇剛剛的Flip安裝目錄裡的usb子目錄,裡頭含有驅動程式。
接下來就稍等一下。
安裝成功囉。
然後在裝置管理員裡便可看到ATmega16U2。您的板子若不是Arduino Uno R3,將會看到別的晶片型號。
接下來,請到這裡下載,裡頭含有能讓Arduino板不斷送出「hello world」的草稿碼(helloworld/helloworld.pde),還有8U2/16U2的新韌體(Arduino-keyboard-0.3.hex),能讓Arduino Uno板變成USB鍵盤。
請拔除板子的電源與USB線進行重置,便可離開DFU模式回到一般的模式,然後燒錄(上傳)剛剛下載的helloworld/helloworld.pde。
接下來要燒錄新韌體,如前所述,讓8U2/16U2的RESET腳位接觸GND接地,一下即可,便可進入DFU模式,然後開啟Flip,出現如下畫面。
點按左上角看起來像是晶片的圖示,或是選「Device-Select...」,以我的例子而言,應選ATmega16U2。您應該選在裝置管理員裡所看到的晶片型號。
然後點按看起來像USB插頭的圖示,然後點按「USB」;或是選「Settings-Communication-USB」。
然後畫面便會從灰色變成彩色。
然後請選「File-Load HEX File...」,選擇剛剛下載的Arduino-keyboard-0.3.hex韌體,點按左下「Run」進行燒錄,然後點按右下的「Start Application」重置。
此時Arduino板便會是USB鍵盤,不斷地送出「hello world」,請隨便開啟一個文字編輯器,便會看到類似下圖的樣子。
若沒看到,可能板子並未重置成功,請手動拔掉板子的電源與USB線,再插入。
以上便上讓Arduino Uno變成USB鍵盤的過程,若你想讓板子回復到原來的樣子,只需重新燒錄原本的「USB轉序列埠」功能的韌體,位於Arduino目錄裡的hardware\arduino\firmwares\atmegaxxu2\arduino-usbserial\Arduino-usbserial-atmega16u2-Uno-Rev3.hex,這支是我Arduino Uno R3板的韌體,您應該找找適合你的板子的韌體,燒錄後即可還原,再以一般方式燒錄其他草稿碼即可。
參考資料:
- Adafruit Learning System的Arduino Tips, Tricks, and Techniques,從頭到腳徹底講解Arduino Uno這塊板子。
- Cooper Maa的如何讓 Arduino Uno 進入 DFU mode、如何用 FLIP 更新 Atmega8u2 的韌體、Arduino Uno Keyboard、USBKeyboard Library、Arduino Uno Mouse、Arduino 滑鼠自動點擊器,一系列的文章,一步一步介紹如何更新8u2/16u2的韌體,化身成為USB鍵盤或滑鼠。
- Arduino官方文件Arduino Uno、Updating the Atmega8U2 on an Uno or Mega2560 using DFU、MIDI Note Player using the MIDI firmware for the 8U2 (Uno and Mega2560 only)、USB Serial Light Adapter。
- Arduino Hacking blog的Arduino UNO Keyboard HID Part 1與Arduino UNO Keyboard HID part 2,詳細介紹如何開發AVR的韌體。
This comment has been removed by the author.
ReplyDelete不好意思請問一下
ReplyDelete我的Arduino似乎進不去DFU mode
我發現好像是16u2的韌體太舊,我剛好也有兩塊arduino,所以想要利用一塊當isp燒錄器來燒錄另一塊Arduino的16u2韌體
但是網路上的資料對於這方面有點複雜,不知道有沒有建議的方向或是資料願意提供呢?
感謝
我沒有用過一塊Arduino當ISP燒錄器來燒錄另一塊Arduino的16u2韌體,也沒用過單獨的ISP燒錄器來燒錄。
Delete沒有這方面的經驗。orz。
沒關係
ReplyDelete最近有找到相關資料了
http://blog.xuite.net/bv2ci/twblog/125382518-Arduino+UNO+R3+%E7%84%A1%E6%B3%95%E9%80%B2%E5%85%A5+DFU+%E6%A8%A1%E5%BC%8F
還是感謝你的幫忙!!
Good.
Delete有空我也會看看,謝謝。
你好,我是arduino新手,請問一下如果今天想要讓板子同時使用mouse click and USB keyboard,是要燒兩個HEX給板子(keyboard 和mouse)嗎?
ReplyDelete但是燒錄是不是一次只能燒一個?
我現在有一塊UNO板子,我想讓他同時可以控制滑鼠與鍵盤,那可以有同時做到這兩個方式嗎?
謝謝你的幫忙
這篇是換掉UNO的Atmega16U2的韌體,模擬USB鍵盤或USB滑鼠。
ReplyDelete根據我的了解,無法同時模擬。
如果是Leonardo,應該可以使用程式庫Keyboard與Mouse,同時模擬。
謝謝你即時的回覆!!
Delete那另外想請教一下,利用模擬USB滑鼠,如果我想要使用mouse.ckick();這個方法,再模擬滑鼠中要怎麼使用呢?
因為我找到的幾乎都是模擬滑鼠移動,不清楚如果我想要模擬double click或是click要如何使用?
真的太謝謝你的幫忙了
我找到似乎是用下面這個方式?
ReplyDeletemouseReport.buttons = 0;
mouseReport.x = 0;
mouseReport.y = 0;
mouseReport.wheel = 0;
但是細節部份還要釐清
呼叫click(button),傳入參數,
Delete參數見http://arduino.cc/en/Reference/MouseClick
我呼叫click他說只適用於arduino leonardo,為什麼會這樣呢
Delete程式庫Keyboard與Mouse只有Leonardo, Micro, or Due能用。
ReplyDelete恩是的,那我是用uno R3,然後目前是換掉UNO的Atmega16U2的韌體,模擬USB滑鼠。
Delete想請問如果在這種方式下,我想要做到跟mouse click這個方法一樣的話,在模擬滑鼠中要怎麼使用?
因為我找到的幾乎都是模擬滑鼠移動,不清楚如果我想要模擬double click或是click要如何使用?
謝謝你的幫忙。
參考http://coopermaa2nd.blogspot.tw/2011/11/arduino-uno-mouse.html
DeletemouseReport.buttons填入底下想要的值:
Bit 0 – Left Button
Bit 1 – Middle Button
Bit 2 – Right Button
恩謝謝你的幫忙,但是目前我不知道要怎麼表示在我想要的座標點去double click,
ReplyDelete例如我想要在(x,y)=(565,573)的地方按下double click,
以上面這個方法我不太清楚應該怎麼表示。
抱歉,我想順便問一下,
Serial.write((uint8_t *)&mouseReport, 4);
Serial.write((uint8_t *)&nullReport, 4);
這兩行是代表甚麼意思呢?
真的感謝你的回答,謝謝!!
Serial.write((uint8_t *)&mouseReport, 4);
DeleteSerial.write((uint8_t *)&nullReport, 4);
是把mouseReport的內容送往Serial,就此情況而言,會是送往電腦端,也就是把滑鼠的狀態,送給電腦。
因為double click就是送出兩次click,
所以應該要執行兩次上述的程式碼。
所以如果我想要在座標(56,57)地方滑鼠double click是這樣寫嗎?
DeletemouseReport.buttons = LEFT_BUTTON;
mouseReport.x = 56;
mouseReport.y = 57;
mouseReport.wheel = 0;
// Send
Serial.write((uint8_t *)&mouseReport, 4);
Serial.write((uint8_t *)&nullReport, 4);
Serial.write((uint8_t *)&mouseReport, 4);
Serial.write((uint8_t *)&nullReport, 4);
delay(50);
抱歉,因為我不清楚要在哪裡指定座標,謝謝你
試試看就知道了。
Delete葉難好師您好, 再參閱您的書後,順利寫出keypad之完成鍵。
ReplyDelete目前想以一個keypad藉由切換,來控制兩個加熱棒
以下是以一個keypad控制一家熱棒的程式
if (key != NO_KEY){
int b = key - 48;//因為是ASCII數值,所以才要-48
lcd.print(b);
if(key == '#'){
Serial.println(a);
lcd.clear();
lcd.print(a);
int ob = a;
analogWrite(heaterPin, ob); // heater輸出功率
}
else if(key == '*'){
a =0;//輸入錯誤從新開始打一次
int ob =0;
}
else{
a = a*10+b;
}
if(key == '*'){
lcd.clear();
}
}
想請教老師,該如何修改做出切換的功能呢?
(ex.同時按下*與#顯是初選擇的畫面,然後再輸入1or2 來選擇所要控制的加熱棒)
以下是我自己亂寫的程式,但無法順利達成目標
if (key != NO_KEY){
if(key == '*' && '#'){
lcd.print("select 1 or 2");
Serial.println("select 1 or 2");
if(key == '1'){
lcd.clear();
int b = key - 48;//因為是ASCII數值,所以才要-48
lcd.print(b);......恕刪
還望老師能指點一下 感激不盡 3Q !!
> 同時按下*與#
ReplyDelete這功能做不到吧。
試試看底下的程式碼。因為沒電路,所以沒測試過。
在heater功率數值最後加上'1'代表要給加熱棒1,加上'2'代表要給加熱棒2。
譬如輸入5431#的話,代表要把543設定給加熱棒1。
if (key != NO_KEY){
int b = key - 48;//因為是ASCII數值,所以才要-48
lcd.print(b);
if(key == '#'){
Serial.println(a);
lcd.clear();
if(a % 2 == 0){ // 代表偶數,代表加熱棒2
a /= 10;
analogWrite(heaterPin_2, a); // heater輸出功率
}
else{ // 代表奇數,代表加熱棒1
a / = 10;
analogWrite(heaterPin_1, a); // heater輸出功率
}
lcd.print(a);
}
else if(key == '*'){
lcd.clear();
a = 0;//輸入錯誤從新開始打一次
}
else{
a = a*10+b;
}
}
感謝 葉難老師的幫忙 以經順利完成了 !! 3Q~~~
Delete您好,
ReplyDelete小弟使用Arduino UNO R3 (from Arduino.Org)於Windows 7時,以老師教授的方法,將Atmega16u2之RESET與GND接觸一下後,
Win 7會自動安裝driver,並回報無法順利安裝,於裝置管理員發現Atmega16u2出現驚嘆號,手動更新驅動程式(指向"Flip 3.4.7\usb")後仍為驚嘆號,
執行Flip於USB時會出現"cannot open USB device",請問老師是否知道發生何事...
感謝幫忙!!!
問題就是「驅動程式沒裝好」。
Delete至於原因與如何解決,嗯,再試試看吧...
瞭解'感謝幫忙!!!
Delete改至Win XP已可進入DFU mode與安裝driver。
您好,
ReplyDelete請問燒錄Atmega16u2之hex file除了您文中提到之"Arduino-usbserial-atmega16u2-Uno-Rev3.hex",另外
在Arduino org之網頁 "http://labs.arduino.org/Guide+to+reflash+Atmega+16u2"
提到需用"UNO-dfu_and_usbserial_combined.hex",老師是否知道兩份hex file有何不同...
小弟將hex file燒錄至Atmega16u2、並將bootloader燒錄至Atmega328P-PU後,目前之Arduino UNO upload
Blink會出現以下message,不知老師是否知道原因...
感謝幫忙!!!
Arduino:1.7.7 (Windows 7), 板子:"Arduino Uno"
草稿碼使用了 1,030 bytes (3%) 的程式存儲空間。最大值為 32,256 bytes。
全域變數使用了 9 bytes (0%) 動態記憶體,剩餘 2,039 bytes 的局部變數。最大值為 2,048 bytes 。
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0xfa
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0xfa
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0xfa
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0xfa
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0xfa
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0xfa
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0xfa
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0xfa
上傳到板子時發生問題。可行建議請見http://www.arduino.cc/en/Guide/Troubleshooting#upload。
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0xfa
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0xfa
這份報告的詳情將會在
"編譯時顯示詳細輸出資訊"
在檔案 > 偏好設定裡啟用。
葉老師您好
ReplyDelete如果我要由rfid讀卡號再將卡號輸出應該如何做?
1.我會讀rfid顯示再lcd
2.轉變成usb鍵盤輸出字串
但是我兩個兜不起來成一個
既然已經能夠讀出rfid卡號,
Delete接著就是以usb鍵盤的身分,把卡號轉成一個個按鍵,送出去。
這一篇主要著重於韌體更換,程式部分,請參考
https://docs.google.com/file/d/0B4GOwiN2Qm96M2FiNmFmMjMtMjU5MS00N2E4LTk5MDUtNDVjYWI5MmExZjlm/edit
裡面的
helloworld.pde
看它如何送出helloworld等字母。
好....我試試...謝謝!
Delete葉老師您好
Delete那如果我要把RFID 讀取的卡號(serNum[0],serNum[1],serNum[2],serNum[3],serNum[4]) 多個 int 轉成一個字串(String)該怎麼做呢?
serNum是個別分開的嗎?還是應該看做一體?
Delete不就是直接丟入String嗎?
String myString = String(n);
或者,可使用stdlib.h的itoa()。
其實若有個int n;,可以直接送往序列埠,Serial.print(n),那就會轉成ASCII編碼的字串。
This comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
Delete板子是UNO R3 ATmega16U2
ReplyDelete進入DFU mode後回不去了...
開啟安裝路徑中的Arduino-usbserial-atmega16u2-Uno-Rev3.hex
到按run都正常
可是一按Start Application
視窗右下角的狀態欄
就從USB ON 變成 Communication OFF
然後會聽到硬體卸載的音效
在裝置管理員也看不到板子
需要短路RESET和GND才能再抓到板子
請問這是為什麼呢?
你想燒錄板子原本的韌體Arduino-usbserial-atmega16u2-Uno-Rev3.hex,對吧,
Delete需要做的動作,應該是從【請拔除板子的電源與USB線進行重置,便可離開DFU模式回到一般的模式...】此處往下。
至於你說的問題,我猜是步驟順序不對吧。不確定。
感謝葉老師的回覆!
Delete覺得奇怪的是我有成功燒錄keyboard-0.3.hex
也有成功的讓打出hello world
是在想燒回板子韌體時才出現Communication OFF的問題
當時也有試過老師所說的移除電源、USB重接
不過一接上電腦還是在DFU模式裡面回不來
覺得沒轍的把板子收起來兩天
沒想到再次拿出來的時候電腦抓到的是一般模式!!
也可以正常的進出DFU
難道是某些暫存器出了問題
因為斷電太久而釋放才變正常了嗎...
嘛,細節不明,無法回答。
Delete總之能動了,恭喜你。
如果我將蜂鳴器反用當作震動感應元件,當arduino收到震動時會讓電腦輸入一個英文字,請問程式碼該如何修改呢?
ReplyDelete摸索了一陣子都沒有頭緒,如果可以的話希望能為我解答,感恩
收到震動時,arduino傳出按鍵(文字)給電腦,不是嗎?
Delete> 如何修改呢?
問題太模糊了。
程式碼?
就是將原本會一直發送hello world修改成只要收到震動arduino就會傳出按鍵文字給電腦。
Delete由於最近才開始接觸arduino所以很多地方還不太明白,請見諒。
如你所說,
Delete在程式裡,不斷地偵測有無震動,
有震動時,就傳出代表按鍵的資料給電腦。
Best regards.
沒錯,就是這個意思,只是我一直搞不太清楚要怎麼做才能夠達到那種效果,請問該怎麼處理呢?
Delete我是想讀取A0的數值然後由數值大小判斷是否讓arduino輸入按鍵,目前嘗試的方法都沒辦法成功。
嗯,基本樣子應該如下吧
Deletevoid loop(){
int x = analogRead(A);
if(x > 800){
// do something...
}
else if(x > 400){
// do something...
}
else{
// do something...
}
}
This comment has been removed by the author.
Delete我目前已經做到這樣了,可是產生了按鍵變成壓著不放的狀況,請問需要加入什麼來讓按鍵放開呢?
Delete#define KEY_D 7
uint16_t val;
uint8_t buf[8] = { 0 };
void setup()
{
Serial.begin(9600);
pinMode(A0, INPUT);
//delay(100);
}
void loop()
{
val = analogRead(A0);
if(val>30){
buf[2] = KEY_D;
Serial.write(buf, 8);
}
delay(100);
}
要放掉按鍵
Deleteuint8_t keyNone[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
Serial.write(keyNone, 8);
成功了!!感謝!!
DeleteThis comment has been removed by the author.
ReplyDelete請問葉難大師你給程式碼能更改輸出的HELLO WORLD嗎,能否改成其他文字?還是只能固定輸出HELLO WORLD?
ReplyDelete修改程式囉。
Delete
ReplyDelete請問葉老師如果要將紅外線、超音波感測器從序列埠上讀取到的多筆數值,輸出成TXT檔可行嗎(週邊界面是Arduino接USB->PC)? 還有主程式寫法是用存檔指令嗎(類似以下範例)?
#include "stdafx.h"
#include "iostream"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
int a[10];
for (size_t i=0; i<10; i++)
{
a[i] = 255;
}
while (true)
{
cin >> a[0];
if ((a[0] - a[9]) <-100)
{
cout << "black" << endl;
}
else
{
cout << "white" << endl;
}
for (size_t i=0; i<10; i++)
{
cout << "a[" << i << "]=" << a[i] << " ; ";
}
cout << endl;
for (size_t i=9; i>0; i--)
{
a[i] = a[i-1];
}
}
system("pause");
return 0;
}
用fstream,開檔,然後就可以用 << 與 >> 來存取檔案。
Delete我买了一个arduino uno r3 Arduino Uno R3 我想学习和使用它。请帮我看看它的基本用法和教程网站 Arduino Uno R3
ReplyDelete