1. 程式人生 > >Arduino微控制器使用和開發問題記錄

Arduino微控制器使用和開發問題記錄

1、將程式上傳到板子時Arduino IDE提示“avrdude: stk500_getsync(): not in sync: resp=0x00”

網上查遇到這個問題的人比較多,有說驅動問題的,有說IDE設定問題的。具體到我遇到的這個情況,原因是板子上插了RF24無線傳輸模組(也許線還沒有插對),拔掉以後再上傳程式就正常了。

2、nRF24L01+無線透傳使用問題

Arduino官網上似乎推薦Mirf這個庫,遇到一個問題,接收端執行幾分鐘後停止響應;試了另外一個RF24庫,遇到傳輸不穩定的問題,一時沒有解決,還是回到Mirf了,之前的停止響應問題沒有再出現。

這個論壇關於無線透傳的討論不少,雖然用arduino的不多。

Mirf的地址問題:Mirf的address是有長度要求的,例如可以用“serv1”、“clie1”作為地址,長度過短會導致無法傳輸,例如用“cl2”作為地址。試了好多次才發現這個問題。

nRF24L01模組(使用Mirf庫時)的自動應答問題:專案裡使用一個nRF24L01(服務端)接收多個nRF24L01(客戶端)的訊息,發現客戶端之間互相收到本應發到服務端的訊息,經過多次試驗,發現應該與nRF24L01的自動應答機制有關。在Mirf.cpp的setTADDR方法裡可以看到,目標地址被同時寫到RX_ADDR_P0和TX_ADDR這兩個暫存器裡,前者是接收自動應答使用的(一個nRF24L01可以有6個接收地址同時工作),導致peer發到服務端的訊息也被當作自動應答了。為避免這種干擾,我實驗下來的方法是:每個客戶端在傳送資料之前先setTADDR到一個無效且唯一的地址,在send之前那一刻再使用setTADDR將地址設定到服務端的地址,傳送完成後馬上setTADDR到那個無效地址。

3、Arduino與Android通過usb通訊

利用usb-serial-for-android這個開源專案。注意,兩側的baudrate要設定一致;android端讀取到的資料可能是不完整資料,需要多讀幾次以便補齊。

“The nature of hardware device interfaces like these is that there is typically no guarantee your data will arrive in a single read(). If you expect 16 bytes of data, you need to read(), successively, until you have received all 16.  If you want to read until there is a newline, you will need to scan all characters until you find a newline -- and then save anything received after it for later.” 

來源連結

4、關於arduino裝置的唯一ID

最後決定使用的方案是:寫一個專門的小程式(量產程式),對每個arduino執行一次,在EEPROM裡寫入唯一的id號。正式程式執行時只需讀取,不做修改。程式碼參考

注意:EEPROM的擦寫次數是有限制的,一般標稱為10萬次,但有人聲稱實驗結果只有100次左右。還好,這個比較靠譜的實驗測試結果是超過100萬次,總之寫入EEPROM時慎重。

5、溫溼度感測器DHT11

3.3v/5v通用,接數字訊號口,使用DHT11這個庫獲得資料。DHT11精度不高,若要求高可使用DHT22(也叫AM2302)。

6、同一段程式碼在兩塊板子上執行效果不同

兩塊板子都是uno+sensor shield+nrf24l01,其中一塊執行完全正常,另一塊無法接收到訊息(可以傳送訊息)。交換sensor shield(連同上面的nrf)無效,交換usb線無效,接外接12v電源無效。最後發現如果在程式碼的loop()里加delay(100)則基本能接收到訊息,但還有部分丟包。兩塊板子是從不同賣家處購買的,看來還是有區別啊。

7、Arduino nano v3.0接nrf24l01模組不工作問題

nano直接連nrf24l01模組無法收發資料;但用nano先接感測器擴充套件板(sensor shield,像這種),再把nrf24l01接到擴充套件板上,則工作正常。仔細檢查過連線沒有問題,且分別替換過nano和nrf模組usb線等,都沒有效果。最後發現nano板子上的3.3v針腳電壓不對,幾乎是零,聯絡賣家檢查後說是nano上少一根線,要把usb口背後的兩個電容(C1和C7)靠近晶片的引腳短接,照此方法問題解決。而擴充套件板上的3.3v針腳是用asm1117-3.3從5v降壓得來,所以沒有這個問題。

nano的官方文件說只有用usb供電時3.3v針腳才有電壓,但經實驗,我手上的這一版(電容短接後)不論用usb供電還是通過vin供電,3.3v針腳都有3.3v電壓。

8、無法上傳程式到arduino pro mini

使用ft232rl連線arduino pro mini,上傳程式時提示:

stk500_getsync(): not in sync: resp=0x00

上傳時按reset按鈕不起作用,DTR線也已經連線。經過反覆實驗,發現兩個問題導致這個現象:1)arduino上的RX應該接ft232rl的TX,TX接RX,我一開始接反了;2)一開始用的FTDI的驅動是最新的2.0.8.30,在這個帖子的提示下,降級到2.0.8.24後問題解決。PS.最好搜尋並下載CDM20824_Setup.exe檔案以便強制降級。

又測試了一下DTR線的作用,如果連線了DTR線,直接上傳程式就可以成功;如果不連線DTR線,在提示Uploading時立刻按一下arduino的reset按鈕,也可以上傳成功,不按按鈕則上傳失敗。

Update 2014/2/19: 不知道什麼原因,ft232rl又無法上傳程式到arduino pro mini了。這個帖子裡有人提到在DTR線上加一個100nF的電容是關鍵的一步,但我手邊沒有這個電容,而且即使我不連線DTR線採用手動reset的方式仍然不行。後來使用PL2303模組的下載線(只有四個腳,與ft232rl相比少了DTR腳)配合手動reset方式可以正常上傳程式到arduino。

9、Arduino的資料型別

Arduino的長整型是32位的,而Java裡是64位,互傳資料時別搞錯了。關於arduino裡的資料型別

10、電池供電方案

我花了不少時間在研究各種供電方案上,要平衡電池容量和帶來的體積增加,還要考慮電池成本因素:

方案1: 5號/7號乾電池供電,為達到至少3.3v的電壓以便驅動arduino pro mini+nrf24l01,需要至少三節電池,體積太大放棄;

方案2:CR2032鈕釦電池供電,同樣電壓不足(標稱3V),實測3.2V但後來會有電壓下降,在3V左右arduino能啟動但無線模組不正常;

方案3:3.7V鋰電池供電,這是目前採用的方案,目標是讓一塊250mAh的鋰聚合物電池能維持裝置執行2個月以上。為節約成本和體積,鋰電池充電模組將採用外接的方式。

這段程式碼可以檢測當前VCC腳的電壓(僅支援328和168),有助於實現提示電池電量不足,我在pro mini 5v上實測可用。

11、減小工作電流

目前採用arduino pro mini 5v/16MHz版本,這個版本在tb上的售價為13元人民幣左右,而3.3v/8MHz的版本要17元左右,實測5v版本用3.3v電源(輸入VCC)仍然可用,只是這時核心頻率可能會低於16MHz,影響不大。

為減小工作電流以獲得儘可能長的工作時間,裝置絕大多數時間進入睡眠模式(使用LowPower庫),利用watchdog週期性醒來發送資料,然後立刻回到睡眠模式。參考連結

nrf24l01模組也需要同時睡眠和醒來,使用Mirf庫裡的powerDown()命令。

實測電流:pro mini 5v版本,3.7v鋰電池供電,HT7533穩壓,LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF)同時Mirf.powerDown(),電流1.48mA。

感測器供電:如果直接將感測器接在5v或3v3上,感測器會一直消耗電流。為了節電,可以將對電流要求不高的感測器接在digital輸出上,當arduino需要使用感測器時再對它通電。參考連結1參考連結2

12、TP4056充電板的充電電流問題

tb上買的TP4056晶片的鋰電池充電板,要更改的Rprog是在電路板下方中部(電路板上文字方向為正)的一個小貼片電阻,出廠時阻值是1.2k。我需要90mA的充電電流,按照說明,替換成15k左右的電阻。

測試充電電流時遇到一點問題:發現充電電流比預想的要低,77mA左右,而且幾乎一開始就緩慢下降,並不是恆流的。查了一些資料後發現,我是把萬用表串接到BAT+口上的,而萬用表對這個電流造成了影響,因為使用不同的檔位測出來的電流值不同,高檔位顯示的電流比較高。實際應該串接到In+口,或者測量Rprog電阻的電壓然後(V/Rprog)*1200得到充電電流。參考連結

13、analogRead(0)與analogRead(A0)的區別?

如果這個帖子所說屬實,在Arduino IDE 0022以上這兩個命令沒有區別,A0的值為14,而analogRead(0)等價於analogRead(14)。補充:又找到一個帖子說的比較詳細。

14、搭建最小系統的問題

a) 我在tb上買的usbasp,vcc腳居然與gnd腳短接(!),vcc腳旁邊的那個看不清字的腳有5v電壓;後來仔細一看,是文字距離對應的針腳太遠,以致於串行了。

b) 我使用Atmega168pa作為核心搭建最小arduino系統,在arduino ide 1.5.5裡選擇board -> arduino ng or older,用usbasp燒錄bootloader時會提示下面的錯誤:

 avrdude: Expected signature for ATMEGA168 is 1E 94 06

原因是atmel168pa與atmel168這兩個晶片的簽名不一樣,arduino自帶的avrdude無法識別。按照這個帖子的方法可以解決,不過可能是arduino ide版本不同的原因,原帖裡的內容需要略作修改,按照ide的錯誤提示來改即可。另一個帖子,雖然我沒實際試驗,但也值得一看。

c) 順便提醒一下用“麵包板專用電源”的,要注意電源插針的極性——電源插在麵包板兩端時正負極剛好是反過來的。

d) 可能是麵包板不太牢靠,在麵包板上搭的最小系統很不穩定,後來焊到洞洞板上就沒有問題。

e) 如果使用programmer(例如usbasp)刷sketches到最小系統,注意每刷一次EEPROM都會被清除,解決的辦法是將EESAVE熔絲位設定為1(見這個連結)。

f) 為了方便除錯,以及解決programmer刷sketches導致EEPROM被清除的問題,我決定還是用ttl(pl2303)上傳程式。連線好Vcc, Gnd, Tx, Rx後發現upload會失敗,reset不起作用,在網上找到這個帖子提到boards.txt裡upload.protocal的設定問題,開啟boards.txt將原來的pro.upload.tool=avrdude改為pro.upload.tool=stk500,再刷一遍bootloader,使用ttl就正常了。

補充:後來使用ttl上傳時又提示missing "upload.params.quiet"錯誤,將pro.upload.tool改回為avrdude解決,比較奇怪。

15、最小系統在5v下工作但在3.3v下不工作

還是atmega168pa晶片,配合8MHz外部晶振,搭好的最小系統上傳blink程式,在5v輸入下led閃爍,但換成3.3v輸入led不亮。測量pin13的電壓輸出為0.5v左右且保持不變,說明blink程式沒有正常執行。後來發現原因是3.3v輸入只接到vcc而沒有接到avcc腳上。進一步測試,如果3.3v只接avcc,led也會閃爍但比較暗,pin13輸出電壓為2.2v左右。說明vcc與avcc需要都接到3.3v供電才可以。

在atmega的datasheet裡有這樣的說明:“AVCC AVCC is the supply voltage pin for Port A and the A/D converter. It should be externally connected to VCC, even if the ADC is not used. If the ADC is used, it should be connected to VCC through a low-pass filter. ”

16、使用Eagle製作電路板

為了進一步縮小成品尺寸,我決定設計自己的電路板,然後再tb上找工廠打樣生產。一開始考慮使用protel做這件事,後來發現eagle更合適,首先後者是可以免費使用的不需要破解,其次eagle的官網上就有很多元件庫可以下載,與arduino有關的庫也比較豐富。eagle上手也不難,推薦看一下Sparkfun上的兩篇教程(連結1連結2)基本就可以開始幹活兒了。

下圖我設計的第一個PCB板(已送去打樣),尺寸為25mmx42mm,電路板上主要集成了基於atmega328p的arduino最小系統和nrf24l01介面,用來實現感測器資料的無線上傳,低功耗設計使用250mAh的鋰電池供電2個月左右。完全手工佈線,雖然過程磕磕絆絆,但還是挺有成就感的。

上圖是第一版設計,打樣回來發現幾個問題:1)絲印有重疊,原因是雖然在eagle裡隱藏了一些層,但gerbers檔案裡這些層仍然可見;解決辦法是在pcb設計圖裡smash元件,然後刪除掉與絲印重疊的name和value;2)有三條線沒有連通(見上圖中的三條細黃線),設計時原本以為地線都靠覆銅連通的就沒有管,其實覆銅不是哪裡都能覆蓋到的,所以打樣前要保證所有飛線都route過(點選ratsnest工具提示nothing to do就表示所有飛線都route好了)。

第二版的設計裡改正了第一版中的問題,並對一些元件進行了重新佈局。

第三版的改動比較大:裡把配對按鈕的下拉(pull-down)改為上拉(pull-up)以便與習慣一致,另外修改了電源介面和感測器介面,atmega328晶片採用45度角佈局方便走線,led從0603改為0805方便焊接,aref與3v3斷開但保留一個跳線,將晶振改為貼片封裝,nrf24l01模組設計在電路板背面以便在焊接後仍然能修改(拆)正面的元件。

16.1 常用單位換算

Eagle裡的鑽孔尺寸單位是英寸inch,乘以39.4就是毫米,例如0.02inch=0.508mm。打樣前要注意廠家對最小鑽孔的要求,一般不能低於0.4mm,因為鑽孔越小使用的鑽頭越小,價格也越貴。

1mil = 1/1000英寸 = 0.0254毫米

1英寸 = 25.4毫米

1毫米 = 39.4mil = 0.0394英寸

16.2 PCB板覆銅

在PCB板上覆銅對走線很有幫助,雙面板一般有一面的覆銅用於地線,上面提到的Sparkfun的pcb教程裡有覆銅的使用方法。

但是要注意,有些地方由於被其他走線包圍,會導致覆銅無法到達,這些地方通常會有遺留的連線(例如上圖中兩個10uF電容之間)需要手工route,如果不route這些線在成品線路板上就只能飛線補救了。

17、從Eagle匯出gerbers檔案

為了打樣,需要給工廠提供設計檔案,但不是每家工廠都接受eagle的原始檔,同時提供原始檔也容易被別人複製自己的設計。因此需要將eagle格式的設計檔案匯出為gerbers檔案,這個絕大多數工廠都接受的檔案格式。我在網上找到了一個簡易教程《Eagle PCB 生成Gerber檔案步驟》,作者孫民強,按照教程所說的步驟打樣“基本”成功。

這次打樣比較明顯的一個問題是,雖然在eagle裡隱藏了tNames層,但匯出gerbers以後這個層依然存在,導致元件自帶的Name與tPlace層的文字同時出現產生重疊。解決方法是先smash帶有Name的元件,然後就可以移動或刪除Name,從而只保留tPlace層。也許在匯出gerbers過程中也可以做一些設定達到相同目的吧,暫時沒有研究。

使用viewmate免費版可以檢視gerbers檔案。

18、電路板焊接注意

焊接atmega晶片前,先確保晶片已經刷好bootloader,用arduino ide刷時要注意選擇正確的board型別(例如arduino pro or pro mini);處理器型別最好也選一下(例如atmega328(3.3v 8MHz)).

貼片LED極性:有彩色線的一端是負極,“|>”指向的一端是負極。

焊接很小的貼片元件時這樣比較容易:先在其中一邊焊盤上掛上錫,然後用鑷子夾住元件貼緊這個焊盤,用烙鐵將錫熔化的同時稍微用力將元件推進去,這一邊就固定好了,這時可以輕鬆將另一邊焊好。

19、最小系統無法工作原因

a)萬用表檢查電源與地線是否短路 b)檢查atmega晶片方向是否正確 c)加電檢查3v3電壓是否正確 d)atmega晶片是否已燒入正確的bootloader