Arduino PS / 2 키보드 에뮬레이터 문제


10

예, Arduino.cc 포럼과 여기를 검색했습니다. 예, ps2dev 라이브러리에 관한 기사를 찾았습니다. 예, 이 웹 사이트 에서 결정적인 PS / 2 인터페이스 기사를 읽었습니다 . 예,이 작업이 약간 있습니다. 완전히 일할 수 있도록 몇 가지 아이디어가 필요합니다. :)

아니요, USB HID 키보드를 에뮬레이트하고 그대로 둘 수는 없습니다. PS / 2 키보드 에뮬레이션이어야합니다. 예, 적절한 make and break 신호를 보내고 있습니다. 심지어 매우 복잡한 키 스트로크 조합도 처리합니다. 현재로서는 Arduino 용으로 작성된 코드가 아래에 게시되어 있으며 (기술적으로 Freeduino 1.22) 직렬 모니터 또는 PuTTY 터미널과 실제 Python 전송기 / 드라이버를 통해 키 입력을 보냈습니다. PS / 2 스캔 코드 정보 (일반적으로 생활이 훨씬 쉬워 짐)는 물론 Arduino의 부담을 덜어줍니다.

지금은 Arduino에서 PS / 2 키보드를 에뮬레이트하는 스케치가 있습니다. 당연히, "대상"머신 (PS / 2 플러그가 들어가는 머신)을 부팅해야하며 "핸드 셰이크"가 발생하는 것을 볼 수 있습니다. WinDoze로 부팅하고 메모장을 연 다음 Python "드라이버"를 사용하여 화면에 키 입력을 성공적으로 수행하십시오. (드라이버는 단순히 Serial Monitor / PuTTY 터미널을 대신하여 PySerial이라는 모듈을 사용하여 직렬 포트를 읽거나 씁니다.) 이것은 모두 ASUS 마더 보드 "대상"의 AMD에서 수행됩니다.

이제 목표는 인텔 마더 보드 기반 "대상"으로 인텔에서 작동하도록하는 것입니다. 플러그를 꽂고 부팅하고 주사위를 사용하지 않습니다. 그래서 저는 스케치를 약간 수정하여 제 작은 Ardy 친구에게 실제로 무슨 일이 일어나고 있는지를 직접 보여주었습니다. 개조 후의 버전이 아래에 표시됩니다. 내가 (코드는 다른 Arduino.cc 포럼의 게시물에서 "빌려"한 그것을 이해 여기에 ) 그것은 때까지 0.5 초 기간에 온보드 LED를 점멸, 시도하고 첫 PS / 2를 통해 "대상"과의 연결을 설정합니다 연결이 설정되었습니다. 인텔 대상이 0.5 초 동안 깜박이지 않고 "호스트"로 직렬 연결이 설정되지 않습니다.

내 질문은 이것입니다 : ps / 2 키보드가 대상 컴퓨터와 통신하는 방식에 큰 차이가 있습니까? 그것은 실제로 디자인의 차이입니까, 아니면 여기서 문제가되는 더 기본적인 것을 찾고 있습니까? 데이터 / 클럭 입력에 풀업 저항이 필요하다는 것에 대해 들었습니다.하지만 코드에서 처리해야합니다. 특히 다른 대상에서 작동하기 때문에 작업 해야하는 대상이 아닙니다.

어떤 아이디어? 이 작업을 최대한 빨리 수행하고 싶습니다. 디버그를 계속하고 싶습니다. 포인터 나 제안은 크게 감사하겠습니다. 이 문제에 대해 새로운 시각이 필요하기 때문에 모두 고려할 것입니다. 아마도 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);
    }
  }
}

몇 가지 질문 : "스케치"는 "프로그램"의 Arduino-lingo입니까? 이 파이썬 드라이버는 대상 컴퓨터와 독립적입니다. 문제는 그것이 하나의 대상 컴퓨터에서 작동하고 다른 기계에서는 작동하지 않는다는 것입니다. PS / 2 키보드가 연결된 상태로 작동하지 않는 대상을 부팅 한 다음 Arduino와 교체하려고 했습니까?
AndreKR

예, Ardu-lingo에서 Sketch == 프로그램입니다. 나는 이것을 시도했지만 작동하지 않는 것 같지만 (문자를 보내기 전에 대상에서 ACK를 기다리지 않도록 스케치를 수정해야합니다.) 테스트 할 기회가되면 알려 드리겠습니다. 나중에 오늘.
chisaipete

그래서 제안한대로 프로그램을 테스트했는데 작동합니다! 결국 키보드 에뮬레이터가 설치된 상태에서 대상의 전원을 껐다 켜고 BIOS 설정을 변경할 수 있기를 원합니다. 시작 핸드 셰이크가 꺼져 있다고 생각합니까?
chisaipete 2016 년

네 아마도. 맨 아래에 초기화 시퀀스가 ​​보입니까?computer-engineering.org/ps2keyboard의 있습니까? 내 시퀀스를 그것과 비교하여 시작합니다.
AndreKR

1
죄송합니다,이 스레드가 오래되었습니다. AndreKR의 솔루션을 시험해 볼 시간이 없었습니다. 또한 풀업 저항을 사용하지 않으므로 풀업 저항이없는 쪽을 결정하기가 어렵습니다. :)
chisaipete

답변:


5

내가 이해하는 것처럼 Arduino를 두 개의 다른 대상 컴퓨터에 연결하고 하나는 작동하고 다른 하나는 작동하지 않습니다.

따라서 두 컴퓨터의 초기화 요구 사항간에 차이가있는 것 같습니다. 에 이 페이지 맨 아래에서 가능한 초기화 시퀀스의 목록이 있습니다. 초기화와 그 초기화를 비교하여 시작하십시오.

로직 분석기를 사용하면 훨씬 쉬워집니다. Intronix Logicport를 사용하고 있지만 동시에 저렴하지는 않지만 더 좋습니다.

어떤 장치가 말하는지 알 수 없기 때문에 오픈 컬렉터 버스에 두드리는 것은 약간 성가신 일입니다. 그러나 풀업이 끝나는 끝에 직렬 저항을 넣으면 아닌 어떤 장치가 버스를 누르고 있는지 전압 레벨로 알 수 있습니다. PS / 2와 같은 모든 오픈 컬렉터 버스에는 풀업 저항이 필요합니다. 일반적으로 PC에 내장되어 있습니다. DSO에서 다양한 전압 레벨을 쉽게 볼 수 있습니다. LA 만 있으면 다른 임계 전압으로 두 번 기록해야합니다.


현상금을 줄 사람의 결정은 어려웠지만 귀하의 답변이 가장 많은 표를 얻었으며 약간 선호합니다. 나는 모든 사람에게 보상을 선호했을 것입니다!
Kortuk

3

프로젝트가 다른 마더 보드가 아닌 하나의 마더 보드에서 작동한다는 점을 고려하면 프로젝트에서, 그리고 아마도 마더 보드 중 하나에서도 "부분 사양 준수"의 전형적인 사례가있는 것 같습니다. 그러나 대부분의 키보드는 모든 마더 보드에서 작동하므로 강력한 구현은 휴대용이어야합니다. 도전은 당신이 왜 그렇지 않은지를 알아 내야한다는 것입니다.

문제를 쳐다보고 어떻게 작동해야하는지 생각하면 (일부 휴식 후 또는 하루 동안 샤워에서 답이 나올 수 있음)이 작업을 수행 할 수 있지만 모니터링 할 수 있으면 더 효과적입니다 무슨 일이야. 범위를 의미하는 전기적 문제의 경우 프로토콜 문제의 경우 로직 분석기입니다. 해당 영역에서 사용할 수있는 저렴한 옵션이 있습니다 (예 : 키보드 프로토콜을위한 특정 기능이있는 "버스 해적"보드 또는 더 긴 캡처 버퍼를 가질 수있는 FPGA 기반) (sump.org 참조).

시도 할 수있는 또 다른 방법은 마이크로 컨트롤러 또는 FPGA와 같은 다른 장치를 사용하여 키보드 호스트를 구축하고 사양의 한계를 향해 프로젝트를 테스트하는 데 사용하는 것입니다.


2

ps2dev 라이브러리가 어떻게 작동하는지 정확히 보지 못했지만 한 가지가 나에게 뛰어납니다.

현재 "호스트"컴퓨터에 연결하려고 한 번 시도했습니다. 실패하면 다시 시도하기 전에 전체 초 (LED on 0.5s, LED off 0.5s)가 대기합니다.

인텔 마더 보드가 키보드 감지를 위해 충분히 오래 기다리지 않으면 부팅 순서를 계속하기 전에 연결 시도를받지 못할 수 있습니다.

대기 시간을 0.1 초로 줄이면 (delay (500) 줄을 delay (50)로 변경) 운이 좋을 수 있습니다.

그렇지 않으면 더 빨리 시도하십시오. 심지어 지체없이 시도해보고 어떻게 진행되는지보십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.