Sí, he buscado en los foros Arduino.cc y aquí. Sí, he encontrado los artículos sobre la biblioteca ps2dev. Sí, he leído (bueno, algunos lo he leído) el artículo definitivo de la interfaz PS / 2 en este sitio web . Sí, tengo esto funcionando, un poco. Necesito algunas ideas para dar el salto al pleno funcionamiento. :)
No, no puedo simplemente emular un teclado USB HID y dejarlo así: debe ser una emulación de teclado PS / 2. Sí, estoy enviando señales adecuadas de hacer y romper, incluso maneja combinaciones de teclas muy complicadas. Tal como está ahora, tengo un código escrito para mi Arduino como se publica a continuación (técnicamente un Freeduino 1.22), y he enviado pulsaciones de teclas a través del monitor serie o terminal PuTTY, así como con un práctico envoltorio / controlador Python que envía La información del código de escaneo PS / 2, y en general me hace la vida mucho más fácil, también quita parte de la carga del Arduino.
En este momento, tengo un boceto ejecutándose en el Arduino que emula un teclado PS / 2. Naturalmente, tengo que arrancar mi máquina "objetivo" (máquina en la que se conecta PS / 2 Plug), y veo que tiene lugar el "apretón de manos". Arrancar en WinDoze, abrir el bloc de notas y conducir pulsaciones de teclas a la pantalla (con éxito) utilizando mi "controlador" de Python. (El controlador simplemente tiene lugar en el terminal Serial Monitor / PuTTY y lee / escribe en el puerto serie usando un módulo llamado PySerial.) Todo esto se hace en un AMD en el "objetivo" de la placa base ASUS.
Ahora, el objetivo es hacer que funcione en mi Intel en el "objetivo" basado en la placa base Intel, lo enchufo, arranco y no tengo dados. Entonces, modifiqué un poco el boceto para intentar tener una idea de lo que realmente está sucediendo con mi pequeño amigo Ardy. La versión después de las modificaciones se muestra a continuación. Según tengo entendido (el código fue "prestado" de otra publicación en el foro de Arduino.cc, aquí ) Intentará establecer una conexión con el "objetivo" a través de PS / 2 primero, parpadeando el LED a bordo en un período de .5 segundos hasta el Se establece la conexión. El objetivo de Intel no supera el parpadeo de 0,5 segundos y la conexión en serie nunca se establece con el "host".
Mi pregunta es esta: ¿hay una diferencia importante en la forma en que los teclados ps / 2 establecen comunicación con su máquina de destino? ¿Es realmente una diferencia de diseño o debería buscar algo más básico que es el problema aquí? Escuché algo sobre la necesidad de resistencias pull-up en las entradas de datos / reloj, pero eso debería manejarse en el código, especialmente porque FUNCIONA en otro objetivo, solo que no es en el que necesito trabajar.
¿Algunas ideas? Me encantaría que esto funcione lo antes posible: voy a seguir depurando, cualquier sugerencia o sugerencia sería muy apreciada. A todos se les dará una consideración completa porque necesito algunos ojos nuevos sobre este tema. ¿Quizás se necesita una mejor implementación en la biblioteca ps2dev?
#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);
}
}
}
Respuestas:
Según tengo entendido, conectas tu Arduino a dos máquinas de destino diferentes y en una funciona y en la otra no.
Parece que hay una diferencia entre los requisitos de inicialización de las dos máquinas. En esta página, en la parte inferior, hay una lista de una posible secuencia de inicialización. Comience comparando su inicialización con esa.
Será mucho más fácil usando un analizador lógico. Estoy usando Intronix Logicport , pero hay otros más baratos y mejores, aunque no al mismo tiempo.
Aprovechar un autobús de colección abierta es un poco engorroso porque no ves qué dispositivo está hablando. Sin embargo, si coloca una resistencia en serie al final donde no está el pullup , puede saber por el nivel de voltaje qué dispositivo está sosteniendo el bus. Cada bus de colector abierto (como PS / 2) necesita resistencias pullup, generalmente están integradas en la PC. Puede ver los diferentes niveles de voltaje fácilmente en un DSO. Con solo un LA, debe grabar dos veces con diferentes voltajes de umbral.
fuente
Dado que su proyecto funciona con una placa base y no con otra, parece tener un caso clásico de "cumplimiento de especificaciones parciales", en su proyecto, y tal vez incluso en una de las placas base. Pero la mayoría de los teclados funcionarán con cualquier placa base, por lo que una implementación robusta debería ser portátil. El desafío es que tendrás que descubrir por qué el tuyo no lo es.
Es posible que pueda hacer esto simplemente mirando el problema y pensando en cómo se supone que funciona (tal vez después de un descanso, o un día la respuesta lo golpee en la ducha), pero será más efectivo si puede monitorear Que esta pasando. Para problemas eléctricos, eso significa un alcance, para los protocolos, un analizador lógico. Hay algunas opciones baratas disponibles en esa área, por ejemplo, la placa "pirata de bus" que tiene alguna capacidad específica para el protocolo de teclado o algo basado en FPGA que podría tener un búfer de captura más largo (ver sump.org).
Otra cosa que podría intentar sería usar otro dispositivo, ya sea un microcontrolador o un FPGA, para construir un host de teclado y usarlo para probar su proyecto hacia los límites de la especificación.
fuente
No he mirado la biblioteca ps2dev para ver exactamente cómo funciona, pero una cosa me llama la atención.
Por el momento, se realiza un solo intento de conectarse a la computadora "host". Cuando eso falla, se espera un segundo entero (LED encendido 0.5s, LED apagado 0.5s) antes de hacer otro intento.
Si la placa base Intel no está esperando el tiempo suficiente para la detección del teclado, es posible que nunca obtenga el intento de conexión antes de continuar con su secuencia de arranque.
Si disminuye el tiempo de espera para decir 0.1s (cambie las líneas de retraso (500) a retraso (50)) puede que tenga suerte.
Si no, intente aún más rápido. Demonios, incluso pruébalo sin demora y ve cómo funciona
fuente