PS2Keyboard Library & VirtualUSB for Arduino Library

Bonjour,

Je réalise un projet pour récupérer les touches envoyées d’un pavé numérique en PS/2 branché sur un ARDUINO (un nano) pour ensuite renvoyer vers le PC en USB d’autres séquence de touches. Le PC reconnait mon arduino comme un periphérique HID USB (un bête clavier USB quoi).

exemple: je tape “1” sur le pavé numérique, Arduino intercepte en PS/2 et renvoie “2” sur l’USB (bon là c’est un exemple). Ainsi c’est comme si on avait tapé directement 2 sur le clavier du PC.

Pour ce faire, j’utilise 2 “libraries” bibliothèques: PS2Keyboard 2.4 & Vusb-for-arduino-005.
http://www.pjrc.com/teensy/td_libs_PS2Keyboard.html et https://code.google.com/p/vusb-for-arduino/

Pour valider mon idée, j’ai fait 2 mini projets:

  • clavier PS/2 + Arduino nano + PS2Keyboard Library 2.4: ça fonctionne, je récupère bien les touches dans la console serie sur le PC
  • Arduino nano + cable USB (différent de l’USB de l’arduino - je parle d’un nouveau port cablé sur les pins digital de l’arduino) vers PC + Vusb-for-arduino-005 : ça fonctionne, mon PC reconnait l’arduino comme un periphérique USB et je peux envoyer des touches au PC comme avec un clavier USB. (je précise que j’utilise obligatoirement l’IDE 1.0 de arduino, sinon ça compile pas avec cette library)

Maintenant, ça ne fonctionne pas lorsque je fusionne les 2 mini projets en un seul.

Voici le programme minimum (en fait ça bloque sur la déclaration des bibliothèques):

#include "PS2Keyboard.h"
#include "UsbKeyboard.h" //utilise arduino IDE 1.0 absolument   

void setup() {
  // put your setup code here, to run once:
}

void loop() {
  // put your main code here, to run repeatedly: 
}

J’obtiens une erreur de compilation sous IDE 1.0:

core.a(WInterrupts.c.o): In function `__vector_1':
C:\Program Files (x86)\arduino-1.0\hardware\arduino\cores\arduino/WInterrupts.c:230: multiple definition of `__vector_1'
UsbKeyboard\usbdrvasm.S.o:(.text+0x32): first defined here

J’ai essayé sous IDE 1.6.4 mais la lib USBKeyboard ne compile pas.

In file included from Y:\Dropbox\Arduino\Sketchbook\libraries\UsbKeyboard/UsbKeyboard.h:14:0,
                 from ccccccc.ino:2:
Y:\Dropbox\Arduino\Sketchbook\libraries\UsbKeyboard/usbdrv.h:479:26: error: variable 'usbDescriptorDevice' must be const in order to be put into read-only section by means of '__attribute__((progmem))'
 char usbDescriptorDevice[];
                          ^
Y:\Dropbox\Arduino\Sketchbook\libraries\UsbKeyboard/usbdrv.h:485:33: error: variable 'usbDescriptorConfiguration' must be const in order to be put into read-only section by means of '__attribute__((progmem))'
 char usbDescriptorConfiguration[];
                                 ^
Y:\Dropbox\Arduino\Sketchbook\libraries\UsbKeyboard/usbdrv.h:491:29: error: variable 'usbDescriptorHidReport' must be const in order to be put into read-only section by means of '__attribute__((progmem))'
 char usbDescriptorHidReport[];
                             ^
Y:\Dropbox\Arduino\Sketchbook\libraries\UsbKeyboard/usbdrv.h:497:27: error: variable 'usbDescriptorString0' must be const in order to be put into read-only section by means of '__attribute__((progmem))'
 char usbDescriptorString0[];
                           ^
Y:\Dropbox\Arduino\Sketchbook\libraries\UsbKeyboard/usbdrv.h:503:31: error: variable 'usbDescriptorStringVendor' must be const in order to be put into read-only section by means of '__attribute__((progmem))'
 int usbDescriptorStringVendor[];
                               ^
Y:\Dropbox\Arduino\Sketchbook\libraries\UsbKeyboard/usbdrv.h:509:31: error: variable 'usbDescriptorStringDevice' must be const in order to be put into read-only section by means of '__attribute__((progmem))'
 int usbDescriptorStringDevice[];
                               ^
Y:\Dropbox\Arduino\Sketchbook\libraries\UsbKeyboard/usbdrv.h:515:37: error: variable 'usbDescriptorStringSerialNumber' must be const in order to be put into read-only section by means of '__attribute__((progmem))'
 int usbDescriptorStringSerialNumber[];
                                     ^
In file included from ccccccc.ino:2:0:
Y:\Dropbox\Arduino\Sketchbook\libraries\UsbKeyboard/UsbKeyboard.h:37:39: error: variable 'usbDescriptorHidReport' must be const in order to be put into read-only section by means of '__attribute__((progmem))'
 PROGMEM char usbHidReportDescriptor[35] = { /* USB report descriptor */
                                       ^
Erreur lors de la compilation.

J’imagine que c’est un problème avec les interruptions sous l’IDE 1.0. Mais je ne comprends jamais rien avec ces messages ésotériques de compilateur.
J’ai absolument besoin d’utiliser les interruptions sur les pins digital 2 et 3 de l’arduino:

  • pin 2 (INT0) pour Vusb-for-arduino-005
  • pin 3 (INT1) pour PS2Keyboard 2.4

J’ai cherché longtemps sur google, sur les forums anglais et français mais je n’ai rien trouvé. J’avais bien trouvé des projets similaires sur le net mais impossible de les compiler et/ou de les faire fonctionner. J’avais même trouvé un message avec exactement le même problème mais personne n’a répondu sur le forum Anglais: http://forum.arduino.cc/index.php?topic=121092.0

J’ai 2 pistes:

  • Je suppose que Vusb-for-arduino-005 utilise les interruptions INT0 et INT1 et comme PS2Keyboard 2.4 a besoin de l’INT1, ça ne compile pas.
  • Je suppose qu’en modifiant Vusb-for-arduino-005 pour le faire tourner sur l’IDE 1.6.4 ça devrait compiler mais je ne sais pas comment faire.

Auriez-vous une idée de ce que je dois changer au niveau des “libraries” afin que cela compile et sous quelle version de IDE? Merci par avance pour votre aide à me faire progresser.

vusb-for-arduino-005 Libraries.zip (347 KB)

PS2Keyboard.zip (10.2 KB)

J'avais trouvé ce projet "kbd_april_fools.pde" (qui est une blague de 1 avril) qui correspond (je pense) à ce que souhaite faire (sans le coté blague): http://hunt.net.nz/users/darran/weblog/329aa/Arduino_PS2_to_USB_Keyboard.html

ça compile sous IDE 1.0 mais je n'arrive pas à le faire fonctionner: le PC ne reconnait pas l'arduino comme un clavier USB HID. où alors j'ai rien compris....

idem içi avec ce projet "Adafruit Trinket PS/2 to USB Hacked Converter" qui ressemble vraiment à ce que je souhaite faire mais moi c'est un arduino nano ATMEGA328P. http://mario.mtechcreations.com/programing/adafruit-trinket-ps2-to-usb-hacked-converter/

Sous IDE 1.6.4:

In file included from Y:\Dropbox\Arduino\Sketchbook\libraries\TrinketKeyboardlite\usbdrvasm_includer.S:24:0:
Y:\Dropbox\Arduino\Sketchbook\libraries\TrinketKeyboardlite\usbdrv/usbdrvasm.S:17:0: warning: "__SFR_OFFSET" redefined [enabled by default]
 #define __SFR_OFFSET 0      /* used by avr-libc's register definitions */
 ^
In file included from c:\program files (x86)\arduino\hardware\tools\avr\avr\include\avr\io.h:99:0,
                 from Y:\Dropbox\Arduino\Sketchbook\libraries\TrinketKeyboardlite\cmdline_defs.h:26,
                 from Y:\Dropbox\Arduino\Sketchbook\libraries\TrinketKeyboardlite\usbdrvasm_includer.S:22:
c:\program files (x86)\arduino\hardware\tools\avr\avr\include\avr\sfr_defs.h:141:0: note: this is the location of the previous definition
 #    define __SFR_OFFSET 0x20
 ^
In file included from Y:\Dropbox\Arduino\Sketchbook\libraries\TrinketKeyboardlite\usbdrvasm_includer.S:24:0:
Y:\Dropbox\Arduino\Sketchbook\libraries\TrinketKeyboardlite\usbdrv/usbdrvasm.S:384:34: fatal error: usbdrvasm16.inc: No such file or directory
 #       include "usbdrvasm16.inc"
                                  ^
compilation terminated.
Erreur lors de la compilation.

Sous IDE 1.0:

In file included from Y:\Dropbox\Arduino\Sketchbook\libraries\TrinketKeyboardlite\usbdrvasm_includer.S:24:
Y:\Dropbox\Arduino\Sketchbook\libraries\TrinketKeyboardlite\/usbdrv/usbdrvasm.S:17:1: warning: "__SFR_OFFSET" redefined
In file included from c:/program files (x86)/arduino-1.0/hardware/tools/avr/lib/gcc/../../avr/include/avr/io.h:99,
                 from Y:\Dropbox\Arduino\Sketchbook\libraries\TrinketKeyboardlite\/cmdline_defs.h:26,
                 from Y:\Dropbox\Arduino\Sketchbook\libraries\TrinketKeyboardlite\usbdrvasm_includer.S:22:
c:/program files (x86)/arduino-1.0/hardware/tools/avr/lib/gcc/../../avr/include/avr/sfr_defs.h:141:1: warning: this is the location of the previous definition
In file included from Y:\Dropbox\Arduino\Sketchbook\libraries\TrinketKeyboardlite\usbdrvasm_includer.S:24:
Y:\Dropbox\Arduino\Sketchbook\libraries\TrinketKeyboardlite\/usbdrv/usbdrvasm.S:384:34: error: usbdrvasm16.inc: No such file or directory

J'ai réessayé en copiant le fichier "usbdrvasm16.inc" de VirtualUSB for Arduino Library dans la library de TrinketKeyboardlite car mon arduino est à 16Mhz. mais cela ne fonctionne toujours pas.

Sous IDE 1.6.4 (+ fichier usbdrvasm16.inc):

In file included from Y:\Dropbox\Arduino\Sketchbook\libraries\TrinketKeyboardlite\usbdrvasm_includer.S:24:0:
Y:\Dropbox\Arduino\Sketchbook\libraries\TrinketKeyboardlite\usbdrv/usbdrvasm.S:17:0: warning: "__SFR_OFFSET" redefined [enabled by default]
 #define __SFR_OFFSET 0      /* used by avr-libc's register definitions */
 ^
In file included from c:\program files (x86)\arduino\hardware\tools\avr\avr\include\avr\io.h:99:0,
                 from Y:\Dropbox\Arduino\Sketchbook\libraries\TrinketKeyboardlite\cmdline_defs.h:26,
                 from Y:\Dropbox\Arduino\Sketchbook\libraries\TrinketKeyboardlite\usbdrvasm_includer.S:22:
c:\program files (x86)\arduino\hardware\tools\avr\avr\include\avr\sfr_defs.h:141:0: note: this is the location of the previous definition
 #    define __SFR_OFFSET 0x20
 ^
Y:\Dropbox\Arduino\Sketchbook\libraries\TrinketKeyboardlite\usbdrv/asmcommon.inc: Assembler messages:
Y:\Dropbox\Arduino\Sketchbook\libraries\TrinketKeyboardlite\usbdrv/asmcommon.inc:45: Error: constant value required
Y:\Dropbox\Arduino\Sketchbook\libraries\TrinketKeyboardlite\usbdrv/asmcommon.inc:61: Error: constant value required
Y:\Dropbox\Arduino\Sketchbook\libraries\TrinketKeyboardlite\usbdrv/asmcommon.inc:98: Error: constant value required
Y:\Dropbox\Arduino\Sketchbook\libraries\TrinketKeyboardlite\usbdrv/asmcommon.inc:99: Error: constant value required
Y:\Dropbox\Arduino\Sketchbook\libraries\TrinketKeyboardlite\usbdrv/usbdrvasm16.inc:333: Error: constant value required
Erreur lors de la compilation.

En gros je bidouille à mort et je pige toujours rien.... :confused:

Après j'ai trouvé cela qui indique à la fin que l'on peut adapter le code pour les ATMEGA 168/328 avec V-usb: https://github.com/tmk/tmk_keyboard/tree/master/converter/ps2_usb

mais je ne sais pas comment faire (modification + compilation du makefile.vusb)

Bonjour Projet intéressant. Je vais te suivre.

Désolé j'y connais rien la dedans, mais pourquoi n'essayerais tu pas de modifier "PS2Keyboard" plutôt que "Vusb-for-arduino-005".

Ton projet me donne une idée pour faire un clavier étendu avec des touche F13 a F24 par exemple. Merci

Bon courage pour la suite

A+

Bonjour,

Parce que je pense que c'est vusb qui "reserve" les interruptions à la fois INT0 et INT1.

Il faudrait qu'il me laisse au moins INT1 pour Ps2keyboard.

Merci de me suivre. Je partagerai le résultat final.

Cdlt,

as tu regardé usbconfig.h ?

This file is an example configuration (with inline documentation) for the USB driver. It configures V-USB for USB D+ connected to Port D bit 2 (which is also hardware interrupt 0 on many devices) and USB D- to Port D bit 4. You may wire the lines to any other port, as long as D+ is also wired to INT0 (or any other hardware interrupt, as long as it is the highest level interrupt, see section at the end of this file). + To create your own usbconfig.h file, copy this file to your project's + firmware source directory) and rename it to "usbconfig.h". + Then edit it accordingly.

pour l'instant, seul INT0 est nécessaire

dfgh: as tu regardé usbconfig.h ?

pour l'instant, seul INT0 est nécessaire

bonsoir j'ai joué un peu avec VUSB, sans etre vraiment conquis de memoire, c'est tres sensible à l'horloge ceci etant , il me semble que le seul imperatif est bien INT0 et que l'autre pin data USB soit sur le meme port physique

Bonjour,

En effet pour INT0 uniquement.

Mais alors comment régler ce problème de compilation sous IDE 1.0?

core.a(WInterrupts.c.o): In function `__vector_1':
C:\Program Files (x86)\arduino-1.0\hardware\arduino\cores\arduino/WInterrupts.c:230: multiple definition of `__vector_1'
UsbKeyboard\usbdrvasm.S.o:(.text+0x32): first defined here

Je comprends que "__vector_1" est déclaré à la fois dans Winterrupts.c et à la fois dans usbdrvasm.S mais comment régler ce problème. J'imagine qu'il faut modifier usbdrvasm.S mais comment? De plus, il devrait y avoir un lien avec ps2keyboard car sans lui ça compile correctement.

Help please

Bon je crois avoir résolu mon problème en passant par un arduino Leonardo + PS2Keyboard (toujours sans drivers à installer).

C'est pas très beau mais au moins ça fonctionne.

Là je pars en vacances, je posterai mon sketch au retour si j'oublie pas (mais rien de sorcier).

Ps: si quelqu'un sait si on peut trouver des Atmega32u4 sur d'autres cartes plus petite que la leonardo, je prends ;-) EDIT: J'ai trouvé Arduino micro ;-)

chose promise…

J’utilise un arduino micro avec un pavé numérique PS/2 relié sur les pins 6 et 3 puis 5V et GND.

Voilà! (il y a du déchet dans mon code mais il fonctionne)

/*  PS2Keyboard to USB V1.0
	transformation d'un clavier PS2 en USB avec commutation de touche
        
*/
   
#include <PS2Keyboard.h>


// Pin du clavier
const int DataPin = 6; //jaune 
const int IRQpin =  3; //vert, ATTENTION TRES IMPORTANT DE CHOISIR UNE PIN AVEC UNE INTERRUPTION EXTERNE SUR L'ARDUINO (DEPEND DE CHAQUE TYPE D'ARDUINO)
const int ledPin = 13; // led

PS2Keyboard keyboardPS2;

void setup() {
  delay(1000);
  keyboardPS2.begin(DataPin, IRQpin, PS2Keymap_French);
  Serial.begin(9600);
    Keyboard.begin();
  pinMode(ledPin, OUTPUT);
 }

void loop() {
  

  if (keyboardPS2.available()) {
    
    // read the next key
    char c = keyboardPS2.read();
    
    // check for some of the special keys
    if (c == PS2_ENTER) {
      Keyboard.write(KEY_RETURN);
      Serial.println();
    } else if (c == PS2_ESC) {
      Keyboard.press(KEY_ESC);
         delay(100);
      Keyboard.releaseAll();
      Serial.print("[ESC]");
    } else {
      
      // otherwise, just print all normal characters
      Serial.print(c);
      
      if (c=='1') {
        //routine à écrire
      
      //Keyboard.write('1');  
        
      Keyboard.press(KEY_LEFT_CTRL);
      Keyboard.press('a');
            delay(100);
      Keyboard.releaseAll();
      
      //blinkLED(ledPin);
              
      }
      if (c=='2') {
        //routine à écrire
        //Keyboard.write('2');
      Keyboard.press(KEY_LEFT_CTRL);
      Keyboard.press('f');
            delay(100);
      Keyboard.releaseAll();
      }
      if (c=='3') {
        //routine à écrire
        //Keyboard.write('3');
      Keyboard.press(KEY_LEFT_CTRL);
      Keyboard.press('h');
            delay(100);
      Keyboard.releaseAll();
      }
      if (c=='4') {
        //routine à écrire
        //Keyboard.write('4');
      Keyboard.press(KEY_F4);
            delay(100);
      Keyboard.releaseAll();
      }
      if (c=='5') {
        //routine à écrire
        //Keyboard.write('5');
      Keyboard.press(KEY_F5);
            delay(100);
      Keyboard.releaseAll();
      }
      if (c=='6') {
        //routine à écrire
        //Keyboard.write('6');
      Keyboard.press(KEY_LEFT_CTRL);
      Keyboard.press('y');
            delay(100);
      Keyboard.releaseAll();
      }
      if (c=='7') {
        //routine à écrire
        //Keyboard.write('7');
      Keyboard.press(KEY_LEFT_CTRL);
      Keyboard.press('d');
            delay(100);
      Keyboard.releaseAll();
      }
      if (c=='8') {
        //routine à écrire
        //Keyboard.write('8');        
      Keyboard.press(KEY_F8);
            delay(100);
      Keyboard.releaseAll();
      }
      if (c=='9') {
        //routine à écrire
        //Keyboard.write('9');        
      Keyboard.press(KEY_LEFT_CTRL);
      Keyboard.press('b');
            delay(100);
      Keyboard.releaseAll();
      }
      if (c=='0') {
        //routine à écrire
        //Keyboard.write('0');        
      Keyboard.press(KEY_LEFT_CTRL);
      Keyboard.press('c');
            delay(100);
      Keyboard.releaseAll();
      }
      if (c=='/') {
        //routine à écrire
        //Keyboard.write('/');        
      Keyboard.press(KEY_LEFT_ALT);
      Keyboard.press(KEY_LEFT_CTRL);
      Keyboard.press(KEY_TAB);
            delay(100);
      Keyboard.releaseAll();
      }
      if (c=='*') {
        //routine à écrire
        //Keyboard.write('*');        
      Keyboard.press(KEY_LEFT_CTRL);
      Keyboard.press(KEY_TAB);
            delay(100);
      Keyboard.releaseAll();
      }
      if (c=='-') {
        //routine à écrire
        //Keyboard.write('-');        
      Keyboard.press(KEY_LEFT_ALT);
      Keyboard.press(KEY_TAB);
            delay(100);
      Keyboard.releaseAll();
      }
      if (c=='+') {
        //routine à écrire
       //Keyboard.write('+');
      Keyboard.press(KEY_LEFT_ALT);
      Keyboard.press('=');
            delay(100);
      Keyboard.releaseAll();
      }
      if (c=='.') {
        //routine à écrire
        //Keyboard.write('.');        
      Keyboard.press(KEY_LEFT_CTRL);
      Keyboard.press('v');
            delay(100);
      Keyboard.releaseAll();
      }
    }
  }
}

void blinkLED(int MaPin) {
        digitalWrite(MaPin, HIGH);   // turn the LED on (HIGH is the voltage level)
        delay(50);              // wait for a second
        digitalWrite(MaPin, LOW);    // turn the LED off by making the voltage LOW
        delay(50); 
  }

Bonjour Centent pour toi que ça fonctionne. Pourrais tu mettre aussi le schema de cablage que tu as utilisé avec les valeurs des composants.

Merci a+