Emulation de clavier avec Arduino

Je l’ai évoqué dans un précédent article, l’interface du pupitre avec le jeu de simulation (OpenRails à ce jour) repose dans le système FerroviSim sur l’émulation d’un clavier d’ordinateur par la carte Arduino qui gère le pupitre. Expliquons tout d’abord ce que cela signifie.

OpenRails est un jeu/logiciel de simulation ferroviaire grand public (disponible sur www.openrails.org). Il est donc avant tout prévu pour être joué avec ce dont tout propriétaire d’ordinateur dispose : un clavier. Ainsi, si vous installez OpenRails, une ligne et une locomotive, vous pourrez la conduire simplement en utilisant les touches Z (passer l’inverseur sur avant), puis D (augmenter la traction). Toutes (ou presque) les actions sur le pupitre se commandent ainsi avec différentes touches de clavier, dont l’affectation se retrouve dans le menu Options – Clavier d’OpenRails.

Partant de ce constat, il apparait évident qu’une solution pour commander OpenRails avec notre pupitre serait de se faire passer pour un clavier : c’est ce qu’on appelle l’émulation de clavier. C’est une des fonctionnalités que propose la carte Arduino Due, qui est celle que j’utiliserai pour les manipulations décrites dans cet article.

Rappel : pour cet article, je pars du principe que vous maitrisez les base d’Arduino, en particulier que vous avez installé l’IDE et que vous savez écrire un programme simple, le téléverser, etc. etc.

La bibliothèque Keyboard

La première étape est d’ajouter à notre projet Arduino la bibliothèque « Keyboard » disponible pour les cartes Due. On initialise ensuite l’émulation de clavier dans la fonction « Setup ».

#include <Keyboard.h>

void setup(){
       Keyboard.begin();
}

N’hésitez pas à consulter ici la documentation de cette bibliothèque : https://www.arduino.cc/reference/en/language/functions/usb/keyboard/

On utilisera ensuite les méthode « press » et « release » pour émuler l’appui et le relâchement d’une touche de clavier. Noter que la méthode « print » ne fonctionne pas avec OpenRails : pour chaque émulation d’un appui d’une touche il faudra bien l’appuyer (« press ») puis la relacher (« release »). Voyons avec un programme simple comment cela se traduit en langage Arduino :

#include <Keyboard.h>

void setup(){
       Keyboard.begin();
}

void loop(){
       Keyboard.press('a'); 
       delay(50); 
       Keyboard.release('a');
       delay(2000);
}

Le programme ci-dessus émule l’appui de la touche ‘a’ toutes les 2 secondes. Si en essayant le système sur votre ordinateur, c’est la touche ‘q’ qui est appuyée, pas de panique : la bibliothèque fonctionne en QWERTY et non en AZERTY. Il faut donc donner la lettre de clavier QWERTY qui correspond à la lettre que vous souhaitez émuler. N’hésitez pas à consulter les correspondances ici.

Le délais de 50 millisecondes entre l’appui et le relâchement est indispensable pour laisser le temps à l’ordinateur de recevoir l’information de l’appui. Il peut éventuellement être réduit mais sans descendre en dessous de quelques dizaines de millisecondes.

Important : L’Arduino Due dispose de deux ports USB : « programming » et « native ». L’utilisation de la bibliothèque Keyboard n’est possible qu’avec le port Native !

N’hésitez pas à modifier légèrement ce code pour mieux comprendre son fonctionnement !

Problème du blocage

Avec ce que nous avons vu ci-dessus, vous savez déjà l’essentiel. Attardons nous désormais sur un problème qui se pose avec le programme ci-dessus : le blocage du programme. Les programmes Arduino s’exécutent de la façon suivante : la fonction « void setup » s’exécute une fois à la mise sous tension, puis la fonction « void loop » est jouée en boucle tant que l’Arduino est alimentée. Le code de cette fonction s’exécute dans l’ordre, et lorsque l’on arrive au bout, on recommence. Or, lorsque le système rencontre une ligne « delay() », l’exécution s’arrête et reprend après la durée en millisecondes inscrite entre parenthèses. Avec un programme simple comme celui-ci, cela ne pose aucun problème, mais si on souhaite effectuer plusieurs actions en parallèle, les blocages du programme par l’utilisation de « delay() » empêchent le bon fonctionnement de l’ensemble. On ne peut donc pas envisager un blocage à chaque appui d’une touche de clavier.

Relâcher les touches au bon moment à l’aide de l’horloge : la fonction millis()

La solution : ne plus interrompre le programme mais utiliser l’horloge de l’Arduino. Pour y accéder, on utilise la fonction millis() qui renvoie le temps absolu en millisecondes depuis la mise sous tension.

Le principe est le suivant :
– Lorsque l’on appui une touche de clavier, on va garder en mémoire cet appui et l’instant auquel il a été effectué
– Lorsqu’un temps de 50 millisecondes sera écoulé depuis cet instant, on provoquera le relâchement de l’appui. On gardera en mémoire ce relâchement et son instant.
– Si la touche est relâchée depuis plus de 2 secondes, on procédera à nouveau à son appui, et ainsi de suite.

#include <Keyboard.h>

unsigned long instant_appui = 0;
unsigned long instant_relachement = 0;
bool etat_appui = 0;

void setup(){
       Keyboard.begin();
}

void loop(){
       if (etat_appui == 1 and millis() > instant_appui + 50) {
             Keyboard.release('a'); 
             etat_appui = 0;
             instant_appui = millis();
       }
       if (etat_appui == 0 and millis() > instant_relachement + 2000) {
             Keyboard.press('a'); 
             etat_appui = 1;
             instant_relachement = millis();
       }
}

La variable « etat_appui » permet de garder en mémoire l’état de l’appui de la touche. Selon son état (0 pour une touche relâchée et 1 pour une touche appuyée), on compare le temps courant ( millis() ) à l’instant d’appui (ou de relâchement) incrémenté du délais souhaité.

Avec ce code, certes plus compliqué que le premier, la boucle « void loop » n’est jamais interrompue, et il est possible de d’effectuer d’autres actions à sa suite (action sur d’autres touches, commande de voyants…) sans que celles-ci ne soit perturbées par l’appui de la touche ‘a’.

Il est clair qu’appuyer toutes les 2 secondes sur une touche ne vas pas permettre d’aller très loin dans la réalisation d’un simulateur, mais vous avez désormais acquis la base de l’émulation de clavier avec Arduino, et pourrez adapter ce code pour, par exemple, provoquer l’appui d’une touche lors de l’appui sur un bouton poussoir. Ce sera l’objet d’autres articles à venir.

Laisser un commentaire