文档章节

红外接收器驱动开发

mbzhong
 mbzhong
发布于 2018/12/14 00:49
字数 1065
阅读 4
收藏 0

背景:使用系统的红外遥控软件没有反应,然后以为自己接线错误,反复测试,结果烧坏了一个红外接收器,信号主板没有问题。所以自己开发了一个红外接收器的python驱动。接线参见https://my.oschina.net/mengyoufengyu/blog/2966992

源码如下:

import time
import RPi.GPIO as GPIO
import queue
import threading

class IRRemoteController:
    def __init__(self, pin_num: int = 18):
        self.pin_num = pin_num
        GPIO.setmode(GPIO.BCM)
        GPIO.setup(self.pin_num, GPIO.IN, GPIO.PUD_UP)
        self.key_queue = queue.Queue(100)
        self.thread = self.myThread(1, "key_detect", 1, self.pin_num, self.key_queue)
        
    
    def release(self):
        GPIO.remove_event_detect(self.pin_num)
        GPIO.cleanup()
        
    def start(self):
        self.thread.start()    
        pass
    
    def stop(self):        
        self.thread.stop()    
        self.release()
        pass
    
    def get_key(self):
        if self.key_queue.empty():
            return None
        else:
            return self.key_queue.get()    
        
    def get_msg(self):
        return self.thread.msg
    
    def add_event(self, key_value, func):
        self.thread.add_event(key_value, func)

    def remove_event(self, key_value):
        self.thread.remove_event(key_value)

    
    class myThread(threading.Thread):
        def __init__(self, threadID, name, counter, pin_num, key_queue):
            threading.Thread.__init__(self)
            self.threadID = threadID
            self.name = name
            self.counter = counter
            self.pin_num = pin_num
            self.key_queue = key_queue
            self.key_event = {}

            self.__pause_flag = threading.Event()     # 用于暂停线程的标识
            self.__pause_flag.set()                   # 设置为True
            self.__running_flag = threading.Event()   # 用于停止线程的标识
            self.__running_flag.set()                 # 将running设置为True
            self.msg = []

        def add_event(self, key_value, func):
            self.key_event[key_value] = func
            
        def remove_event(self, key_value):
            del self.key_event[key_value]
            
        def get_low_meaning(self, diff_time):
            low_pulse_type = 0
            if 0.0004 < diff_time < 0.0009:
                low_pulse_type = 1  # 一个0.560ms的脉冲
            elif 0.008 < diff_time < 0.015:
                low_pulse_type = 2  # 一个9mS的脉冲
            else:
                low_pulse_type = 0
            return low_pulse_type
            
        def get_high_meaning(self, diff_time):
            high_pulse_type = 0
            if  0.0004 < diff_time < 0.0009:
                high_pulse_type = 1 # 0.560ms的高电平
            elif  0.0009 < diff_time < 0.0018:
                high_pulse_type = 2 # 1.13ms的高电平
            elif 0.0018 < diff_time < 0.003:
                high_pulse_type = 4 # 2.25ms的高电平
            elif 0.004 < diff_time < 0.006:
                high_pulse_type = 8 # 4.5ms的高电平
            elif 0.02 < diff_time < 0.2:
                high_pulse_type = 16 # 39ms或95ms的高电平
            else:
                high_pulse_type = 0   
            return high_pulse_type
        
        def get_high_low_meaning(self, high_pulse_type, low_pulse_type):
            # 根据高低电平意义的出这个脉冲的意思
            key_char = ""
            if low_pulse_type == 2 and high_pulse_type == 8:
                key_char = "Z" #  引导码: 0的时间(ms):9.067 1的时间(ms):4.517
            elif low_pulse_type == 2 and high_pulse_type == 4:
                key_char = "Y" #  重复码: 0的时间(ms):9.093 1的时间(ms):2.265
            elif low_pulse_type == 1 and high_pulse_type == 16:
                key_char = "X" #  时间对齐码: 0的时间(ms):0.550 1的时间(ms):39.362     0的时间(ms):0.550 1的时间(ms):95.722
            elif low_pulse_type == 1 and high_pulse_type == 1:
                key_char = "0" #  逻辑0: 0的时间(ms):0.553 1的时间(ms):0.632
            elif low_pulse_type == 1 and high_pulse_type == 2:
                key_char = "1" #  逻辑1: 0的时间(ms):0.535 1的时间(ms):1.684
            return key_char
            
        def get_high_low_char_process(self, last_key_char, key_char, high_pulse_type, low_pulse_type):
            new_key_char = self.get_high_low_meaning(high_pulse_type, low_pulse_type)
            if new_key_char == "Z" or new_key_char == "Y":
                key_char = new_key_char
            else:
                key_char += new_key_char
                
            # key_char += self.get_high_low_meaning(high_pulse_type, low_pulse_type)  
            if key_char.endswith("X"):
                if key_char.startswith("Z"):
                    last_key_char = key_char
                # 重复码处理            
                elif key_char.startswith("Y"):
                    last_key_char = last_key_char
                else:
                    last_key_char = ""
                # 对键值进行处理
                key_value = last_key_char[1:-1]
#                             print(last_key_char, key_value)
                if key_value:
                    key_value = hex(int(key_value, base=2))
                    if self.key_queue.full():
                        self.key_queue.get()
                    self.key_queue.put(key_value)
                    if key_value in self.key_event:  # 实时触发事件
                        self.key_event[key_value]()

                # 恢复key_char                            
                key_char = ""
            return last_key_char, key_char
        
            
        def run(self):
            last_signal = GPIO.HIGH
            start_time = time.time()
            low_pulse_type = 0  # 0表示无用  1表示9mS的脉冲 2 表示0.565ms的脉冲
            high_pulse_type = 0  # 0表示无用  1表示9mS的脉冲 2 表示0.565ms的脉冲
            
            last_key_char = key_char = ""
            
            
            while self.__running_flag.isSet():
                self.__pause_flag.wait()      # 为True时立即返回, 为False时阻塞直到内部的标识位为True后返回        buffer = []
                new_signal = GPIO.input(self.pin_num)
                now_time = time.time()
                if new_signal == last_signal == GPIO.HIGH and key_char and now_time - start_time > 0.095:
                    new_signal = GPIO.LOW
                    
                if new_signal != last_signal:  # 进入接受信号开始
                    end_time = now_time
                    diff_time = end_time - start_time
                    start_time = end_time                    
                            
                    # 上一个信号是低电平,根据时间解析其意义
                    if last_signal == GPIO.LOW:
                        low_pulse_type = self.get_low_meaning(diff_time)
                    else: # 上一个信号是高电平,根据时间解析其意义
                        high_pulse_type = self.get_high_meaning(diff_time)
                        
                    self.msg.append([last_signal, new_signal, diff_time, low_pulse_type, high_pulse_type,key_char]) 
                    if (last_signal == GPIO.HIGH and new_signal == GPIO.LOW) :  # 高变低,这时候完成一个高低电平信号,要进行处理
                        # 根据高低电平意义的出这个脉冲的意思
                        last_key_char, key_char = self.get_high_low_char_process(
                            last_key_char, key_char, high_pulse_type, low_pulse_type)
                        low_pulse_type = 0
                        high_pulse_type = 0
                    last_signal = new_signal
                time.sleep(0.00001)

        def pause(self):
            self.__pause_flag.clear()     # 设置为False, 让线程阻塞

        def resume(self):
            self.__pause_flag.set()       # 设置为True, 让线程停止阻塞

        def stop(self):
            self.__pause_flag.set()       # 将线程从暂停状态恢复, 如何已经暂停的话
            self.__running_flag.clear()        # 设置为False   
        
    @staticmethod
    def example():
        irrc = IRRemoteController()
        print("开始采集数据:")
        
        def left():
            print("[0xffa25d CH-] 前进Forward")
            
        def mid():
            print("[0xff629d CH] 停止 Stop")
            
        def right():
            print("[0xffe21d CH+] 后退 Back off")
            
        def main_exit():
            print("[0xff906f EQ] 主线程退出")
            
            
        irrc.add_event('0xffa25d', left)
        irrc.add_event('0xff629d', mid)
        irrc.add_event('0xffe21d', right)
        irrc.add_event('0xff906f', main_exit)
        irrc.start()
        now_time = time.time()
        while time.time() - now_time < 50:
            key = irrc.get_key()
            if key is None:
                time.sleep(0.01)
                continue
            
            if key == "0xff906f":
                break
#             else:
#                 print(key)
                
        print("结束采集数据:")
        
        irrc.stop()
        
#         for item in irrc.get_msg():
#             print(item)

if __name__ == "__main__":
    IRRemoteController.example()

 

© 著作权归作者所有

共有 人打赏支持
mbzhong
粉丝 1
博文 91
码字总数 63866
作品 0
济南
程序员
私信 提问
通过红外的遥控板,实现在安卓开发板上控制应用.

红外的遥控板,实现在安卓开发板上控制应用. 比如发送一个红外命令1,开发板接收器收到后, 怎么处理,才能让上层app调用到这个信息.

lihaibo_cs
2014/04/25
78
0
Ardunio 红外遥控PC音乐播放器_Java后端

Ardunio 红外遥控PC音乐播放器 程序说明: 本程序通过红外遥控器,发射信号给接收器,然后由Ardunio 通过 USB 传给 PC端,实现一个播放器 本播放器可以 播放,暂停,上一首,下一首,静音,循...

Deng小尧
2013/07/18
0
1
Linux 2.6.36 带来了什么?

Linux 2.6.36带来了什么? 最新的Linux内核很值得注意,因为它没有带来体积的增长,却包含了成百上千个进展,将会对通常都察觉不到Linux内核升级所带来的改变的最终用户带来显著的体验提升。...

xyxzfj
2010/10/22
2.6K
3
做快两年了。技术该往哪个方向走。

先谈谈自己的项目经历,差不多11年这个时候来到公司,一直干在现在。 在将近前面一年多时间做的都是一些简单 单片机开发的小程序。期间做的小项目是挺多的。 第一个小项目是门磁开关:基本上...

oschina啊辉
2013/04/02
1K
8
VR体验中的追踪定位,现在可以换成低成本的Wi-Fi了

斯坦福大学研究团队用Wi-Fi技术实现VR应用中的追踪定位。 在目前实现的VR游戏体验中,用户佩戴好设备,看着系统屏幕投影的虚拟3D世界,然后在规定的区域运动。但是限于追踪限制,用户也只能在...

行者武松
2018/03/06
0
0

没有更多内容

加载失败,请刷新页面

加载更多

牛津词典 2018 年度词汇 ——「有毒」!

简评:本文并没有「标题党」,牛津词典公布的 2018 年度词汇就是 Toxic. 意为「有毒的」。 2018 was toxic. Toxic 这个词是什么意思呢? 牛津词典(Oxford Dictionaries)在 Word of the Da...

极光推送
18分钟前
1
0
浅谈Service Mesh体系中的Envoy

https://blog.csdn.net/yunqiinsight/article/details/81019255

易野
26分钟前
1
0
嵌入式应用选择合适的微控制器

准备所需硬件接口列表 使用微控制器的基本硬件框图,准备一份微控制器需要支持的所有外设接口的列表。微控制器中有两种常见的接口类型需要列出。第一种是通信接口,这些是外围设备,如USB,S...

linuxCool
34分钟前
3
0
Group by使用

概述 GROUP BY我们可以先从字面上来理解,GROUP表示分组,BY后面写字段名,就表示根据哪个字段进行分组,如果有用Excel比较多的话,GROUP BY比较类似Excel里面的透视表。 GROUP BY必须得配合...

小橙子的曼曼
45分钟前
4
0
机械臂写中文

Make Me a Hanzi https://www.skishore.me/makemeahanzi/ 使用uArm Swift Pro机械臂写中文-毛笔字 https://github.com/makelove/Robot_Arm_Write_Chinese...

itfanr
57分钟前
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部