第20章 红外遥控实验

第二十章 红外遥控实验

1. 红外遥控简介

红外遥控是一种无线、 非接触控制技术, 具有抗干扰能力强, 信息传输可靠,功耗低, 成本低, 易实现等显著优点。 由于红外线遥控不具有像无线电遥控那样穿过障碍物去控制被控对象的能力, 所以不用担心串码问题。

红外遥控通信系统一般由红外发射装置和红外接收设备两大部分组成。

  • 红外发射装置

红外发射装置, 也就是通常我们说的红外遥控器, 如下所示:

屏幕截图 2024 08 14 093722

通常的红外遥控器是将遥控信号(二进制脉冲码) 调制在 38KHz 的载波上,经缓冲放大后送至红外发光二极管, 转化为红外信号发射出去的。

二进制脉冲码的形式有多种, 其中最为常用的是 NEC Protocol 的 PWM 码(脉冲宽度调制)和 Philips RC-5 Protocol 的 PPM 码(脉冲位置调制码, 脉冲串之间的时间间隔来实现信号调制)。 如果要开发红外接收设备, 一定要知道红外遥控器的编码方式和载波频率, 我们才可以选取一体化红外接收头和制定解码方案。 我们配套的红外遥控器使用的是 NEC 协议, 其特征如下:

  1. 8 位地址和 8 位指令长度;

  2. 地址和命令 2 次传输(确保可靠性)

  3. PWM 脉冲位置调制, 以发射红外载波的占空比代表“ 0” 和“ 1” ;

  4. 载波频率为 38Khz;

  5. 位时间为 1.125ms 或 2.25ms;

NEC 码的位定义: 一个脉冲对应 560us 的连续载波, 一个逻辑 1 传输需要2.25ms(560us 脉冲+1680us 低电平) , 一个逻辑 0 的传输需要 1.125ms(560us脉冲+560us 低电平) 。 而红外接收头在收到脉冲的时候为低电平, 在没有脉冲的时候为高电平, 这样, 我们在接收头端收到的信号为: 逻辑 1 应该是 560us 低+1680us 高, 逻辑 0 应该是 560us 低+560us 高。 所以可以通过计算高电平时间判断接收到的数据是 0 还是 1。 NEC 码位定义时序图如下图所示:

屏幕截图 2024 08 14 093937

NEC 遥控指令的数据格式为: 引导码、 地址码、 地址反码、 控制码、 控制反码。 引导码由一个 9ms 的低电平和一个 4.5ms 的高电平组成, 地址码、 地址反码、 控制码、 控制反码均是 8 位数据格式。 按照低位在前, 高位在后的顺序发送。 采用反码是为了增加传输的可靠性(可用于校验) 。 数据格式如下:

屏幕截图 2024 08 14 094005

NEC 码还规定了连发码(由 9ms 低电平+2.5m 高电平+0.56ms 低电平+97.94ms 高电平组成), 如果在一帧数据发送完毕之后, 红外遥控器按键仍然没有放开, 则发射连发码, 可以通过统计连发码的次数来标记按键按下的长短或次数

  • 红外接收设备

红外遥控接收器的主要作用是将遥控发射器发来的红外光信好转换成电信号, 再放大、 限幅、 检波、 整形, 形成遥控指令脉冲, 输出至遥控微处理器。 近几年不论是业余制作还是正式产品, 大多都采用成品红外接收头。 成品红外接收头的封装大致有两种: 一种采用铁皮屏蔽; 一种是塑料封装。 均有三只引脚, 即电源正(VDD) 、 电源负(GND) 和数据输出(VOUT) 。 其外观实物图如下图所示:

屏幕截图 2024 08 14 094216

正对接收头的凸起处看, 从左至右, 管脚依次是 1: VOUT, 2: GND, 3: VDD。

由于红外接收头在没有脉冲的时候为高电平, 当收到脉冲的时候为低电平,所以可以通过外部中断的下降沿触发中断, 在中断内通过计算高电平时间来判断接收到的数据是 0 还是 1。

2. 硬件设计

本实验使用到硬件资源如下:

  • 红外遥控和红外接收头模块

  • ESP32 GPIO

本章实验使用 ESP32 的 IO14 引脚, 接线如下所示:

屏幕截图 2024 08 14 094347

3. 软件设计

3.1 MicroPython函数使用

本实验通过外部中断下降沿触发对红外遥控解码, 因此外部中断模块使用可参考前面章节。

外部中断也是通过 machine 模块的 Pin 子模块来配置, 先来看构造函数和使用方法:

屏幕截图 2024 08 14 094504

3.2 代码分析

#导入Pin模块
from machine import Pin
import time

#定义IRED控制对象
ired=Pin(14,Pin.IN,Pin.PULL_UP)

#存储红外遥控器键值
gired_data=[0,0,0,0]

#外部中断函数
def ired_irq(ired):
    ired_high_time=0  #保存高电平时间,鉴别数据1还是0
    
    if ired.value()==0:
        time_cnt=1000
        while (not ired.value()) and time_cnt:  #等待引导信号9ms低电平结束,若超过10ms强制退出
            time.sleep_us(10)
            time_cnt-=1
            if time_cnt==0:
                return
        
        if ired.value()==1:  #引导信号9ms低电平已过,进入4.5ms高电平
            time_cnt=500
            while ired.value() and time_cnt:  #等待引导信号4.5ms高电平结束,若超过5ms强制退出
                time.sleep_us(10)
                time_cnt-=1
                if time_cnt==0:
                    return
            for i in range(4):  #循环4次,读取4个字节数据
                for j in range(8):  #循环8次读取每位数据即一个字节
                    time_cnt=600
                    while (ired.value()==0) and time_cnt:  #等待数据1或0前面的0.56ms结束,若超过6ms强制退出
                        time.sleep_us(10)
                        time_cnt-=1
                        if time_cnt==0:
                            return
                    time_cnt=20
                    while ired.value()==1:  #等待数据1或0后面的高电平结束,若超过2ms强制退出
                        time.sleep_us(100)
                        ired_high_time+=1
                        if ired_high_time>20:
                            return
                    gired_data[i]>>=1  #先读取的为低位,然后是高位
                    if ired_high_time>=8:  #如果高电平时间大于0.8ms,数据则为1,否则为0
                        gired_data[i]|=0x80
                    ired_high_time=0  #重新清零,等待下一次计算时间
        if gired_data[2]!=~gired_data[3]:  #校验控制码与反码,错误则返回
            for i in range(4):
                gired_data[i]=0
                return
             
    print("红外遥控器操作码:0x%02X" % gired_data[2])
            
#程序入口
if __name__=="__main__":
    ired.irq(ired_irq,Pin.IRQ_FALLING)
    
    while True:
        pass


2024.8.23 第一次修订,后期不再维护

posted @ 2024-08-23 09:11  hazy1k  阅读(2)  评论(0编辑  收藏  举报