terça-feira, 5 de outubro de 2010

Arduino USBMultiHID

Depois de um bom tempo sem brincar com meu arduino, como dá pra perceber pela data do post anterior, recentemente voltei e tô me divertindo muito com ele.

Para um projeto que estou montando (e em breve posto mais detalhes), precisava que meu arduino fosse reconhecido como um teclado e/ou mouse e/ou joystick pelo PC e que de preferência funcionassem com plug-and-play. Nisso, fui estudar um pouco sobre Human Interface Devices (HID) - teclados e mouses USB são reconhecidos como dispositivos do tipo HID pelos PCs.

Nessas pesquisas encontrei o projeto V-USB (Virtual USB port for AVR Microcontrollers), que nada mais é que uma implementação por software para dispositivos USB de baixa velocidade para microcontroladores Atmel AVR, e que por a caso é o tipo de controlador utilizado pelo arduino! Ai sim fomos surpreendidos! hehehehehe... Já existe um conjunto de bibliotecas para fazer o que eu precisava! Além de muita informação sobre o assunto e projetos reais de exemplo.

Procurando também outras referências achei algumas bem interessantes:
http://code.rancidbacon.com/ProjectLogArduinoUSB - Qualquer fonte de informação sobre Arduino + USB-HID faz referência a esse cara! Muito explicativo, conta todos os detalhes da sua implementação e de como resolver os problemas (inclusive de como fazer a biblioteca funcionar nas versões mais recentes da IDE Arduino). O CARA MANJA PRA CARAMBA! ME AJUDOU MUITO!
http://www.practicalarduino.com/projects/virtual-usb-keyboard - Exemplo do livro Practical Arduino (ótimo livro sobre arduino, com projetos bem legais), criando um teclado USB simplificado para PC.
http://orbduino.sourceforge.net/ - Projeto OrbDuino e OrbShield, com biblioteca e shield para arduino, e que foi desenvolvido para converter joysticks seriais antigos (principalmente da série SpaceOrbs) em controle USB-HID plug-and-play, totalmente customizável por programação, e que permite que os comandos do joystick sejam representados por mais de um HID simultaneamente.
http://www.obdev.at/products/vusb/projects.html - No site da Objective Development (responsável pela biblioteca V-USB) tem esta lista para vários projetos baseados na sua biblioteca, separados por categoria, e com link para os projetos que na sua maioria disponibilizam seus códigos-fonte, esquemas e contam detalhes da implementação.

A partir disso tudo montei a biblioteca USBMultiHID, que me possibilita ter uma interface simultânea a múltiplos dispositivos de entradas em um PC (múltiplos HIDs) a partir de um único dispositivo, O ARDUINO! Desta forma, qualquer comando de Teclado e/ou Mouse e/ou Joystick pode ser enviado ao PC a partir de todo o tipo de atuador que possa ser conectado ao arduino (sensores de movimento, potenciometros, botões, etc.).

Para fazer uma demonstração utilizei um WiiChuck para leitura de movimentos e de botões (hora o WiiChuck é usado como Mouse e hora como Joystick) e uma pequena montagem com botões representando um teclado. Abaixo o vídeo com a demonstração e algumas explicações:


Abaixo estão mais alguns detalhes sobre a montagem e os códigos utilizados:

Esquema para a Virtual-USB. Deve ser respeitada a utilização das portas digitais 2 e 4 do arduino devido à implementação da biblioteca AVRUSB.

Montagem, em protoboard, utilizada na demonstração com o circuito da Virtual-USB à esquerda e o "teclado" logo a baixo do arduino. Não está representado nesta montagem o WiiChuck que foi conectado utilizando as portas analógicas 2, 3, 4 e 5 do arduino.

Códigos:
Biblioteca WiiChuck - Biblioteca WiiChuck com alguns ajustes e que utiliza as portas analógicas 2 e 3 como terra e fonte, respectivamente, devido ao uso do conector. Deve ser disponibilizada na pasta "libraries" utilizada pela sua versão da IDE Arduino.
Biblioteca USBMultiHID - Biblioteca que define a comunicação USB com o PC e os dispositivos que serão representados. Nela estão os códigos customizados e as bibliotecas do AVRUSB. Deve ser disponibilizada na pasta "libraries" utilizada pela sua versão da IDE Arduino.
UsbMultiHID_Demo.pde - Código Arduino da Demonstração.

Rodei sem problemas utilizando as versões 18 e 19 da IDE Arduino

Abraços!

13 comentários:

  1. Dae, então, eu tenho quase o mesmo problema, mas o que eu quero é o seguinte, somente mandar uma tecla para o computador, como você faz com os Botões BTN1 e BTN2, porém não está dando certo...
    O código que eu tenho é o seguinte:

    // Biblioteca USB
    #include "UsbMultiHID.h"

    // Definições de botões e controles
    #define BT1 6

    #define BYPASS_TIMER_ISR 1
    #define TIME_DELAY 20
    int val=0;

    //----- Início - Definição e controle de alimentação do Buffer de Teclas
    int key_cursor = 1;
    byte keypresses[KEYPRESS_BUFFER_LENGTH];

    void cleanKeyBuffer() {
    //Limpa buffer de teclas
    memset( keypresses, 0, KEYPRESS_BUFFER_LENGTH );
    key_cursor = 1;
    }

    void pressKey(byte key) {
    pressKey(key, 0);
    }

    void pressKey(byte key, byte modifiers) {
    // Monta, bit a bit do byte 0, com os modificadores passados
    if (modifiers != 0) keypresses[0] |= modifiers;

    // Monta, byte a byte, apartir do byte 1 até o limite de 6, o buffer de teclas
    if ((key != 0) && (key_cursor < KEYPRESS_BUFFER_LENGTH)) {
    keypresses[key_cursor++] = key;
    }
    }
    //----- Fim - Definição e controle de alimentação do Buffer de Teclas


    //----- Início - Implementação alternativa para o Delay
    #if BYPASS_TIMER_ISR
    void delayMs(unsigned int ms) {
    for (int i = 0; i < ms; i++) {
    delayMicroseconds(1000);
    }
    }
    #endif
    //----- Fim - Implementação alternativa para o Delay


    // Inicialização das portas utilizados, das variáveis gobais e do controle de delay
    void setup() {
    pinMode(BT1, INPUT);
    Serial.begin(9600);
    digitalWrite(BT1, HIGH);

    // Definição para uso de alternativa para o Delay
    #if BYPASS_TIMER_ISR
    // disable timer 0 overflow interrupt (used for millis)
    TIMSK0&=!(1<<TOIE0); // ++
    #endif
    }


    void loop() {
    // preparação e delay padrão
    usbMultiHID.update();
    #if BYPASS_TIMER_ISR // check if timer isr fixed.
    delayMs(TIME_DELAY);
    #else
    delay(TIME_DELAY);
    #endif

    val= digitalRead(BT1);

    // Verificação de botões de teclado sempre ativa
    /***** CONTROLE DE TECLADO *****/
    //cleanKeyBuffer();
    if (val!=0) {
    pressKey(KEY_SPACE);
    usbMultiHID.send_keyboard_report(KEYPRESS_BUFFER_LENGTH, keypresses);
    }
    }

    Outra coisa, queria saber se funciona no Mac OS-X, ou somente no Windows?

    ResponderExcluir
  2. olá amigo, ao pc está reconhecendo que algo se conectou ao pc, mas ainda está desconhecido e acredito que por isso não está funcionando, tem algum driver para instalar ?

    ResponderExcluir
  3. Guilherm£ eu sugiro fazer o seguinte ajuste na área de CONTROLE DO TECLADO:

    /***** CONTROLE DE TECLADO *****/
    cleanKeyBuffer();
    if (val!=0) {
    pressKey(KEY_SPACE);
    }

    usbMultiHID.send_keyboard_report(KEYPRESS_BUFFER_LENGTH, keypresses);


    Isso porque independente de uma tecla ser apertada ou não, o dispositivo precisa enviar o BUFFER ao PC. Por isso deve ser feita, a cada passagem do loop, a limpeza e o envio da tecla, sendo que o comando pressKey vai acumulando quantas teclas forem possíveis no BUFFER para um único envio.

    Espero que isso ajude no seu teste.

    Abraço.

    ResponderExcluir
  4. guigontijo não precisei de nenhum driver para fazer esse código rodar, eu utilizo Windows XP. Qual SO está utilizando? Qual a versão da IDE do Arduino que está utilizando?

    Não testei ainda em outros sistemas operacionais ou versões do Windows. Mas na demonstração do Practical Arduino, comentada no post, ele executa em Linux.

    Abraço.

    ResponderExcluir
  5. bem, eu utilizo o xp e a IDE é a 0022,outra coisa importante, estou usando o arduino Mega...
    até então nunca tive contato com bibliotecas, só usava ele para brincar com sensores motores ext.. mas reparei que era importante o uso dos pinos 2 e 4, no arduino mega essas servem como pwm tb, teria algo haver com a prioridade ja que no mega o as IO 2 e 4 podem não estar ligadas ao mesmos tipos de pinos do arduino uno/2009 ?

    ResponderExcluir
  6. Bom, eu tenho o código assim, porém, quando eu conecto no Computador, ele aparece como dispositivo desconhecido...
    Windows, Arduino Mega1280...
    Queria saber se é necessário configurar algo de driver e tals...

    ResponderExcluir
  7. Cara que arquivos precisa estar na pasta do projeto?

    ResponderExcluir
  8. Daew fernando,parabens cara achei muito interessante seu projeto,eu queria conectar um joystick comunm desses usb para pc no arduino e ler suar teclas para controlar um robozinho mas estou meio perdido,será que poderia dar uma luz a um novato nesse assunto?

    Valew

    Murilo

    ResponderExcluir
  9. Olá Fernando,
    primeiramente parabéns pelo trabalho e em segundo, espero que ainda leia o seu blog hehehe

    Gostaria de saber qual versão do avr-gcc/WinAVR que está usando, porque aqui no meu linux não funciona nenhum projeto com v-usb.

    Tendo compilado com a versão 4.7.0 do avr-gcc
    Eis meu erro
    [14532.605272] usb 2-6: new low speed USB device number 116 using ohci_hcd
    [14533.011912] usb 2-6: device not accepting address 116, error -62
    [14533.011942] hub 2-0:1.0: unable to enumerate USB device on port 6

    Abração

    ResponderExcluir
  10. Fernando,

    preciso alterar alguma coisa no firmware para que o Windows reconheça como um dispositivo HID?
    No código não consegui encontrar algo que faça essa identificação.
    Preciso compilar e jogar algo para dentro do Arduino além do próprio código que você postou?

    abraço,

    ResponderExcluir
  11. Gostaria de saber se vc pode me ajudar em uma modificação no codigo.
    pois estou querendo usar o arduino como se fosse um joystick no computador para eu poder jogar usando o arduino.

    por exemplo:
    conectar 4 botões e quando eu apertar o botão 1 o computador interpretar como se eu estivesse apertando o botão X do joystick comum entendeu ?

    ResponderExcluir
    Respostas
    1. Oi Radson,

      conseguiu evoluir com esse projeto? Estou com o meu totalmente parado. Não dei conta de fazer o PC reconhecer o Arduino como um Joystick.

      O Fernando não respondeu aqui e nem no YouTube.

      abs,

      Excluir
  12. Ola tenho a mesma duvida do amigo abaixo:

    André Gustavo28 de janeiro de 2012 00:56
    Fernando,

    preciso alterar alguma coisa no firmware para que o Windows reconheça como um dispositivo HID?
    No código não consegui encontrar algo que faça essa identificação.
    Preciso compilar e jogar algo para dentro do Arduino além do próprio código que você postou?

    abraço,

    ResponderExcluir