Arduino单片机使用和开发问题记录
>>> 博客搬家,本文已迁移至:https://bjzhanghao.com/p/24 <<<
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