• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

ir-remote: библиотека для управления техникой по ИК каналу

DarkSide

New member
Исходный код доступен по адресу https://github.com/valkuc/esp8266-ir-remote
Библиотека позволяет отправлять ИК коды для протоколов NEC, Panasonic, Sony, Samsung. Тайминги были взяты из одноименной библиотеки для Arduino.

Идеи:
- было бы неплохо вместо TIMER ISR использовать SIGMA-DELTA для ШИМ, но запутался в конец с этими регистрами. Если есть желающие - welcome!
 

aIDAR

New member
Здравствуйте DarkSide, я недавно приобрел ЕСП-07, пытаюсь изучить но ничего толком не получается. Моя цель подключить IR передатчик и переключать каналы телевизора через WIFI.
На ардуине все сам сделал все работает только через блютуз. Не могли бы Вы мне подсказать что да как делать, как подключить передатчик к какому выходу на ЕСП, как залить программу и как отправлять запросы
 

DarkSide

New member
Здравствуйте. Я использовал ESP-01. Подключение ИК-диода и вспомогательных кнопок во вложении. Особенность данной схемы в том, что ИК-диод подтянут к VCC резистором. Это необходимо для старта ESP модуля, т.к. ИК-диод подключен к GPIO2.
 

Вложения

Creature

New member
@DarkSide прошу прощения за совсем уж ламерский вопрос... А нет ли где-нибудь более подробного описания вашего проекта? Я во всем этом новичок, начал собирать систему домашней автоматизации, есть BananaPi, которая посредством OpenHAB уже управляет устройствами на 433мГц, но категорически не хватает интерфейса ИК-управления и самым удобным было бы построить его на 8266. Но я, конечно же, вообще не имел с ней дело и не совсем понятно как именно собрать микропрограмму для нее. Был бы премного благодарен за HOWTO с примерами управляющих команд, отправляемых на 8266.
 

DarkSide

New member
@DarkSide прошу прощения за совсем уж ламерский вопрос... А нет ли где-нибудь более подробного описания вашего проекта? Я во всем этом новичок, начал собирать систему домашней автоматизации, есть BananaPi, которая посредством OpenHAB уже управляет устройствами на 433мГц, но категорически не хватает интерфейса ИК-управления и самым удобным было бы построить его на 8266. Но я, конечно же, вообще не имел с ней дело и не совсем понятно как именно собрать микропрограмму для нее. Был бы премного благодарен за HOWTO с примерами управляющих команд, отправляемых на 8266.
Пример отправки команды вы можете посмотреть в файле https://github.com/valkuc/esp8266-ir-remote/blob/master/user/user_main.c
Например, ir_remote_send_nec(0x5EA1F807, 32); - отправить 32 битны код 0x5EA1F807
Для ваших нужд одной отправки кодов будет мало, т.к. эти коды, я так понимаю, вы хотите отправлять по wifi с banana-pi. Для этого нужно написать TCP/UPD-сервер на стороне ESP, который будет принимать эти коды и отправлять в ИК-диод.

HOWTO по командам вам никто писать не будет - есть известные и стандартные протоколы от не менее известных брендов - это NEC, Panasonic, Samsung, Sony (ну может еще парочка найдется). Ищите даташит на протокол, изучаете команды. Либо более простой вариант: сканирование кода который отправляет пульт. Для этого нужен ИК приемник, руки и гугл (яндекс).

Сама библиотека ir-remote документирована - смотрите файл https://github.com/valkuc/esp8266-ir-remote/blob/master/include/ir_remote.h

Так же предоставляю вам кусок кода который создает слушающий UDP сервер и передает команды в ИК-либу:
Код:
void ICACHE_FLASH_ATTR udp_server_task(void *pvParameters)
{
    struct sockaddr_in server_addr, client_addr;
    int server_sock, client_sock;
    socklen_t sin_size = sizeof(client_addr);

    bzero(&server_addr, sizeof(struct sockaddr_in));
    server_addr.sin_family = AF_INET;
    server_addr.sin_len = sizeof(struct sockaddr_in);
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(93);

    if (-1 == (server_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)))
    {
        return;
    }

    if (-1 == bind(server_sock, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr)))
    {
        return;
    }

    printf("UDP server listening on port: %d\n", ntohs(server_addr.sin_port));

    int recbytes;
    uint32_t code;

    for (;;)
    {
        if ((recbytes = recvfrom(server_sock, &code, sizeof(code), 0, (struct sockaddr *)&client_addr, &sin_size)) != -1)
        {
            if (code > 0)
            {
                ir_remote_send_nec(code, 32);
                // 40ms after the pulse burst that signified the end of the message
                vTaskDelay(40 / portTICK_RATE_MS);
            }
        }
    }
}

void ICACHE_FLASH_ATTR user_init(void)
{
    uart_init();

    ir_remote_init(2, true);

    if (wifi_station_get_auto_connect() != 1)
        wifi_station_set_auto_connect(1);
    if (wifi_get_phy_mode() != PHY_MODE_11N)
        wifi_set_phy_mode(PHY_MODE_11N);
    if (wifi_get_sleep_type() != MODEM_SLEEP_T)
        wifi_set_sleep_type(MODEM_SLEEP_T);

    // connect to wifi here

    xTaskCreate(udp_server_task, "udp_server_task", 256, NULL, 1, NULL);
}
Код писался еще под версию rtos sdk < 1.0.0 (даже не помню точно версию).
 

tolyan23

New member
Так же предоставляю вам кусок кода который создает слушающий UDP сервер и передает команды в ИК-либу:
Код:
void ICACHE_FLASH_ATTR udp_server_task(void *pvParameters)
{
    struct sockaddr_in server_addr, client_addr;
    int server_sock, client_sock;
    socklen_t sin_size = sizeof(client_addr);

    bzero(&server_addr, sizeof(struct sockaddr_in));
    server_addr.sin_family = AF_INET;
    server_addr.sin_len = sizeof(struct sockaddr_in);
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(93);

    if (-1 == (server_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)))
    {
        return;
    }

    if (-1 == bind(server_sock, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr)))
    {
        return;
    }

    printf("UDP server listening on port: %d\n", ntohs(server_addr.sin_port));

    int recbytes;
    uint32_t code;

    for (;;)
    {
        if ((recbytes = recvfrom(server_sock, &code, sizeof(code), 0, (struct sockaddr *)&client_addr, &sin_size)) != -1)
        {
            if (code > 0)
            {
                ir_remote_send_nec(code, 32);
                // 40ms after the pulse burst that signified the end of the message
                vTaskDelay(40 / portTICK_RATE_MS);
            }
        }
    }
}

void ICACHE_FLASH_ATTR user_init(void)
{
    uart_init();

    ir_remote_init(2, true);

    if (wifi_station_get_auto_connect() != 1)
        wifi_station_set_auto_connect(1);
    if (wifi_get_phy_mode() != PHY_MODE_11N)
        wifi_set_phy_mode(PHY_MODE_11N);
    if (wifi_get_sleep_type() != MODEM_SLEEP_T)
        wifi_set_sleep_type(MODEM_SLEEP_T);

    // connect to wifi here

    xTaskCreate(udp_server_task, "udp_server_task", 256, NULL, 1, NULL);
}
for (;;) я так понимаю бесконечный цикл в котором все и слушается?
можно увидеть содержимое xTaskCreate(udp_server_task, "udp_server_task", 256, NULL, 1, NULL); или хотябы описание что это такое и что делает
recvfrom() какая то функция которая считывает новые данные полученные в запросе
что значит !=-1 не равно -1 а в каком случае функция возвращает -1?
 

CHERTS

Moderator
Команда форума
DarkSide, а нет ли у Вас желание переписать эту библиотеку на классический Espressif SDK?
 

chubuchnyi

New member
Подскажите пожалуйста, может кто сталкивался с таким. Настраиваю hw_timer на работу на определенной частоте, использую стандартные средства Espressif SDK:
Код:
hw_timer_init(FRC1_SOURCE,0);//timer use frc1 isr as isr source., 0 - not autoload
    hw_timer_set_func(pwm_tim1_intr_handler);
    hw_timer_arm(20);
при этом в прерывании сбрасываю таймер,
Код:
void pwm_tim1_intr_handler()
{
//мой код просто инвертируем состояние выхода
//.......
    hw_timer_arm(20);//сбрасываю таймер

}

При этом работает сервер, которые периодически отвечает на GET запросы.
Но мне необходимо в процессе работы устройства периодически менять ssid и пароль в SoftAP. При смене данных SoftAP меняется частота прерываний аппаратного таймера при этом она падает с 22кГц до 20кГц. Это происходит при первой смене настроек SoftAP, затем при смене настроек до перезагрузки модуля частота остается в пределах 20кГц.



Функция для смены настроек FiWi:
Код:
void ICACHE_FLASH_ATTR wifiInit(char *ssid, char *pass)
{

struct softap_config ap_config;

    wifi_set_opmode(SOFTAP_MODE);
    os_delay_us(10000);
    os_memset(&ap_config, 0, sizeof(ap_config));
    wifi_softap_get_config(&ap_config);

        int len = os_strlen(ssid);
            os_memcpy(ap_config.ssid, ssid, len);
            ap_config.ssid_len = len;


             len = os_strlen(pass);
            if(len > (sizeof(ap_config.password) - 1))
            {
                len = sizeof(ap_config.password) - 1;
             }
            os_memset(&ap_config.password, 0, sizeof(ap_config.password));
            os_memcpy(ap_config.password, pass, len);

        ap_config.channel = 1;
        ap_config.authmode = AUTH_WPA_WPA2_PSK;
        ap_config.ssid_hidden = 0;
        ap_config.max_connection = 4;
        //ap_config.beacon_interval = 100;
        wifi_set_phy_mode(1);
        wifi_softap_set_config(&ap_config);
        struct ip_info info;

        IP4_ADDR(&info.ip, 192, 168, 4, 1);
        IP4_ADDR(&info.gw, 192,168, 4, 1);
        IP4_ADDR(&info.netmask, 255, 255, 255, 0);
        wifi_set_ip_info(SOFTAP_IF, &info);
       
        wifi_softap_start();
        wifi_softap_dhcps_start();

}
Кто сталкивался с подобным, подскажите - мне очень важно, чтобы частота прерываний таймера была стабильной
 

pvvx

Активный участник сообщества
Кто сталкивался с подобным, подскажите - мне очень важно, чтобы частота прерываний таймера была стабильной
У WiFi есть режим sleep = light - он отключает все прерывания и тактирование аппаратуры проца на паузу между beacon. В принципе этот метод понижения потребления не работает, если модуль ещё и в режиме SOFTAP, но возможны зависимости. По умолчанию режим sleep у wifi = modem. Кроме того в режиме sleep = light таймеры обработки потока Lwip и прочие увеличены беспредельно в сотни раз (китай фича). Это не позволяет работать с потоком TCP более 1 пакета в десяток секунд. Возникают переполнения у Lwip, т.к. таймер счета закрытий и обработки стека (да вообще всего потока) увеличен с 25 ms до 6000.
 

RjLexx

New member
@DarkSide,а протокол RC6 не поддерживается случаем? Я ардуину с телеком Philips по этому протоколу дружил. Хотелось бы теперь ESP вместо ардуинки использовать
 

DarkSide

New member
@DarkSide,а протокол RC6 не поддерживается случаем? Я ардуину с телеком Philips по этому протоколу дружил. Хотелось бы теперь ESP вместо ардуинки использовать
RC6 я не добавлял, но поидее его добавить очень просто. Посмотрите Arduino-IRremote/ir_RC5_RC6.cpp at master · z3t0/Arduino-IRremote · GitHub - и добавьте по аналогии. У меня сейчас нет возможности этим заниматься.
 

DarkSide

New member
Обновил библиотеку. Изменения:
1) Теперь в репозитории на гитхабе 2 бранча - sdk и rtos_sdk; первый (он же основной) для обычной SDK, второй - для RTOS SDK
2) Код обоих версий обновлен и протестирован на SDK 1.5.2 и RTOS_SDK 1.3.0
3) Немного изменена логика генерации ШИМ
4) Добавлена поддержка протоколов RC5 и RC6 (не тестировалось ибо не на чем)
 

sega6549

New member
Приветствую, а нет ли случайно примерчика как передавать коды кнопок по протоколу mqtt, то есть, я сканирую кнопки с пульта, и передаю по mqtt на сервер, это я сделал в принципе, далее я пытался передать на esp данные коды кнопок но проблема в написании функции callback, нужно конвертировать из того что она получает в тот формат который понимает команда irsend, перепробовал кучу вариантов преобразования но в итоге либо пишет ошибку несовместимы типа типов либо на выходе ноль получаю, можете подсказать хотя бы как правильно преобразовывать
 
Сверху Снизу