Decodifica codice Morse via software

29 04 2013

In questo periodo in cui tutto è digitale ci è sembrato interessante rispolverare un vecchio tasto morse. A prima vista potrebbe sembrare anacronistico ma in realtà se pensiamo all’alfabeto morse non come una sequenza di punti e linee ma come una sequenza di 0 e 1 ci rendiamo conto che forse quella di Samuel Morse è stata la prima trasmissione digitale della storia.

Un vecchio tasto Morse comprato ad una fiera collegato tra i piedini A0 e massa sono sufficienti per realizzare la decodifica dell'alfabeto Morse

Un vecchio tasto Morse comprato ad una fiera collegato tra i piedini A0 e GND sono sufficienti per realizzare la decodifica dell’alfabeto Morse. Volendo è possibile collegare un piccolo altoparlante tra il piedino 11 e GND per poter ascoltare i toni generati.

Abbiamo quindi riadattato un lavoro scritto in “C” da Budd Churchward WB7FHC in modo da farlo funzionare anche con il nostro hardware. Si tratta di un software molto interessante perché adatta la decodifica alla velocità del radiotelegrafista. Questo progetto utilizza la nostra LCD Shield per il suo funzionamento.

Codice Morse internazionale.

Codice Morse internazionale. Una linea dura quanto 3 punti e la distanza tra i punti e le linee è lunga un punto. Tra una lettera e un’altra c’è una “distanza” di 3 punti. Tra le parole invece è di 5 punti. *Parentesi e sottolineature vanno trasmesse prima e dopo.

/* Decodificatore LCD di codice morse
   riadattamento di Luca IW3HME di un lavoro di
   (c) 2011, Budd Churchward - WB7FHC  
*/

int myKey=14;    // Pulsante collegato su A0 (pull-up 2k2)
int speaker=11;  // Altoparlante
int val=0;                   // A value for key up and down
int myTone=440;              // Frequency of our tone
boolean ditOrDah=true;       // We have a full dit or a full dah
int dit=100;                 // If we loop less than this with keydown it's a dit else a dah
int averageDah=150;          // Start with this value we will adjusted it each time he sends a dah
boolean characterDone=true;  // A full character has been sent
int myBounce=2;              // Handles normal keybounce but we needed to do more later
int downTime=0;              // We are going to count the cycles we loop while key is down
long FullWait=10000;     // This value will be set by the sender's speed - the gap between letters
long WaitWait=FullWait;  // WaitWait is for the gap between dits and dahs
long newWord=0;          // For the gap between words
int nearLineEnd=10;      // How far do you want to type across your monitor window?
int letterCount=0;       // To keep track of how many characters have been printed on the line
int myNum=0;  // We will turn the dits and dahs into a data stream and parse
              // a value that we will store here

// The place a letter appears here matches the value we parse out of the code
char mySet[] ="##TEMNAIOGKDWRUS##QZYCXBJP#L#FVH09#8###7#######61#######2###3#45";

#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
const int backlight = 10;

void setup() {
  pinMode(myKey, INPUT);
  pinMode(speaker,OUTPUT);
  pinMode(backlight, OUTPUT);
  digitalWrite(backlight, HIGH); //Accende lo schermo
  lcd.begin(16,2);
  lcd.print("Morse ready");
   lcd.setCursor(0,1); //Riga 1
}

 void loop() {
   val=digitalRead(myKey);   // Is it up or is it down?
   if (!val) keyIsDown();    // Any value here means it is down.
   if (val) keyIsUp();       // Should be 0 when it is up.
}

 void keyIsDown() {
   tone(speaker,myTone);  // Turn on the sound
   WaitWait=FullWait;     // Reset our Key Up countdown
   downTime++;            //Count how long the key is down

  if (myNum==0) {       // myNum will equal zero at the beginning of a character
      myNum=1;          // This is our start bit  - it only does this once per letter
    }

  characterDone=false;  // we aren't finished with the character yet, there could be more
  ditOrDah=false;       // we don't know what it is yet - key is still down
  delay(myBounce);      // short delay to keep the real world in synch with Arduino
 }

 void keyIsUp() {
  noTone(speaker);     // Turn off the sound
  if (newWord>0) newWord--;     // Counting down to spot gap between words
  if (newWord==1) printSpace(); // Found the gap, print a space but only once next time it will be 0
  if (!ditOrDah) {              // We don't know if it was a dit or a dah yet, so ...
      shiftBits();              // let's go find out! And do our Magic with the bits
    }

  if (!characterDone) {
      WaitWait--;               // We are counting down 
      if (WaitWait==0) {        // Bingo, keyUp just timed out! A full letter has been sent
        WaitWait=FullWait;      // Reset our  keyUp counter
        printCharacter();       // Go figure out what character it was and print it  
        characterDone=true;     // We got him, we're done here
        myNum=0;                // This sets us up for getting the next start bit
      }
      downTime=0;               // Reset our keyDown counter
   }
}

void printSpace() {
  letterCount++;                  // we're counting the number of characters on the line  
  if (letterCount>nearLineEnd) {  // when we get past our threshold we do this:
    lcd.setCursor(0,1); //Riga 2
    letterCount=0;                // reset our character counter
    return;                       // Go back to loop(), we're done here.
  }  
   lcd.print(" ");
}

void printCharacter() {           
  FullWait=averageDah*100;        // the keyUp counter gets reset based on sender's speed
  newWord=FullWait*5;             // word gap counter is also adjusted by sender's speed
  letterCount++;                  // we're counting the number of characters on the line
  if (myNum>63) {  
    printPunctuation();           // The value we parsed is bigger than our character array
                                  // It is probably a punctuation mark so go figure it out.
   return;                       // Go back to the main loop(), we're done here.
  }
  lcd.print(mySet[myNum]); 
}

void printPunctuation() {
  byte pMark='#'; // Just in case nothing matches
  if (myNum==71) pMark=':';
  if (myNum==76) pMark=',';
  if (myNum==84) pMark='!';
  if (myNum==94) pMark='-';
  if (myNum==101) pMark='@';
  if (myNum==106) pMark='.';
  if (myNum==115) pMark='?';
  lcd.print(pMark);
}

void shiftBits() {
  ditOrDah=true;        // we will know which one in two lines
  if (downTime<dit/3) return;  // ignore my keybounce
  if (downTime<dit) {
    // We got a dit
    myNum = myNum << 1;  // shift bits left
    myNum++;             // add one because it is a dit
  }
  else {
    // We got a dah
    myNum = myNum << 1; // shift bits left

    // The next three lines handle the automatic speed adjustment:
    averageDah=(downTime+averageDah)/2;  // running average of dahs
    dit=averageDah/3;                    // normal dit would be this
    dit=dit*2;                           // double it to get the threshold between dits and dahs
  }
}

Azioni

Information

6 responses

5 02 2014
fedro

ma come avete fatto ad adattare la decodifica alla velocità del radiotelegrafista ??

9 02 2014
cfpmanfredini

Ciao Fedro,
la decodifica del codice Morse viene adattata alla velocità del radiotelegrafista grazie a 3 righe di codice. Sono le ultime 3 righe del programma, quelle che iniziano con “averageDah=”. Ovviamente per una corretta decodifica bisogna scrivere alcuni caratteri in modo che il software “impari” la nostra velocità. Ecco che i caratteri inizialmente verranno decodificati in modo errato, ma poi, se manteniamo la velocità di battitura costante, verranno interpretati correttamente.

10 03 2014
big bang

My partner and i really enjoy, result in I came across what precisely I was interested in. You have was over my own four day prolonged search! Goodness Thank you man. Use a terrific time. L8rs

7 02 2016
Alessandro Riva

Fantastico!!! l’ho provato e va benissimo… Un solo problemino, ho dovto scambiare KeyIsUp e KeyIsDown alle linee 42 e 43 del programma, altrimenti il buzzer continuava a suonare e si interrompeva quando premevo il tasto… è un problema di tasto? Io me lo sono autocostruito, quando è premuto c’è pasaggio di corrente, quando è rilasciato no… l’ho fatto al contrario? Nel caso mi basta cambiare un collegamentino…

4 07 2016
xiao

Ho provato questo programma e funziona perfettamente ma non riesco ad inserire i segni di punteggiatura. Come mai?

4 07 2016
gigi

Problema con i segni di punteggiatura.

Lascia un commento