Operácie

Ultrazvukový radar s HC-SR04: Rozdiel medzi revíziami

Zo stránky SensorWiki

StudentMIPS (diskusia | príspevky)
StudentMIPS (diskusia | príspevky)
 
(6 medziľahlých úprav od rovnakého používateľa nie je zobrazených.)
Riadok 56: Riadok 56:
Podrobne opíšte použité komponenty (okrem základnej dosky s ATmega328P procesorom), pridajte linky na datasheety alebo opis obvodu.  
Podrobne opíšte použité komponenty (okrem základnej dosky s ATmega328P procesorom), pridajte linky na datasheety alebo opis obvodu.  


[[Súbor:HC-SR04_federmayer.jpg|600px|thumb|center|Celkový pohľad na zariadenie.]]
[[Súbor:HC-SR04_federmayer.jpg|600px|thumb|center|Celkový pohľad na zariadenie HC-SR04.]]


=== Schéma zapojenia ===
=== Schéma zapojenia ===
Riadok 266: Riadok 266:
=== Overenie ===
=== Overenie ===


Ako ste overili funkciu, napríklad... Na používanie našej aplikácie stačia dve tlačítka a postup používania je opísaný v sekcii popis riešenia.
Funkčnosť zariadenia bola overená praktickým meraním vzdialenosti. Po zapojení senzora k doske bol program nahratý do mikrokontroléra ATmega328P. Následne bol v počítači otvorený sériový terminál PuTTY, v ktorom sa zobrazovali namerané hodnoty vzdialenosti v cm.
Na konci uvádzame fotku hotového zariadenia.  


[[Súbor:GeminiAI-image1.jpg|400px|thumb|center|Aplikácia.]]
Overenie teda prebiehalo tak, že pred senzor bola umiestnená nejaká prekážka v rôznych vzdialenostiach. Pri zmene polohy prekážky sa menila aj hodnota vypisovaná v termináli. Tým sa overilo, že senzor správne reaguje na zmenu vzdialenosti a že program správne spracúva dĺžku impulzu ECHO. V prípade, že sa odrazený impulz nevrátil (napr. preto, že pred senzorom nebola prekážka), program vypísal chybové hlásenie.
[[Súbor:Zariadenie_federmayer.jpg|500px|thumb|center|Moje zapojenie zariadenia.]]


'''Video:'''
'''Video:'''
<center><youtube>D0UnqGm_miA</youtube></center>
<center><youtube>XPmf4I_7_0k</youtube></center>


== Čo by som urobil inak ==
== Čo by som urobil inak ==
Pri riešení projektu som postupoval tak, že som sa najskôr sústredil na základnú funkčnosť senzoru. Dôležité bolo hlavne správne zapojiť senzor, spustiť meranie a overiť, že sa nameraná vzdialenosť správne zobrazuje cez sériovú linku. Tento postup sa mi osvedčil, pretože pri prípadnej chybe bolo jednoduchšie zistiť, či problém vznikol v zapojení, v meraní impulzu alebo vo výpise do terminálu.


Zamyslite sa spätne nad problémom, ktorý ste riešili a napíšte, čo sa vám nepodarilo a nabudúce by ste spravili inak.  
Do budúcna by bolo možné projekt rozšíriť o zobrazovanie vzdialenosti na LCD displeji, čo som mal aj pôvodne v pláne. Avšak pri tomto riešení vznikol problém v tom, že displej, ktorý som mal k dispozícii doma, nebol rovnaký ako displej používaný na cvičeniach. Z toho dôvodu by bolo potrebné použiť inú knižnicu. Keďže používanie iných, cudzích knižníc je v rámci zadania zakázané, zvolil som riešenie so zobrazením výsledku cez sériovú linku.


Kľúčové slová 'Category', ktoré sú na konci stránky nemeňte.


[[Category:AVR]] [[Category:MIPS]]
[[Category:AVR]] [[Category:MIPS]]

Aktuálna revízia z 10:18, 4. jún 2026

Záverečný projekt predmetu MIPS / LS2026 - Werner Federmayer


Zadanie

Úlohou projektu bolo navrhnúť a naprogramovať ultrazvukový merač vzdialenosti s použitím senzora HC-SR04 a vývojovej dosky Arduino. Program má zabezpečiť vyslanie spúšťacieho impulzu na pin TRIG, odmeranie dĺžky impulzu na pine ECHO a následný výpočet vzdialenosti v centimetroch. Nameraná vzdialenosť sa zobrazuje cez sériovú linku.

Bloková schéma zariadenia na meranie vzdialenosti pomocou ultrazvukového senzora HC-SR04.


Literatúra:


Analýza a opis riešenia

Zariadenie je určené na meranie vzdialenosti prekážky pomocou ultrazvukového senzora HC-SR04. Ako riadiaca jednotka bola použitá vývojová doska Arduino Uno s mikrokontrolérom ATmega328P. Arduino zabezpečuje ovládanie senzora, spracovanie nameraného časového impulzu a následný výpočet vzdialenosti v centimetroch. Výsledok merania sa zobrazuje cez sériovú linku v počítači.

Senzor HC-SR04 má štyri vývody: VCC, TRIG, ECHO a GND. Vývod VCC je pripojený na napájanie 5 V a vývod GND na zem. Vývod TRIG je pripojený na digitálny výstup Arduina a slúži na spustenie merania. Vývod ECHO je pripojený na digitálny vstup Arduina a prenáša časový impulz, ktorý sa ďalej spracúva v programe.

Pri riešení bol využitý časovač Timer1 mikrokontroléra ATmega328P. Timer1 slúži na presné meranie dĺžky impulzu na výstupe ECHO. Nameraná hodnota sa následne prepočíta na vzdialenosť v centimetroch a vypíše sa cez sériovú linku do terminálu v počítači.

Princíp merania

Meranie sa začne krátkym spúšťacím impulzom na pine TRIG. Tento impulz má dĺžku približne 10 µs. Po jeho prijatí senzor vyšle ultrazvukový signál a čaká na jeho odraz od prekážky. Počas tohto čakania nastaví výstup ECHO do logickej 1. Keď sa odrazený signál vráti späť, ECHO sa nastaví do logickej 0. Program preto meria čas medzi nábežnou a zostupnou hranou ECHO impulzu.

Výpočet vzdialenosti

Ako sme už vyššie spomínali, meranie vzdialenosti je založené na meraní času, za ktorý sa ultrazvukový signál dostane od senzora k prekážke a po odraze späť k senzoru. Senzor HC-SR04 teda nemeria priamo vzdialenosť, ale čas trvania impulzu na výstupe ECHO.

Rýchlosť zvuku vo vzduchu je približne v = 343 m/s pri izbovej teplote. Túto hodnotu môžeme previesť na centimetre za mikrosekundu:

343 m/s = 34300 cm/s = 0,0343 cm/μs

Nakoľko celková dráha predstavuje cestu od senzora k prekážke aj späť. Skutočná vzdialenosť prekážky od senzora je preto iba polovica tejto dráhy:

​d = v * t / 2

Po dosadení rýchlosti zvuku v jednotkách cm/µs dostaneme:

d = (0,0343 · t) / 2

po úprave:

d = t / 58

kde t je čas impulzu ECHO v mikrosekundách a d je vzdialenosť v centimetroch.

V programe sa dĺžka impulzu Echo nemeria priamo v mikrosekundách, ale pomocou časovača ako počet tickov. Pri frekvencii mikrokontroléra 16 MHz a nastavenej preddeličke časovača 8 má jeden tick časovača dĺžku 0,5 µs. Ak označíme počet nameraných tikov ako N, potom čas impulzu je:

t = N * 0,5 μs

Po dosadení času vyjadreného pomocou počtu tikov dostaneme:

d = N * 0,5 / 58 = N / 116

Opíšte sem čo a ako ste spravili, ak treba, doplňte obrázkami... Podrobne opíšte použité komponenty (okrem základnej dosky s ATmega328P procesorom), pridajte linky na datasheety alebo opis obvodu.

Celkový pohľad na zariadenie HC-SR04.

Schéma zapojenia

Na schéme zapojenia je znázornené pripojenie ultrazvukového senzora HC-SR04 k vývojovej doske Arduino Uno. Senzor je napájaný z 5 V výstupu Arduina a jeho vývod GND je pripojený na spoločnú zem. Vývod TRIG je pripojený na digitálny pin D9 a vývod ECHO je pripojený na digitálny pin D8. V programe je pin D9 nastavený ako výstup a pin D8 ako vstup. Pin D8 bol zvolený preto, že na mikrokontroléri ATmega328P zodpovedá vstupu ICP1, ktorý umožňuje meranie impulzu pomocou funkcie Timer1 Input Capture.

Schéma zapojenia.

Algoritmus a program

Program je napísaný v jazyku C pre mikrokontrolér ATmega328P. Na meranie vzdialenosti využíva ultrazvukový senzor HC-SR04, časovač Timer1 a sériovú komunikáciu UART. Vývod TRIG je pripojený na pin D9 a slúži na spustenie merania. Vývod ECHO je pripojený na pin D8, ktorý zodpovedá vstupu ICP1 pre funkciu Input Capture časovača Timer1.

Program je rozdelený do viacerých funkcií. Funkcia timer1_init() nastavuje Timer1 do normálneho režimu, zapína preddeličku 8 a povoľuje prerušenie Input Capture. Funkcia senzor_init() nastavuje smer pinov, pričom TRIG je výstup a ECHO je vstup. Funkcia senzor_start() spustí nové meranie tým, že vyšle približne 10 µs impulz na pin TRIG a zároveň pripraví Timer1 na zachytenie nábežnej hrany ECHO impulzu.

Meranie dĺžky impulzu prebieha v obsluhe prerušenia ISR(TIMER1_CAPT_vect). Pri nábežnej hrane sa uloží aktuálna hodnota registra ICR1 do premennej start. Následne sa časovač prepne na zachytenie zostupnej hrany. Pri zostupnej hrane sa vypočíta šírka impulzu ako rozdiel ICR1 - start a nastaví sa príznak hotovo.

V hlavnej funkcii main() sa najprv inicializuje UART, senzor a Timer1. Potom sa povolia prerušenia pomocou sei(). V nekonečnej slučke sa opakovane spúšťa meranie, čaká sa na jeho dokončenie a následne sa vypočíta vzdialenosť v centimetroch podľa vzťahu vzdialenost_cm = sirka_impulzu / 116. Výsledok sa vypisuje cez sériovú linku do terminálu. Ak sa meranie v stanovenom čase nedokončí, program vypíše chybové hlásenie.

Zdroják + moje poznámky sú uvedené nižšie, spolu s knižnicami uart.h a uart.c.

#define F_CPU 16000000UL
#define TRIG PB1   // D9
#define ECHO PB0   // D8

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

volatile unsigned int start = 0;
volatile unsigned int sirka_impulzu = 0;
volatile unsigned char hotovo = 0;

FILE uart_stream = FDEV_SETUP_STREAM(uart_putc, uart_getc, _FDEV_SETUP_RW);

void timer1_init(void)
{
    TCCR1A = 0x00; // normal mode
    TCCR1B = (1 << CS11); // clock 8
    TCCR1B |= (1 << ICES1); // Capture on rising edge
    TCNT1 = 0;  // 16-bit Counter reset
    TIMSK1 = (1 << ICIE1); // povolenie Input Capture prerusenia
}

void senzor_init(void)
{
    DDRB |= (1 << TRIG); // PB1 vystup
    DDRB &= ~(1 << ECHO); // PB0 vstup

    PORTB &= ~(1 << TRIG); // TRIG na zaciatku v 0, spusti sa az impulzikom
}

void senzor_start(void)
{
    hotovo = 0; // hotovo= ci uz meranie bolo dokoncene: 0 nie, 1 ano, teraz 0 lebo nove meranie nie je hotove
    sirka_impulzu = 0; // nulujem stary vysledok merania
	TCNT1 = 0; // hodnota timera1, teraz 0 lebo pocitam od 0 = vynulujem stopky pred meranim
    TCCR1B |= (1 << ICES1); // pri novom merani cakam na nabeznu hranu
    TIFR1 = (1 << ICF1); // vymazanie pripadneho stareho priznaku/sumu v input capture

    PORTB &= ~(1 << TRIG); // pred spustenim impulzu overim ze trig=0 = 0Volt
    _delay_us(2); // aby mal senzor pred spustenim stabilnu log 0

    PORTB |= (1 << TRIG); // spustim impulz, trig=1 = 5Volt
    _delay_us(10);

    PORTB &= ~(1 << TRIG); // impulz skoncil dam spat do 0
	//po tomto senzor vysle ultrazvuk a nastavi echo na log 1, timer1 input capture potom zachyti nabeznu a dobeznu hranu echo impulzu
}

//pozn. TCNT1 je register timeru1 obsahuje aktualnu hodnotu casovaca (stopky), teda timer1 pocita cas v TCNT1, a ked pride vybrana hrana, ulozi hodnotu do ICR1.
//TCCR1B je riadiaci register pre timer1 = hovori ako ma pracovat - nastavuje ho, ICES1 je bit v tomto registri
//ICES1 je bit v registri TCCR1B sluzi na vyber hrany pre input capture

ISR(TIMER1_CAPT_vect)
{
    if (bit_is_set(TCCR1B, ICES1)) // zistujem aku hranu zachytaval timer1, ak ICES1=1 nabezna hrana, ak ICES1=0 dobezna hrana
    {
        start = ICR1; // ICR1 ma hodnotu timer1 v okamihu zachytenia nabeznej hrany = tu zacal echo impulz
        
		TCCR1B &= ~(1 << ICES1); // vynulujem ICES1 lebo dalsiu hranu cakam dobeznu, teda nastavim timer1 aby dalsikrat cakal dobeznu hranu
    }
    else
    {
        sirka_impulzu = ICR1 - start; //lebo teraz je v ICR1 cas konca echo impulzu
        hotovo = 1; //meranie je ukoncene
		
        TCCR1B |= (1 << ICES1); // nastavim takto aby pri dalsom merani cakal na nabeznu hranu
    }
}

int main(void)
{
    unsigned int vzdialenost_cm;
    unsigned char poc_cakania; // toto je pocitadlo cakania, aby program nefreezol keby sa echo impulz nevratil

    uart_init();
    stdout = &uart_stream;

    senzor_init();
    timer1_init();

    sei();  //povoli prerusenia celkovo

    printf("HC-SR04 meranie vzdialenosti\r\n");
    printf("TRIG = D9, ECHO = D8\r\n"); // \r\n znamena novy riadok v terminali

    while (1)
    {
        senzor_start();

        poc_cakania = 0; // zacinam cakat na vysledok noveho merania, teda musim ist od nuly

        while (!hotovo && poc_cakania < 60) // kym meranie este nie je dokoncene a cakam len do 60 krokov
        {
            _delay_ms(1); // cakam 1ms, aby poc_cakania zodpovedal cca milisekundam
            poc_cakania++;
        }//tato slucka konci 2 moznostami:
		//hotovo sa nastavilo na 1 = meranie prebehlo
		//poc_cakania dosiahlo 60 = meranie zlyhalo alebo senzor nic nezachytil

        if (hotovo) // kontrola ci meranie bolo uspesne (bola zachytena aj nabezna aj dobezna)
        {
            vzdialenost_cm = sirka_impulzu / 116; // lebo 1 tick je 0.5 [mikrosek], teda z rychlosti zvuku: vzdialenost = (0,0343 [cm/mikrosek] * cas)/2 (lebo meria sa tam a spat) ziskam: vzdialenost = cas/58, dalej viem ze cas = sirkaimpulzu*0.5, takze: vzdialenost = sirkaimpulzu*0.5/58 = sirkaimpulzu/116

            printf("Vzdialenost: %u cm\r\n", vzdialenost_cm);
        }
        else
        {
            printf("Chyba merania alebo mimo rozsah\r\n");
        }

        _delay_ms(300); // aby sa merania nerobili furt, chvilu sa pocka
    }

    return 0;
}
#ifndef uart_h_
#define uart_h_


void uart_init( void );
     
void uart_putc( char c );
void uart_puts( const char *s );

char uart_getc( void );


#endif /* UART_H_ */
#include <avr/io.h>
#define F_CPU 16000000UL
#define BAUD 9600

#include <util/setbaud.h>

void uart_init( void ) 
{
    UBRR0H = UBRRH_VALUE;
    UBRR0L = UBRRL_VALUE;

#if USE_2X
    UCSR0A |= _BV(U2X0);
#else
    UCSR0A &= ~(_BV(U2X0));
#endif

    UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); /* 8-bit data */
    UCSR0B = _BV(RXEN0) | _BV(TXEN0);   /* Enable RX and TX */
}


void uart_putc(char c) 
{
   if (c == '\n') 
    {
       uart_putc('\r');
    }
   loop_until_bit_is_set(UCSR0A, UDRE0); /* Wait until data register empty. */
   UDR0 = c;
}


void uart_puts(const char *s)
{
    while (*s != '\0')
    {
        uart_putc(*s);
        s++;
    }
}
char uart_getc(void) {
    loop_until_bit_is_set(UCSR0A, RXC0); /* Wait until data exists. */
    return UDR0;
}

Zdrojový kód: zdrojaky_Federmayer.zip

Overenie

Funkčnosť zariadenia bola overená praktickým meraním vzdialenosti. Po zapojení senzora k doske bol program nahratý do mikrokontroléra ATmega328P. Následne bol v počítači otvorený sériový terminál PuTTY, v ktorom sa zobrazovali namerané hodnoty vzdialenosti v cm.

Overenie teda prebiehalo tak, že pred senzor bola umiestnená nejaká prekážka v rôznych vzdialenostiach. Pri zmene polohy prekážky sa menila aj hodnota vypisovaná v termináli. Tým sa overilo, že senzor správne reaguje na zmenu vzdialenosti a že program správne spracúva dĺžku impulzu ECHO. V prípade, že sa odrazený impulz nevrátil (napr. preto, že pred senzorom nebola prekážka), program vypísal chybové hlásenie.

Moje zapojenie zariadenia.

Video:

Čo by som urobil inak

Pri riešení projektu som postupoval tak, že som sa najskôr sústredil na základnú funkčnosť senzoru. Dôležité bolo hlavne správne zapojiť senzor, spustiť meranie a overiť, že sa nameraná vzdialenosť správne zobrazuje cez sériovú linku. Tento postup sa mi osvedčil, pretože pri prípadnej chybe bolo jednoduchšie zistiť, či problém vznikol v zapojení, v meraní impulzu alebo vo výpise do terminálu.

Do budúcna by bolo možné projekt rozšíriť o zobrazovanie vzdialenosti na LCD displeji, čo som mal aj pôvodne v pláne. Avšak pri tomto riešení vznikol problém v tom, že displej, ktorý som mal k dispozícii doma, nebol rovnaký ako displej používaný na cvičeniach. Z toho dôvodu by bolo potrebné použiť inú knižnicu. Keďže používanie iných, cudzích knižníc je v rámci zadania zakázané, zvolil som riešenie so zobrazením výsledku cez sériovú linku.