IR интерфейс, Raspberry и LIRC

    Моя задача сейчас — научиться отправлять команды кондиционерам и другим устройствам в доме. Исходно эти устройства имеют только IR remote control. Для решения этой задачи у меня есть Raspberry Pi и IR transceiver shield. В статье можно найти конфиги, команды, советы и немного теории. Из софта будут LIRC (Linux Infrared Remote Control) и Python.


    LIRC я нашел с помощью Гугла. В процессе исследования выяснил, что LIRC работает как с передатчиками, так и с приемниками IR сигналов, может декодировать принятый сигнал и выполнять какие-то действия в связи с этим. Сейчас прием сигналов мне не нужен, но в будущем может оказаться полезным. Если будете возиться с LIRC сами, прочтение LIRC Configuration Guide крайне рекомендуется.


    Конфигурация


    apt-get update
    apt-get install lirc

    # /etc/modules (добавить в конец)
    lirc_dev
    lirc_rpi gpio_in_pin=18 gpio_out_pin=17

    # /etc/lirc/hardware.conf (по умолчанию файла нет, надо создать)
    LIRCD_ARGS="--uinput --listen"
    LOAD_MODULES=true
    DRIVER="default"
    DEVICE="/dev/lirc0"
    MODULES="lirc_rpi"

    # /boot/config.txt (в конце уже есть заготовка секции про lirc, исходно пустая)
    dtoverlay=lirc-rpi,gpio_in_pin=18,gpio_out_pin=17
    

    # /etc/lirc/lirc_options.conf (найти и заменить эти параметры)
    driver    = default
    device    = /dev/lirc0

    reboot
    sudo /etc/init.d/lircd status

    Запись


    Сначала необходимо создать конфигурационный файл с последовательностями данных для всех необходимых команд. Я дальше называю этот файл lircd.conf, но на самом для каждого устройства создается свой файл my_device_name.lircd.conf в каталоге /etc/lirc/lircd.conf.d.


    Формат файла описан здесь. Если есть пульт, то можно записать передаваенмые им сигналы в файл с помощью утилиты irrecord.


    /etc/init.d/lircd stop
    irrecord -d /dev/lirc0 ~/my_device.lircd.conf
    mv ~/my_device.lircd.conf /etc/lirc/lircd.conf.d/

    irrecord анализирует последовательности и пытается определить протокол и временные параметры. В некоторых случаях irrecord терпит неудачу в анализе, поэтому есть возможность сохранить последовательность как она была принята, в "сыром" (raw) виде, для этого есть ключ --force.


    Но даже с --force irrecord пытается что-то анализировать, и тоже может потерпеть неудачу. Тогда можно записать последовательности с помощью mode2 и создать файл самостоятельно.


    mode2 печатает последовательно длительности наличия и отсутствия сигнала, из которых и складываются передаваемые данные. Длительность измеряется в микросекундах (1e-6 секунды). В raw формате в lircd.conf указыватся эти же длительности, начиная с 'pulse' (ведущий 'space' не нужен). Сответственно, всегда должно быть нечетное количество чисел (начинается и заканчивается наличием сигнала — 'pulse').


    Для автоматизации я сделал скрипт для записи, который спрашивает имя команды, запускает mode2 на 5 секунд, запоминает и в конце печатает результат в формате, готовом для lircd.conf (см. под спойлером).


    Скрипт
    #!/usr/bin/env python3
    
    import io
    import sys
    import os
    
    r = """begin remote
    
      name  DEVICE_NAME_CHANGE_ME
      flags RAW_CODES
      eps            30
      aeps          100
    
      gap          19037
    
      begin raw_codes
    
    """
    
    while True:
            print()
            print("enter the command name, or just press Enter to finish")
    
            a = sys.stdin.readline().rstrip("\n\r")
            if not a:
                    break
    
            first_space = True
            n = 0
    
            r += "    name " + a + "\n"
    
            for line in os.popen('timeout 5s mode2 -d /dev/lirc0 2> /dev/null').read().split('\n'):
                    words = line.split()
                    if len(words) < 2:
                            continue
    
                    if words[0] != 'space' and words[0] != 'pulse':
                            continue
                    if first_space and words[0] == 'space':
                            first_space = False
                            continue
    
                    if n % 4 == 0:
                            r += "\n        "
    
                    r += words[1] + "  "
                    n = n+1
    
            if n > 5:
                    print ("got", n, "values, looks good")
            else:
                    print ("no signal, something went wrong")
    
            r += "\n\n"
    
    r += """  end raw_codes
    end remote
    """
    
    print()
    print(r)
    print()

    Созданный файл можно еще раз попытаться "распознать" с помощью irrecord --analyse. Не всегда это проходит удачно, не спешите выбрасывать старый файл. Моя статистика такая: пульт от телевизора LG был понят с легкостью, все кондиционеры и пылесос потребовали ручного создания, пылесос был потом обработан --analyse.


    Просто как пример: вот так выглядит файл для моего пылесоса.


    Стандартные имена команд


    LIRC по своему прямому назначению должен принятый и распознанный IR сигнал превратить в событие Linux input. Поэтому по умолчанию от нас требуют, чтобы имена команд в lircd.conf были из стандартного списка. Можно посмотреть список допустимых имен:


    irrecord --list-namespace

    Кондиционеры под этот шаблон не попадают. Требование к именам можно выключить, добавив при записи параметр:


    irrecord  --disable-namespace ....

    Отладка


    Проверить приемник помогает утилита mode2, которая печатает все видимые сигналы.


    /etc/init.d/lircd stop
    mode2 -d /dev/lirc0

    Проверить передачу проще всего, если есть другой приемник и запущенная на нем mode2. В особо безнадежных случаях можно менять значение на выходе GPIO и проверять тестером или осцилографом, куда доходит сигнал. Команда gpio входит в состав пакета wiringpi.


    while sleep 1; do
      gpio -g toggle 17
    done

    Посмотреть на логи можно с помощью journalctl, в частности это позволяет увидеть ошибки в файле конфигурации:


    journalctl -b 0 /usr/sbin/lircd

    Отправка команд


    Для передачи записанных команд есть утилита irsend. Она же может показать список известных устройств, и список известных команд для каждого устройства. Обратите внимание на "пустые аргументы" в примере ниже, они там нужны.


    irsend — это клиент для lircd, поэтому если что-то пошло не так, заглядывайте в логи (см. выше).


    # список устройств
    irsend LIST "" ""
    
    # список команд для устройства LG_TV
    irsend LIST LG_TV ""
    
    # отправить команду ON
    irsend SEND_ONCE LG_TV ON

    Теоретически, есть еще одна возможность — отправлять команды в lircd через его сокет. Не разбирался.


    Вызов из Python


    Почти все библиотеки являются всего лишь обвесом над irsend. Единственная найденная мной библиотека, которая компилирует клиента для API через сокет, не работает на Raspberry (нужна другая версия lircd). Поэтому смысла в них мало, команду вызвать я могу сам:


    import subprocess
    
    subprocess.call(["irsend", "send_once", "BEDROOM_AC", "OFF"])

    Hardware


    IR hat

    Я использую готовую плату, их много на Amazon и AliExpress. Гуглить можно как "Raspberry infrared sheild". Она использует GPIO 17 на выход, и GPIO 18 на вход, что видно из конфигов выше.


    На плате есть место для второго (дополнительного) светодиода D2, который по умолчанию не установлен. При использовании двух светодиодов, они подключаются последовательно. Поэтому при отсутствии светодиода D2 нужно замкнуть перемычку SJ1. С удивлением обнаружил, что на всех моих платах перемычка исходно была разомкнута. Пришлось доработать паяльником.


    Фотография крупнее для желающих поразглядывать

    IRDA Hat


    Итоги


    Работает: сигнал передается, устройства его видят и правильно на него реагируют.


    Многое зависит от положения диода-излучателя, он должен быть точно направлен на приемник. Один неподвижный передатчик не может управлять всеми устройствами в комнате. Клонировать решение на базе Raspberry Pi для каждого гаджета дорого, нужно или доработать излучатель для "покрытия большей площади", или найти более дешевую платформу.


    LIRC исходно создавался для преобразования IR сигналов в стандарнтные линуксовые события устройств ввода. Поэтому для него ествественно, что одна кнопка — один код. Для некоторых устройств (болшинства Air conditioner) это не так: при нажатии на любую кнопку пульт передает пакет данных, содержащий полное состояние устройства (включено, режим работы, температура, режимы работы вентилятора, время, таймер и т.д.). Возможности собирать многокомпонентный пакет на основе нескольких параметров в LIRC нет, поэтому как быстрый инструмент "из коробки" он помогает, но дальше придется искать что-то еще. Хотя для большинства случаев записанных данных с привычными настройками вентилятора и без экзотических режимов вполне достаточно.

    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 13

      0
      Понимаю что у Вас речь идет о самостоятельном изучении работы с IR, спасибо за статью! Просто дополню, похожую задачу я лично решал при помощи Aqara Air Conditioning Companion, это такая розетка от Xiaomi с IR и Wi-Fi, может бысть использована как через приложения Xiaomi так и интегрироваться с Android или Apple HomeKit (через homebridge на Raspberry PI), а также может управляться вручную через протокол MIIO. При этом сам Raspberry может находиться где-то в кладовке, а рядом с кондером будет лишь данная розетка-переходник и связь по Wi-Fi.

      Вот в этом репозитории можно почитать подробнее github.com/LASER-Yi/homebridge-mi-acpartner, там же в issues#64 есть дополнение как завести с любым кондером.

      PS: Сорри если слегка не в тему)
        0
          +1
          Статьи про ИК управление кондиционером:
          habr.com/ru/company/iridiummobile/blog/389049
          habr.com/ru/post/419963
          habr.com/ru/post/189142
          habr.com/ru/post/419797
            0
            Спасибо.
            0
            Имхо немного «из пушки по воробьям». Подобные задачи с легкостью решал на ESP8266 + светодиодик или фотодиодик. В какой то момент даже запилил управление через облако прикрутив обычный websocket клиент к 8266
              0
              А исходничками и схемкой не поделитесь? как раз есть свободная есп8266 и зоопарк техники с кучей пультов. Спасибо.
              0
              Откровенное из пушки по воробьям, совершенно согласен, я об этом в конце пишу. Когда с общей архитектурой своего «дома» определюсь, перепилю все на ESP32. Но как прототип свою роль выполняет прекрасно: там обычный линукс внутри, и можно связь с облаком сделать любым привычным способом.
              0
              А как правильно получить lircd.conf для работы с несколькими устройствами? Я например, ручками копирую и вставляю секцию begin-end в общий lircd.conf из каждого, созданного для одного пульта.
                0
                именно так и указано в мануалах lirc
                +1

                Хахахаха как раз вчера в Инстаграме постил: https://www.instagram.com/s/aGlnaGxpZ2h0OjE3ODcyODQyOTE5NDIwNTQz?igshid=1qsnk768yh2vq

                  0

                  От себя добавлю, если хотите проверить правильно ли замапились сигналы, используйте irw


                  При нажатии будет печатать какая мапа сдетектилась.

                    0
                    Кстати на последнем обновлении ядра они все поломали :(

                    www.raspberrypi.org/forums/viewtopic.php?f=28&t=235256

                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                    Самое читаемое