Manual

do

Maker

.

com

USB Host Shield para Arduino

USB Host Shield para Arduino

Imagine que legal usar o Arduino como um dispositivo de entrada, digitando os comandos diretamente nele, simplesmente conectando um teclado USB. Legal? E imagine conectá-lo a um smartphone para controlar, por exemplo, um LED RGB, relés e tudo o mais. Mas não é só isso que ele faz, você pode usar o controle do XBOX, PS4, dispositivos bluetooth, leitor de código de barras, ou utilizá-lo para ler dados de um pendrive com sistema de arquivos FAT. Um artigo só para todos esses recursos não é viável, mas prometo artigos curtos mostrando um ou dois recursos, então algumas aplicações. Hoje vamos começar com a comunicação entre o keyboard e o Arduino utilizando esse USB Host Shield.

Onde comprar seu USB Host Shield

Para esse usb host shield, recomendo a aquisição na Eletrogate, clicando aqui. É muito válido ter um usb host shield, considerando a quantidade de diversão e recursos!

A biblioteca tem muitos exemplos!

Eu já escrevi um artigo sobre controle de LED RGB através do Android, utilizando um ethernet shield, como você pode ver clicando nesse link. Também fiz um exemplo de controle de LED RGB através de uma ligação para o PBX Asterisk, configurado em meu notebook e ligando a partir de um softphone, do Android para o PBX e controlando o LED RGB a partir de uma URA (Unidade de Resposta Audível). Confira aqui. Estava programando um app em Qt, mas não tem uma interface do Android que dá acesso aos dispositivos do sistema por um meio que não seja Java, e eu estava programando em Qt. Por isso decidi partir pelo teclado, mas vamos ver essa comunicação também por outro meio.

 

Sketch para o Arduino

No repositório oficial do Arduino você encontrará a USB host shield library 2.0 (em algum momento a versão mudará, mas baseie-se pelo nome da biblioteca), contendo montanhas de exemplo de utilização. Vamos utilizar o sketch de exemplo USB Host Shield Library 2.0 > adk > ArduinoBlinkLEDquando com Android. Esse sketch aguarda 1 Byte para ligar ou desligar o LED. Desse modo é bastante simples escrever uma aplicação para o Android, pois só precisamos de 1 botão para acender o LED.

Para o teclado, vamos utilizar o exemplo que sem encontra em File > Examples > USB Host Shield Library 2.0 > HID > USBHIDBootKbd. A biblioteca é compatível com diversos Arduino, como UNO e Leonardo. Hoje estou utilizando o Arduino Leonardo porque meus Arduino UNO estão em uso em outro projeto.

Eu optei por subir o sketch antes de colocar o shield. O sketch não é lá muito amigável, tem uma classe declarada nele próprio, mas não tem muita complexidade nesse exemplo.

Após subir o sketch e conectar o shield, já abra o monitor serial e então coloque o teclado no Arduino. As teclas já estarão mapeadas e a partir daí você pode montar um array das chaves lidas para tomar uma ação, ou então criar comandos que respondam a modificadores, como o simples pressionamento da tecla Ctrl:

#include <hidboot.h>
#include <usbhub.h>

// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <SPI.h>

class KbdRptParser : public KeyboardReportParser
{
    void PrintKey(uint8_t mod, uint8_t key);

  protected:
    void OnControlKeysChanged(uint8_t before, uint8_t after);

    void OnKeyDown	(uint8_t mod, uint8_t key);
    void OnKeyUp	(uint8_t mod, uint8_t key);
    void OnKeyPressed(uint8_t key);
};

void KbdRptParser::PrintKey(uint8_t m, uint8_t key)
{
  MODIFIERKEYS mod;
  *((uint8_t*)&mod) = m;
  Serial.print((mod.bmLeftCtrl   == 1) ? "C" : " ");
  Serial.print((mod.bmLeftShift  == 1) ? "S" : " ");
  Serial.print((mod.bmLeftAlt    == 1) ? "A" : " ");
  Serial.print((mod.bmLeftGUI    == 1) ? "G" : " ");

  Serial.print(" >");
  PrintHex<uint8_t>(key, 0x80);
  Serial.print("< ");

  Serial.print((mod.bmRightCtrl   == 1) ? "C" : " ");
  Serial.print((mod.bmRightShift  == 1) ? "S" : " ");
  Serial.print((mod.bmRightAlt    == 1) ? "A" : " ");
  Serial.println((mod.bmRightGUI    == 1) ? "G" : " ");
};

void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key)
{
  Serial.print("DN ");
  PrintKey(mod, key);
  uint8_t c = OemToAscii(mod, key);

  if (c)
    OnKeyPressed(c);
}

void KbdRptParser::OnControlKeysChanged(uint8_t before, uint8_t after) {

  MODIFIERKEYS beforeMod;
  *((uint8_t*)&beforeMod) = before;

  MODIFIERKEYS afterMod;
  *((uint8_t*)&afterMod) = after;

  if (beforeMod.bmLeftCtrl != afterMod.bmLeftCtrl) {
    Serial.println("LeftCtrl changed");
  }
  if (beforeMod.bmLeftShift != afterMod.bmLeftShift) {
    Serial.println("LeftShift changed");
  }
  if (beforeMod.bmLeftAlt != afterMod.bmLeftAlt) {
    Serial.println("LeftAlt changed");
  }
  if (beforeMod.bmLeftGUI != afterMod.bmLeftGUI) {
    Serial.println("LeftGUI changed");
  }

  if (beforeMod.bmRightCtrl != afterMod.bmRightCtrl) {
    Serial.println("RightCtrl changed");
  }
  if (beforeMod.bmRightShift != afterMod.bmRightShift) {
    Serial.println("RightShift changed");
  }
  if (beforeMod.bmRightAlt != afterMod.bmRightAlt) {
    Serial.println("RightAlt changed");
  }
  if (beforeMod.bmRightGUI != afterMod.bmRightGUI) {
    Serial.println("RightGUI changed");
  }

}

void KbdRptParser::OnKeyUp(uint8_t mod, uint8_t key)
{
  Serial.print("UP ");
  PrintKey(mod, key);
}

void KbdRptParser::OnKeyPressed(uint8_t key)
{
  Serial.print("ASCII: ");
  Serial.println((char)key);
};

USB     Usb;
//USBHub     Hub(&Usb);
HIDBoot<USB_HID_PROTOCOL_KEYBOARD>    HidKeyboard(&Usb);

KbdRptParser Prs;

void setup()
{
  Serial.begin( 115200 );
#if !defined(__MIPSEL__)
  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif
  Serial.println("Start");

  if (Usb.Init() == -1)
    Serial.println("OSC did not start.");

  delay( 200 );

  HidKeyboard.SetReportParser(0, &Prs);
}

void loop()
{
  Usb.Task();
}

Esse sketch vai imprimir o valor ASCII e mostrar qual o valor da tecla pressionada. Com pouca modificação (algumas linhas), já dá pra fazer uma brincadeira.

Agora, pensou que legal fazer um sniffer de teclado? Mas claro que para isso precisariamos ter o caminho de volta ao computador, uma vez que o teclado estará no shield e o Arduino, se comunicando via serial. Sabe por que usei o Arduino Leonardo? Bem, porque ele pode ser um teclado - e pretendo escrever a respeito em um próximo artigo, o quanto antes, inclusive porque para fazer um sniffer, pode ser o ideal, fazendo a leitura do teclado via shield e enviando via USB-serial. Pra ter uma ideia, olhe a implementação da função de teclado no Arduino Leonardo:

#include "Keyboard.h"

void setup() {
  Serial.begin(9600);
  Keyboard.begin();
}

void loop() {
  if (Serial.available() > 0) {
    char inChar = Serial.read();
    Keyboard.write(inChar + 1);
  }
}

Isso é tão simples que podemos estar gravando um conjunto de dados da EEPROM, ou dependendo do volume de dados pretendido, em um micro SD. Mas já pensou que legal dar uma sacaneada em alguém, fazendo substituição de letras enquanto a pessoa digita, pensando que é um erro de digitação? Vamos fazer essa pegadinha no próximo artigo então, acompanhe!

Se ainda não tem um Arduino Leonardo, vale muito a pena. Ele possui 2 seriais e alguns recursos extras que vou discorrer a respeito conforme escrever os artigos, então, recomendo que pegue o seu nesse link da EletroGate.

Inscreva-se no nosso canal Manual do Maker no YouTube.

Também estamos no Instagram.

Nome do Autor

Djames Suhanko

Autor do blog "Do bit Ao Byte / Manual do Maker".

Viciado em embarcados desde 2006.
LinuxUser 158.760, desde 1997.