Skocz do zawartości

Klawiatura Numeryczna USB z Arduino Host


Pomocna odpowiedź

Napisano

Posiadam aktualnie układ pracujący z klawiaturą membranową 4x4. Działa poprawnie 

Naszła mnie chęć wymiany jej na klawiaturę numeryczną USB. 
Czy da się to zrealizować w arduino po tych 4 przewodach? Ktoś ma to już za sobą bądź jest mi w stanie pomóc?

To zależy jakie Arduino masz. Na przykład Arduino Zero chodzi na SAMD21, które potrafi obsługiwać USB Host, i dla którego są przykłady obsługi klawiatury USB. Z UNO się nie da.

  • Lubię! 1

Świetnie, dziękuję. Myślę, że to pomoże. 
Czy wiesz może, czy piny cyfrowe 2-13 są w dalszym ciągu do użytku (na górze płytki są wyprowadzenia) czy są już one wykorzystywane przez ten układ?

Jeżeli nie potrzebujesz mocno urządzeń peryferyjnych atmegi, czyli real-time, liczników, SPI, może I2C, to polecam przejście na jakieś raspberry pi. Nawet wersję 1, która kosztuje teraz pewnie mniej niż schield USB do Arduino.

  • Lubię! 1
(edytowany)
#include <hidboot.h>
#include <usbhub.h>

#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;


}

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;

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

  if (Usb.Init() == -1)
    Serial.println("OSC did not start.");
  HidKeyboard.SetReportParser(0, &Prs);

    pinMode(2, OUTPUT);            
}

void loop()
{
  Usb.Task();


  
  digitalWrite(2, LOW);
  
  switch(???????????){
      case '?????????': digitalWrite(2, HIGH); break;
      
  }
}


Załadowałem taki kod, odczytuje poprzez host USB z klawiatury numerycznej. Przykładowo na zdjęciu odczytane kolejno klawisze ,,Num Lock", ,,7", ,,4", ,,1", ,,0". 

Chcę odwołać się do tego za pomocą switcha, aby klikając np. przycisk ,,Num Lock" na PIN 2 podawany był stan wysoki. W jaki sposób odnieść się do tego? Co zawrzeć zamiast znaków zapytania w ostatnich liniach kodu?

83264488_482928929069119_1863013812068679680_n.jpg

Edytowano przez qro9qs

@qro9qs możesz np. umieścić tego switcha w funkcji OnKeyUp i wtedy wykorzystujesz zmienną 'key', a w poszczególnych case'ach wpisujesz to co masz na podglądzie w monitorze portu szeregowego 🙂

W ten sposób nie działa, chyba, że coś zapisałem źle?

void KbdRptParser::OnKeyUp(uint8_t mod, uint8_t key)
{
  pinMode(2, OUTPUT); 
  Serial.print("UP ");
  PrintKey(mod, key);
  switch(key){
    case '53': digitalWrite(2, HIGH); break;
    
  }
}

 

Niestety żaden z proponowanych pomysłów nie pracuje. 
Zapytam raz jeszcze....gdzie powinienem umieścić w głownym kodzie switcha oraz w jaki sposób zadeklarować go? Switch po keyu i case z liczbami jak np. '53' lub '5F' nie działa. 

 

Switch:
 

pinMode(2, OUTPUT);
pinMode(3, OUTPUT);

switch(????){
  case 'klawisz oznaczony jako 53': digitalWrite(2, HIGH), digitalWrite(3, LOW);break; 
  case 'klawisz oznaczony jako 5F': digitalWrite(2, LOW), digitalWrite(3, HIGH);break;
}



Główny kod:

#include <hidboot.h>
#include <usbhub.h>
#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;
}

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

void KbdRptParser::OnKeyPressed(uint8_t key)
{
};

USB     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

  if (Usb.Init() == -1)
    Serial.println("OSC did not start.");
  HidKeyboard.SetReportParser(0, &Prs);
}

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

 

7 godzin temu, qro9qs napisał:

Zapytam raz jeszcze....gdzie powinienem umieścić w głownym kodzie switcha oraz w jaki sposób zadeklarować go? Switch po keyu i case z liczbami jak np. '53' lub '5F' nie działa. 

@qro9qs czy testowałeś zapis zgodny z sugestią @ethanak tzn. z przedrostkiem 0x (bo to są liczby zapisane w systemie szesnastkowym)?

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...