Wydział Informatyki i Nauki o Materiałach, Uniwersytet Śląski Jakub Biliński, TPD, semestr letni Sprawozdanie Projekt dekodera Morse a z wykorzystaniem mikrokontrolera na przedmiot Systemy Wbudowane.
1. Założenia Założeniem projektu było zbudowanie dekodera kodu Morse a z użyciem: - mikrokontrolera AVR - ATmega328P-PU będzie on główną jednostką obliczeniową i będzie się zajmował wszystkimi zadaniami logicznymi w projekcie; - gniazdo micro-usb będzie ono służyło jako złącze do podłączenia zasilania do urządzenia; - Wyśwetlacz LCD (16x2) najpopularniejszy model wyświetlacza, który to będzie wyświetlał zdekodowane frazy; - oraz inne elementy pasywne; Dzięki zastosowaniu takich komponentów będzie możliwe zbudowanie tego projektu w stosunkowo krótkim czasie oraz będzie on dosyć tani w budowie. Dodatkowo urządzenie będzie programowane z wykorzystaniem Arduino IDE, ponieważ jest to na obecną chwilę najwygodniejsza metoda programowania mikrokontrolerów, a do tego gniazdo micro-usb jest bardzo użyteczne, ponieważ w dzisiejszych czasach przyjęło się ono za standard we wszystkich małych urządzeniach. Dzięki temu, będzie można tą płytkę uruchomić bez dodatkowych zasilaczy, czy baterii. Zawsze gdzieś w pobliżu znajduje się ładowarka tego typu, co dodaje temu urządzeniu niezwykłą uniwersalność i łatwość obsługi.
2. Projektowanie teoretyczne Projekt na początku został przygotowany teoretycznie. Poniżej znajduje się schemat urządzenia.
Na podstawie tego schematu przygotowałem projekt na płytkę prototypową. Rysunek również znajduje się poniżej.
Dzięki zastosowaniu programu Fritzing udało mi wygenerować płytkę PCB. Niestety wykonanie jednowarstwowej płytki PCB było niemożliwe ze względu na dużą ilość połączeń, dlatego schemat przedstawia płytkę PCB, która jest zaprojektowana w technologii dwustronnej.
3. Testowanie projektu na płytce uniwersalnej Jak wiadomo projekt nie zawsze musi działać. Dlatego właśnie przed przystąpieniem do dalszej pracy postanowiłem zweryfikować projekt i zbudować go na płytce uniwersalnej. Niestety w trakcie budowy miałem problem z plątaniną przewodów i przełącznik krańcowy WK320 musiał zostać przeniesiony w innej miejsce, podobnie jak rezonator kwarcowy.
Po takim podłączeniu jak na poprzednim rysunku udało się uruchomić układ bez zwarcia, co był już połowicznym sukcesem. Następnie do mikrokontrolera wgrałem bootloader od Arduino oraz przykładowy program dla wyświetlacza LCD. Udało mi się go uruchomić bez przeszkód. Następnie przetestowałem potencjometr, który miał sterować jasnością obrazu na wyświetlaczu. Również działał on bez problemu. Na sam koniec przetestowałem przycisk odpowiedzialny za reset. Również działał on tak jak powinien. Oznaczało to, że cały projekt został poprawnie zbudowany, gdyż nie wykryto podczas fazy testów żadnych problemów z działaniem. Również gniazdo micro-usb dostarczało prąd potrzebny do pracy tak jak założono, jednak nie było ono specjalnie testowane, gdyż służy ono tylko do zasilania i nie są nim przekazywane żadne dane. Po tych testach mogłem przejść do trudniejszej fazy, czyli tworzenia płytki PCB.
4. Budowanie płytki PCB Budowa płytki PCB była dla mnie priorytetem. Postanowiłem zbudować dwustronną płytkę PCB dla mojego projektu. Do podstawy mojej płytki użyłem laminatu FR4. Płytka została wykonana procesem technologicznym zwanym fotochemicznym. Jest to proces znany ze swojej dokładności, szczególnie tworząc kliszę z użyciem LaserJet u. Co prawda nie jest to najbardziej dokładna metoda dostępna na rynku i istnieją już lepsze, ale do tego projektu metoda ta była, aż za dokładna i tak. W płytce zostały z obu stron wytrawione ścieżki. Po zakończeniu tego procesu oczyściłem płytkę, a następnie wprowadziłem do niej dodatkowe modyfikacje jakimi była metalizacja otworów (by możliwe było używanie płytki bez przelotek) oraz soldiermaska (w celu ochrony płytki przez zwarciami oraz uszkodzeniem ścieżek). Wiele osób pewnie po zobaczeniu tej płytki uzna, że soldiermaska była zbędna i była to tylko strata czasu i pieniędzy na nią. Częściowo jest to prawda, ale nie do końca. Stworzenie dobrze wyglądającej soldiermaski jest trudne i czasochłonne, ale wygląd płytki z nią dodaje takiego uczucia, że ma się kontakt z czymś profesjonalnym, a nie zrobionym na kolanie. Dzięki tej o to farbie w kolorze zielonym (w tym projekcie) możemy poczuć, że płytka była wykonana z dbałością o każdy szczegół i to nawet tak drobny. Poza tym płytka dzięki temu będzie mogła wytrzymać długi lata bez problemów, co jest dla mnie bardzo ważne osobiście, bo chciałem stworzyć coś co zostawi po sobie ślad na lata. Jedyne czego moim zdaniem brakuje tej płytce to cynowanie chemiczne. Dzięki temu pad y były by bardziej odporne na korozje, które niestety moim zdaniem mogą wystąpić, jeżeli ta płytka będzie znajdować się w nieodpowiednich warunkach. Jednak trzeba również pamiętać, że jest to dość trudne i co najważniejsze nie chciałem wydać aż tyle gotówki na to oraz dodatkowo jest to tylko projekt na zaliczenie modułu, a nie praca inżynierska. Na takiej pracy jak inżynierska, można by dodać również takie detale jak mówiłem, a nawet dodać pozłacanie, które to dodało by płytce zupełnie inny wymiar jakości, który to jest praktycznie niespotykane w tego typu projektach. Jednak nie ma co gdybać, bo moim zdaniem efekt końcowy był oszałamiający i tak. Prezentował się on tak jak na dwóch kolejnych zdjęciach.
Płytka z jednej strony:
Płytka z drugiej strony:
Teraz nie pozostało mi nic innego jak przylutować wszystkie elementy. Wykorzystałem do tego lutownicę WEP 937D oraz spoiwo lutownicze z ołowiem. Po zlutowaniu wykonałem odpowiednie zdjęcie.
Dodatkowo należy wspomnieć, że popełniłem błąd podczas lutowania i przylutowałem kondensator elektrolityczny złą stroną i musiałem go wylutowywać i wlutowywać ponownie. Niestety przez to nie jest tak płytka idealna. Niestety nie jest on wlutowany przez to w sposób przewlekany, ale nie można było już tego poprawić. Ważne było to, że układ po podłączeniu zasilania uruchomił się poprawnie.
5. Programowanie mikrokontrolera Programowanie układu mikrokontrolera można przeprowadzić w wielu narzędziach i językach. Ja wybrałem narzędzie Arduino. Dlaczego? Otóż jest on dla mnie najbardziej intuicyjny i przejrzysty. Poza tym pracowałem z nim długi czas i znam jego tajniki i dlatego właśnie napisanie programu nie było dla mnie, aż tak, pomimo tego, że podczas programowanie napotkałem małe problemy. Jednakże poradziłem sobie z nimi sam. Dzięki temu programowi zdobyłem sporo ciekawych doświadczeń życiowych jako przyszły programista. Kiedyś mam zamiar pracować jako programista więc każde doświadczenie jest na wagę złota. Natomiast kod programu znajduje się poniżej i został podzielony na trzy kolumny. #include <LiquidCrystal.h> static const struct {const char letter; String code; morsemap[] = { { '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', " ", ; byte blackbox[8] = { B11111, B11111, B11111, B11111, B11111, B11111, B11111, ; byte emptychar[8] = { B00000, B00000, B00000, B00000, B00000, B00000, B00000, ; const int keypin = 8; const int delaytime = 100; int codetimer = 0; int nulltimer = 0; int randomnumber; bool buttonkeystate = false; String code = ""; String inputword = ""; String introauthorname = "Jakub Bilinski"; String introprojectname = "Dekoder Morse'a"; String tutorial1 = "Uzyj przycisku"; String tutorial2 = "by rozpoczac."; LiquidCrystal lcd(12, 11, 5, 4, 3, 2); void setuplcd() { lcd.createchar(0, blackbox); lcd.createchar(1, emptychar); lcd.begin(16, 2); lcd.clear(); lcd.nocursor(); void introanimation() { for (int i = 0; i < 16; i++) { lcd.setcursor(i,0); lcd.write(byte(0)); lcd.setcursor(i,1); lcd.write(byte(0)); delay(100); delay(250); for (int i = 0; i < 16; i++) { lcd.setcursor(i,0); lcd.write(byte(1)); lcd.setcursor(i,1); lcd.write(byte(1)); delay(100); delay(250); for (int i = 15; i >= 0; i--) { lcd.setcursor(i,0); if (i > 13) lcd.write(byte(1)); else lcd.write(introauthorname[i]); lcd.setcursor(i,1); if (i > 14) lcd.write(byte(1)); else lcd.write(introprojectname[i]); delay(100); delay(1500); for (int i = 0; i < 16; i++) { lcd.setcursor(i,0); lcd.write(byte(0)); lcd.setcursor(15-i,1); lcd.write(byte(0)); delay(100); delay(250); for (int i = 0; i < 16; i++) { lcd.setcursor(15-i,0); lcd.write(byte(1)); lcd.setcursor(i,1); lcd.write(byte(1)); delay(100); void buttonkeytobool() { if (digitalread(keypin) == HIGH) { buttonkeystate = true; else { buttonkeystate = false; char getletterfromcode(string inputvalue) { for (int i = 0; i < sizeof morsemap / sizeof *morsemap; i++){ if (morsemap[i].code == inputvalue) return morsemap[i].letter; return '?'; void inctimer() { if (buttonkeystate == true) { codetimer++;
nulltimer = 24; else { codetimer = 0; void decodesignal() { if (buttonkeystate == false) { if (codetimer >= 2 && codetimer < 8) { code += "."; else if (codetimer >= 8) { code += "_"; if (nulltimer > 0) { nulltimer--; else if (nulltimer == 0 && code!= "") { inputword += getletterfromcode(code); nulltimer = -1; code = ""; char randomcharacter() { randomnumber = random(0,sizeof morsemap / sizeof *morsemap); return morsemap[randomnumber].letter; void updatelcd() { lcd.clear(); lcd.setcursor(0, 0); lcd.print(inputword); if (code!= "") lcd.print(randomcharacter()); lcd.setcursor(0, 1); lcd.print(code); void waitforinput() { lcd.clear(); lcd.print(tutorial1); lcd.setcursor(0,1); lcd.print(tutorial2); while (true) { if (digitalread(keypin) == HIGH) { return; delay(50); void setup() { randomseed(analogread(0)); pinmode(keypin, INPUT); setuplcd(); introanimation(); waitforinput(); void loop() { buttonkeytobool(); decodesignal(); inctimer(); updatelcd(); delay(delaytime);
6. Testowanie Taka ilość kodu nie była napisana od razu uruchomiona i działała. Oczywiście, że nie. Kod był testowany małymi kroczkami, że tak powiem iteracyjnie. Pisałem pojedyncze funkcje, a następnie testowałem. Oczywiście na początku testowałem wyciągając mikrokontroler i wsadzając go do programatora, jednak po tym jak uszkodziłem w nim nóżki i musiałem kupić drugi doszedłem do wniosku, że to jest gra nie warta świeczki. Dlatego właśnie do pinów TX, RX, Reset dolutowałem przewody, które po okresie testowania odlutowałem i usunąłem tak by nie było śladów. Jednakże to bardzo przyśpieszyło proces testowania i programowania, ponieważ umożliwiało to praktycznie natychmiastowy podgląd działania kodu bez potrzebny mechanicznej ingerencji w układ mikrokontrolerowy. Po zakończeniu testów udokumentowałem działanie zdjęciami.
7. Podsumowanie Projekt ten rozbudował na pewno moje zdolności z dziedziny projektowania układów i mikrokontrolerów. Niestety po zakończeniu projektu doszedłem do wniosku, że układ mógł być mniejszy. Dokładnie węższy o prawie 3 cm! Niestety było już za późno. Jednak i tak uważam, że taka wiedze, że teraz zrobił bym to lepiej jest ważniejsza od wszystkiego. Daje mi to nadzieję, że kiedyś będę mógł projektować lepsze układy, ponieważ jest to moje hobby i lubię to robić, mimo, że do bycia w tym dobrym dużo mi brakuje. Poza tym projektowanie takich rzeczy uczy jeszcze jednego. Jak programować układy o małej ilości pamięci i o relatywnie wolnym zegarze. Pokazuje to, że nie potrzeba nam tak naprawdę super komputerów jakie mamy dziś w domach by zrobić coś co jest użyteczne i potrafi nam ułatwić życie. Urządzenie takie jak to mogło by się przydać gdybyśmy chcieli sprawdzić co oznacza dana wiadomość w kodzie morsa, a go nie znamy. Projekt uznaję za udany i jestem szczęśliwy, że udało mi się go stworzyć oraz że działa.