Arduino 中国 | Flamingo EDA

CAT | DIY

Apr/08

26

深入理解Arduino Bootloader

在调试新装的Arduino Diecimila贴片版本时,遇到一个非常诡异的现象:在将Bootloader通过编程器写入到ATmega168里之后,再通过Arduino的集成开发环境下载程序时,第一次下载完全正常,可第二次就无法完成下载了!

一开始怀疑是熔丝位设置的问题,可奇怪的是相同的设置在直插版本上就没有问题,试了一个晚上,无果。第二天Google了一下,Arduino论坛上有人遇到了现象跟我类似的问题,别人提供的解释是说没有对加锁位(Lock Bit)进行设置。以为找到了问题的症结所在,晚上回到家继续用我的编程器狂写ATmega168,但现象依然如旧:第一次下载没有问题,第二次无法下载。几乎崩溃!

同一个问题纠缠了两天,虽然没有解决,但是了解到了不少ATmega168有关熔丝位和Lock Bit的设置知识。根据Wolf Paulus对熔丝位的描述Aduino Playground里对锁定位的描述,在我的编程器里分别做了如下的设置:


其中BLB1的设置比较重要,它是用来对Bootloader进行保护的。其中SPIEN经实验,在不选中时用下载线能够正常下载Bootloader。

仔细分析了各种可能性,最后还是在对照PCB检查电路时发现了问题,焊接时没有焊C11,焊上去之后就一切正常了,郁闷了我三个晚上的尽然就是一个小小的电容!

查了查 Arduino Diecimila有关自动重启的说明,总算搞清这个电容是用来连接FT232RL的DTR和ATmega168的RESET,如果不接这个电容,或者数值不对(比如今天我就错接了22pF的),都有可能导致Arduino程序无法正确下载。

同样的问题也会发生在Arduino Mini上,得到的启示是在连接USB Adapter和Arduino Mini时,除了电源之外,还要将DTR和RST通过一个100nF的电容连接起来! 真是到处都是陷阱啊,不过这么一折腾,倒是弄清楚了不少东西,虽然时间是花了不少:)

No tags Hide

Apr/08

21

Arduino Mini与USB适配器

Arduino Mini在设计上力求很小的体积,因此并不具有完整版的Arduino的全部功能,其中的USB下载部分就是通过USB适配器(Adapter)来实现的。USB Adapter其实就是一个USB转串口的电路,采用的是FT232RL芯片,因此原理上除了可以做为Arduino Mini的适配器外,还能够用于其它需要USB转串口(TTL电平)的场合:

在配合Arduino Mini使用时,要只需要将USB Adapter上的5V,GND,TX,RX四个端口,与Arduino Mini上相应的5V,GND,TX,RX四个端口相连接就可以了。

为了配合之后的验证,上面的电路中还加了一个LED灯,其目的是用下面的Arduino程序来验证Arduino Mini上的数字输出功能:


int BASE = 2;
int NUM = 12;
int index = 0;

void setup()
{
  for (int i = BASE; i < BASE + NUM; i ++) {
    pinMode(i, OUTPUT);
  }
}

void loop()
{
  for (int i = BASE; i < BASE + NUM; i ++) {
    digitalWrite(i, LOW);
  }
  digitalWrite(BASE + index, HIGH);
  index = (index + 1) % NUM;
  delay(100);
}

这次还算顺利,上面的程序通过USB适配器很轻松地就下载到了Arduino Mini中,并且将LED接在相应的数字管脚上,都可以看到LED一闪一闪的效果。

现在基本能够确定USB Adapter的工作是正常的,Arduino Mini也部分正常工作了,接下来还需要验证的功能包括Arduino Mini的模拟输入部分,以及9V电源部分。此时上次买的直流电源就派上用场了,直接把输出调整到9V,接到Arduino Mini的9V和GND端口,发现刚才写入的程序完全正常,并且用万用表量了Arduino Mini上的5V管脚,电压也是5V :)

今天先到这里,明天想想如何验证模拟输入部分,休息,休息,好好休息!

No tags Hide

Apr/08

21

与Arduino Mini的首次博弈

制作Arduino Mini的念头由来已久,但直到差不多四周之前才花了一周左右的时间来画Arduimo Mini的原理图和PCB,然后送去工厂做板又一直拖了两周才拿到电路板。这周末总算可以动手焊接了,难度不算太大,唯一能算上的麻烦的就是板子实在太小(长3.1厘米宽1.9厘米)了,要在上面定位表贴元件可不是件轻松的事情。

Arduino Mini采用的是贴片版本的ATmega168,本来打算买一个编程器转换座,直接在编程器上将Bootloader写进去,但一打听价格居然要300多块,最终决定还是决定用自己做的USB编程器。于是在实验板上搭了一个简单的Arduino Mini下载电路,并连接上USB编程器:

之后整整一个下午加一个晚上就浪费在如何将Bootloader下载到Arduino Mini里了。先是USB编程器组装好之后,在Windows上怎么也找不到这一USB设备,好在上次有成功的经验,知道电路肯定没有问题,来来回回研究了好几轮熔丝位的设置,USB编程器总算是可以被Windows识别出来了。期间一直纳闷为啥当初没有把送Whale的那个编程器的熔丝位读出来:(

接下去的过程更加令人郁闷,用avrdude怎么也无法与Arduino Mini正确地通信上,期间一度怀疑是不是Arduino Mini的板子画得有问题,但一根一根线用万用表查看似乎又是正确的,至少是ISP这一部分。于是乎不断地检查复位电路、晶振电路、ISP接口,时间就这样一点一点地流去,一点进展也没有。上网查了不少资料,唯一得到的经验就是用一个LED来检查MISO、MOSI、SCK和RST几个管脚,来看这几个信号是不是正确的,在我的Arduio Mini上,MOSI是没有任何反应的。

现象只能说明一点,ATmega168没有给出任何反馈,但一个最简单的单片机系统就只是依赖一个晶振电路和RST电路,这两部分在我看来都没有什么问题,倒底是怎么回事呢?

最后连我自己都没有想清楚为什么会去检查USB编程器,并在JP2上加了一个跳线,问题得到解决。原因是这样的,默认出厂的ATmega168使用的是内部晶振,频率非常低,而我做的这个USB编程器在芯片频率很低的情况下必须使用JP2这个跳线。这一情况在上次烧写ATtiny的时候也遇到过,并且也是费了好大的劲才解决,看来上次得到的教训还是不够深刻啊。

再后来的过程就算比较正常了,使用avrdude设置Arduino Mini的熔丝位,并下载Bootloader:

avrdude -c usbasp -p m168 -V -e -U lock:w:0×3F:m -U hfuse:w:0xDF:m -U lfuse:w:0xFF:m -U efuse:w:0xf8:m
avrdude -c usbasp -p m168 -V -D -U flash:w:ATmegaBOOT_168_diecimila.hex:i
avrdude -c usbasp -p m168 -V -U lock:w:0xCF:m

第一步老提示我扩展熔丝位要从0xf8变成0,我选了N,没有发现什么问题,再用智峰的ProgISP读出来也是0xf8。Bootloader下载完后,在数字I/O的13号管脚上接了一个小LED,发现是一闪一闪的,总算第一步算是完成了。兴许后面还会有别的问题,留到以后再慢慢解决吧,今天的确没有时间和精力再去纠缠了。

最近的问题是想做的事情和东西很多,自己得保持一个合适的速度和计划,还是觉得时间不够花,效率又不是那么高,不过只是玩玩,无所谓了:)

No tags Hide

Jan/08

28

DIY Wiring: 外部电源和EEPROM

整个Wiring最后两部分电路是外部电源和EEPROM。外部电源电路与Arduino上的基本没有什么区别,采用的也是78M05这样的电源芯片,相应的元件清单如下:

类型 标记 数量 规格
电源芯片 IC4 1 LM78M05
电容 C10, C11 2 100nF
电容 C12, C13 2 100uF
整流二极管 D1 1 1N4004

Wiring电路上带一个4K字节的EEPROM,其作用是可以用来保存一些程序的数据,如用户的配置数据等。EEPROM的电路部分并不算复杂,估计大部分工作都在于软件上,下面是相应的元件列表:

类型 标记 数量 规格
EEPROM芯片 IC3 1 93C46
电阻 R5 1 10K, 1/4W
电阻 R6 1 2.2K, 1/4W

最后焊接完的效果如下图所示:

为了对其中的EEPROM功能进行验证,我试验了另外一个Wiring工程:


#include 
char val; 

void setup() {
  if(EEPROM.read(16) != 'F') {
    EEPROM.write(16, 'F');
  }
  val = EEPROM.read(16);

  pinMode(48, OUTPUT);
} 

void loop() {
  if( 'F' == val) {
    digitalWrite(48, HIGH);
  }
  delay(100);
}

上述Wiring工程在初始化过程中先读取EEPROM中地址为16的字节单元中的值,并在其不是字符F的情况下,往该地址单元中写入字符F,然后再从中读取这来。这样如果EEPROM正常工作的话,就能够保证变量val在setup()函数执行完后,其值一定是字符F。在loop()函数中,如果检查出val的值确实是字符F,就点亮Wiring板子上自带的LED(接在数字I/O的48管脚上)。

习惯了Arduino程序下载时不需要按复位键,并且在下载完成后也不需要按复位键,刚接触到Wiring时对其在这两个位置上还需要按复位键的做法的确有些不适应:-) 真希望Wiring在接下去的版本中能对这一地方进行改进。昨天发邮件问Wiring的作者为什么不把bootloader的源码公布出来,得到的答案居然是他把源码弄丢了,现在只有二进建的版本,我晕…

最后贴一张我制作的Wiring在运行上述EEPROM工程时的效果图,用的是外接电源,右侧的红灯是电源灯,左侧的绿灯是Wiring自带的LED。

No tags Hide

Jan/08

27

DIY Wiring: AVR电路

Wiring的核心是一个ATmega128单片机,也是整个电路中最复杂和最容易出错的部分。焊接上因为有了之前FT232BL的相关经验,并没有遇上太大的麻烦,而剩下的一些贴片元件基本上也不算太难。唯一遇到的问题可能就是这些元件实在太小,本人的眼神又不算太好,经常弄飞一两个,掉在地上找不着了:)

类型 标记 数量 规格
AVR单片机 IC1 1 ATmega128-16AU
电容 C6, C7 2 22pF
电容 C8, C9 1 100nF
电阻 R7 1 10K
电阻 R8, R9 2 1.8k
电阻 R11 1 270
电阻 R14, R15 2 1K
晶振 Q2 1 16M, 二脚直插式
晶振 Q3 1 32.768K, 32C31, 四脚表贴式
按钮 RESET 1 四脚直插式
发光二极管 PWR 1 红色
发光二极管 LED 1 绿色
10P引脚座 ISP 1 黑色

最后焊好的效果图:

Wiring的bootloader是事先驻留在ATmega128里的一小段程序,它的作用接收来自于Wiring IDE的命令,实现Wiring工程的下载。往AVR芯片里烧bootloader是非常关键的一步,同时也是对芯片能否正常工作做初步的检测,AVR系列芯片都提供ISP接口,借助这一接口和PonyProg这样的软件,就能够实现对bootloader的烧写。

早先就听网友说过Wiring的bootloader在Wiring的网站上找不到,试了一下果然如些,难怪Wiring不如Arduino那么流行;-) 没有办法,按照论坛里的提示,给作者发了一个邮件要bootloader,等了一天拿到bootloader的HEX文件。

有了之前DIY Arduino的经验,AVR熔丝位的设置这回一开始就考虑到了,按照网上搜索到的文章里的说明,下图在PonyProg中为ATmega128设置的熔丝位:

接下去的过程比较顺利,用PongProg和自制的并口下载线成功地将bootloader烧写到Wiring上的ATmega128中,由于ATmega128的Flash有128K,所以相应的烧写时间比较长。

最后一步就是如何将Wiring程序下载到Wiring板上了,这与在Arduino上是一样的。下面是我试验的第一个Wiring程序:


int ledPin = 0;

void setup()
{
  pinMode(ledPin, OUTPUT);
}

void loop()
{
  digitalWrite(ledPin, HIGH);
  delay(1000);
  digitalWrite(ledPin, LOW);
  delay(1000);
}

该程序比较简单,只是不断地点亮接在数字I/O管脚0上的LED,实验成功!之前我担心最有可能出现问题的电路部分基本算是调试成功。当然,之后要一个一个验证每个管脚的功能,一共50个,哈哈:)

No tags Hide

Older posts >>

Find it!

Theme Design by devolux.org