Implementacja kodu Morse’a (Arduino + dioda + buzzer)

Wstęp – czym jest kod Morse’a?
sos-wikiKod Morse’a to sposób reprezentacji alfabetu, cyfr i znaków z wykorzystaniem impulsów elektrycznych, światła, dźwięku lub dwóch znaków: kropki i kreski. Pierwotnie stworzono go z zamiarem wykorzystania w telegrafach elektronicznych, jednak swoje największe zastosowanie znalazł w telekomunikacji radiowej. Obecnie wykorzystywany jest głównie przez krótkofalowców. Dlaczego zatem warto się z nim zapoznać? Chociażby dlatego, że możemy nim nadawać przy użyciu prymitywnych środków takich jak mruganie latarką czy dowolne źródło dźwięku. Historia pokazała, że jego zastosowanie uratowało już niejedno ludzkie istnienie.

Zasady nadawania

Wszystkie znaki reprezentowane są przez kilkuelementowe serie sygnałów – krótkich (kropek) i długich (kresek). Kreska powinna trwać co najmniej tyle czasu, co trzy kropki. Odstęp pomiędzy elementami znaku powinien trwać jedną kropkę. Odstęp pomiędzy poszczególnymi znakami – trzy kropki. Odstęp pomiędzy grupami znaków – siedem kropek.”

~Wikipedia

1206_7219_big.gif
Kod Morse’a – alfabet

Potrzebny sprzęt

Do wykonania projektu będziemy potrzebować następujących części:

  • dowolna płytka Arduino (z mojej strony polecam Leonardo, Uno lub jakikolwiek nowszy model),

  • płytka stykowa (wystarczy 170 pól, jednak ja polecam jak największą – przyda się na przyszłość do bardziej rozbudowanych projektów) lub płytka uniwersalna, jeśli ktoś ma ochotę stworzyć układ na stałe,

  • buzzer z generatorem,

  • czerwona dioda led 5mm,

  • dwa rezystory 220R/0,25W/5%,

  • mikroprzycisk tact switch 7,8mm,

  • kolorowe kabelki męsko-męskie do połączeń pomiędzy wspomnianymi wyżej komponentami.

 

Nadawanie przyciskiem

Ten sposób implementacji kodu Morse’a pozwoli nam na spróbowanie swoich sił w ręcznym nadawaniu komunikatów. Zapewniam, że po chwili treningu można nabrać wprawy i wysyłać coraz to trudniejsze wiadomości. Zabawa jest jeszcze lepsza, jeżeli towarzyszy nam ktoś, kto potrafi rozszyfrować nadane przez nas komunikaty.

Zacznijmy od schematów:

Zmontowanie takiego układu nie jest trudne. Dla ułatwienia dołączę na koniec wpisu pliki projektu z programu Fritzing. Kiedy mamy już gotowy sprzęt, możemy przejść do programowania.

const int buttonPin = 11; //numer pinu przycisku
const int buzzerPin = 12; //numer pinu buzzer'a
const int ledPin = 13; //numer pinu diody led
const int buzzerToneFrequency = 5000; //częstotliwość "bzyczenia"

int buttonState = LOW; //stan przycisku(wciśnięty/nie wciśnięty)

void setup() {  
  pinMode(ledPin, OUTPUT);  //ustawiam pin diody led na wysyłanie 
  pinMode(buzzerPin, OUTPUT); //ustawiam pin buzzer'a na wysyłanie 
  pinMode(buttonPin, INPUT);  //ustawiam pin przycisku na odbieranie
}

void loop() {  
  buttonState = digitalRead(buttonPin); //wczytuję stan przycisku

  if (buttonState == HIGH) {  //jeśli przycisk jest wciśnięty
    tone(buzzerPin, buzzerToneFrequency); //włączam "bzyczenie" na określonej częstotliwości aż do odwołania     
    digitalWrite(ledPin, HIGH); //zapalam diodę led
  } 
  else { //jeśli nie jest wciśnięty
    noTone(buzzerPin);  //wyłączam bzyczenie
    digitalWrite(ledPin, LOW); //gaszę diodę led
  }
}

Myślę, że moje komentarze dołączone do kodu rozwieją wszelkie wątpliwości, w przeciwnym razie zapraszam do kontaktu.

Nadawanie przez port szeregowy

Jeśli chodzi o schemat podłączenia komponentów, to jest on taki sam jak poprzedni, oczywiście z pominięciem przycisku, ponieważ tutaj będziemy nadawać przez port szeregowy otworzony w komputerze. Aby z niego skorzystać możemy posłużyć się wbudowanym w Arduino IDE monitorem szeregowym lub skorzystać z programu Putty. Kod prezentuje się następująco:

const int buzzerPin = 12; //numer pinu buzzer'a
const int ledPin = 13; //numer pinu diody led
const int buzzerToneFrequency = 5000; //częstotliwość "bzyczenia"
const int dotLength = 100; //długość trwania kropki w milisekundach

char readChar = ' '; //wczytany znak

const char charTable[37] = { //tablica z literami i cyframi
  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
  'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'w', 'v', 'x', 'y', 'z',
  '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'
};

const char capitalLetter[27] = { //tablica dużych liter, pozycje w tablicy analogiczne do małych liter
  'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
  'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'W', 'V', 'X', 'Y', 'Z'
};

const short morseTable[37][7] = { //dwuwymiarowa tablica, pierwszy wymiar odpowiada za dany znak z tablicy liter i cyfr, 
                                  //a drugi zawiera przetworzony ciąg kropek i kresek - zrozumiały w kodzie morse'a.
  //0 - dot, 1 - dash, 2 - end //jako kropkę oznaczamy 0, kreska to 1, a koniec ciągu to 2
  {0, 1, 2},//a
  {1, 0, 0, 0, 2},//b
  {1, 0, 1, 0, 2},//c
  {1, 0, 0, 2},//f
  {0, 2},//e
  {0, 0, 1, 0, 2},//f
  {1, 0, 0, 2},//g
  {0, 0, 0, 0, 2},//h
  {0, 0, 2},//i
  {0, 1, 1, 1, 2},//j
  {1, 0, 1, 2},//k
  {0, 1, 0, 0, 2},//l
  {1, 1, 2},//m
  {1, 0, 2},//n
  {1, 1, 1, 2},//o
  {0, 1, 1, 0, 2},//p
  {1, 1, 0, 1, 2},//q
  {0, 1, 0, 2},//r
  {0, 0, 0, 2},//s
  {1, 2},//t
  {0, 0, 1, 2},//u
  {0, 1, 1, 2},//w
  {0, 0, 0, 1, 2},//v
  {1, 0, 0, 1, 2},//x
  {1, 0, 1, 2},//y
  {1, 1, 0, 0, 2},//z
  {0, 1, 1, 1, 1, 2},//1
  {0, 0, 1, 1, 1, 2},//2
  {0, 0, 0, 1, 1, 2},//3
  {0, 0, 0, 0, 1, 2},//4
  {0, 0, 0, 0, 0, 2},//5
  {1, 0, 0, 0, 0, 2},//6
  {1, 1, 0, 0, 0, 2},//7
  {1, 1, 1, 0, 0, 2},//8
  {1, 1, 1, 1, 0, 2},//9
  {1, 1, 1, 1, 1, 2}//0
  //0 - dot, 1 - dash, 2 - end
};

void setup() {
  
  Serial.begin(9600); //ustanawia komunikację przez port szeregowy z prędkością 9600 bitów na sekundę
  while (!Serial); //oczekuje na połączenie, bez niego nie można się komunikować z komputerem
  Serial.println("Hello! Type character(s):"); //wyświetla komunikat startowy
  
  pinMode(ledPin, OUTPUT); //ustawia pin buzzer'a na wysyłanie
  pinMode(buzzerPin, OUTPUT); //ustawia pin diody led na wysyłanie

  digitalWrite(ledPin, LOW); //profilaktycznie ustawia diodę led jako wygaszoną
  digitalWrite(buzzerPin, LOW); //podobnie z buzzer'em
}

void loop() {
  
  if (Serial.available() > 0) { //jeśli otrzyma dane
    
    readChar = Serial.read(); //zapisuje wczytany znak

    Serial.print("Load character '"); //wyświetla komunikat
    Serial.print(readChar); //z wczytanym znakiem
    Serial.print("'");
    for (int i = 0; i < 27; i++) { //iteruje po 26 elementach, tyle ile ma tablica z wielkimi literami 
      
      if (readChar == capitalLetter[i]) { //sprawdza, czy wczytana litera jest dużą
        readChar = charTable[i]; //zmienia na małą literę
      }
    }

    for (int i = 0; i < 37; i++) { //iteruje po tablicy z literami i cyframi
      
      if (readChar == charTable[i]) { //jeśli wczytany znak odpowiada temu spośród liter i cyfr
        Serial.print(", sending { "); //wysyla komunikat
        
        for (int j = 0; j < 6; j++) { //6, ponieważ tyle maksymalnie znaków(kropek, kresek i zakończeń) moze miec przypisane litera lub liczba
          
          if (morseTable[i][j] == 0) { //jeśli napotka na 0, to zgodnie z ustaleniem jest to kropka
            playDot(); //nadaję kropkę
            Serial.print(". ");
          }
          else if (morseTable[i][j] == 1) { //jeśli napotka na 1, to zgodnie z ustaleniem jest to kreska
            playDash(); //nadaję kreskę
            Serial.print("- ");
          }
          else { //w innym przypadku musi to być 2, czyli koniec ciągu
            pauseChar(); //nadaje przerwę między znakami zgodną z zasadami nadawania kodem morse'a
            Serial.println(" } done.");
            break; //przerywa tą pętlę i wychodzi poziom wyżej
          }
        }        
        break;
      }
    }    
  }
}

void playDot() { //funkcja do nadawania kropki przy pomocy buzzera i diody led
  
  digitalWrite(ledPin, HIGH);  //zapala diodę led
  tone(buzzerPin, buzzerToneFrequency, dotLength); //włącza "bzyczenie" na określonej częstotliwości i na dany czas
  delay(dotLength); //oczekuje zgodnie z zasadami nadawania
  digitalWrite(ledPin, LOW); //gasi diodę led
  //digitalWrite(buzzerPin, LOW);
  noTone(buzzerPin); //wyłącza bzyczenie
  delay(dotLength); //oczekuje zgodnie z zasadami nadawania
}

void playDash() { //funkcja do nadawania kreski przy pomocy buzzera i diody led
  
  digitalWrite(ledPin, HIGH);  //zapalam diodę led
  tone(buzzerPin, buzzerToneFrequency, dotLength * 3); //włącza "bzyczenie" na określonej częstotliwości i dany czas
  delay(dotLength * 3); //oczekuje zgodnie z zasadami nadawania
  digitalWrite(ledPin, LOW); //gasi diodę led
  //digitalWrite(buzzerPin, LOW);
  noTone(buzzerPin); //wyłącza bzyczenie
  delay(dotLength); //oczekuje zgodnie z zasadami nadawania
}

void pauseChar() { //funkcja wymuszajaca przerwę w nadawaniu pomiędzy znakami
  
  delay(dotLength * 2); //oczekuje zgodnie z zasadami nadawania
}

void pauseWord() { //funkcja wymuszajaca przerwę w nadawaniu pomiędzy wyrazami
  
  delay(dotLength * 6); //oczekuje zgodnie z zasadami nadawania
}

Tutaj również komentarze są obszerne, dlatego nie ma potrzeby dodatkowych wyjaśnień. A oto efekt, który uzyskamy, po wgraniu powyższego programu:

2015-12-31 00_49_42-COM8 (Arduino Leonardo)
Efekt wgrania programu

Podsumowanie

Mam nadzieję, że w miarę przystępny sposób przedstawiłem moją implementację kodu Morse’a przy użyciu Arduino, buzzer’a i diody led. Zachęcam do testów i wprowadzania modyfikacji, a także dyskusji nad omówionym w tym wpisie zagadnieniem. Na koniec przedstawiam zdjęcie gotowego projektu i krótki filmik z działania.

Gotowy złożony układ
Gotowy złożony układ


Filmik pokazujący pracujący układ:

Źródła i przydatne linki

autor: Bartek Poniatyszyn


Artykuł zgłoszony do konkursu świątecznego

Sponsorem nagród jest firma Kamami oraz Hybrid Lizard:

kamami-1421338058

hl_mb

Karol Wojsław

Karol Wojsław -- licealista, założyciel i redaktor Mechatrobot.pl. Interesuje się robotyką i elektroniką oraz informatyką. Z racji swojego wieku nie ma ogromnej wiedzy, ale wytrwale dąży do tego, aby artykuły, które publikuje były coraz lepsze.