[arduino|macro]基于OBD系统反馈的霹雳游侠灯

Photobucket

像我这样的标准80后,小时候难免对《霹雳游侠》着迷,尤其里面那辆超帅气的“KITT”(这是那辆车的名字)印象深刻。话说这真是大陆最早引进的美剧之一了,在那个还没有私家车这一说的年代,长大能拥有辆那样的车肯定是当时的梦想之一。

如今,汽车也正逐渐进入寻常百姓家。广大车主,尤其是年青车主越来越热衷于升级扮靓自己的爱车。灯光改造由于其个性显著、安装简易的特点广受青睐,市面上也有大量相关产品,包括,底盘灯、日行灯、迎宾灯、轮毂灯等等,举不胜举。当然肯定也有号称“霹雳游侠灯”的产品,“霹雳游侠”的形象那么深入人心,成为改装的标杆也是理所当然。但仔细分析,就会发现,市面上现有的这些都形式固定,要么单调循环,要么手工遥控。前者平淡乏味,后者操作过程中可能对行车造成安全隐患。那单调封闭的动画形式,与霹雳游侠所应有的“智能”、“生动”的形象是截然相反的。

为什么不利用开源硬件平台Arduino打造一款“相对更智能”的“霹雳游侠灯”呢?“相对智能”就好,让车辆的行驶状态能与灯的显示形成互动就好。这样,在车外的行人、其他驾车人员也能通过灯光状态,获取本车的形式状态,能有提高安全系数的效果。另外,动画之间的切换也能摆脱单调的循环。同时,驾车人员无需操作动画切换的多余动作,灯光控制只是原有驾驶操作的副产品,无需人工干预。

Photobucket

要获取行车数据,最经济而且最简单易行的方法,就是从“OBD(On-Board Diagnostics,行车诊断系统)”中获取。OBD已经成为现代车辆的强制标准配置,像发动机转速、车速、机油温度、冷却液温度、油门大小,都是其中最为基本的检查项目。所以我的这个系统,就是建立 OBD > “ELM327” > Arduino 甲 > 315M 无线传输 > Arduino 乙 > 护栏管 的开环控制系统。

其中,“ELM327”,是OBD的CAN总线到串行总线的转换媒介。我所使用的”ELM327″是淘宝上常见的铝盒装。其实其内部并没有真正的“ELM327”芯片,而是“山寨”的,好在功能总算都实现了,原先的输出接口是USB。拆机后了解其串口转USB芯片就是常用的CP2102,则可得知其主系统的输出,就是TX/RX的串行总线。在圣源的帮助下,我们把这两条线都引出来,这样,我们就可以用Arduino直接对其进行波特率为38400的串行通讯。配合一个1604的液晶屏,进行数据显示,这样作为我们系统的一部分,就已经实现了一个小型的行车电脑,可以实时显示车速、发动机转速、油门打开程度的附属仪表盘,用于监视车辆运行状态,相信还有改善驾驶习惯的效果。

Photobucket

Arduino与OBD之间的互动,感谢@stanleyhuangc先前的尝试,他的OBDCon是这次自己编写OBD发送端很重要参考。因为目前项目处在实验阶段,所以并没有太多的型号选择和超时处理,只考虑到在手边现成的测试车辆。在OBD指令中也有查看OBD各种传感器支持列表的指令,而实测发现,测试用的2012款新宝来Bora支持的数据项目并不多,甚至可以说少得可怜,希望能有机会对更多车型进行测试。而车辆4S店使用的OBD诊断系统除了能够查看已有的这些数据,还能对一些内部参数进行调整,例如刷新保养里程之类。可见,除了通用OBD指令集,各个车厂可能还有大量自定义的指令系统并没有对外开放,这部分潜能还有待进一步发掘。

护栏管,是我们“黑”掉的第二个部件。去破解现成的东西,改装提升它,是不是也很体现极客精神呀?制作原型,能就地取材最好。而现有大多数的LED灯条都无法实现逐段控制,要么全量要么全灭,没有什么控制的价值,少数能显示动画的LED等条又都是集成内控。虽然理论上可以切断内控,外接控制器,但实际操作过程中,它的软基PCB完全经不起折腾,易折,而引线焊接困难。所以,我们选用的是常用于桥梁道路、楼宇广场灯光工程的护栏管。护栏管也有内控外控之分,我们选用的是外控12V直流的16段全彩护栏管。控制部分,我们用Arduino乙对护栏管进行驱动,实现逐段的RGB控制;直流12V的供电,我们就可以直接从车载电瓶中取得。

我们使用的护栏管采用TM1812作为主芯片。TM1812是单总线、
12路PWM输出、可级联的LED专用驱动芯片。在16段的护栏管中,每3组RGBLED构成一段,每4段由一片TM1812控制,就有4片TM1812。因为1812使用单总线,控制这么多数据,要求实现400+/-50ns的电平长度,输入频率高达800kHz。而这就完全超出了传统意义上Arduino的极限。就一般使用的digitalWrite()函数来说,运行时间就达到ms级别,而1ms=1,000us=1,000,000ns。我采用了各种方法对其进行改进,将函数调用改为宏替换,预存寄存器及偏移变量,也只能把电平长度控制到us级别。在最后的尝试中,我们对IO寄存器进行直接调用,并关闭定时器中断,终于勉强达到了时序要求。这可是借助逻辑分析仪慢慢调试才得出的结果。但这样已然是AVR的极限,依然无法实现对动态灰度的控制,除非将开发平台升级到stm32类的ARM平台上,驱动这些数据就会变得从容不迫了。

护栏管中的每组RGB,有3个并排的LED的组成,所以个人感觉混色的效果并不好,尤其是近看的时候。所以在我们测试的视频中,都是全管单色的显示,不过我们是实现了逐段颜色的控制。另外,由于护栏管使用半透明外壳,所以“光晕”本来就比较大,所以虽然没有实现灰度控制,但依然可以有一点渐变的效果。护栏管由于常常运用在楼宇外观,所以外壳、接头也都有密封防水的特性,倒是更适合在车上进行实验。

Photobucket

完成了OBD数据和护栏管的驱动,我们使用最为常用的315M无线收发模块进行远程通讯。毕竟直接连线穿过引擎仓还是不太安全,而且成本比较高,甚至会造成因为“擅自改装”,导致4S店拒绝进行保养,所以我们要使用基本不影响汽车系统而且易于拆装的方式,发射端在OBD端,接收端在护栏管端。一般来说,对于无线接收,不管是用无线电还是红外,在接收端,我们一般使用外部中断作为数据接收端口。但是,就像在之前提到的,因为中断部分已经被关闭以保证对TM1812的正确驱动,所以,我们不得不使用带有PT2272的接收模块对其进行解码,而非用单片机来解码。而且所使用的PT2272还必须是带有锁存功能,能保持输出状态。如果无法锁存,单片机可能错过解码到的信号,所以我们使用的是315M的PT2272-T4解码模块。

都接上了,我们就可以上路测试了。测试阶段动画代码比较简单:

  • 驻车状态(车速为0):双蓝迂回,比方说在等红灯。
  • 巡航状态(车速大于30):单蓝色迂回。
  • 加速状态(车速小于30,且速度增加):双绿迂回,比方说绿灯亮,则汽车开始起步加速。
  • 减速状态(车速小于30,且速度降低):双红迂回,比方说遇到红灯亮,则汽车减速准备驻车。

对于实际效果感兴趣的朋友,欢迎来 http://v.youku.com/v_show/id_XNDg2Mjg5ODk2.html 观看视频。视频的拍摄环境设备都非常简陋,最后跟车那段,是我自己反坐在摩托车后座手持单反拍摄,抖动比较厉害,能人车安全地拍完,已经很开心了,至于画面抖动请诸位看官见谅。

路测视频:

项目开源托管地址:https://github.com/aguegu/LS2000

特别感谢:圣源、久顺、@stanleyhuangc@汐锦0221在开发过程中提供各种协助。同时感谢无线电杂志

本作品有参加:无线电杂志举办的2012年Arduino挑战赛,希望能得到您的支持~

关于aGuegu

向着更高的逼格
此条目发表在LS2000 霹雳游侠灯分类目录,贴了, , , , , , , 标签。将固定链接加入收藏夹。
  • 云飞

    非常好的DIY啊,看了让人蠢蠢欲动。

  • bony

    你好,很棒的设计,可是防水问题如何解决呢?

    • 原型没有考虑防水呢,灯管本身是防水的,要做防水的话,主要就是arduino这边

  • Very Cool!

  • meiyan

    方便分享一下TM1812.h及相关库文件吗?谢谢阿古!

    • tm1812的资料网上应该很容易搜到,主要还是对于时序的要求比较高,而用16MHz的avr已经很难满足这个要求了,建议升级性能更好的芯片呀