[PYTHON] Infrared remote control reception with Intel Edison

Infrared remote control reception is performed using GPIO of Intel Edison Arduino Board. This time, the infrared remote control receiver module used was PL-IRM0101.

Infrared sensor connection

Use a breadboard to connect the Intel Edison Arduino Board to the PL-IRM0101.

The pins of PL-IRM0101 are ** Vout ** (4.5 to 5.5V), ** GND **, ** VCC ** (4.5 to 5.5V) from the left side, so the left side pin. Connect to digital I / O 8, the middle pin to GND, and the right pin to Power 5V.

irsensor.png

DSC_0219.JPG

DSC_0220.JPG

Infrared remote control format

The format of the infrared remote controller is not clearly defined by RFP etc., but it seems that it conforms to the NEC format or the Home Appliances Association format in Japan. For details of each format, refer to the following materials.

http://akizukidenshi.com/download/k4174_format.pdf

This time, we will implement the analysis part of the command sent in the home appliance cooperative format with python2.7.

Infrared remote control command analysis program

The default OS of Intel Edison includes the hardware abstraction library ** MRAA ** provided by Intel from the beginning, and it can be used from Python as if it were a standard library.

irsensor.py


#! /usr/bin/env python
# -*- coding: utf-8 -*-

import mraa
import time

PIN = 8          #GPIO number of Arudino Board to which Vout is connected
BUF = 0.35       # HIGH/Allowable blur width for LOW duration[ms]
FLAME_SPACE = 50 #The duration of LOW to determine that a series of commands has ended[ms]

HIGH, LOW = 1, 0


class KadenkyoDecoder(object):
    L_HIGH = 3.2   #HIGH duration in the leader code of the consumer electronics cooperative format[ms]
    L_LOW = 1.6    #LOW duration in the leader code of the home appliance cooperative format[ms]

    D_LOW_0 = 0.4  #LOW duration when 0 in the data code of the home appliance cooperative format[ms]
    D_LOW_1 = 1.2  #LOW duration in case of 1 in the data code of the home appliance cooperative format[ms]

    def __init__(self, code):
        self.code = code

    def decode(self):
        if len(self.code) <= 3: #Received HIGH/If the size of the LOW list is 3 or less, it is considered as noise.
            return "UNKNOWN"

        paired = self.__make_pair(self.code[:-1])

        if not self.__is_valid_format(paired[0]):
            return "UNKNOWN"
        else:
            return "".join(map(str, map(self.__make_bit, paired[1:])))

    def __make_pair(self, code): # HIGH/HIGH the list of LOW durations&Convert to a list of LOW pairs
        def pair(l):
            for i in xrange(0, len(l), 2):
                yield {"H": l[i]["len"], "L": l[i + 1]["len"]}
        return list(pair(code))

    def __is_valid_format(self, lc): #Check if it matches the reader code of the home appliance cooperative format
        h = self.L_HIGH - BUF <= lc["H"] <= self.L_HIGH + BUF
        l = self.L_LOW - BUF <= lc["L"] <= self.L_LOW + BUF
        return h and l

    def __make_bit(self, dc): #HIGH according to the definition of the data code of the home appliance cooperative format&Convert LOW pairs to 0 or 1
        if self.D_LOW_0 - BUF <= dc["L"] <= self.D_LOW_0 + BUF:
            return 0
        elif self.D_LOW_1 - BUF <= dc["L"] <= self.D_LOW_1 + BUF:
            return 1
        else:
            return 9


def print_code(code):
    for i, elem in enumerate(code):
        s = "LOW " if elem["state"] == HIGH else "HIGH"
        print "%03d: %s %5.2f[ms]" % (i, s, round(elem["len"], 2))


def main():
    ir = mraa.Gpio(PIN) #Get the specified GPIO voltage state using Intel's MRAA library
    ir.dir(mraa.DIR_IN)

    recv, last, st, nt, code = False, LOW, 0, 0, []
    while True:
        current = not ir.read()  # PL-IRM0101 returns 0 when it receives infrared rays, so bit inversion
        nt = time.time() * 1000
        if last != current: #Measure edge time from the edge where HIGH and LOW are inverted
            last = current
            if not recv:
                recv = True
                st = time.time() * 1000
                continue
            code.append({"state": last, "len": nt - st})
            st = nt
        if recv and last == LOW and nt - st > FLAME_SPACE: # FLAME_If it continues to be LOW during SPACE, it is judged that the command has finished.
            # print_code(code)
            s = KadenkyoDecoder(code).decode()
            print s
            recv, last, st, nt, code = False, LOW, 0, 0, []

if __name__ == "__main__":
    try:
        print "start"
        main()
    except KeyboardInterrupt as err: # Ctrl-Exit when C is entered
        print "end"

In the above code, the following processing is roughly performed (error processing is not implemented at all, so it is better to add it as needed).

  1. main (): From the voltage change of Vout of the infrared remote control receiving module, measure and list the time when infrared rays are received (HIGH) and the time when infrared rays are not received (LOW).
  2. KadenkyoDecoder (code) .decode (): Decomposes the obtained infrared pulse into a reader code, data code, and stop bit in light of the definition of the home appliance cooperative format.
  3. If the format is followed, the data code part is decoded into a 48-bit bit array and returned.
  4. Returns "UNKNOWN" if not following the Home Appliances Association format

Note that the Vout obtained from PL-IRM0101 returns 0 when receiving infrared rays and 1 when not receiving infrared rays.

The PIN number, BUF seconds, and FLAME_SPACE seconds may vary depending on the environment. I want you to adjust it to a good one.

Execution result

Execution result


root@edison:~# ./irsensor.py 
start
010000000000010000000001000000001011110010111101
UNKNOWN
UNKNOWN
010000000000010000000001000000000010110000101101
UNKNOWN
UNKNOWN
010000000000010000000001000000001010110010101101
UNKNOWN
UNKNOWN
UNKNOWN
UNKNOWN
010000000000010000000001000000001010110010101101
UNKNOWN
UNKNOWN
010000000000010000000001000000001010000010100001
UNKNOWN
UNKNOWN
UNKNOWN
UNKNOWN
010000000000010000000001000000001011110010111101
UNKNOWN
UNKNOWN
^Cend

When I pointed the infrared remote control for a certain set-top box at the sensor and pressed some buttons, the above result was obtained.

This infrared remote controller for set-top boxes seems to be able to send four types of commands according to the home appliance cooperative format that operates the TV itself, and multiple commands that do not follow the home appliance cooperative format that operates the set-top box.

Correspondence between sent commands and TV operation buttons


010000000000010000000001000000001011110010111101  =>Power on/OFF
010000000000010000000001000000000010110000101101  =>On the channel
010000000000010000000001000000001010110010101101  =>Under the channel
010000000000010000000001000000001010000010100001  =>Input source switching

Summary

This time, using the ntel Edison Arduino Board and the infrared remote control receiver module, we analyzed the commands of the home appliance cooperative format of the infrared remote control.

In the future, it will be interesting to support the NEC format, support when the button is held down, and support the command learning function of the infrared remote controller.

Recommended Posts

Infrared remote control reception with Intel Edison
I learned how the infrared remote control works with Raspberry Pi
[ev3dev × Python] SSH Control (remote control with keyboard)
Startup Intel Edison
Control LED bulbs from a microcomputer (Intel Edison) (1)
Control LED bulbs from a microcomputer (Intel Edison) (2)
Pepper-kun remote control environment construction with Docker + IPython Notebook
Face recognition with Edison
Geolocation on Intel Edison
Use GPS with Edison
Control scripts with exceptions