Медиа панель / клавиатура для пк

Тема в разделе "Arduino & Shields", создана пользователем Resistor, 4 ноя 2021.

  1. Resistor

    Resistor Нерд

    Всем привет!
    Появилась необходимость собрать небольшую панель/клавиатуру для переключения треков в аудио плеере, увеличения/уменьшения уровня громкости в системе и все это для ПК Windows 10. По типу как в старых клавиатурах были кнопки для управления медиаконтентом.

    Есть ATmega32U4 подключается по microusb и определяется как USB HID клавиатура.
    Код пишу в "Arduino IDE".
    Как программно отправить скан-код? Сочетания клавиш не подходят. Нужно именно отправлять скан-коды, как это делает обычная клавиатура с медиа кнопками.
    P.S. Пробовал библиотеку "Keyboard", но она поддерживает только печатные символы. Писал в таком формате
    Код (C++):
    Keyboard.press(0xE0);
    Тоже ничего дельного не получилось. Подскажите, решение.
     
  2. akl

    akl Гуру

    в ардуиновском хидрепорте клавиатуры что в файле Arduino\libraries\Keyboard\src\Keyboard.cpp
    есть такая штука
    0x25, 0x73, // LOGICAL_MAXIMUM (115)
    может его увеличить до 0xA4 (164) например.
    ну и отправлять надо наверно типа
    Keyboard.press(0x7F); //Keyboard Mute
    https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf

    но не факт что это поможет, потому что эти кнопки по крайней мере в моей клавиатуре это некий отдельный девайс с вот таким дескриптором

    Код (C++):
    Usage Page (Consumer Devices) 05 0C
    Usage (Consumer Control) 09 01
    Collection (Application) A1 01
        Report ID (1) 85 01
        Logical Minimum (0) 15 00
        Logical Maximum (1) 25 01
        Report Size (1) 75 01
        Report Count (24) 95 18
        Usage (AC Home) 0A 23 02
        Usage (AL Email Reader) 0A 8A 01
        Usage Minimum (AC Back) 1A 24 02
        Usage Maximum (AC Refresh) 2A 27 02
        Usage (AC Search) 0A 21 02
        Usage (AC Bookmarks) 0A 2A 02
        Usage (Play/Pause) 09 CD
        Usage (Stop) 09 B7
        Usage (Scan Previous Track) 09 B6
        Usage (Scan Next Track) 09 B5
        Usage (Volume Increment) 09 E9
        Usage (Volume Decrement) 09 EA
        Usage (Mute) 09 E2
        Usage (AL Consumer Control Configuration) 0A 83 01
        Usage (AC New) 0A 01 02
        Usage (AC Open) 0A 02 02
        Usage (AC Save) 0A 07 02
        Usage (AC Undo) 0A 1A 02
        Usage (AC Redo/Repeat) 0A 79 02
        Usage Minimum (AC Copy) 1A 1B 02
        Usage Maximum (AC Paste) 2A 1D 02
        Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02
    End Collection C0
     
    короче там всё сложно в этом юсб я не шарю

    Keyboard.press(0x7F); работать точно не будет - там в этой функции ардуиновской не предназначено для этого. Надо самому вручную хидрепорт заполнять или переделывать функцию библиотеки
     
    Resistor нравится это.
  3. akl

    akl Гуру

    короче попробуй в этом файле Keyboard.cpp

    добавить вот такие функции
    Код (C++):
    size_t Keyboard_::putKey(uint8_t k)
    {
        uint8_t i;
        // Add k to the key report only if it's not already present
        // and if there is an empty slot.
        if (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&
            _keyReport.keys[2] != k && _keyReport.keys[3] != k &&
            _keyReport.keys[4] != k && _keyReport.keys[5] != k) {
         
            for (i=0; i<6; i++) {
                if (_keyReport.keys[i] == 0x00) {
                    _keyReport.keys[i] = k;
                    break;
                }
            }
            if (i == 6) {
                setWriteError();
                return 0;
            }  
        }
        sendReport(&_keyReport);
        return 1;
    }

    size_t Keyboard_::releaseKey(uint8_t k)
    {
        uint8_t i;
        // Test the key report to see if k is present.  Clear it if it exists.
        // Check all positions in case the key is present more than once (which it shouldn't be)
        for (i=0; i<6; i++) {
            if (0 != k && _keyReport.keys[i] == k) {
                _keyReport.keys[i] = 0x00;
            }
        }
        sendReport(&_keyReport);
        return 1;
    }
    а в файле Keyboard.h соответственно в раздел public:
    добавить строчки
    Код (C++):
    size_t putKey(uint8_t k);
    size_t releaseKey(uint8_t k);
    тогда по идее может сработать прямое отправление кодов клавишь типа
    Keyboard.putKey(0x7F);
    Keyboard.releaseKey(0x7F);
    0x7F это должно быть мьют судя по таблицам (страница 56), так же там рядом прибавление и убавление громкости.
    https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf
    насчет переключения треков и прочего хз
    и даже нет никакой гарантии что это 0x7F будет как-то работать в виндосе
     
    Последнее редактирование: 5 ноя 2021
    Resistor нравится это.
  4. Resistor

    Resistor Нерд

    Привет akl!
    Вы первый, кто на форумах ответил по делу.
    Все сделал по вашим примерам. Скомпилировал, загрузил. Только светодиод моргает при выполнении команд и на этом все.
    Задачу не выполняет, к сожалению. Но в любом случае, теперь все стало более-менее понятно куда копать. Благодарю за помощь!
     
  5. parovoZZ

    parovoZZ Гуру

    коды клавиш есть в первоисточнике - библиотека LUFA
    https://github.com/abcminiuser/lufa

    примеры из библиотеки рабочие, прекрасно документированы. проверял лично.
     
  6. Resistor

    Resistor Нерд

    Все оказалось намного проще.
    Устанавливаем библиотеку "HID-Project", причем через меню "добавить .ZIP библиотеку" нормально не работало, сыпало ошибки, ручное добавление тоже не помогло. Вот когда загрузил через менеджер библиотек тогда все заработало!

    Собственно сам код
    Код (C++):
    #include "HID-Project.h"

    #define BS_PLAY_PAUSE     0xCD
    #define BS_STOP           0xB7
    #define BS_SKIP_FORWARD   0xB5
    #define BS_SKIP_BACKWARD  0xB6
    #define BS_MUTE           0xE2
    #define BS_VOL_DOWN       0xEA
    #define BS_VOL_UP         0xE9

    void setup(){}

    void loop(){
      delay(1000);
      Consumer.write(BS_MUTE);
    }
    Еще раз благодарю akl за помощь!)
     
    Un_ka и Рокки1945 нравится это.
  7. Рокки1945

    Рокки1945 Гуру

    я тоже хочу - но не понял что код делает?
    любая дунька подойдет?
    кароче нажимаешь определенную кнопку и её прописываешь константу
     
  8. Un_ka

    Un_ka Гуру

    Нет. Из возможных Леонардо с ATmega32U4 или Микро, но у китайцев такой я не находил.
     
  9. Resistor

    Resistor Нерд

    На aliexpress в поиске введите: "TENSTAR ROBOT Pro Micro".
     
  10. Рокки1945

    Рокки1945 Гуру

    а на уно разве нету её - там 16 у2 -
     
  11. parovoZZ

    parovoZZ Гуру

    Китайцы на уно ставят всякую разную порнуху, но только не16и2. Такая только у олимекса и оригинала.
     
  12. Рокки1945

    Рокки1945 Гуру

    у оригинала стоит - но мне надо понимать как у него хид клава в диспетчере читается ?
     
  13. Рокки1945

    Рокки1945 Гуру

    то бишь она читается и как ардуино в компортах и как хид? Я правильно понял?
    Что там за бутлаудер?
     
  14. parovoZZ

    parovoZZ Гуру

    LUFA может повесить два USB девайса на порт. Но только на u4. Дурина - нет.
     
    Рокки1945 нравится это.
  15. Рокки1945

    Рокки1945 Гуру

    кароче надо купить такую штуку - давно искал
     
  16. Рокки1945

    Рокки1945 Гуру

  17. akl

    akl Гуру

    я сделяль проще

    короче ложишь в папку Arduino\libraries\Keyboard\src\ (там где лежит Keyboard.h и Keyboard.cpp)
    два файла что прикреплены (KeyboardС.h и KeyboardС.cpp)
    и можешь тупо вот так создавать составное устройство из клавы и какого-то мутного контроллера (сделан по образу и подобию того что лезет из моей клавиатуры)
    Код (C++):

    #include "Keyboard.h"
    #include "KeyboardC.h"

    void setup() {
      digitalWrite(11,1);
      Keyboard.begin();
      KeyboardC.begin();
      delay(2000);
    }

    void loop() {
    if(!digitalRead(11)){
       KeyboardC.putKey(SOUND_CONTROLS,VOL_MUTE);
       delay(200);
       KeyboardC.release();
       delay(500);
       Keyboard.press('1');
       delay(200);
       Keyboard.release('1');
    }
    }
    эти медиакнопки используются путем функции KeyboardC.putKey(b,k); и KeyboardC.release();
    b - это байт в который надо ложить кнопку, а k это собственно кнопка
    все что есть на моей клавиатуре выглядит так
    Код (C++):

    #define AC_CONTROLS 0
    #define AC_HOME 0x01
    #define AL_EMAIL 0x02
    #define AC_BACK 0x04
    #define AC_FORWARD 0x08
    #define AC_SEARCH 0x40
    #define AC_BOOKMARKS 0x80

    #define AC_CONTROLS_2 2
    #define AC_CUT 0x40
    #define AC_COPY 0x20
    #define AC_PASTE 0x80

    #define SOUND_CONTROLS 1
    #define VOL_INCREM 0x10
    #define VOL_DECREM 0x20
    #define VOL_MUTE 0x40
    #define TRACK_PAUSE 0x01
    #define TRACK_STOP 0x02
    #define TRACK_PREV 0x04
    #define TRACK_NEXT 0x80
     
    чтобы прибавить громкость надо например сделать так
    KeyboardC.putKey(SOUND_CONTROLS,VOL_INCREM);
    KeyboardC.release();

    а чтобы нажать "вырезать"
    KeyboardC.putKey(AC_CONTROLS_2,AC_CUT);
    KeyboardC.release();

    особо не тестировал, но в целом работает.
    кстати кнопки AC_COPY AC_CUT AC_PASTE у меня тупо не работают даже с клавиатуры (настоящей). но громкость крутится

    и еще - после того как файлы положены в папку надо ардуино-иде перезапустить
     

    Вложения:

    • KeyboardC.h
      Размер файла:
      901 байт
      Просмотров:
      140
    • KeyboardC.cpp
      Размер файла:
      1,4 КБ
      Просмотров:
      164
    Последнее редактирование: 6 ноя 2021
    Николай М и Resistor нравится это.
  18. akl

    akl Гуру

    не углублялся, но подозреваю что имеется в виду та уна, у которой юсб-уарт на атмеге 16u2 или типа того - там вот эта 16u2 перепрошивается в клавиатуру со всеми вытекающими неудобствами. короче плохой метод - лучше леонардо использовать
     
  19. Un_ka

    Un_ka Гуру

    В War thunder столько параметров, которыми можно управлять осями джойстиков, что я решил использовать teensy 3.6.
    Только в стандартном ядре ком порт джойстики и т.д. включаются в настройках Arduino IDE. Вообщем начудили американцы.
     
  20. Спасибо большое! Это решение у меня работает.