红外接收器驱动开发

背景:使用系统的红外遥控软件没有反应,然后以为自己接线错误,反复测试,结果烧坏了一个红外接收器,信号主板没有问题。所以自己开发了一个红外接收器的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()

 

转载于:https://my.oschina.net/mengyoufengyu/blog/2988296

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值