Implementacja kodu Morse’a (Arduino + dioda + buzzer)
Wstęp – czym jest kod Morse’a?
Kod 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

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:

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.

Filmik pokazujący pracujący układ:
Źródła i przydatne linki
autor: Bartek Poniatyszyn
Artykuł zgłoszony do konkursu świątecznego