вторник, 26 апреля 2022 г.

IR remote + STM32 to usb, firmware and board

Simply combine decoding algorithm from post about decoding and USB keyboard driver from that post. Only one deal is left is decoding table. It will match codes of ir with keyboard button codes. Maybe if I get unuseful keyboard I will make IR wireless keyboard from it.

As for building and board assembling all like in previous devices. Building with my libraries and makefile using gcc. Two layer board using film photoresist, laser printer photomask and micro 1mm rivets. Here are some photos:

Decode table

Main work of that device is in matching IR codes to a keyboard codes. Then I can configure a applications on my PC to be runnable by keyboard hotkeys, written in this codetable. Here is fragment of codetable init function from file ir_remote.c:

void codeTableInit() { codeTable[0].irCode = 0xd02f; codeTable[0].keyboardCode = 0x52; codeTable[1].irCode = 0xd629; codeTable[1].keyboardCode = 0x51; codeTable[2].irCode = 0x827d; ... }

Firmware

As sayed in header the main idea of whole firmware in this function. It reads port with IR receiver connected to it. Applies just got sample to the decoder function. Then if decoder function is already recognized the code from any amount of concequtive samples, this function will find keyboard codes appropriate to obtained IR code. After it will send a USB keyboard report with necessary codes.

uint16_t code = detect((uint8_t)(IR_PORT & IR_PIN), 0xffff); uint8_t report[8] = {0}; if(code != 0xffff) { report[0] = codeTable[findCode(code)].tabCode; report[2] = codeTable[findCode(code)].keyboardCode; sendKbdReport(report); delay = 100; }

This function is quiet compact, I like when I succeeed in writing compact and transparent code. Which do not need in any comments or any other documentation. Device usage example see in the next post.

18 комментариев :

  1. Чистил маслят через та порт на стм 32 оторвал камень приклеил суперклеем не работает

    ОтветитьУдалить
    Ответы
    1. в ответах мэил ру советуют мешать суперклей с тертым графитом от карандаша, тогда он становится токопроводящим, а еще с али можно токопроводящий маркер заказать

      Удалить
  2. не хватает комментариев на гитхабе разобраться с remote :-(
    if(code == ONCODE) {
    ON_PORT |= (uint32_t)ON_PIN;
    delay_ms(80);
    ON_PORT &= ~(uint32_t)ON_PIN;
    }
    - видимо, какой-то светодиод мигает?
    как часто срабатывает этот TIM3_Handler?
    насколько валидно из него дважды вызывать (под мои нужды) sendKbdReport(value), sendKbdReport(nulled)?

    ОтветитьУдалить
    Ответы
    1. позже опишу эту фичу, это нажиматор на кнопку вкл системника, что бы с пульта компьютер включать как телек.

      Удалить
    2. таймер тактирует опрос ик приемника, частота, 5 кГц, если правильно помню

      Удалить
  3. плюс полностью непонятны коды (что за ИК пульт и какие клавиатурные коды выдает)

    ОтветитьУдалить
  4. в предыдущем посте была инормация про распознание кодировки пульта. То есть алгоритм работы следующий, берем какой то пульт, распознаем его кодировку по графику. Потом кодам пульта назначаем коды кнопок по вкусу. У меня пульт от видика samsung, назначил стрелочки, циферки, enter esc bckspace, пробел.

    ОтветитьУдалить
  5. программа, строящая график есть так же на гитхабе, скачать ее можно в позапрошлом посте.

    ОтветитьУдалить
  6. спасибо! более-менее становится понятно.
    на всякий случай еще спрошу: а не существует ли в природе exti_regs? :-)

    ОтветитьУдалить
    Ответы
    1. Ой, совсем про них забыл. в libopencm3 использовал кнопки по прерыванию, тут про них забыл, допишу завтра.

      Удалить
    2. спасибо!

      вообще планирую подключить AB-энкодер на них для управления ЧПУ, в exti прерываниях менять steps (+/-), а в таймере в каждом вызове отправлять соответствующий код и приближать steps обратно к нулю. по моему разумению для этого нужно обнулять отправляемый код - вот и недопонимание: sendKbdReport должен вызываться из обработчика таймера только один раз? пауз же там по идее быть не должно (хотя там есть delay_ms(80))? а с другой стороны еще неизвестно, как поведет себя хост, когда в него такое количество событий посыпется.

      (крутилка дает 100 пульсов на оборот, за секунду они вполне достижимы, быстрее - уже вряд ли)

      сейчас соорудил нечто на пины А1 и А2, оно даже прошилось и энумерация выполнилась, но коды пока не шлются (скорее всего с настройками exti накосячил - завтра продолжу эксперименты)

      Удалить
    3. Похоже вы меня совсем не поняли. С частотой 5 кГц стабильно вызывается прерывание. в этом прерывании опрашивается порт IR_PIN функцией detect. Если рекуррентная функция detect распознает код в последовательности выборок, то она отправляет его в USB функцией sendKbdReport, а если этот код - код красной кнопки power, то срабатывает тот if с портом ON_PIN и задержкой, до которого вы доебались.

      Удалить
    4. Обратите внимание на то, что это приёмник пульта, а не ЧПУ с энкодером.

      Удалить
    5. а, я той части ответа не увидел.
      про пульт - это всё понятно, я просто хочу взять за основу вашу реализацию usb, выкинуть ненужный мне IR, добавить нужный мне обработчик энкодера.

      Удалить
    6. тогда мимо, вот есть usb com порт, через него удобнее обмениваться информацией с компьютером. https://github.com/dltech/usb_device3/tree/main/usbcom

      Удалить
  7. тут проще вот от этого примера отталкиваться. https://gitlab.com/dltech/lowlevellib/-/blob/main/ws281x/main.c
    Данные, приходящие по usb хранятся в буфере extern uint8_t vcpRxBuffer[64]; Размер прилетевших по шине данный запрашивается через getUsbComRxCount();.
    Отправлять можно через функцию void vcpTx(uint8_t *data, int size);.

    ОтветитьУдалить
    Ответы
    1. С com портом удобно обращаться через библиотеку QT.

      Удалить