Operácie

Dekodér morzeovky: Rozdiel medzi revíziami

Zo stránky SensorWiki

StudentMIPS (diskusia | príspevky)
Bez shrnutí editace
StudentMIPS (diskusia | príspevky)
Bez shrnutí editace
 
(3 medziľahlé úpravy od rovnakého používateľa nie sú zobrazené.)
Riadok 1: Riadok 1:
= Dekodér morzeovky =


Záverečný projekt predmetu MIPS / LS2026 - '''Oleh Chuiko'''
Záverečný projekt predmetu MIPS / LS2026 - '''Oleh Chuiko'''
Riadok 6: Riadok 7:
Cieľom projektu bolo vytvoriť jednoduchý dekodér Morseovej abecedy pomocou mikrokontroléra ATmega328P na vývojovej doske ACROB.
Cieľom projektu bolo vytvoriť jednoduchý dekodér Morseovej abecedy pomocou mikrokontroléra ATmega328P na vývojovej doske ACROB.


Mikropočítač prijíma vstup z tlačidla, meria dĺžku jeho stlačenia a podľa času rozlišuje krátke a dlhé impulzy Morseovej abecedy.
Mikropočítač prijíma vstup z tlačidla a podľa dĺžky stlačenia rozlišuje jednotlivé symboly Morseovej abecedy. Krátke stlačenie predstavuje bodku (<code>.</code>) a dlhé stlačenie predstavuje čiarku (<code>-</code>). Následne program vytvorí Morse sekvenciu, dekóduje ju na príslušné písmeno a vypíše výsledok cez UART do sériového terminálu.
Krátke stlačenie predstavuje bodku (.) a dlhé stlačenie predstavuje čiarku (-).


Postupne zadané symboly sa ukladajú do buffera a následne sa dekódujú na jednotlivé písmená. Výsledok sa vypisuje cez UART do sériového terminálu.
Zadanie slúži na demonštráciu práce so vstupnými tlačidlami, meraním času, jednoduchým spracovaním textových údajov a UART komunikáciou.


[[Súbor:morse_device.jpg|450px|thumb|center|Celkový pohľad na zariadenie.]]


'''Literatúra:'''
'''Literatúra:'''


[http://ap.urpi.fei.stuba.sk/sensorwiki/index.php/Acrob_technical_description Dokumentácia k doske Acrob]
* [[http://ap.urpi.fei.stuba.sk/sensorwiki/index.php/Acrob_technical_description](http://ap.urpi.fei.stuba.sk/sensorwiki/index.php/Acrob_technical_description) Dokumentácia k doske Acrob]
* [[https://en.wikipedia.org/wiki/Morse_code](https://en.wikipedia.org/wiki/Morse_code) Morse code]
* [[https://www.microchip.com/en-us/product/atmega328p](https://www.microchip.com/en-us/product/atmega328p) Dokumentácia ATmega328P]


[https://en.wikipedia.org/wiki/Morse_code Morse code]


[https://www.microchip.com/en-us/product/atmega328p Dokumentácia ATmega328P]
== Analýza a opis riešenia ==


TOC
'''Ako základ''' pre projekt bola použitá vývojová doska ACROB s mikrokontrolérom ATmega328P. Mikrokontrolér pracuje na frekvencii 16 MHz a zabezpečuje spracovanie vstupu z tlačidla a komunikáciu cez UART.


== Analýza a opis riešenia ==
'''Pre ovládanie dekodéra''' bolo použité jedno tlačidlo pripojené na vstupný pin mikrokontroléra. Tlačidlo slúži na zadávanie Morseových symbolov. Krátke stlačenie predstavuje bodku a dlhé stlačenie predstavuje čiarku.
 
'''Program priebežne sleduje''' stav tlačidla a meria čas jeho stlačenia. Na základe dĺžky impulzu rozhoduje, či ide o krátky alebo dlhý Morse signál. Rozpoznané symboly sa ukladajú do buffera a po dokončení sekvencie sa dekódujú na konkrétne písmeno.
 
'''Dekódovanie Morseovej abecedy''' je realizované pomocou porovnávania prijatej sekvencie s uloženými Morse kódmi. Po úspešnom rozpoznaní sa výsledné písmeno odošle cez UART do počítača.
 
'''UART komunikácia''' slúži na výpis dekódovaných znakov do sériového terminálu. Vďaka tomu je možné jednoducho sledovať funkciu programu počas testovania.


Projekt využíva tlačidlo ako vstupný prvok pre zadávanie Morseovej abecedy. Mikrokontrolér priebežne sleduje stav tlačidla a meria čas jeho stlačenia.
[[Súbor:morse_device.jpg|400px|thumb|center|Zapojenie tlačidla na vývojovej doske ACROB.]]


Ak je tlačidlo stlačené krátko, program zaznamená bodku. Pri dlhšom stlačení sa zaznamená čiarka. Takto vytvorená sekvencia sa uloží do textového buffera.
Tlačidlo bolo pripojené medzi vstupný pin mikrokontroléra a GND. Program využíva interný pull-up rezistor mikrokontroléra, takže nie je potrebné externé pull-up zapojenie.


Po ukončení zadávania znaku program porovná prijatú sekvenciu s tabuľkou Morseových kódov a vyhľadá zodpovedajúce písmeno.
=== Algoritmus a program ===
Výsledný znak sa následne odošle cez UART do počítača.


Pri projekte bola použitá:
Program pracuje v nekonečnej slučke, v ktorej sleduje stav tlačidla. Počas stlačenia sa meria čas trvania impulzu. Podľa nameranej hodnoty program rozhodne, či ide o bodku alebo čiarku.


vývojová doska ACROB s ATmega328P
Rozpoznané symboly sa ukladajú do textového buffera. Po ukončení zadávania znaku program porovná prijatú sekvenciu s uloženou tabuľkou Morseových znakov a nájde zodpovedajúce písmeno.


tlačidlo pripojené na vstupný pin mikrokontroléra
Výsledný znak sa následne odošle cez UART do sériového terminálu.


UART komunikácia
Hlavné časti programu:


jednoduché časovanie na rozlíšenie bodky a čiarky
* čítanie tlačidla
* meranie dĺžky stlačenia
* rozlíšenie bodky a čiarky
* ukladanie Morse sekvencie do buffera
* dekódovanie znakov
* výpis cez UART


buffer pre ukladanie Morse sekvencie
<tabs>
<tab name="main.c"><syntaxhighlight lang="c++" style="background: LightYellow;">
#define F_CPU 16000000UL


[[Súbor:morse_device.jpg|400px|thumb|center|Zapojenie tlačidla na vývojovej doske ACROB.]]
#include <avr/io.h>
#include <util/delay.h>
#include "uart.h"
#include <stdio.h>
#include <string.h>


Tlačidlo bolo pripojené medzi vstupný pin mikrokontroléra a GND. Program využíva interný pull-up rezistor mikrokontroléra.
#define set_bit(ADDRESS,BIT)    (ADDRESS |=  (1<<BIT))
#define clear_bit(ADDRESS,BIT)  (ADDRESS &= ~(1<<BIT))


=== Algoritmus a program ===
#define LED1    PB5
#define SW1    PB3


Program pracuje v nekonečnej slučke, v ktorej sleduje stav tlačidla.
#define BAUD 9600
Počas stlačenia sa meria čas trvania impulzu. Podľa nameranej hodnoty program rozhodne, či ide o bodku alebo čiarku.


Dekódovanie Morseovej abecedy je realizované pomocou porovnávania prijatej sekvencie s uloženými Morse znakmi.
FILE uart_output = FDEV_SETUP_STREAM(uart_putc, NULL, _FDEV_SETUP_WRITE);
Po úspešnom rozpoznaní sa výsledné písmeno odošle cez UART.


Hlavné časti programu:
typedef struct
{
const char *morse;
char letter;


čítanie tlačidla
} MorseCode;


meranie dĺžky stlačenia
MorseCode morse_table[] =
{
{".-",    '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'}
};


rozlíšenie bodky a čiarky
#define MORSE_TABLE_SIZE 26


ukladanie Morse sekvencie do buffera
void delay_ms_variable(uint16_t ms)
{
while(ms--)
{
_delay_ms(1);
}
}


dekódovanie znakov
char decode_morse(char *code)
{
uint8_t i;


výpis cez UART
```
for(i = 0; i < MORSE_TABLE_SIZE; i++)
{
    if(strcmp(code, morse_table[i].morse) == 0)
    {
        return morse_table[i].letter;
    }
}


#include "uart.h"
return '?';
```


#define BUTTON_PIN PB3
}


int main(void)
int main(void)
{
{
uint16_t press_time = 0;
uint16_t pause_time = 0;
```
uint8_t button_pressed = 0;
char morse_buffer[10];
uint8_t morse_index = 0;
char decoded_char;
set_bit(DDRB, LED1);
clear_bit(DDRB, SW1);
set_bit(PORTB, SW1);
uart_init();
uart_init();


while (1)
stdout = &uart_output;
 
printf("
```
 
");
printf("semestralny project Oleh Chuiko r
");
 
```
while(1)
{
{
     /* Morse decoder logic */
     if(bit_is_clear(PINB, SW1))
    {
        _delay_ms(20);
 
        if(bit_is_clear(PINB, SW1))
        {
            button_pressed = 1;
 
            press_time = 0;
 
            set_bit(PORTB, LED1);
 
            while(bit_is_clear(PINB, SW1))
            {
                delay_ms_variable(10);
                press_time += 10;
            }
 
            clear_bit(PORTB, LED1);
 
            if(press_time < 400)
            {
                morse_buffer[morse_index] = '.';
                morse_index++;
 
                printf(".");
            }
            else
            {
                morse_buffer[morse_index] = '-';
                morse_index++;
 
                printf("-");
            }
 
            pause_time = 0;
        }
    }
 
    if(button_pressed)
    {
        delay_ms_variable(10);
        pause_time += 10;
 
        if(pause_time > 1000)
        {
            morse_buffer[morse_index] = '�';
 
            decoded_char = decode_morse(morse_buffer);
 
            printf(" -> %c
```
 
", decoded_char);
 
```
            morse_index = 0;
 
            memset(morse_buffer, 0, sizeof(morse_buffer));
 
            pause_time = 0;
 
            button_pressed = 0;
        }
    }
}
}
```


}
} </syntaxhighlight></tab>


<tab name="uart.h"><syntaxhighlight lang="c++" style="background: LightYellow;">
/* ************************************************************************* */
/* FileName:            uart.h                                              */
/* ************************************************************************* */


#define LED PB5


#define set_bit(ADDRESS, BIT)(ADDRESS |= (1 << BIT))
#define set_bit(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define clear_bit(ADDRESS, BIT)(ADDRESS &= ~(1 << BIT))
#define clear_bit(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))


#ifndef UART_H_
#ifndef UART_H_
Riadok 95: Riadok 254:
#include <stdio.h>
#include <stdio.h>


void uart_init(void);
#define BAUD_PRESCALE  (((F_CPU / (BAUDRATE * 16UL))) - 1)
int uart_putc(char c, FILE * stream);
 
void uart_puts(const char * s);
void hw_init( void );
char uart_getc(void);
void uart_init( void );
 
int uart_putc( char c, FILE *stream );
void uart_puts( const char *s );


#endif
char uart_getc( void );
 
void delay(int delay);


#endif /* UART_H_ */ </syntaxhighlight></tab>


<tab name="uart.c"><syntaxhighlight lang="c++" style="background: LightYellow;">
/* ************************************************************************* */
/* FileName:            uart.c                                              */
/* ************************************************************************* */


#include <avr/io.h>
#include <avr/io.h>
#include <util/delay.h>
#include <util/delay.h>
#include "uart.h"


#include "uart.h"
void hw_init( void )
{
DDRB |= (1<<LED);
}


void uart_init(void)
void uart_init( void )
{
{
#include <util/setbaud.h>
#include <util/setbaud.h>
Riadok 115: Riadok 288:
UBRR0H = UBRRH_VALUE;
UBRR0H = UBRRH_VALUE;
UBRR0L = UBRRL_VALUE;
UBRR0L = UBRRL_VALUE;
#if USE_2X
#if USE_2X
UCSR0A |= (1 << U2X0);
UCSR0A |= (1 << U2X0);
Riadok 122: Riadok 294:
#endif
#endif


```
UCSR0C = _BV(UCSZ01) | _BV(UCSZ00);
UCSR0C = _BV(UCSZ01) | _BV(UCSZ00);
UCSR0B = _BV(RXEN0) | _BV(TXEN0);
UCSR0B = _BV(RXEN0) | _BV(TXEN0);
```


}
}


int uart_putc(char c, FILE * stream)
int uart_putc( char c, FILE *stream )
{
if (c == '\n')
{
{
loop_until_bit_is_set(UCSR0A, UDRE0);
if (c == '
UDR0 = '\r';
')
}
uart_putc('
',stream);


loop_until_bit_is_set(UCSR0A, UDRE0);
loop_until_bit_is_set(UCSR0A, UDRE0);
UDR0 = c;
UDR0 = c;
return 0;
return 0;
}


char uart_getc(void)
{
loop_until_bit_is_set(UCSR0A, RXC0);
return UDR0;
}
}


 
void delay(int delay)
{
for (int i=1; i<=delay; i++)
_delay_ms(1);
} </syntaxhighlight></tab> </tabs>


Zdrojový kód: [[Médiá:OlehChuiko_MorseDecoder.zip|OlehChuiko_MorseDecoder.zip]]
Zdrojový kód: [[Médiá:OlehChuiko_MorseDecoder.zip|OlehChuiko_MorseDecoder.zip]]
Riadok 153: Riadok 334:
Počas testovania bolo sledované:
Počas testovania bolo sledované:


správne rozpoznávanie bodiek a čiarok
* správne rozpoznávanie bodiek a čiarok
 
* stabilita merania času stlačenia tlačidla
stabilita merania času stlačenia tlačidla
* správne dekódovanie znakov
 
* správny výpis cez UART
správne dekódovanie znakov
 
správny výpis cez UART


Video demonštruje reálnu funkčnosť zariadenia a proces dekódovania Morseovej abecedy.
Video demonštruje reálnu funkčnosť zariadenia a proces dekódovania Morseovej abecedy.


'''Video:'''
'''Video:'''
<center><youtube>vh-u5UzWHfU</youtube></center>


== Čo by som urobil inak ==
== Čo by som urobil inak ==

Aktuálna revízia z 18:55, 16. máj 2026

Dekodér morzeovky

Záverečný projekt predmetu MIPS / LS2026 - Oleh Chuiko

Zadanie

Cieľom projektu bolo vytvoriť jednoduchý dekodér Morseovej abecedy pomocou mikrokontroléra ATmega328P na vývojovej doske ACROB.

Mikropočítač prijíma vstup z tlačidla a podľa dĺžky stlačenia rozlišuje jednotlivé symboly Morseovej abecedy. Krátke stlačenie predstavuje bodku (.) a dlhé stlačenie predstavuje čiarku (-). Následne program vytvorí Morse sekvenciu, dekóduje ju na príslušné písmeno a vypíše výsledok cez UART do sériového terminálu.

Zadanie slúži na demonštráciu práce so vstupnými tlačidlami, meraním času, jednoduchým spracovaním textových údajov a UART komunikáciou.


Literatúra:


Analýza a opis riešenia

Ako základ pre projekt bola použitá vývojová doska ACROB s mikrokontrolérom ATmega328P. Mikrokontrolér pracuje na frekvencii 16 MHz a zabezpečuje spracovanie vstupu z tlačidla a komunikáciu cez UART.

Pre ovládanie dekodéra bolo použité jedno tlačidlo pripojené na vstupný pin mikrokontroléra. Tlačidlo slúži na zadávanie Morseových symbolov. Krátke stlačenie predstavuje bodku a dlhé stlačenie predstavuje čiarku.

Program priebežne sleduje stav tlačidla a meria čas jeho stlačenia. Na základe dĺžky impulzu rozhoduje, či ide o krátky alebo dlhý Morse signál. Rozpoznané symboly sa ukladajú do buffera a po dokončení sekvencie sa dekódujú na konkrétne písmeno.

Dekódovanie Morseovej abecedy je realizované pomocou porovnávania prijatej sekvencie s uloženými Morse kódmi. Po úspešnom rozpoznaní sa výsledné písmeno odošle cez UART do počítača.

UART komunikácia slúži na výpis dekódovaných znakov do sériového terminálu. Vďaka tomu je možné jednoducho sledovať funkciu programu počas testovania.

Zapojenie tlačidla na vývojovej doske ACROB.

Tlačidlo bolo pripojené medzi vstupný pin mikrokontroléra a GND. Program využíva interný pull-up rezistor mikrokontroléra, takže nie je potrebné externé pull-up zapojenie.

Algoritmus a program

Program pracuje v nekonečnej slučke, v ktorej sleduje stav tlačidla. Počas stlačenia sa meria čas trvania impulzu. Podľa nameranej hodnoty program rozhodne, či ide o bodku alebo čiarku.

Rozpoznané symboly sa ukladajú do textového buffera. Po ukončení zadávania znaku program porovná prijatú sekvenciu s uloženou tabuľkou Morseových znakov a nájde zodpovedajúce písmeno.

Výsledný znak sa následne odošle cez UART do sériového terminálu.

Hlavné časti programu:

  • čítanie tlačidla
  • meranie dĺžky stlačenia
  • rozlíšenie bodky a čiarky
  • ukladanie Morse sekvencie do buffera
  • dekódovanie znakov
  • výpis cez UART
#define F_CPU 16000000UL

#include <avr/io.h>
#include <util/delay.h>
#include "uart.h"
#include <stdio.h>
#include <string.h>

#define set_bit(ADDRESS,BIT)    (ADDRESS |=  (1<<BIT))
#define clear_bit(ADDRESS,BIT)  (ADDRESS &= ~(1<<BIT))

#define LED1    PB5
#define SW1     PB3

#define BAUD 9600

FILE uart_output = FDEV_SETUP_STREAM(uart_putc, NULL, _FDEV_SETUP_WRITE);

typedef struct
{
const char *morse;
char letter;

} MorseCode;

MorseCode morse_table[] =
{
{".-",    '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'}
};

#define MORSE_TABLE_SIZE 26

void delay_ms_variable(uint16_t ms)
{
while(ms--)
{
_delay_ms(1);
}
}

char decode_morse(char *code)
{
uint8_t i;

```
for(i = 0; i < MORSE_TABLE_SIZE; i++)
{
    if(strcmp(code, morse_table[i].morse) == 0)
    {
        return morse_table[i].letter;
    }
}

return '?';
```

}

int main(void)
{
uint16_t press_time = 0;
uint16_t pause_time = 0;

```
uint8_t button_pressed = 0;

char morse_buffer[10];
uint8_t morse_index = 0;

char decoded_char;

set_bit(DDRB, LED1);

clear_bit(DDRB, SW1);
set_bit(PORTB, SW1);

uart_init();

stdout = &uart_output;

printf("
```

");
printf("semestralny project Oleh Chuiko r
");

```
while(1)
{
    if(bit_is_clear(PINB, SW1))
    {
        _delay_ms(20);

        if(bit_is_clear(PINB, SW1))
        {
            button_pressed = 1;

            press_time = 0;

            set_bit(PORTB, LED1);

            while(bit_is_clear(PINB, SW1))
            {
                delay_ms_variable(10);
                press_time += 10;
            }

            clear_bit(PORTB, LED1);

            if(press_time < 400)
            {
                morse_buffer[morse_index] = '.';
                morse_index++;

                printf(".");
            }
            else
            {
                morse_buffer[morse_index] = '-';
                morse_index++;

                printf("-");
            }

            pause_time = 0;
        }
    }

    if(button_pressed)
    {
        delay_ms_variable(10);
        pause_time += 10;

        if(pause_time > 1000)
        {
            morse_buffer[morse_index] = '�';

            decoded_char = decode_morse(morse_buffer);

            printf(" -> %c
```

", decoded_char);

```
            morse_index = 0;

            memset(morse_buffer, 0, sizeof(morse_buffer));

            pause_time = 0;

            button_pressed = 0;
        }
    }
}
```

}
/* ************************************************************************* */
/* FileName:             uart.h                                              */
/* ************************************************************************* */

#define LED PB5

#define set_bit(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define clear_bit(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))

#ifndef UART_H_
#define UART_H_

#include <stdio.h>

#define BAUD_PRESCALE  (((F_CPU / (BAUDRATE * 16UL))) - 1)

void hw_init( void );
void uart_init( void );

int uart_putc( char c, FILE *stream );
void uart_puts( const char *s );

char uart_getc( void );

void delay(int delay);

#endif /* UART_H_ */
/* ************************************************************************* */
/* FileName:             uart.c                                              */
/* ************************************************************************* */

#include <avr/io.h>
#include <util/delay.h>
#include "uart.h"

void hw_init( void )
{
DDRB |= (1<<LED);
}

void uart_init( void )
{
#include <util/setbaud.h>

UBRR0H = UBRRH_VALUE;
UBRR0L = UBRRL_VALUE;
#if USE_2X
UCSR0A |= (1 << U2X0);
#else
UCSR0A &= ~(1 << U2X0);
#endif

```
UCSR0C = _BV(UCSZ01) | _BV(UCSZ00);
UCSR0B = _BV(RXEN0) | _BV(TXEN0);
```

}

int uart_putc( char c, FILE *stream )
{
if (c == '
')
uart_putc('
',stream);

loop_until_bit_is_set(UCSR0A, UDRE0);
UDR0 = c;
return 0;
}

char uart_getc(void)
{
loop_until_bit_is_set(UCSR0A, RXC0);
return UDR0;
}

void delay(int delay)
{
for (int i=1; i<=delay; i++)
_delay_ms(1);
}

Zdrojový kód: OlehChuiko_MorseDecoder.zip

Overenie

Funkčnosť projektu bola overená pomocou zadávania rôznych Morseových sekvencií cez tlačidlo. Program správne rozlišoval krátke a dlhé impulzy a dekódované znaky vypisoval cez UART do terminálu.

Počas testovania bolo sledované:

  • správne rozpoznávanie bodiek a čiarok
  • stabilita merania času stlačenia tlačidla
  • správne dekódovanie znakov
  • správny výpis cez UART

Video demonštruje reálnu funkčnosť zariadenia a proces dekódovania Morseovej abecedy.

Video:

Čo by som urobil inak

Na ďalšíkrát by som doplnil podporu väčšieho počtu znakov a presnejšie časovanie pomocou hardvérových timerov.

Taktiež by bolo zaujímavé doplniť LCD displej alebo zvukový výstup, aby bolo možné dekódovaný text zobrazovať priamo na zariadení.