基于android开发手机控制空调的程序(硬件+软件)
2015-07-01 20:28
489 查看
本文适用于在没有红外发射器的手机上,利用音频接口连接相关发射器进行信号发射。效果展示:http://t.cn/RLhOuCf
2016年2月28日更新:
使用音频还是要给手机插音频线,所以具有相当大的局限性。而且在开发过程中还不容易采样,容易受各种因素干扰。用声波模拟脉冲信号也具有一定难度。最近在玩Arduino,发现这个开发板很适合用来做采样和发射。
通过Arduino录制红外与播放红外信号的相关信息写在了这篇博文中:
http://blog.csdn.net/luhanglei/article/details/50762325
2016年06月07日更新
关于“正弦波”的作用:
通过在Arduino上实验就能知道,传感器接收红外信号的时候,并不是只要红外发光二极管亮起就是1,灭掉就是0。
红外接收器其实只接收频率为38KHz的信号(不是光的频率,就是通断电而闪烁的频率),因此当需要输出为1的信号的时候,发出的实际是一个20KHz(因为其实20KHz也可以被接收到)的信号,而不是常亮。
硬件:
作者的手机型号是nexus4,使用直接连接红外发射管(直接无反应)和DIY使用三极管,进行信号放大的方式(光太暗),均告失败。。。
在制作硬件的过程中,可以使用①用手机摄像头观察和②暂时用可见光发光二极管替代的方法查看效果。
最终解决方法:jd买了一个usb小音响(19RMB左右),把喇叭全都拆掉,将红外二极管串联相应大小的电阻(电阻大小多少合适,有公式请百度),焊接到原来喇叭的位置上。
效果图:
![](http://img.blog.csdn.net/20150701203647120?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbHVoYW5nbGVp/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
原理:手机输出的音频信号太弱,势必要进行放大才够我们使用,三极管放大的效果还是太弱。这时候小音箱就成了救命稻草了。。。它很便宜,关键是有着很成熟的音频信号放大电路!
以上内容完成以后可以使用现有的遥控类软件进行测试。
软件:
①首先查找要目标设备的遥控器编码文档。
②现在网上已经可以下到很多可以让手机当遥控器的软件了,他们不开源,但是可以获取他们输出的信号参考一下。
(下图是用一根两端都是公头的音频线,一端连接手机,另一端连接电脑麦克口,使用录音软件,用44100采样率录下来的,再用cooledit打开分析的。线也可以在jd买到,不到10块)
![](http://img.blog.csdn.net/20150701205451105?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbHVoYW5nbGVp/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
根据我空调的文档,前面9000μs高电平+4500μs低电平是起始码,后面的01都是高低电平组合,一高一低为一位,低电平短的是0,长的是1。放大以后可以看到,生成的是很漂亮的正弦波。
③自己根据需要生成带有高低电平的声波。
根据网上搜索到的正弦波生成算法,作者仿造了上面的正弦波,但发现再次用电脑声卡捕获以后,高电平全体在低电平一侧,而且低电平的坐标出现很大的偏移。
![](http://img.blog.csdn.net/20150701210726947?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbHVoYW5nbGVp/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
图中内容为低电平出现偏移,一开始认为是在播放一开始就发声会导致偏移,图中已经采取相关措施,看来这个猜想不正确。即使文件开始很久之后才开始发声,还是会偏移。
后来经过多次测试,发现问题出在“低电平”的处理上。在使用8bit pcm编码的情况下,一直认为正弦波与横轴交点的纵坐标意味着0,上为正,下为负,于是作者简单的将低电平置为了0x00,后来发现问题就出在这里。正弦波的与横轴的焦点,是整个宽度的中间值,而不是一个负值。
生成高低电平波代码如下(HEIGHT为振幅):
生成0,1的代码如下:
作者将以上功能放到了一个service中来控制,实现了安卓手表(android wear)控制空调的功能,效果:http://t.cn/RLhOuCf
建议在开发过程中遇到问题的时候多抓取音频分析,发现问题所在。
如果出现开头丢失的问题,可以在数据之前加入一定的中低电平和低电平信号,来当炮灰。
感谢
http://blog.csdn.net/kangear/article/details/39376105
http://m.blog.csdn.net/blog/caoshichao520326/8646913
2016年2月28日更新:
使用音频还是要给手机插音频线,所以具有相当大的局限性。而且在开发过程中还不容易采样,容易受各种因素干扰。用声波模拟脉冲信号也具有一定难度。最近在玩Arduino,发现这个开发板很适合用来做采样和发射。
通过Arduino录制红外与播放红外信号的相关信息写在了这篇博文中:
http://blog.csdn.net/luhanglei/article/details/50762325
2016年06月07日更新
关于“正弦波”的作用:
通过在Arduino上实验就能知道,传感器接收红外信号的时候,并不是只要红外发光二极管亮起就是1,灭掉就是0。
红外接收器其实只接收频率为38KHz的信号(不是光的频率,就是通断电而闪烁的频率),因此当需要输出为1的信号的时候,发出的实际是一个20KHz(因为其实20KHz也可以被接收到)的信号,而不是常亮。
硬件:
作者的手机型号是nexus4,使用直接连接红外发射管(直接无反应)和DIY使用三极管,进行信号放大的方式(光太暗),均告失败。。。
在制作硬件的过程中,可以使用①用手机摄像头观察和②暂时用可见光发光二极管替代的方法查看效果。
最终解决方法:jd买了一个usb小音响(19RMB左右),把喇叭全都拆掉,将红外二极管串联相应大小的电阻(电阻大小多少合适,有公式请百度),焊接到原来喇叭的位置上。
效果图:
原理:手机输出的音频信号太弱,势必要进行放大才够我们使用,三极管放大的效果还是太弱。这时候小音箱就成了救命稻草了。。。它很便宜,关键是有着很成熟的音频信号放大电路!
以上内容完成以后可以使用现有的遥控类软件进行测试。
软件:
①首先查找要目标设备的遥控器编码文档。
②现在网上已经可以下到很多可以让手机当遥控器的软件了,他们不开源,但是可以获取他们输出的信号参考一下。
(下图是用一根两端都是公头的音频线,一端连接手机,另一端连接电脑麦克口,使用录音软件,用44100采样率录下来的,再用cooledit打开分析的。线也可以在jd买到,不到10块)
根据我空调的文档,前面9000μs高电平+4500μs低电平是起始码,后面的01都是高低电平组合,一高一低为一位,低电平短的是0,长的是1。放大以后可以看到,生成的是很漂亮的正弦波。
③自己根据需要生成带有高低电平的声波。
根据网上搜索到的正弦波生成算法,作者仿造了上面的正弦波,但发现再次用电脑声卡捕获以后,高电平全体在低电平一侧,而且低电平的坐标出现很大的偏移。
图中内容为低电平出现偏移,一开始认为是在播放一开始就发声会导致偏移,图中已经采取相关措施,看来这个猜想不正确。即使文件开始很久之后才开始发声,还是会偏移。
后来经过多次测试,发现问题出在“低电平”的处理上。在使用8bit pcm编码的情况下,一直认为正弦波与横轴交点的纵坐标意味着0,上为正,下为负,于是作者简单的将低电平置为了0x00,后来发现问题就出在这里。正弦波的与横轴的焦点,是整个宽度的中间值,而不是一个负值。
生成高低电平波代码如下(HEIGHT为振幅):
/** * @param waveLen 周期,每个周期占用多少次采样率 * @param length 长度,单位同样是占用了多少次采样率。例如采样率为44100,需要1秒长,则length值为44100/waveLen * @return */ public static byte[] getHigh(int waveLen, int length) { byte[] wave = new byte[length]; for (int i = 0; i < length; i++) { wave[i] = (byte) (HEIGHT * (1 - Math.sin(2 * Math.PI * ((i % waveLen) * 1.00 / waveLen)))); } return wave; } public static byte[] getLow(int waveLen, int length) { byte[] wave = new byte[length]; for (int i = 0; i < length; i++) { wave[i] = (byte) (HEIGHT); } return wave; }
生成0,1的代码如下:
private byte[] get0() { int highLength = (int) Math.round(sampleRate / 1000000.0 * HIGHTIME / WAVELEN) * WAVELEN;//采样率/1000000.0*高电平时间=高电平占用的采样次数,先除后乘是想得到一个整数倍的周期,具体有没有益处未证实 byte[] high = getHigh(WAVELEN, highLength); int lowLength = (int) Math.round(sampleRate / 1000000.0 * LOWTIMEOF0 / WAVELEN) * WAVELEN; byte[] low = getLow(WAVELEN, lowLength); byte[] res = new byte[highLength + lowLength]; System.arraycopy(high, 0, res, 0, high.length); System.arraycopy(low, 0, res, high.length, low.length); return res; } private byte[] get1() { int highLength = (int) Math.round(sampleRate / 1000000.0 * HIGHTIME / WAVELEN) * WAVELEN; byte[] high = getHigh(WAVELEN, highLength); int lowLength = (int) Math.round(sampleRate / 1000000.0 * LOWTIMEOF1 / WAVELEN) * WAVELEN; byte[] low = getLow(WAVELEN, lowLength); byte[] res = new byte[highLength + lowLength]; System.arraycopy(high, 0, res, 0, high.length); System.arraycopy(low, 0, res, high.length, low.length); return res; }将生成好的数据按照编码格式拼接起来,连接到发射器播放,即可控制空调等设备。
AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_8BIT, wave.length, AudioTrack.MODE_STATIC); if (audioTrack != null) { audioTrack.write(wave, 0, wave.length); audioTrack.play(); }
作者将以上功能放到了一个service中来控制,实现了安卓手表(android wear)控制空调的功能,效果:http://t.cn/RLhOuCf
建议在开发过程中遇到问题的时候多抓取音频分析,发现问题所在。
如果出现开头丢失的问题,可以在数据之前加入一定的中低电平和低电平信号,来当炮灰。
感谢
http://blog.csdn.net/kangear/article/details/39376105
http://m.blog.csdn.net/blog/caoshichao520326/8646913
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories