Arduino uno+w5100+yeelink实现红外转码与网络控制



Arduino uno+w5100+yeelink实现红外转码与网络控制先贴两张作品图
<ignore_js_op>
<ignore_js_op>
最近双蛋大学搞了个arduino竞赛,开学之初稍有空闲就报了个名。初中时曾玩过一阵AVR,之后一直忙于学业,现在总算有自由时间重拾单片机。好久不关注这一领域,顿时发现这几年来,单片机还是进步不少的。这是我第一次接触arduino,顿时发现软硬件方面开发系统都简约亲切不少,还是挺容易上手的。首个arduino项目,也不指望太复杂,实现个简单功能就行。
淘宝上买了个初学者套件,整套一百七十多。原来以为各器件都是arduino专用,后来才发现市面上大多元件arduino都可以支持,而且套件中有许多不需要的器件,这样一想感觉还是挺贵的,推荐新手们分元件单独购买。
<ignore_js_op>
<ignore_js_op>
客服还是挺好的,提供了一套详尽的资料。在看教程时,突然对红外发射接收感兴趣,于是就结合之前的想法,想做一个红外控制器。只需一个遥控器就可控制家中所有用红外控制的家电,后来知道这就是红外转码功能。
通过程序设计控制遥控器各键功能,红外接收器接收到控制遥控器的按键后,经arduino按预先设定的对应关系,发射相应的红外指令。
本项目使用的库文件在最后会有汇总并提供下载!
<ignore_js_op>
使用IRromote库中的IRrecvDump与IRsendDemo例子分别举例了接受、发射红外代码的使用方法,基于这两个程序,构成了我的红外转码程序。
鉴于家中和寝室的红外控制设备有限,仅针对格力空调、美的电扇、iptv创维电视设计红外转码。

开发流程
一、红外转码部分
1.使用IRrecvDump接受各电器红外编码
普及一下知识,红外遥控器发射的其实是一连串的方波信号,接收器根据信号有无及其间隔的时间长度计算所代表的1/0信号。
下图是常用的NEC编码方式(也是本项目中电扇和iptv的编码方式)。NEC编码由十六位二进制数构成,前八位是地址,后八位是命令。

 

<ignore_js_op>

 

发送信号时,首先是一段9ms高电平和一段4.5ms低电平作为开始标记,随后是信号内容。
先是8位的地址及其反向编码(确保信息准确),再是8位的命令编码及其反向编码。最后以一小段高电平结束。
知道了NEC的编码形式,我们就可以通过读取遥控器的红外指令,得到各个信号的代码,并依照其编码方式发射NEC信号。
硬件部分:
连接非常简单,只需将三个引脚接到指定位置即可。

红外接收头及接法: <ignore_js_op>

软件部分:
好在IRromte库十分强大,其IRrecvDump的example可以将读取的红外信息直接打印到Serial Monitor。
例如,项目中的总控制遥控器的第一个按钮的dump结果如下:
FFA25D
Decoded NEC: FFA25D (32 bits)
Raw (72): 18448 8900 -4450 550 -550 600 -500 600-550 550 -550 600 -500 600 -550 550 -550 550 -550 600 -1600 600 -1650 600 -1650550 -1650 600 -1650 550 -1650 600 -1600 600 -1650 550 -1650 600 -550 550 -1650600 -550 550 -550 550 -550 600 -1600 600 -550 600 -500 600 -1650 550 -550 550-1650 600 -1650 600 -1650 550 -500 600 -1650 600 26086 8900 -2200 600

 

“FFA25D”就是转换成16进制的编码,之后只要用它发射就行了。“NEC”代表程序已判断出这种型号的形式是NEC格式的。“32 bits”代表编码长度。后面的Raw是每个方波的长度。正值代表高电平,负值代表低电平,数值大小代表持续长度。根据NEC规则,一高一低的一组电平变化代表一个数。若560us高电平1690us低电平代表1,560us高电平560us低电平代表0,由于程序精度限制,只能以50us为倍数测量,所以只能看到近似的结果,但是这样的分辨率下分辨1与0自然是没有问题的。程序已经帮我们计算好信号的编码了,只要用就行。

<ignore_js_op>

一个个按钮点过去,获取各键编码
具体请见附件:编码表 <ignore_js_op> 遥控器编码(正式).rar (10.6 KB, 下载次数: 152)

 

注意:有些编码形式特殊(如格力空调),将在第三步中阐述。
注意:有些编码长度很长,需要修改IRremote.h#define RAWBUF 200的数值以使得编码能完整dump出。
2.发射红外编码
收集完所有编码后,就可以尝试发射编码了。
硬件部分:

一开始一直感觉功率不够,一定要很近才行。。于是尝试改小电阻,增加发射头数量等方式。

<ignore_js_op>

提示:红外线虽然肉眼不可见,但在镜头下是可以看到的!用此方法可以快速判断线路通断。
改小电阻对单片机有危险,而增加发射头效果依然不理想,于是考虑用三极管放大。下图所示为电路连接图及实际测试各点电压:
<ignore_js_op>

 

不解的是为什么一直处在饱和区,哪怕减小R2也不行。。正在求教:http://www.geek-workshop.com/thread-7536-1-1.html
欢迎高手们继续指点!
经大神点拨,好像红外信号是要处在饱和区的,从效果上来看还是不错的。
软件部分:
IRromte库提供了多种发射编码的函数,具体可以打开头文件和cpp文件查看,代码都很容易懂。
因为是NEC编码,所以使用的是voidIRsend::sendNEC(unsigned long data, int nbits),直接将刚才得到的十六进制编码值给这个函数就可以了。data代表发送的NEC编码值,nbits是编码长度。在刚才的dump中都已经告诉你了。
例如
IRsend irsend;
irsend.sendNEC(0xFFA25D ,32);

 

另一种发射的函数是void IRsend::sendRaw(unsigned int buf[], int len, int hz),有些不使用编码协议的信号要用它发射。
三个参数分别代表要发送的数组,数组长度,和发送红外光的频率(一般都是38(khz))。
例如创维电视开机信号:
unsigned int tvonoff[68]={4500, 4400,600, 550,550,1650,600, 1600,600, 1650,550, 550,600, 500,600, 500,600, 550,550, 550,600,1600,600, 1600,600, 1650,600, 500,600, 500,600, 500,600, 550,600, 500,600,500,600, 1600,600, 1650,600, 500,600, 500,600, 500,600, 550,600, 1600,600,1600,600, 550,600, 500,600, 1600,600, 1650,550, 1650,600, 1600,600};//已去除第一个值
IRsend irsend;
irsend. sendRaw (tvonoff,68,38);
注意:
dump中RAW的第一个值是不需要的。因为NEC编码的规范是在9ms高4.5ms低电平之后才开始,所以之前的值不是信号一部分,若加上会导致错误。同样,因为NEC一定以低电平结尾,最后一个高电平值也不是信号的一部分,但加上也不会影响发射。
注意:
有些编码虽然解码结果显示为NEC但只能用sendRaw发射,例如创维电视!
注意:
每一次发射红外信号后,一定一定需要记得加上irrecv.enableIRIn();这句来重新开启红外接收功能,否则下一个按键就不会被接收!查过代码,发射的时候好像是为了保证信号不受干扰,把Timer2 的时钟关闭了,但没有时钟,根本就不能进行红外接收(红外接收主要就是靠对高低信号计时),enableIRIn函数中有一句就是开启时钟,所以才能正常接收。
3.格力空调的编码方式及发射方式
开发中遇到的一大问题就是格力空调的编码问题。
格力空调不知是出于什么样的心态,特立独行地设计了自己的一套编码方式,但奇怪之处在于通过sendRaw也不能实现控制。在琢磨这点上我花了不少时间,走了不少弯路。
后来在
的启发下总算明白了编码机制。
竟然在一个信号中间部分空出一段低电平!!前后两部分还有某种特殊关系。所以用红外接收头dump出的就是有问题的代码,当然发射不出正确的。
而且与风扇等信号不同,空调遥控器发射的是状态信号,不是功能信号。每一个信号中完整包含了空调状态的所有信息(温度、模式、扫风……)所以按下升温降温后,发射的不是升降温的指令,而是当前状态加减一度后的新状态编码。编码中每一位数起什么功能都是定好的,比如说温度信息就体现在第3、4和第17、18位上。
根据上述两个例子的代码,自己改了改,总算成功实现控制。心情无比激动!

 

4.加装温湿度传感器
想法是检测室温(湿度),当达到一定温度时自动开启风扇空调。
实际操作时发现实践起来十分简单,几乎没花什么时间一次就成功了。
硬件部分:
使用的是DHT11的温湿度传感器。

<ignore_js_op>

注意:引脚3不用接线!
软件部分:
从网上找了一个库,直接照它的代码用就行了。
获取温度:
int dat;
int chk = DHT11.read(DHT11PIN);
return dat=(float)DHT11.temperature;

 

获取湿度:
int dat;
  int chk = DHT11.read(DHT11PIN);
  return dat=(float)DHT11.humidity;
5.加装蜂鸣器提示
总不能一直用串口查看运行状态吧,最后需要实现的是用电池驱动,所以一定要加上一个指示装置表达当前运行状态,否则功能一多一定搞不清了。当时还不会lcd,就用最简单的无源蜂鸣器。

 

设定蜂鸣器声音含义
程序调用void warning(int freq, int time)发声,通过改变两个参数实现不同声音。freq代表声音频率,1最高4最低,time代表声音时长,25最短100最长
int freq
int time
Typechangebuzz(repeat times is mode  number)
1
25
Signal sending
2
50
Cannot find number_in_mp3
3
50
Temperature incorrect
4
100
Other no function button
Silent
Silent

 

6.加装lcd屏幕
硬件方面:
之前初学者套间里提供了一块lcd1602的液晶屏,但是看到那么多接口和教程里的复杂接线就望而生畏了。后来在淘宝店里发现一块适用于1602的转I2C口芯片,将十几个口简化为四个口,就果断买下,并以我拙劣的焊接水平勉强将芯片焊上。
在连线上又遇到问题了,搜了半天才发现arduino unoI2C口在模拟口45
四条线从上到下分别接GND5VA4A5

<ignore_js_op>

软件部分 
线总算连接好了,但屏幕上半片黑,下半片白,库文件找了好多都没解决,搜了好多资料,总算找到个能用的。
下面这篇写得很详细,使用方法也很简单,相信看了库中示例后都能学会。最后总算在它的指导下完成了!
http://forum.arduino.cc/index.php?topic=128635.msg967608
之后又遇到了一个很郁闷的事情,在我信心满满把程序中需要输出结果的地方都加上lcd指令后发现输入arduino后什么动静都没了,就像死机了一样。原来以为是冲突的问题,就一条条试代码,一条条删除直到正常为止。发现保留某几条lcd指令是可以正常问题的,而另一些一旦加入必定出事。研究了好几天,一直没有明白,在我几乎放弃之际,偶然间屏幕出现了“Temperature:”这竟然是我Serial.print出来的东西!!!顿时明白Serial输出与lcd输出之间必然有冲突!!!删除所有Serial后,一切正常。
切记:Serial.print与lcd.print不能同时使用!!!

 

7.设计的控制遥控器使用方法:
空调开关
电扇开关
改变
风类
Iptv开关
风扇
摇头
频道
频道
温度
温度
改变
风速
电视
开关
音量
音量
0
模式
切换
模式
切换
模式
切换
待机
确认
1
2
3
4
5
6
7
8
9
          Mode1:Air-conditioner                                      Mode2:Fan                                   Mode3:Iptv
空调模式下数字需要连续输入两个,先十位数后个位数,且范围在18-30度之间,否则报警且需重新输入

注意:IDE中的1.0.5虽然是稳定版,但引用的一些库好像不能正常通过编译,1.5.1却可以,建议使用。

 

视频展示
红外转码之 空调遥控


 

红外转码之 风扇遥控

 

红外转码之 iptv电视遥控

 

红外转码之 模式切换与lcd显示

 

 

下文有局部放大图
到这里为止,就把红外转码部分的内容介绍完了。

 

二、网络控制部分
红外控制的功能已经实现,接下来就是项目的优化过程。
最先想到的就是基于网络实现远程控制。后来知道,这就是物联网的概念。思路是这样的,通过温湿传感器反馈当前环境的温湿度,将数据上传到网络,如果到了警示值,通过邮件、微博通知用户,用户打开控制页面,发送指令(如开空调),uno定时访问网络,当发现需要执行指令时,发射相应的红外指令(空调开启)。
看了几篇相关的文章,发现在实现网络控制方面,以亿联(yeelink)和乐联网两个网站最为热门,且都提供相应的现成程序上传下载数据。
有了网站的支持和网友们经验的分享,看似高霸上的网络控制其实还是可以完成的,就是与之前遇到的一样,总有一些意想不到的困难。
硬件方面:
联网的组件比较流行的有两种。一是本项目使用的w5100,还有就是ENC28J60。W5100使用的人比较多,而且程序提供的比较多,容易上手,但缺点是价格有点昂贵,都和uno一个价了。相比之下ENC28J60十几元的价格还是挺实惠的。另外,w5100还有microSD接口(注意不是SD,尽管大多网店都说是SD)可以实现文件读取。令人欣喜的是,我们亲爱的学校提供500元经费支持项目,那么毫不犹豫,果断w5100。
W5100是uno的扩展,直接在uno上叠起来就可以使用。
但是马上遇到的是端口占用问题。也不知道w5100是怎么样的设计,端口被占用不少,至少我发现D10以上端口是没法用的,也不排除有其他端口。反正,把原来的接线接上后完全没法用了。这又让我郁闷了很久,反复调试都没法解决。
之前发过贴问过,还是没能解决。
http://www.geek-workshop.com/thread-7377-1-1.html
最后我灵机一动,经费充足,干脆就用两块uno算了。(我不是土豪)两者的通信方式就直接用红外了。也就是,原有的uno(控制uno)接线不变,新的uno搭载w5100(网络uno),并用红外发射管向红外接收器发射信号,实现单向的信息传输,且传送的信息就是控制遥控器的按键信息,发射头就放在接收头下。单向传输的特性决定了温湿度传感器不能向网络uno传输数据,所以就调整到网络uno上接收温湿度传感器值。
最后加上一个重复发射按钮发射上一个信号以便调试时测试响应距离。
这样就完成了硬件部分的所有连接。
附上局部图: <ignore_js_op>

 

其中下侧黄色和蓝色线连接网络uno

 

软件方面:
必须承认,网络控制方面,最主要和最烦人的是程序和配置的问题。
由于资料比较多,一开始使用的是乐联网,但是发现网关配置的东西一直搞不清楚,不仅需要网关地址还要公网地址,不知道是什么意思,不知道怎么配置,搞了半天没弄明白,就放弃了。
改用亿联(yeelink),虽然功能没有乐联网那么全,但是亿联不用设置网关,而且没有传感器数量限制。
Yeelink有官方库,但是我试了半天,总是不能同时上传与下载,最后还是根据某大神的代码更改完成了功能。
这篇文章对我帮助很大
http://hi.baidu.com/mizuda/item/fdd9c38a8e8237d9d1f8cdf6
首先要了解上传下载的流程,这需要涉及到http的知识。基本原理是,连入网络后
如需下载某开关值,需要先用client,print以http格式发送设备、开关编号及你的U-ApiKey号码(为了身份认证),服务器会返回一串Json代码,通过读取某一特定位置(倒数第二位)的值来判断开关的状态;如需上传,需要用client.print将待上传的值以特定的http格式,连同设备、传感器号及U-ApiKey发送。
需要注意的是,下载是分发送与接收两个步骤进行的。
注意:yeelink要求两次上传有最小时间间隔10s!否则传了也没用。
Yeelink在警示方面做得也是不错的,主要有邮件与微博警报,可以在yeelink用户中心进行设置,方法很简单,这里也不再阐述。
Yeelink还有手机app,使用起来同样很简单。
视频:
Yeelink网络控制 之 多设备远程控制

 

Yeelink网络控制 之 风扇遥控

 

Yeelink网络控制 之 邮件警报

 

Yeelink网络控制 之 微博警报

 

 

   这样,项目就基本完成了,历时一个月,走过不少弯路,但是都被一一化解,想想真是不容易。写作本文,一是备忘,更多的是希望新手们能免于重蹈我的覆辙。Arduino的功能是很强大的,也具有趣味性,但是往往一些意想不到的状况会消磨新手的兴趣。这时,类似极客工坊的网站应该承担起责任,为新手们提供技术支持与交流平台,引领新人们成长。Arduino是软硬件全部开源的单片机,所以希望大神们能多多将制作的产品与大家共享,交流开发中遇到的问题,与网友们共同交流,这也应该是arduino设计者们开源想要达到的效果。

 

成本估算:
2012最新款 Arduino UNO R3 开发板配SUB线   *2…………78
新版 Arduino Ethernet W5100 网络扩展板SD卡扩展…………40
Arduino IIC/I2C/接口 LCD1602转接板 ………… 6.5
LCD1602A液晶特价促销…………8.2
AOSONG(奥松)DTH11温湿度传感器,DHT11温湿度模块  …………4.5
HS0038B HS0038B SIP3 红外遥控接收头 红外接收管 VISHAY  …………1.8
优质面包板/迷你小面包板实验板 8.5CM 5.5CM 可以组合拼接…………5.5
GP 超霸无线话筒电池 玩具遥控器电池 6F22 9V电池 GP9V电池 *2 …………3.4
9V 电池盒带线电池盒 不带盖 开关 *2…………3.6
蜂鸣器…………0.6
以上¥152.1

 

以下材料只使用部分
盒装14种长度140根优质跳线面包板线 面包板专用线 面包板跳线…………10.0
面包线 面包板线面包板扎线 连接线测试线 实验线杜邦线一捆65…………5.3
常用小功率三极管包等17170  …………7.5
1/4W五色环电阻1%精密度 金属膜电阻包 30种常用阻值每种阻值20 …………5.9
5MM发射管 940nm红外发射管(20只) …………2.6
线束 杜邦线彩排40P 双头1P 一头公一头母 20CM 12股优质铜…………6.5
网线、焊锡、按钮开关费用不计
总计:¥152.1+37.8=189.9

这是我完成的首个arduino作品,欢迎大家交流指教!

最后是代码:

控制uno: <ignore_js_op> control.rar (2.9 KB, 下载次数: 233)
网络uno: <ignore_js_op> net.rar (2.8 KB, 下载次数: 277)

库文件:
红外IRremote: <ignore_js_op> IRremote.rar (30.62 KB, 下载次数: 104)
lcd: <ignore_js_op> LiquidCrystal.rar (437.18 KB, 下载次数: 104)
dht11: <ignore_js_op> DHT11.rar (2.93 KB, 下载次数: 126)
打包: <ignore_js_op> libraries.rar (470.67 KB, 下载次数: 222)