Go Down

Topic: Librairie Keyboard (utilisation, explication et conversion AZERTY) (Read 1 time) previous topic - next topic

nico78

Le code Keyboard_Azerty.ino est attaché a ce message
[Mise à jour, prend en charge certains caractères spéciaux directement V1.01]


Explication du fonctionnement de la librairie Keyboard

Nous allons étudier la façon dont la librairie keyboard fonctionne, son utilisation pour produire les caractères français ainsi que les problèmes de conversion.

Le clavier est un ensemble de touches, à chaque touche correspond un code 8 bits (scan code) qui n'est pas directement en rapport avec le caractère qui lui est assigné, c'est le système d'exploitation qui va mapper le scan code suivant le type de clavier qui est déclaré dans le système, il peut être d'ailleurs changé en passant par les paramètres. La touche a du clavier français AZERTY dont la disposition correspond à la valeur 'q' du clavier QWERTY a la valeur 0x14 en hexa soit 20 en décimal.

Pour voir l'ensemble des scan codes du clavier QWERTY, cliquer sur ce lien, l'image se trouve en bas de page:
par rapport au clavier AZERTY, l'emplacement de la touche 0x31 fait partie de la touche 'Entrée', par contre l'emplacement de la touche du scan code 0x32 sera pour nous le 0x31 et correspond à la touche '* et µ'.
https://github.com/qlyoung/armory-keyboard

Il existe un document PDF microsoft listant une correspondance HID USB et PS2 où l'on retrouve ces scan codes, suivre la colonne HID Usage ID :
https://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/translate.pdf

La librairie Keyboard n'offre pas la possibilité directement de simuler les touches du clavier par leurs 'scan codes' mais offre une translation par l'alphabet à partir du clavier de référence qui est le QWERTY. On comprend tout de suite les problèmes que l'on va rencontrer, d'une part parce que l'emplacement des caractères n'est pas la même ou diffère demandant l'appui du shift pour la produire et d'autre part le nombre de caractère français est plus important et demande en plus de la commande shift, l'utilisation de la commande Alt Gr pour produire l'ensemble des caractères de notre clavier AZERTY.

Cependant, la lecture du code source de la librairie Keyboard.cpp nous permet de comprendre que l'on peut utiliser les scan codes en ajoutant la valeur 0x88 en hexa ou 136 en décimal.

Voici un exemple de code qui reproduit la frappe des 48 touches imprimables par les scan codes:

Code: [Select]

// ---------------------------------------------------
// nico78
// scancode keyboard qwerty et correspondance azerty
// ---------------------------------------------------
//  Alt Gr azerty                   €                                                                       ~  #  {  [  |  `  \  ^    @  ]  }  ¤      
//   Shift azerty       Q  B  C  D  E  F  G  H  I  J  K  L  ?  N  O  P  A  R  S  T  U  V  Z  X  Y  Z  1  2  3  4  5  6  7  8  9  0    °  +  ¨  £  µ  No fr  M  %  NONE  .  /  §    >
//         azerty       q  b  c  d  e  f  g  h  i  j  k  l  ,  n  o  p  a  r  s  t  u  v  z  x  y  z  &  é  "  '  (  -  è  _  ç  à    )  =  ^  $  *  No fr  m  ù   ²    ;  :  !    <
//         qwerty       a  b  c  d  e  f  g  h  i  j  k  l  m  n  o  p  q  r  s  t  u  v  w  x  y  z  1  2  3  4  5  6  7  8  9  0    -  =  [  ]  \  No US  ;  '   `    ,  .  /   No US      
//       scancode       4, 5, 6, 7, 8, 9, 10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,  45,46,47,48,49,  50,  51,52, 53,  54,55,56,  100};

#include <Keyboard.h>

void setup() {

  // put your setup code here, to run once:
  
  Keyboard.begin();
  delay(5000);

  for (int c=4; c<40; c++){
    keyboardScanCode(c);
  }

  // 50 ou 0x32 n'est pas utilisé sur notre clavier
  for (int c=45; c<50; c++){
    keyboardScanCode(c);
  }

  for (int c=51; c<57; c++){
    keyboardScanCode(c);
  }

  // Scan code pour la touche '< et >'
  keyboardScanCode(100);
  
  Keyboard.end();
}

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

void keyboardScanCode(byte code){
  Keyboard.press(code+136);
  delay(5);
  Keyboard.release(code+136);
}


Pour composer les caractères nécessitant l'appui de la touche shift ou Alt Gr, il faut le programmer tel qu'on le ferait à la main sur le clavier, en voici quelques exemples:

Code: [Select]

// ------------------------------------------------
// nico78
// scancode, exemple de composition de caractères
// ------------------------------------------------
//  Alt Gr azerty                   €                                                                    ~  #  {  [  |  `  \  ^  @    ]  }     ¤      
//   Shift azerty       Q  B  C  D  E  F  G  H  I  J  K  L  ?  N  O  P  A  R  S  T  U  V  Z  X  Y  Z  1  2  3  4  5  6  7  8  9  0    °  +  ¨  £  µ  No fr  M  %  NONE  .  /  §    >
//         azerty       q  b  c  d  e  f  g  h  i  j  k  l  ,  n  o  p  a  r  s  t  u  v  z  x  y  z  &  é  "  '  (  -  è  _  ç  à    )  =  ^  $  *  No fr  m  ù   ²    ;  :  !    <
//         qwerty       a  b  c  d  e  f  g  h  i  j  k  l  m  n  o  p  q  r  s  t  u  v  w  x  y  z  1  2  3  4  5  6  7  8  9  0    -  =  [  ]  \  No US  ;  '   `    ,  .  /   No US      
//       scancode       4, 5, 6, 7, 8, 9, 10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,  45,46,47,48,49,  50,  51,52, 53,  54,55,56,  100};

#include <Keyboard.h>

void setup() {
  // put your setup code here, to run once:
  
  Keyboard.begin();
  delay(5000);

  // Pour composer le A majuscule"
  Keyboard.press(KEY_LEFT_SHIFT);
  keyboardScanCode(20); // ou keyboard.print('q');
  Keyboard.release(KEY_LEFT_SHIFT);

  // Pour composer le caractère @
  // Alt Gr = Ctrl + Alt
  Keyboard.press(KEY_LEFT_CTRL);
  Keyboard.press(KEY_LEFT_ALT);
  keyboardScanCode(39); // ou keyboard.print('0');
  Keyboard.release(KEY_LEFT_ALT);
  Keyboard.release(KEY_LEFT_CTRL);  

  // Pour composer le caractère ê
  // nécessite deux séquences de touches, l'appui sur la touche ^ (0x2F)(dead key)
  // puis ensuite la touche e (0x08)
  keyboardScanCode(47);
  keyboardScanCode(8); // ou keyboard.print('e');

  
  Keyboard.end();
}

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

}

void keyboardScanCode(byte code){
  Keyboard.press(code+136);
  delay(5);
  Keyboard.release(code+136);
}

nico78

Nous avons vu comment accéder aux touches du clavier, concernant les caractères imprimables; maintenant voyons comment utiliser les touches de commandes.

Le site Arduino les listent sur leur site, ils sont appelés 'Keyboard Modifiers', consultable ici:
https://www.arduino.cc/en/Reference/KeyboardModifiers

En fait si vous regardez bien, on comprend que les valeurs supérieures à 0x87 ne sont pas les valeurs réelles, il a été ajouté la valeur 0x88 à la valeur réelle comme nous l'avons vu précédemment. C'est le codage utilisé dans le fichier Keyboard.cpp qui l'impose.

Par exemple, la touche BackSpace (retour arrière) à la valeur réelle 0x2A hexa ou 42 en décimal, si on lui ajoute la valeur 0x88, on obtient 0xB2, soit bien la valeur déclarée dans les fichiers de la librairie.

Les valeurs allant de 0x80 à 0x87 ne sont pas non plus les valeurs réelles mais cela n'aura pas d'impact pour nous. On pourra utiliser toutes ces valeurs sans difficulté.


Réalisation d'un clavier:

Si l'on désire concevoir un clavier avec un montage arduino, choses que je n'ai pas réalisé, il faudra faire attention à l'utilisation des matrices qui ne permettent pas d'exploiter deux appuis sur deux touches en même temps. Il sera alors nécessaire de séparer certaines touches des autres dans la gestion du code comme les deads key ^ , ¨ , ~ , ` le shift et le Ctrl + Alt

Concernant le clavier numérique, on pourra aussi le simuler; encore une fois toutes les valeurs sont listées dans le document microsoft téléchargeable dans le premier post.

Ainsi le chiffre 1 du clavier numérique a le scan code 0x59, il faudra ajouter 0x88, ce qui donne 0xE1 en hexa ou 225 en décimal.



Ecrire du texte à la volée:

Pour écrire du texte à la volée, il faut soit modifier le code de la librairie soit créer un code de conversion.

Il existe une librairie KeyboardAzertyFr qui permet d'écrire une partie des caractères français disponible, on ne pourra pas écrire les caractères avec accents, les dead keys (combinaison de deux séquences de touche) et les caractères accessibles par Alt Gr; mais je pense qu'elle pourra suffire si l'on souhaite exécuter des scripts, le lien ici:
https://github.com/martin-leo/KeyboardAzertyFr

L'installation de cette librairie pourra sembler ne pas fonctionner, en fait ça dépendra si on a dèjà compiler ou pas le même code avant cette librairie. J'ai dû faire des suppressions à la main, je ne le met pas ici car je ne suis plus très sûr de ce que j'ai fais. De mémoire dans le dossier arduino de 'mes document's et dans les fichiers de compilation temporaires, le chemin s'affiche en bas lors de la compilation.


Pourquoi la conversion de tous les caractères français n'existent pas encore?

D'abord, elle existe maintenant puisque je l'ai moi-même réalisé mais ce n'est pas une librairie; c'est la raison pour laquelle je fais ce tuto. Le code de conversion sera disponible dans les prochains posts. J'aurais évidemment voulu contribué à la librairie KeyboardAzertyFr, mais mes connaissances en codage en c pure sont limités, de plus avec le problème des caractères que nous allons abordé, je ne voyais pas de solution simple à part utiliser des tableaux sur deux octets au lieu de 1 octet actuellement mais ça risque de consommer énormément de mémoire.

Le problème que j'ai rencontré, c'est que les chaînes de caractères sont codées en UTF-8, ainsi l'ensemble de nos caractères français ne tient pas sur un octet pour tous, il en faut parfois 2 (asccii supérieur à 127), voire trois pour le caractère €. Donc traité des caractères qui n'occupent pas le même espace devient nettement plus ardu pour une conversion et devient un problème pour modifier la librairie Keyboard. Aussi si vous utilisez des Teensyduino, et que vous avez installé l'exécutable qui met en place les fichiers, celui-ci supprime la librairie de son emplacement.

Cela dit, il faut savoir que sur le site d'Arduino, des codes de conversions UTF-8 ascii étendu existent, ce qui pourrait simplifier la création d'une nouvelle librairie au moins pour nous, à voir ici:
https://playground.arduino.cc/Main/Utf8ascii

J'ai donc entrepris la création d'une conversion qui je l'espère permettra aussi d'adapter le code à d'autres langages que le français.

Vu l'heure tardive, je posterais l'ensemble du code qui nécessitera deux posts demain, cela me permettra de procéder à une dernière vérification.

nico78

Notification des leds du clavier (CAPS LOCK, NUM LOCK, SCROLL LOCK)
Comme vous le savez, lorsque vous appuyer sur Verr Maj (verrouillage des majuscules), une led s'affiche sur votre clavier et cela ne va pas seulement affecter votre clavier sur lequel la touche a été activée mais les autres périphériques claviers aussi. (l'emploi de plusieurs claviers ne posant pas de problème pour l'OS). Le système d'exploitation va notifier systématiquement les autres périphériques concernés de l'état de ces touches. Ainsi si Verr Maj est activé sur un clavier, l'autre sera automatiquement en verrouillage des majuscules, les miniscules se transformeront en majuscules etc...

Il devient alors nécessaire si on souhaite envoyer des chaînes de caractères de s'assurer notamment que la touche Verr Maj n'est pas activée, voire aussi pour NUM LOCK et SCROLL LOCK.

Par chance, sur le forum arduino, une personne a fourni l'ensemble des fichiers à remplacer. J'ai testé ces fichiers et cela a bien fonctionné.

Je vous donne le lien où j'ai puisé l'information:
https://forum.arduino.cc/index.php?topic=173583.15

nico78

En téléversant le code de conversion avec le test inclus, notepad va s'exécuter et tous les caractères du clavier vont s'afficher avec en plus l'exécution d'un copier-coller à la fin comme le montre le gif ci-dessous.





jfs

Héberge ton gif ailleurs que sur google.... là ça marche pas.
Pas d'aide par MP !!!

Concernant le fonctionnement du forum tout se trouve dans les messages épinglés en tête de page.

nico78

Mise à jour V1.01, correction et amélioration du code, voici la liste des fonctions:

// sendtext("abcd...") --> pour envoyer du texte (longueur maxi 254 caractères à la fois)
// sendtextln("abcd...") --> pareil avec retour chariot (longueur maxi 254 caractères à la fois)
// sendkeypad(0123456789/*-+E) pour simuler le clavier numérique, E pour la touche Entrée
// altunicode("0169"); 2 à 4 chiffres en argument pour afficher d'autres caractères unicodes dans les éditeurs qui les acceptent
// ÇÉÈ æ œ øØ ↨↑↓→←↔ ►◄▲▼ ☺☻ ♥♦♣♠ ♂♀ ♪♫ ☼ "" ™©® --> caractères spéciaux que l'on peut utiliser directement (utilise altunicode automatiquement)
// sendkeycombi(KEY_LEFT_GUI, 'r') permet de taper deux touches en même temps (une touche system + une touche ascii), ici 'window + r'
// selectall() permet de sélectionner tout le texte
// cut() pour couper du texte
// copy() pour copier du texte
// paste() pour coller du texte
// homekey() pour déplacer le curseur vers le début du texte lors d'une sélection
// endkey() pour déplacer le curseur vers la fin du texte lors d'une sélection
// leftkey(nb) déplace le curseur vers la gauche (nb = nombre de fois)
// rightkey(nb) déplace le curseur vers la droite (nb = nombre de fois)
// upkey(nb) déplace le curseur vers le haut (nb = nombre de fois)
// downkey(nb) déplace le curseur vers le bas (nb = nombre de fois)
// tabkey(nb) permet de faire une tabulation (nb = nombre de fois)
// returnkey(nb) permet de revenir à la ligne (nb = nombre de fois)
// backspacekey(nb) touche Retour Arrière du clavier (nb = nombre de fois)
// deletekey(nb) touche Suppr du clavier (nb = nombre de fois)
// sendkeycommand(command) permet d'envoyer des commandes qui ne sont pas utiliser dans les fonctions précédentes comme
// KEY_ESC , KEY_INSERT , KEY_PAGE_UP , KEY_PAGE_DOWN , KEY_CAPS_LOCK

bengibbs

Super post qui est très intéressant pour mon projet actuel... même si a 90% mon projet fonctionne comme je voudrais, je bute toujours sur un problème, émuler la touche espace, qui correspond à u  raccourci clavier dans un logiciel que j'utilise, et que je ne peu pas modifier .....si tu as une piste que je pourrais suivre je te remercie d'avance !

Go Up