Probleme mit dem Arduino PS / 2-Tastaturemulator


10

Ja, ich habe die Arduino.cc-Foren und hier durchsucht. Ja, ich habe die Artikel zur ps2dev-Bibliothek gefunden. Ja, ich habe den endgültigen Artikel zur PS / 2-Benutzeroberfläche auf dieser Website gelesen (okay, einige habe ich überflogen) . Ja, das funktioniert irgendwie. Ich brauche einige Ideen, um den Sprung zum vollen Funktionieren zu schaffen. :) :)

Nein, ich kann nicht einfach eine USB HID-Tastatur emulieren und dabei belassen - es muss sich um eine PS / 2-Tastaturemulation handeln. Ja, ich sende die richtigen Make- und Break-Signale - es werden sogar sehr komplizierte Tastenkombinationen verarbeitet. So wie es jetzt aussieht, habe ich Code für mein Arduino geschrieben, wie unten angegeben (technisch ein Freeduino 1.22), und ich habe Tastenanschläge über den seriellen Monitor oder das PuTTY-Terminal sowie mit einem handlichen Python-Wrapper / -Treiber gesendet, der tatsächlich sendet PS / 2-Scancode-Informationen - und erleichtern mir im Allgemeinen das Leben - entlasten auch den Arduino.

Im Moment läuft auf dem Arduino eine Skizze, die eine PS / 2-Tastatur emuliert. Natürlich muss ich meinen "Ziel" -Maschinen booten (Computer, in den der PS / 2-Stecker eingeht), und ich sehe, dass der "Handshake" stattfindet. Booten Sie zu WinDoze, öffnen Sie den Editor und fahren Sie mit meinem Python-Treiber (erfolgreich) Tastenanschläge auf den Bildschirm. (Der Treiber ersetzt einfach das Serial Monitor / PuTTY-Terminal und liest / schreibt mit einem Modul namens PySerial auf die serielle Schnittstelle.) Dies erfolgt alles auf einem AMD im ASUS-Motherboard "target".

Jetzt ist das Ziel, es auf meinem Intel in Intel Motherboard-basierten "Ziel" zum Laufen zu bringen, ich stecke es ein, starte und ohne Würfel. Also habe ich die Skizze ein wenig modifiziert, um mir ein Bild davon zu machen, was tatsächlich mit meinem kleinen Ardy-Freund los ist. Die Version nach den Mods wird unten angezeigt. Wie ich es verstehe (Code „ausgeliehen“ von einem anderen Arduino.cc Forumsbeitrag wurde, hier ) Es wird versuchen, eine Verbindung mit dem „Ziel“ über PS / 2 zunächst zu etablieren, in einer 0,5 Sekunden Zeit , das Onboard - LED blinkt , bis die Verbindung wird hergestellt. Das Intel-Ziel überschreitet nicht die Blinkzeit von 0,5 Sekunden und die serielle Verbindung wird niemals mit dem "Host" hergestellt.

Meine Frage lautet: Gibt es einen großen Unterschied in der Art und Weise, wie ps / 2-Tastaturen die Kommunikation mit ihrem Zielcomputer herstellen? Ist es wirklich ein Designunterschied oder sollte ich nach etwas Grundlegenderem suchen, um das es hier geht? Ich habe etwas über die Notwendigkeit von Pull-up-Widerständen an den Daten- / Takteingängen gehört, aber das sollte im Code behandelt werden, insbesondere weil es auf einem anderen Ziel funktioniert, nur nicht auf dem, an dem ich arbeiten muss.

Irgendwelche Ideen? Ich würde es lieben, wenn dies so schnell wie möglich funktioniert - ich werde weiterhin debuggen, alle Hinweise oder Vorschläge wären sehr dankbar. Sie werden alle umfassend berücksichtigt, da ich neue Augen für dieses Thema brauche. Vielleicht ist eine bessere Implementierung in der ps2dev-Bibliothek erforderlich?

#include "ps2dev.h" // to emulate a PS/2 device

// Orange = 2
// Blue = 3
// Red = 5V (3 in)
// Black = GND (4 in)
// EXT Power, USB for COM only

PS2dev keyboard(3,2); // PS2dev object (2:data, 3:clock)
int enabled = 0; // pseudo variable for state of "keyboard"
boolean serialConnected = false;
int incomingByte = 0;

void ack() {
  //acknowledge commands
  while(keyboard.write(0xFA));
}

int kbdCmd(int command) {
  unsigned char val;
  switch (command) {
  case 0xFF: //reset
    ack();
    //the while loop lets us wait for the host to be ready
    while(keyboard.write(0xAA)!=0);
    break;
  case 0xFE: //resend
    ack();
    break;
  case 0xF6: //set defaults
    //enter stream mode
    ack();
    break;
  case 0xF5: //disable data reporting
    //FM
    enabled = 0;
    ack();
    break;
  case 0xF4: //enable data reporting
    //FM
    enabled = 1;
    ack();
    break;
  case 0xF3: //set typematic rate
    ack();
    keyboard.read(&val); //do nothing with the rate
    ack();
    break;
  case 0xF2: //get device id
    ack();
    keyboard.write(0xAB);
    keyboard.write(0x83);
    break;
  case 0xF0: //set scan code set
    ack();
    keyboard.read(&val); //do nothing with the rate
    ack();
    break;
  case 0xEE: //echo
    //ack();
    keyboard.write(0xEE);
    break;
  case 0xED: //set/reset LEDs
    ack();
    keyboard.read(&val); //do nothing with the rate
    ack();
    break;
  }
}

void connectHost() {
  while (Serial.available() <= 0) {
    Serial.print('A');   // send a capital A
    delay(300);
  }
}

void setup() {
  pinMode(13, OUTPUT);
  //establish serial connection with host
  Serial.begin(9600);
  // establish ps/2 connection with target
  while(keyboard.write(0xAA)!=0){
    digitalWrite(13, HIGH);
    delay(500); 
    digitalWrite(13, LOW);
    delay(500);
  }
  delay(100);  
  
  connectHost();
  Serial.println("\nSerial Host Connected");
  Serial.flush();
}

void loop() {
  unsigned char c;
  if( (digitalRead(3)==LOW) || (digitalRead(2) == LOW)) {
    if(digitalRead(3)==LOW){
      Serial.println("pin 3  is LOW");
    } else {
      Serial.println("pin 2 is LOW");
    }
    while(keyboard.read(&c));
    kbdCmd(c);
    Serial.print("Target: 0x");
    Serial.println(c, HEX);
  }  
  else {//if host device wants to send a command:
    //echo ASCII code from terminal and write to ps/2
    if(Serial.available() > 0) {
      incomingByte = Serial.read();
      keyboard.write(incomingByte);      
      Serial.print("Host: 0x");
      Serial.print(incomingByte, HEX);
      Serial.print(" ");
      Serial.print(incomingByte);
      Serial.print(" ");
      Serial.println(incomingByte, BIN);
    }
  }
}

Ein paar Fragen: "Sketch" ist Arduino-Jargon für "Programm"? Dieses Python-Treiber-Zeug ist unabhängig vom Zielcomputer, oder? Ihr Problem ist, dass es auf dem einen Zielcomputer funktioniert und nicht auf dem anderen, oder? Haben Sie versucht, das nicht funktionierende Ziel mit einer angeschlossenen PS / 2-Tastatur zu booten und dieses dann mit dem Arduino auszutauschen?
AndreKR

Ja, Sketch == Programm in Ardu-Jargon. Ich habe es versucht und es schien nicht zu funktionieren (aber ich muss die Skizze ändern, damit sie nicht auf die ACKs vom Ziel wartet, bevor ich Zeichen sende.) Ich werde Sie wissen lassen, wenn ich die Gelegenheit habe, sie zu testen im Laufe des Tages.
Chisaipete

Also habe ich das Programm getestet, wie Sie vorgeschlagen haben, und es funktioniert! Am Ende möchte ich in der Lage sein, das Ziel mit installiertem Tastaturemulator aus- und wieder einzuschalten und damit die BIOS-Einstellungen zu ändern. Ich denke also, der Start-Handshake ist ausgeschaltet?
Chisaipete

Ja möglicherweise. Haben Sie die Initialisierungssequenz ganz unten auf computer-engineering.org/ps2keyboard gesehen ? Ich würde damit beginnen, meine Sequenz damit zu vergleichen.
AndreKR

1
Entschuldigung, ich habe diesen Thread veraltet gelassen - ich hatte keine Zeit, die Lösung von AndreKR auszuprobieren. Außerdem verwende ich keine Pullup-Widerstände, daher ist es schwierig zu bestimmen, an welchem ​​Ende keine Pullup-Widerstände vorhanden sind :)
Chisaipete

Antworten:


5

Soweit ich weiß, verbinden Sie Ihr Arduino mit zwei verschiedenen Zielcomputern und auf einem funktioniert es und auf dem anderen nicht.

Es scheint also einen Unterschied zwischen den Initialisierungsanforderungen der beiden Maschinen zu geben. Auf dieser Seite ganz unten finden Sie eine Auflistung einer möglichen Initialisierungssequenz. Vergleichen Sie zunächst Ihre Initialisierung mit dieser.

Mit einem Logikanalysator wird es viel einfacher. Ich benutze den Intronix Logicport , aber es gibt sowohl billigere als auch bessere, wenn auch nicht gleichzeitig.

Das Anschließen eines Open-Collector-Busses ist etwas umständlich, da Sie nicht sehen, welches Gerät spricht. Wenn Sie jedoch an dem Ende, an dem der Pullup nicht erfolgt , einen Vorwiderstand einsetzen , können Sie anhand des Spannungspegels erkennen, welches Gerät den Bus gedrückt hält. Jeder Open-Collector-Bus (wie PS / 2) benötigt Pullup-Widerstände, die normalerweise im PC eingebaut sind. Sie können die verschiedenen Spannungspegel auf einem DSO leicht sehen. Mit nur einem LA müssen Sie zweimal mit unterschiedlichen Schwellenspannungen aufnehmen.


Die Entscheidung, wer das Kopfgeld geben soll, war schwieriger als ich erwartet hatte, aber Ihre Antwort erhielt die meisten Stimmen und ich bevorzuge es etwas. Ich hätte es vorgezogen, alle zu belohnen!
Kortuk

3

Angesichts der Tatsache, dass Ihr Projekt mit einem Motherboard und nicht mit einem anderen funktioniert, scheinen Sie einen klassischen Fall von "partieller Spezifikationskonformität" zu haben - in Ihrem Projekt und möglicherweise sogar in einem der Motherboards. Die meisten Tastaturen funktionieren jedoch mit jedem Motherboard, sodass eine robuste Implementierung portabel sein sollte. Die Herausforderung besteht darin, dass Sie herausfinden müssen, warum Ihre nicht ist.

Möglicherweise können Sie dies tun, indem Sie nur auf das Problem starren und darüber nachdenken, wie es funktionieren soll (vielleicht nach einer Pause - oder eines Tages trifft Sie die Antwort unter der Dusche), aber Sie sind effektiver, wenn Sie es überwachen können Was ist los. Für elektrische Probleme bedeutet dies einen Bereich, für Protokollprobleme einen Logikanalysator. In diesem Bereich gibt es einige günstige Optionen, zum Beispiel die "Buspiraten" -Karte, die bestimmte Funktionen für das Tastaturprotokoll bietet, oder etwas FPGA-basiertes, das einen längeren Erfassungspuffer haben könnte (siehe sump.org).

Sie könnten auch versuchen, ein anderes Gerät, entweder einen Mikrocontroller oder ein FPGA, zu verwenden, um einen Tastaturhost zu erstellen und damit Ihr Projekt an den Grenzen der Spezifikation zu testen.


2

Ich habe mir die ps2dev-Bibliothek nicht angesehen, um genau zu sehen, wie es funktioniert, aber eines fällt mir auf.

Im Moment wird ein einzelner Versuch unternommen, eine Verbindung zum "Host" -Computer herzustellen. Wenn dies fehlschlägt, wird eine ganze Sekunde gewartet (LED an 0,5 s, LED aus 0,5 s), bevor ein weiterer Versuch unternommen wird.

Wenn das Intel-Motherboard nicht lange genug auf die Tastaturerkennung wartet, wird der Verbindungsversuch möglicherweise nie ausgeführt, bevor die Startsequenz fortgesetzt wird.

Wenn Sie die Wartezeit auf 0,1 s verkürzen (ändern Sie die Verzögerungszeilen (500) in Verzögerung (50)), haben Sie möglicherweise etwas Glück.

Wenn nicht, versuchen Sie es noch schneller. Zur Hölle, versuchen Sie es sogar ohne Verzögerung und sehen Sie, wie das geht.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.