Mallory Coeur -

Décoder du morse avec un arduino

L’alphabet morse ou code morse, est un code permettant de transmettre un texte à l’aide de séries d’impulsions courtes et longues, qu’elles soient produites par des signes, une lumière ou un geste.
- Wikipedia

Origines du projet
Partie 1 - Montage électronique
Partie 2 - Programmation

Origines du projet

Qu'est-ce qui peut bien pousser un être humain normal à avoir besoin de comprendre du code morse ?
Dans mon cas, tout vient de l'excellent jeu Keep Talking and Nobody Explodes, dans lequel vous devez résoudre de nombreux puzzles. L'un d'entre eux requiert de comprendre un mot en morse.
Bien entendu, un "dictionnaire" morse est fourni, mais il ne m'aura pas fallu longtemps avant de vouloir automatiser tout ça.

La première solution était simplement un programme de quelques lignes en NodeJs, mais pour ne pas complètement casser l'immersion du jeu, j'ai choisi d'en faire un objet physique.

Partie 1 - Montage électronique

Toutes les pièces nécessaires au montage de ce projet étaient présentes dans le starter kit Arduino, que j'utilise depuis le début de mon aventure dans l'électronique.
Aucune soudure n'est nécessaire pour le prototype que nous faisons sur une breadboard.

La principale difficulté de ce projet est le montage de l'écran LCD. S'il nécessite un bon paquet de fils, il ne présente pas d'obstacle, pourvu qu'on y prête un minimum d'attention.

Les paragraphes suivants décrivent en détail le montage et la fonction de chaque fil. Je vous recommande vivement de vous y intéresser pour comprendre ce que vous faites.
Dans tous les cas, je mettrai plus bas un schéma de montage récapitulant le tout.

Le câblage de l'écran peut être décomposé en trois catégories.

L'alimentation :
Toute l'alimentation de l'écran sera effectuée en 5V. On utilisera donc les deux lignes supérieures de notre breadboard pour apporter le courant.
L'alimentation principale de l'écran se fait via les pins #1 et #2. On relie donc le pin #1 au GND, et le pin #2 au V+.
Le rétroéclairage de l'écran nécessite une alimentation séparée, via les pins #15 et #16.
Cette alimentation a besoin d'être protégée. Certains LCD disposent d'une résistance intégrée. N'étant pas certain que ce soit le cas du mien, j'ai joué la sécurité et utilisé une résistance de 230Ω. On relie donc le pin #15 au V+ (avec la résistance) et le pin #16 au GND.
Le pin #3 du LCD permet de régler le contraste. Il sera au minimum en y appliquant 5V, et au minimum lorsqu'il est relié au GND. Dans un montage propre, il serait malin d'utiliser un potentiomètre afin de pouvoir le régler. J'ai choisi un montage plus simple en reliant ce pin au GND afin d'avoir toujours le contraste maximum.

Les pins de contrôle :
Les choses sérieuses commencent. Les pins suivants servent à communiquer avec l'écran. On commence donc à les relier au Arduino.

Les pins de données :
Maintenant que notre LCD est alimenté et qu'il est capable de suivre nos instructions, il faut être en mesure de lui envoyer des informations à afficher. Ces informations sont envoyées sur les pins #11 à #14 du LCD. On les relie respectivement aux pins #9 à #12 du Arduino.

C'est tout pour l'écran !

Il ne reste plus qu'à ajouter un bouton pour avoir un prototype fonctionnel.
Reliez un pin au GND, l'autre au V+ avec une résistance 10kΩ et reliez le tout au Arduino. J'ai choisi d'utiliser le pin #13 pour avoir un retour visuel grâce à la LED intégrée.

Une fois le montage terminé, vous devriez obtenir quelque chose comme ça :

Schema de montage arduino

Dans la vraie vie, en faisant ce qu'on peut niveau câbles, ça ressemble plutôt à ça :

Photo du montage arduino

Partie 2 - Programmation

L'essentiel du code est axé sur deux principes :

Les tableaux permettront de faire la correspondance entre le code morse et l'alphabet.
Par exemple, si je cherche à décoder le code morse ".-.." (un signal court, puis un long, puis deux courts), je peux chercher cette occurrence dans le tableau en morse.
Je trouve ce code à la douzième position de mon tableau en morse, je peux donc en conclure qu'il s'agit de la douzième lettre de l'alphabet : le L.

Pour contrôler le LCD, j'utilise la bibliothèque LiquidCrystal.
Il suffit d'instancier le LCD en spécifiant les pins utilisées sur le arduino, puis la taille de l'écran (en digits - dans notre cas, 16x2).

Voici le code complet (voir sur github) :

/*
 * Arduino morse code decoder
 * Build instructions (french) : https://www.mallorycoeur.com/posts/decoder-du-morse-avec-un-arduino.html
 * Mallory COEUR - 2016
 */

#include <LiquidCrystal.h>

LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
int input;
int tick = 10; // ms
int state;
String dictionnary[] = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--.."};
char alphabet[27] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
String morse = "";
String translation = "";

void setup() {
  lcd.begin(16, 2);
  pinMode(13, INPUT); // button
}

void loop() {
  input = digitalRead(13);

  if (input == HIGH) {
    if (state <= 0)
      state = 0;
    state++;
  }
  else if (input == LOW) {
    if (state > 0) {
      if (state > 10)
        morse += "-";
      else
        morse += ".";
      state = 0;
    }
    state--;
  }

  if (state <= -30 && morse != "")
  {
      translation += findInDictionnary(morse);
      morse = "";
      writeLine(0, "                ");
      writeLine(1, "                ");
  }

  writeLine(0, translation);
  writeLine(1, morse);
  delay(tick);
}

char findInDictionnary(String word) {
  for(int i = 0; i < 26; i++)
  {
    if (dictionnary[i] == word)
      return alphabet[i];
  }
  return false;
}

void writeLine(int line, String text)
{
  lcd.setCursor(0, line);
  lcd.print(text);
}