Today's the day

向软件大牛炫耀我会焊单片机,向硬件大牛炫耀我会写 Rails,向软硬件大牛炫耀我生物,向软硬件生物大牛炫耀我会折腾期货 -_-bbb

单片机项目总结(一)-- 稳定性

以前只写桌面软件和 Web 程序,感觉一个稍有规模的软件要想做到良好的稳定性是要下一番功夫的,更不要说系统软件、内核模块、操作系统了这些了,因为他们确实太复杂了。

与此相对的,初涉单片机的时候,就感觉这东西很简单,也很难出故障,这个感觉和平常的经验也相符,毕竟,你什么时候看到过电子表死机?遥控器死机?刮胡刀死机?电梯死机?因为他们的逻辑就那么简单,根本就不可能死嘛……

不过现在才明白,如果你在实验室里做个电子玩具,那么以上是成立的,当你准备把这个玩具做成产品的时候,那么诸多问题就来了:你的产品也许不会像电 脑主机一样放在桌角就不动了,它也许会被放在 -20 度的户外,也许会被阳光晒到 50 度以上,也许会在湿度经常达到 80% 以上的南方夏天使用,也许会在干燥得一碰就能打出静电火花的北方冬天使用,也许会正好放在冰箱的压缩机旁边,也许会从桌上摔到地上再弹起来……

最初没有认识到这点,以为原型搞定了就算完工,结果之后在稳定性上花了大量的时间。不过也算了解了不少东西,特此记录一下~

1. Watchdog

看门狗,一直以来都知道有这么个东西,但是从来没有用过。第一印象是觉得这个模块的作用怎么这么弱智,不就是个定时的复位器吗,还要在程序中不断” 喂狗“,为啥要这么麻烦……现在明白了,因为你不知道你的程序会在什么地方跑飞,或者进入死循环,即便是设计的 100% 完美的代码,也可能在外部干扰、电压不稳的情况下,到错误的地方执行错误的代码,看门狗给让你的程序至少不会失去响应,大多数还有标志位让你能分辨出看门 狗重启从而做特殊处理。

无奈的是看门狗是要消耗电量的,对电池设备不是那么合适,不过如果你的设备不是要求一节纽扣电池就要运行两三年的话,那么还是把看门狗打开吧~

如果追求更低的功耗,和更健壮的稳定性,那么用专用的外部看门狗芯片也是不错的。除此之外也有不少芯片有看门狗这个附加功能,比如 HT1621,不用白不用~ :)

2.BOD

BOD 给我的第一感觉,也跟看门狗一样,不就是个低电压复位器嘛,认为在电压很波动的环境中用用还情有可原,一般情况下用不到。其实不然,因为电压过低是造成程 序混乱的一个主要原因,最低电压 1.8V 的处理器,在 1.0V 电压下也可以运行,但是内部已经混乱了。这次就遇到了用电池的设备在低温下莫名其妙跑飞的情况,最后才发现是电池在电量快耗尽的时候,在低温下电压会降得 很厉害,加上 BOD 就 OK 了。

BOD 也有同样的问题,就是一般也是要耗电的,因为为了比较电压,至少要维护一个电压基准。不过比如 MSP430 就有 zero-power BOD 技术做到零功耗的 BOD,新版采用 picoPower 技术的 AVR 处理器也有 Sleeping BOD 功能,同样可以达到睡眠状态下 BOD 无功耗,所以,也是不用白不用啦~ :D

3.好用的 EPPROM

对于一般功能的设备来说,有 Watchdog 和 BOD 就足够了,但是对于一些要维护状态信息和长期运行的设备,比如数据记录器、监控器,那么程序跑飞,就不能简单的重启了事,更重要的是要恢复现场,接着跑飞前的地方继续运行。

这就需要非易失存储器的帮助了,而 EPPROM 又是其中最好用的一个,100 万次的写入寿命,并且大部分处理器都内置了 EPPROM,又是不用白不用,即便没有,添加一块外置的 EPPROM,比如 24c02,也只需要几毛钱。

虽然 EPPROM 只有几千个字节的存储空间,却足够可以保存运行时的所有变量,配合 Watchdog 的重启中断,可以在处理器被重启前,把重要的运行时参数保存到 EPPROM 里去,重启之后再装载回来。

现在的项目中,把运行时的变量保存在一个 configs 数组中,然后定期把这个数组保存到 EPPROM 中,这样即便掉电重启,也可以快速恢复到最近的一个备份上~

4.插拔和对接

这里主要指运行中设备的插拔,和两个运行中设备的对接,因为在这些情况下会有一些需要注意的问题。

曾经做过一个设备,需要在 3V 和 5V 电源之间无缝切换,当 5V 电源插入的时候,就自动用 5V 电源,5V 拔下就自动用内部的 3V 电池。做好之后却发现一个奇怪的问题,3V 切换到 5V 没有任何问题,当把 5V 拔下来的时候,处理器重启了。一直以为是电源的切换速度不够快,5V 掉电却没有来得及切换到 3V 上去,但是后来发现原因不在这里,原因竟然出在电容上。因为 5V 是外接电源,所以习惯性的在电源入口处放了个大电容(下图 C11),这样当 5V 拔下的时候,这个电容就会瞬间放电,这个瞬时的高压就将处理器复位了,去掉这个大电容,一切正常了~

双系统对接,电压不匹配是主要问题,比如 3V 和 5V 系统之间通过 I2C 总线互联。原来以为,只要 3V 的设备可以耐受 5V 的高压,双方的 VOH 什么的也可以保证逻辑正确的话就可以直接对接了,在实验室里中也经常这样干,但是在产品中用却发现了诸多的问题。比如做 3V 和 5V 设备直接的互联,3V 的设备要插入到 5V 设备上的端口上去,大部分时候插入没有问题,但是少数时候,一插入 3V 的设备就立刻死机了。

原因在于大部分处理器的 IO 口都有钳位二极管的保护(上图中红色框内),让 IO 口的输入电压不会高于 VCC 也不会低于 GND。这也就是为什么3V 和 5V 的系统互联后,即便双方 VCC 没有连接,但是还会发现 3V 系统的 VCC 变成将近 5V 了(其实就是 5V 减一个二极管的压降);这也是为什么有的芯片,不接电压,直接给它的 IO 口输入驱动也能跑起来。因为电流通过 IO 口的钳位二极管流到 VCC 去了。

但是通常钳位二极管有最大电流的限制,3V 与 5V 之间 2V 的电压差,在设备内阻的配合下,会造成将近 10mA 的电流流过钳位二极管,大部分情况下这个电流已经太大了,会造成设备闭锁失去响应,应该控制在 uA 的等级之内才对。

简易的解决办法就是将双方的电压拉近,比如将 5V 的电压用稳压器降到 3.3V,那么和 3V 之间只有 0.3V 的电压差,造成的影响就会减少很多。

除此之外一个效果不错又省事的办法就是加限流电阻(下图中 Rser),这样可以有效的限制住电流大小,因为双方只要 VCC 不互联,那么电压做到严格一致是不可能的,有了限流电阻,就稳妥得多,并且这个电阻还可以有防止双方高频互扰的效果。负面效果就是电阻会拖慢边沿速度,高 速系统中不是很适用,但对于 I2C 这类只有几百 K 的应用,串联个 100 欧左右的电阻,是非常合适的。

更多的不同电压转换技巧,网上可以搜索到一份 Microchip 的 3V 5V 电压转换技巧手册,非常有参考性。

5. Delay and Try

单片机的固件中,经常看到类似的代码:

...
enable_adc();

while((!(ADCSRA & (1<<ADIF)));

read_adc_data();
...

中间用 while 来等待标志位置位,即便不用轮询而用中断方式,也会遇到类似的判断,比如在 I2C 传输中判断 I2C 中断标志位是否已经被清除、循环等待 ACK 信号之类的。

这种无限期的等待就有死循环的风险,如果硬件错误使得标志位置位失败,或者是 I2C 设备意外掉电,ACK 信号丢失,处理器就卡死在 while 这里一直等下去了。

虽说有看门狗可以在这种情况下复位,但是更好的方法是 Delay and Try,让程序稍微有点容错性:

unsigned char i = 10;
do{
    _delay_ms(2);
    i--;
}while((!(ADCSRA & (1<<ADIF))) && (i != 0));

这样,重试 10 次,在足够长的 20ms 内要是还是没有置位,就不再等了,当然后面的程序要有相应的处理机制。

同样的机制,也可以用在桌面软件中。一些特殊的操作,比如检测硬件、从硬件中读取数据、和驱动交互之类的不是每次都能成功,加个 Delay and Try,会稳定不少:

bool succes = false;
int retry = 10;

do
{
     succes = dwObj.FindDeviceFromID(VendorID, ProductID, ref path);
     if (succes)
        break;
     
     Thread.Sleep(200);

     retry -= 1;
} while (retry != 0);

return succes;

虽然方法很迂腐,但是很有效~ :)

各位节日快乐

写写代码,焊焊东西,喝喝咖啡,啃啃汉堡,推推推特,看看漫画,拆拆元件,调调程序,揉揉眼睛……又是一天

看到推特上有人说祝你“年年有今日,岁岁有今朝”,寒……

不过说实话,如果衣食无忧,这种生活挺爽,哇咔咔~

翻出一张老图

Win 7 发售了,对我的意义来说就是又多了一个平台要测试,软件是基于 .net  的,应该问题不大,就是看看驱动是否能够不修改移植过去。

昨天整理硬盘,翻出一张老图:

哇哈哈,10 年前的《电脑爱好者》杂志。这图片貌似是当初第一次买扫描仪,随便抓了本杂志试扫描仪留下的。

64M 内存,6.4G 硬盘,估计当时算海量吧,现在连个 Win7 都安装不下……

手上的那块 ARM 开发板,除了没有独立显卡,其他硬件性能已经超过 10 年前的电脑了~

10 年后又是啥样捏,现在多扫描点东西留起来

慎用焊锡膏

焊东西都要加点助焊剂,一直以来用松香,便宜又好用,但是焊多脚的 SMD 贴片很不方便,后来换成日本产的一款焊油,相当好用。

但是这个日本焊油太贵了,而且含铅,前两天正好买元件,就顺便买了个国产的焊锡膏,两块钱一大桶,心想可用 n 年了。

结果,就被这桶焊锡膏搞了,晚上焊了几块板子,焊的时候感觉不错,甚至比那款日本的焊油感觉都好用,不过焊完了问题就来了。

先是工作电流应该只有几 uA 的电路,一上电就有三四 mA 的电流,而且还在不断变化,但是电路板上却找不到短路的地方,似乎一切正常。

于是开始一个一个拆元件,排除错误,哪里连焊了?芯片烧了?电容穿了?过孔连了?……

都不是。

最后我就震惊了,因为把所有的原件都拆除,就剩一张空板子,上电还有 1mA 左右的电流……

然后才怀疑到这个新焊锡膏上,测试了一下,果然如此。

拿了张新板子,板子上有一个 QFP 封装的 100pin 芯片,虽然引脚很密,但两个引脚肯定是绝缘的。

但是粘点焊锡膏,然后再拿烙铁烫烫刷刷,再测,竟然两个相邻的引脚有 50K 电阻!引脚相邻越远,电阻也就越大,不过即便很远的两个引脚,也有 2M 左右的电阻。

这下总算知道了为什么测不出短路,但是还有这么大的电流,因为这个焊锡膏,不是完全绝缘的!

可上焊锡膏的壳子上却印着”绝缘性良好“,网上查了一下,也确实有人提到焊锡膏腐蚀性很大,不适合电子焊接。

我也不知道是真不适合,还是国产货的质量太差,还是使用方法不对,也许是焊锡膏把板子腐蚀坏了吧。总之现在还是老老实实用回那个日本焊油和松香了了,虽然贵但是放心啊。

为了贪便宜耗费了一个晚上……

图为罪魁祸首。

改用 HootSuite 推

HootSuite 真不错啊,试用了一把就喜欢上了,可以同时用多个账号推,可以用多个分栏监视不同的推,UI 做得也很舒服,在宽屏下用起来很爽。

用了 HootSuite 才知道以前漏看了不少人的 reply,估计当时发了推就去睡觉或者去吃饭了,回来的时候被其他消息刷走了我又没仔细看。这下好了,reply 单独一栏~

今天在 HootSuite 上看大月饼直播,比看电视有趣多了~