基于android开发手机控制空调的程序(硬件+软件)

本文适用于在没有红外发射器的手机上,利用音频接口连接相关发射器进行信号发射。效果展示: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左右),把喇叭全都拆掉,将红外二极管串联相应大小的电阻(电阻大小多少合适,有公式请百度),焊接到原来喇叭的位置上。

效果图:

基于android开发手机控制空调的程序(硬件+软件)_第1张图片

原理:手机输出的音频信号太弱,势必要进行放大才够我们使用,三极管放大的效果还是太弱。这时候小音箱就成了救命稻草了。。。它很便宜,关键是有着很成熟的音频信号放大电路!

以上内容完成以后可以使用现有的遥控类软件进行测试。

软件:

①首先查找要目标设备的遥控器编码文档。

②现在网上已经可以下到很多可以让手机当遥控器的软件了,他们不开源,但是可以获取他们输出的信号参考一下。

(下图是用一根两端都是公头的音频线,一端连接手机,另一端连接电脑麦克口,使用录音软件,用44100采样率录下来的,再用cooledit打开分析的。线也可以在jd买到,不到10块)

基于android开发手机控制空调的程序(硬件+软件)_第2张图片

根据我空调的文档,前面9000μs高电平+4500μs低电平是起始码,后面的01都是高低电平组合,一高一低为一位,低电平短的是0,长的是1。放大以后可以看到,生成的是很漂亮的正弦波。

③自己根据需要生成带有高低电平的声波。

根据网上搜索到的正弦波生成算法,作者仿造了上面的正弦波,但发现再次用电脑声卡捕获以后,高电平全体在低电平一侧,而且低电平的坐标出现很大的偏移。基于android开发手机控制空调的程序(硬件+软件)_第3张图片

图中内容为低电平出现偏移,一开始认为是在播放一开始就发声会导致偏移,图中已经采取相关措施,看来这个猜想不正确。即使文件开始很久之后才开始发声,还是会偏移。

后来经过多次测试,发现问题出在“低电平”的处理上。在使用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

你可能感兴趣的:(基于android开发手机控制空调的程序(硬件+软件))