ИК дистанционное управление компом через DigiSpark
- Войдите на сайт для отправки комментариев
Задумал сделать дисташку для компа на дижиспарке, но выяснилось что стандартная библа IR-Remote занимает в 3 раза больше места, чем есть в дижиспарке. Альтернативная библа Ir-Remote для Tiny оказалась неюзабельной из-за вечно ожидающих while. Накатал свой обработчик IR-Remote. Места вообще не занимает, нет никаких while , но занимает внешнее прерывание и таймер0. Обработчик писал под имеющийся у меня пульт от ресивера Pioneer, но по идее алгоритм совместим со всеми пультами стандарта NEC, и может ещё какими. Потом проверял из любопытства пульты, что нашёл дома - пульт от телека JVC подошёл, а от самсунга -нет. Если снять ремарку с 23 строки, то можно печатать коды клавиш в любой текстовый редактор. Для эмуляции клавиатуры нужна библа от адафрута, о её возможностях рассказывал тут недавно. Только это оригинальная версия адафрута, её переделывать не нужно. Стандартный фотоприёмник типа TSOP подключается на порт PB2, изменять нельзя, привязано к прерыванию. Скетч:
// Скетч дистанционного управления для DigiSpark и V-USB библиотеки TrinketHidCombo for DigispArk // ****TSOP подключен к порту PB2****////// volatile uint8_t m=0, complete=0,tcnt=0, startflag=0; uint32_t irdata=0,keydata=0 ; #include <avr/delay.h> #include "TrinketHidCombo.h" void setup() { DDRB|=(1<<DDB1); //P1 (LED) OUT в скетче не использован PORTB|=1<<PB2; // подтяжка PB2 не помешает. GIMSK|=1<<INT0; //interrupt int0 enable MCUCR|= 1<<ISC00; //Any logical change on INT0 generates an interrupt request GTCCR|=1<<PSR0; TCCR0A=0; TCCR0B= (1<<CS02)|(1<<CS00); // divider /1024 TIMSK=1<<TOIE0;//interrupt Timer/Counter1 Overflow enable TrinketHidCombo.begin(); // start the USB device engine and enumerate } void loop() { if (complete) { // если был принят код // TrinketHidCombo.println(keydata,HEX); //снять ремарку ниже что бы печатать код клавиш // ниже пример управления винампом if (keydata==0x7B845AA5) TrinketHidCombo.pressKey(0x03, KEYCODE_W );TrinketHidCombo.pressKey(0, 0); //Cntrl-Shift-W Hot-Key Запуск winamp if (keydata==0x7D825AA5) TrinketHidCombo.pressKey(0, KEYCODE_X); TrinketHidCombo.pressKey(0, 0); // (X) Play if (keydata==0x7C835AA5) TrinketHidCombo.pressKey(0, KEYCODE_V); TrinketHidCombo.pressKey(0, 0); // (C) Stop if (keydata==0x7F805AA5) TrinketHidCombo.pressKey(0, KEYCODE_B); TrinketHidCombo.pressKey(0, 0); // (B) next if (keydata==0x7E815AA5) TrinketHidCombo.pressKey(0, KEYCODE_Z); TrinketHidCombo.pressKey(0, 0); // (Z) prev. ms_delay(200);// во избежание слишком частого повтора ввода клавиш complete=0; } _delay_ms(1);//сдерживать поллинг USB на пустых циклах TrinketHidCombo.poll(); // check if USB needs anything done } ISR (INT0_vect){ if (PINB& 1<<2) { // Если лог1 TCNT0=0; } else { tcnt=TCNT0; // если лог 0 if (startflag){ if (30 > tcnt && tcnt >2) {if (tcnt > 15&&m<32) {irdata|=((uint32_t)1<<m);} m++; } } else startflag=1; } } ISR (TIMER0_OVF_vect) { //если сработало это прерывание, значит конец посылки if (m) {complete=1; m=0; startflag=0; keydata=irdata; irdata=0; // если индекс не 0, то создать флаг конца } } void ms_delay(uint16_t x){ // функция задержки с USB поллом for (uint16_t m=0; m< (x/10); m++){ _delay_ms(10); TrinketHidCombo.poll(); } }
Круто! Такую функцию умять в такую маленькую платку
а TSOP подключается напрямую или ему нужны резисторы? Digispark же только 5В имеет.
А чтобы печатать коды клавиш, видимо, надо снять ремарку с 20 строки?
rucoda, TSOP напрямую. Ему вроде бы по даташиту рекомендовалось резюк, но и без него всё работает идеально. Я как написал этот пост и собрал дисташку, с тех пор пользуюсь -не единого глюка. Редко такое бывает, что сам доволён) Кстати спустя некоторое время поапалась библа для ИК, специализированная под диджиспарк. Но её не тестировал, т.к. уже не актуально было. А сейчас и адрес забыл где находил, (но на форуме где-то ссылку написал). Про ремарку -да.
Предложение: если добавить мигание светодиодом во время получения кода, будет видно, заметил ли приемник сигнал пульта или нет:
if
(keydata==0x7B845AA5) TrinketHidCombo.pressKey(0x03, KEYCODE_W );TrinketHidCombo.pressKey(0, 0);
а можно поподробнее про синтаксис? можно было сделать просто
if
(keydata==0x7B845AA5) TrinketHidCombo.pressKey(0x03, KEYCODE_W ); ?
Shino Kuyo, про синтаксис подробнее можно посмотреть в библиотекe TrinkedHidCombo. Код отпускания клавиши сократить нельзя. Попробуйте нажать кнопки на клавиатуре и не отпуская их продолжить работу. Получится?)
dimax, в библиотеке ничего такого не нашел, потому спросил.
нашел там такое:
TrinketHidCombo.pressKey(0x03, KEYCODE_W );TrinketHidCombo.pressKey(0, 0);
//Cntrl-Shift-W
Shino Kuyo,
(1) там 2 типа мультимедийных кнопок громкости, стандартные без букв _KB_. О тех что с буквами -не помню для чего они.
(2) Для понимания какая кнопка эмулируется -важен не только скан-код кнопки, но и функция которая его вызывает. В моём случае 0x03 - это код двух зажатых клавиш.
#define KEYCODE_MOD_LEFT_CONTROL 0x01
#define KEYCODE_MOD_LEFT_SHIFT 0x02
Но если бы я вызывал код 0x03 через функцию pressSystemCtrlKey() то сэмулировалась бы кнопка "WAKE"
TrinketHidCombo.println(keydata,HEX);
печатает в блокнот нули в столбик: 0 0 0 0 0 0 0 0
куда копать не скажете?
вот это непонятно: моём случае 0x03 - это код двух зажатых клавиш.
#define KEYCODE_MOD_LEFT_CONTROL 0x01 #define KEYCODE_MOD_LEFT_SHIFT 0x02
0х01 прибавляем 0х02 = 0х03? :)
вот тут нашел похожий проект http://www.instructables.com/id/DIY-USB-IR-receiver/?ALLSTEPS
скетч для получения кодов пульта выдает вот что, вместо нулей:
Shino Kuyo, если печатает 0 , ( но всё включено правильно! ) -значит неподдерживаемый стандарт пульта. Попробовать другой пульт.
хочется именно этот пульт из-за эогономичности :(
попробовал другой пульт
Shino Kuyo, (1) Для поддержки неподдерживаемых пультов нужно переписывать основной алгоритм программы, понятное дело что я этого делать не буду :) (2) эффект зажатой клавиши - это от вас зависит. Настройте программу так, что б при входящей "единичке" повторялся бы последний полный код.
понятно, что не будете))
боюсь программа (Kodi (XBMC)) будет эту "единичку" воспринимать как цифру и реагировать как на цифру. эх.
привинтил пульт от apple tv2
все вроде бы работает, но как "нажать" мультимедиа клавишу? play|pause конкретно
if (keydata == какой-то код) TrinketHidCombo.pressMultimediaKey(MMKEY_PLAYPAUSE);
ага, спасибо! я писал просто PressMMKey
Добрый день. Подскажите пожалуйста, а как снять коды HEX с пульта (keydata==0x7B845AA5)?
Maltsev.v.v, посмотрите пристально на 20 строчку скетча в топике.
Спасибо огрмное, теперь разобрался
День добрый, подскажите пожалуйста, как научить digispark с Вашем скетчем, запускаться после перезагрузки ОС.
Пример реализации http://obruboff.ru/no-detect-usb-tiny-device-after-reboot-problem/.
PS. Ваша программа самая универсальная для пультов, из всех что пробовал. только она спасобна работаеть с пультом от тв Samsung, lg
Maltsev.v.v, за полтора года пользования пультом со скетчем из топика у меня такой проблемы не было. Так что судя по данному факту можно предположить, что скетч и библиотека тут не причём.
Да, действительно. Проверил на новой метеринской плате, работает. Но к сожалению на ноутбуке 2012 года, такая проблемка есть.
Здравствуйте.
Появилась необходимость залить сей код через ардуино как програматор, но на стороке
происходит ошибка
в чём может быть причина, и главное как её решить.
причина необходимост прошивки через програматор http://arduino.ru/forum/obshchii/attiny85-i-zaderzhka-zapuska
Dmitriyxz, причина в том, что ардуиновский аддон дижиспарка и аддон тини используют разные таймеры для системных функций. Соответссно в одном случае компилится без проблем, во втором получается что вы пытаетесь сесть на тот-же вектор, который уже заняла библа ардуины. Вариантов решения два -долго курить конфиги ардуины что б корректно вырезать из них функции, занимающие таймеры. Либо полностью отключить все ардуиновские функции перейдя от setup(){} loop(){} к традиционным int main(){ while(1)} , второй способ разумеется повлечет за собой необходимость подключения нужных библиотек. В общем что так что эдак -задачка не для начинающих.
поменял:
Dmitriyxz, да, действительно, можно и такой вариант- просто перенести на другое прерывание :)
Почему для УНО я не могу скомпилировать, выбрасывает ошибку?
Для UNO точно такое работать не будет, так как там нет эмуляции клавиатуры ( есть ардуинки на чипе ATmega32U4 - те умеют... и то код менять надо будет)
roman12121993, потому, что написано для attiny85. Для UNO это нафиг не нужно. Используйте стандартную либу IRremote.
фото одной из модификаций DigiSpark...
приветствую снова)))
в общем работала эта плата хорошо. но надо бы ее прошить под другой пульт.
и вот тут облом! она просто определяется как клавиатура и все. никаких 5 секунд не ждет прошивки. сразу клавиатура.
она одноразовая?
В библиотеке нет кнопки "+"
Вот код для добавления #define KEYCODE_PLUS
0x57
https://yandex.ru/images/search?text=код+клавиши+на+клавиатуре+hex&img_url=https%3A%2F%2Fwww.mcselec.com%2Fimages%2Fstories%2Fmcse%2Fan%2F197%2FUSB_Keyboard_Hid_codes.jpg&pos=0&rpt=simage&stype=image&lr=65&parent-reqid=1545543935505181-1612624050320050870019243-sas1-8301&source=wiz
Подскажите, как реализовать непрерывное нажатие? Нужно для управления медиацентром, чтоб up/down/left/right и vol up/down можно было держать зажатыми.