Android红外遥控开发实践

一、简介

随着科技进步,手机逐渐融入了我们的生活。通过在手机中内置红外发射器,手机可以模拟各种遥控器的操作,实现对不同家电设备的控制。在电视精灵的Android版本中,也支持了红外遥控器功能,实现对移动高清机顶盒的遥控操作,提升了用户手机控制大屏的体验。红外遥控器的具体样式,如下图1所示,基本涵盖了用户日常操作指令。

红外遥控是一种古老而实用的技术,它是利用红外线的特性来传递信息。红外线是一种不可见光,具有较强的穿透力和方向性。在红外遥控中,发射器会将控制指令编码成特定的红外信号,并通过发射二极管将其发射出去。当这些红外信号到达接收设备时,接收设备中的红外接收器会将其接收并解码,从而执行相应的操作。接下来,本文将详细介绍一下红外系统的实现原理,并以电视精灵红外遥控为例,介绍如何在Android系统上开发红外遥控功能。


图1 电视精灵红外遥控g

二、红外遥控原理

2.1 红外系统

红外遥控系统通常由红外发射器和红外接收器组成。红外发射器将控制信号转换为红外光信号发射出去,而红外接收器则接收这些红外光信号,并将其转换回电信号,从而实现对设备的控制。红外遥控系统发送和接收的主要组成部分,如下图所示。

图2 红外系统组成结构

发送端:

  1. 指令输入:用户通过遥控器上的按键输入控制指令。

  2. 编码:将指令编码为红外信号格式。

  3. 调制:使用特定的调制方式,将编码后的信号与载波进行调制。

  4. 红外发射:通过红外发射二极管将调制后的红外信号发射出去。

接收端:

  1. 红外接收:红外接收二极管接收红外信号。

  2. 解调:对接收的信号进行解调,还原出编码信息。

  3. 解码:将解码后的信息转换为具体的控制指令。

  4. 指令执行:根据接收到的控制指令,执行相应的操作,如控制家电设备的开关、调节等。

2.2 红外编码

红外遥控器发射的信号由一串“0”和“1”的二进制代码组成,不同的芯片对“0”和“1”的编码有所不同,通常有曼彻斯特 (Manchester) 编码和脉冲宽度编码 (PWM)。

2.2.1 曼彻斯特编码(Manchester Encoding)

  • 原理:曼彻斯特编码是一种双相编码,通过电平的高低转换来表示“0”或“1”。每位中间的电平转换既表示了数据代码,也作为定时信号使用。

  • 特点:

    • 每位数据都有一个电平跳变,位中间的跳变既作时钟信号,又作数据信号。

    • 数据传输速率是调制速率的1/2,因为每个码元都被调制成两个电平。

    • 编码效率约为50%,因为每个时钟位都必须有一次变化。

2.2.2 脉冲宽度编码(PWM, Pulse Width Modulation)

  • 原理:脉冲宽度编码以发射红外载波的占空比代表“0”和“1”。一般通过固定发射红外载波的时间,通过改变不发射载波的时间来改变占空比。

  • 特点:

    • 节省能量,因为发射红外载波的时间固定。

    • 解码方便,通常包含引导码以辅助解码。

    • 不同芯片或制造商的PWM编码可能有所不同。

2.2.3 脉冲宽度编码举例

家用电器使用的红外遥控器绝大部分都是脉冲宽度编码,例如常用的电视遥控器使用NEC upd6121芯片,其“0”为载波发射0.56ms,不发射0.56ms;其“1”为载波发射0.56ms,不发射1.68ms。如下图所示:

图3 脉冲电平
图4 红外编码

2.3 红外调制

在红外通信中,将编码后的二进制信号调制成特定频率(如38kHz)的间断脉冲串是一个常见的做法。这种调制方式通常被称为脉冲调制或载波调制。在这个过程中,原始的二进制信号(由“0”和“1”组成)被用来控制一个高频载波信号(如38kHz的脉冲信号)的开关状态。

具体实现时,二进制信号中的“1”和“0”,分别由不同38kHz载波和低电平组成。如“0”为由 0.56ms 的 38kHz 载波和 0.56ms 的无载波低电平组合而成;“1”由 0.56ms 的 38kHz 载波和 1.69ms 的无载波低电平组合而成。这样,原始的二进制信号就被转换成了一个间断的脉冲串,其中每个脉冲都对应于原始信号中的一个位。

如下图所示,以下是一个简化的描述,说明如何使用高低电平来控制红外信号的调制:

  1. 原始二进制信号:例如,我们有二进制信号“0010”。

  2. 载波频率:选择38kHz作为载波频率。

  3. 调制过程:

    1. 当二进制信号为“1”时,生成一个由0.56ms 的 38kHz 载波和 1.69ms 的无载波低电平脉冲

    2. 当二进制信号为“0”时,生成一个由0.56ms 的 38kHz 载波和 0.56ms 的无载波低电平脉冲。

图5 载波调制

2.4 红外解调

解调是调制的逆过程,是通过红外接收管进行接收的。其基本工作过程为:当接收到调制信号时,输出高电平,否则输出为低电平。

图6 红外解调

2.5 红外解码

解码是将解调输出的脉冲,还原为二进制的“0”和“1”,得到二进制的“0”,“1”序列,进而通过编码协议分析传输内容所含的用户码和数据码。

图7 红外解码

三、开发实践

3.1 Android红外开发

截止目前,iphone手机内部没有配置红外发射硬件,因此在iphone手机上是不支持红外指令发射的。文中后续的开发介绍,以Android系统为基础。

3.1.1 权限申请

在App工程的AndroidManifest.xml中补充红外权限配置。

<!--红外遥控-->
<uses-permission android:name="android.permission.TRANSMIT_IR" />
<!-- 是否仅在支持红外的设备上运行 -->
<uses-feature android:name="android.hardware.ConsumerIrManager" android:required="false" /> 

3.1.2 API调用

红外遥控功能从Android4.4之后才开始支持,对应的管理类名叫ConsumerIrManager,常用的三个方法分别是:

  • 检测设备是否支持红外发射器
/**
* 返回true表示支持红外发射,返回false表示不支持红外发射
*/
public boolean hasIrEmitter()
  • 获得红外发射器可用的载波频率范围
/**
* 返回CarrierFrequencyRange类型数组,表示红外发射器可用的载波频率范围
*/
public CarrierFrequencyRange[] getCarrierFrequencies()
  • 发射红外信号
/**
* @param carrierFrequency 信号频率,单位赫兹(Hz),家用电器的红外频率通常使用38000Hz
* @param pattern 整型数组形式的信号格式
*/
public void transmit(int carrierFrequency, int[] pattern)

3.1.3 码值编码

红外编码由“引导码 + 用户编码(高八位)+ 用户编码(低八位)+ 键数据码 + 键数据反码 + 结束码”组成,然后按照一定的编码规则,合成数组的形式。以NEC6122协议举例,引导码固定为(9000 + 4500),结束码固定为(560,20000)。不同遥控器差别主要在于用户码和数据码,同一个遥控器的用户码是一样的,不同按键有不同的码值,码值可以转换出对应的数据码和数据反码。

红外键值

上述表格中列了NEC协议的几个指令,下面以按键数字2进行举例。

数字按键2的十六进制表示:

  • 用户码:0x08E6

  • 码值:0x41

转换为二进制:

  • 用户码

    • 高八位:00001000(表示08)

    • 低八位:11100110(表示E6)

  • 数据码

    • 原码:01000001(表示41)

    • 反码:10111110(41的反码)

由于手机与遥控器的信号编码有区别,需要逆序编码。

逆序编码:

  • 用户码

    • 高八位: 00010000

    • 低八位: 01100111

  • 数据码

    • 原码:10000010

    • 反码:01111101

编码转换完成,通过transmit方法进行发送。但是参数要传递整型数组形式的信号,并不是二进制数而是电平信号数据。电平是电路中某一点电压的高低状态,在数字电路中常用高电平表示“1”,用低电平表示“0”。根据上文可以看出,遥控器发射红外信号之时,通过“560us高电平+1690us低电平”代表“1”,通过“560us高电平+565us低电平”代表“0”。于是编写Android代码的时候,使用“560,1690”表示二进制的1,使用“560,565”表示二进制的0,具体数组值如下所示:

int[] patternForKey2 = {9000,4500, // 开头两个数字表示引导码
// 下面两行表示用户码: 00010000 01100111
560,565, 560,565, 560,565, 560,1690, 560,565, 560,565, 560,565, 560,565,560,565, 560,1690, 560,1690, 560,565, 560,565, 560,1690, 560,1690, 560,1690,
// 下面一行表示数据码:10000010
560,1690, 560,565, 560,565, 560,565, 560,565, 560,565, 560,1690, 560,565,
// 下面一行表示数据反码:01111101
560,565, 560,1690, 560,1690, 560,1690, 560,1690, 560,1690, 560,565, 560,1690,
560,20000}; // 末尾两个数字表示结束码

3.1.4 指令发送

当我们做好指令和数组值的映射,并选定信号频率。在需要发射红外信号处调用如下:

/**
 * 按下按键发射红外信号
 */
 public void transmit() {
     ConsumerIrManagerApi.transmit(38000, patternForKey2);
 }

3.2 电视精灵红外遥控实现

红外遥控功能,已经在电视精灵的Android版本中落地。为了保证用户体验和功能的有效性,在开发过程中,我们考虑并解决了以下两个问题:

  1. 电视精灵需要控制多种不同款的机顶盒,不同类型机顶盒,可能支持的红外码是不一样的。

  2. 用户快速点击多个指令,如何确保指令不丢失?

针对如上两个问题,对应解决方案分别是:

  1. 根据绑定设备类型,动态获取红外码值。

  2. 提供指令队列,防止指令丢失。

3.2.1 红外码值动态获取

红外遥控为了兼容不同设备,采用了红外码值动态下发的方式。主要流程如下图所示:

  1. 应用启动判断当前是否绑定设备,并发起红外配置获取请求,如果有设备则带上设备相关信息。

  2. 红外配置获取成功,则使用云端配置信息初始化红外遥控。

  3. 红外配置获取失败,则使用本地兜底数据初始化红外遥控。

图8 红外码值动态下发方案

3.2.2 指令队列控制

当用户快速点击红外遥控时,可能会导致部分指令丢失。为了确保每个指令在手机端都能得到处理,我们基于线程池框架,实现红外操作指令的控制队列,具体实现如下所示。

  1. 定义发码线程池
private static ExecutorService executorService = Executors.newSingleThreadExecutor();
  1. 单线程发码保证先后顺序,确保每次只有一个指令在执行
/**
 * 发射红外信号
 * @param carrierFrequency 红外频率
 * @param pattern 红外码
 */
public void transmit(int carrierFrequency, int[] pattern) {
    executorService.submit(new Runnable() {
        @Override
        public void run() {
            if(consumerIrManager != null){
                consumerIrManager.transmit(carrierFrequency, pattern);
            }
        }
    });
}

四、总结

红外遥控是一项非常实用的技术,它让我们能够轻松地操控各种家电设备。红外遥控具有操作简单、成本相对较低等优点,在家庭和日常生活中得到了广泛应用。但它也存在一些不足之处,比如信号容易被阻挡、对角度有一定要求,且不同设备之间可能存在兼容性问题。尽管如此,红外遥控依然是我们生活中不可或缺的一部分,它为我们带来了便利,也见证了科技的发展与进步。

参考文献

  1. Android 红外Uart数据发送APP开发_android红外给设备写信息-CSDN博客

  2. 红外遥控及Android手机红外遥控器开发

  3. Android 新增红外遥控支持 安卓有红外线遥控吗_GhostLover的技术博客_51CTO博客

  4. android 红外遥控器编码接收 红外遥控编码原理_mob6454cc670f76的技术博客_51CTO博客

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,063评论 6 510
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,805评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,403评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,110评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,130评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,877评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,533评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,429评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,947评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,078评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,204评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,894评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,546评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,086评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,195评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,519评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,198评论 2 357

推荐阅读更多精彩内容