Meranie vzdialenosti ultrazvukovým snímačom HC-SR04: Rozdiel medzi revíziami
Zo stránky SensorWiki
Bez shrnutí editace |
|||
Riadok 36: | Riadok 36: | ||
<tabs> | <tabs> | ||
<tab name=" | <tab name="main.c"><source lang="c++" style="background: LightYellow;"> | ||
#include <avr/io.h> | #include <avr/io.h> | ||
#include | #include "uarth.h" | ||
#define F_CPU 16000000UL | |||
#define BAUDRATE 9600 | |||
#include <stdio.h> | #include <stdio.h> | ||
FILE mystdout = FDEV_SETUP_STREAM(uart_putc, NULL, _FDEV_SETUP_WRITE); | FILE mystdout = FDEV_SETUP_STREAM(uart_putc, NULL, _FDEV_SETUP_WRITE); | ||
void | int main(void) | ||
{ | |||
adc_init(); | |||
hw_init(); | |||
uart_init(); | |||
stdout = &mystdout; | |||
unsigned int measuredValue; | |||
DDRD |= (1 << PD6); // PD6 as output (OC0A) | |||
TCNT0 = 0; // initialize counter value | |||
OCR0A = 0; // initialize OCR0A value | |||
TCCR0A |= (1 << COM0A1) | (1 << COM0B1) | (1 << WGM01) | (1 << WGM00); // set fast PWM mode and non-inverting mode | |||
TCCR0B |= (1 << CS02) | (1 << CS00); // set prescaler to 1024 | |||
while(1) | |||
{ | |||
measuredValue = adc_read(4); // read ADC from channel 4 | |||
printf("hodnota: %04d \r", measuredValue); | |||
OCR0A = measuredValue / 4; // adjust PWM duty cycle | |||
// | } | ||
return 0; | |||
} | } | ||
</source></tab> | |||
<tab name="adc.h"><source lang="c++" style="background: LightYellow;"> | |||
#include <avr/io.h> | |||
void adc_init(void); | |||
unsigned int adc_read(char a_pin); | |||
</source></tab> | </source></tab> | ||
<tab name="adc.c"><source lang="c++" style="background: LightYellow;"> | |||
#include <stdio.h> | #include <stdio.h> | ||
#include "adc.h" | |||
void adc_init(void) { | |||
ADMUX = (1 << REFS0); // reference voltage set to AVcc | |||
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // enable ADC and set prescaler to 128 | |||
} | |||
unsigned int adc_read(char a_pin) { | |||
a_pin &= 0x07; // limit input to 0-7 | |||
ADMUX = (ADMUX & 0xF8) | a_pin; // select ADC channel with safety mask | |||
/ | ADCSRA |= (1 << ADSC); // start conversion | ||
while (ADCSRA & (1 << ADSC)); // wait for conversion to complete | |||
return ADC; // return the ADC value | |||
} | |||
</source></tab> | |||
<tab name="uarth.h"><source lang="c++" style="background: LightYellow;"> | |||
#ifndef UARTH_H | |||
#define UARTH_H | |||
<tab name=" | |||
#include <avr/io.h> | #include <avr/io.h> | ||
void | void uart_init(void); | ||
int uart_putc(char c, FILE *stream); | |||
int uart_getc(FILE *stream); | |||
void uart_init( void ) | void uart_init(void) { | ||
{ | // Set baud rate | ||
// | uint16_t baudrate = (F_CPU / (16UL * BAUDRATE)) - 1; | ||
/ | UBRR0H = (uint8_t)(baudrate >> 8); | ||
UBRR0L = (uint8_t)baudrate; | |||
// Enable transmitter and receiver | |||
UCSR0B = (1 << TXEN0) | (1 << RXEN0); | |||
// Set frame format: 8 data bits, 1 stop bit | |||
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); | |||
} | } | ||
int uart_putc(char c, FILE *stream) { | |||
int uart_putc( char c, FILE *stream ) | if (c == '\n') { | ||
{ | uart_putc('\r', stream); | ||
} | |||
while (!(UCSR0A & (1 << UDRE0))); // Wait until the buffer is empty | |||
UDR0 = c; | |||
return 0; | |||
} | } | ||
int uart_getc(FILE *stream) { | |||
while (!(UCSR0A & (1 << RXC0))); // Wait until data is received | |||
{ | return UDR0; | ||
/ | |||
} | } | ||
#endif // UARTH_H | |||
</source></tab> | </source></tab> | ||
</tabs> | </tabs> | ||
Zdrojový kód: [[Médiá:projektJozefCsabi.zip|zdrojaky.zip]] | Zdrojový kód: [[Médiá:projektJozefCsabi.zip|zdrojaky.zip]] | ||
=== Overenie === | === Overenie === |
Verzia z 18:12, 26. máj 2024
Záverečný projekt predmetu MIPS / LS2024 - Jozef Csabi
Zadanie
Pripojenie senzora vzdialenosti HC-SR04 k vývojovej doske Arduino NANO. Našim cieľom je pripojiť senzor a odmerať vzdialenosť od prekážky.
![](/sensorwiki/images/thumb/7/78/Arduino_nano.jpg/400px-Arduino_nano.jpg.png)
HC-SR04
Je to ultrazvukový senzor pre meranie vzdialenosti. funguje tak, že vysiela krátky ultrazvukový impulz, potom detekuje jeho odrazený signál. Zmeriame, koľko toto trvá a vieme vypočítať vzdialenosť. Senzor spotrebúva 8 mA, jeho minimálna vzdialenosť je 1 cm a maximálna 300 cm. Frekvencia ultrazvuku je 40 kHz. Trigger puls má 10 ms a uhol detekcie je 15°.
![](/sensorwiki/images/thumb/2/25/Dsaf-5.jpg/400px-Dsaf-5.jpg)
Literatúra:
Analýza a opis riešenia
Najprv sme si pridali do nášho programu knižnice uart.h, uart.c, ktoré sme si vytvorili na cvičení, aby sme mohli vypisovať vzdialenosť cez Putty. Inicializovali sme UART, vytvorili volatile premennú, do ktorej sme zapisovali vzdialenosť, ktorú sme následne vydelili 41, aby nám vyšla v cm. Následne sme si inicializovali trigger_pulse, aby vyslal signál a mohli sme začať merať. Potom sme čakali, kým bude Echo pin na vysokej úrovni, zmerali sme dĺžku signálu a vypočítali vzdialenosť v cm. Nakoniec sme dĺžku len vypísali cez Putty-ho, počkali chvíľu a merali sme znova.
Zapojenie
Zapojenie sme realizovali pripojením Trigger pinu na D9, Echo pinu na D10 a následne pripojením Gnd na zem a Vcc na 5V. Potom sme zapojili aj ARDUINO na zem.
![](/sensorwiki/images/thumb/0/0d/HC-SR04Ultrasonic_Nano_schem.png/400px-HC-SR04Ultrasonic_Nano_schem.png)
Algoritmus a program
#include <avr/io.h>
#include "uarth.h"
#define F_CPU 16000000UL
#define BAUDRATE 9600
#include <stdio.h>
FILE mystdout = FDEV_SETUP_STREAM(uart_putc, NULL, _FDEV_SETUP_WRITE);
int main(void)
{
adc_init();
hw_init();
uart_init();
stdout = &mystdout;
unsigned int measuredValue;
DDRD |= (1 << PD6); // PD6 as output (OC0A)
TCNT0 = 0; // initialize counter value
OCR0A = 0; // initialize OCR0A value
TCCR0A |= (1 << COM0A1) | (1 << COM0B1) | (1 << WGM01) | (1 << WGM00); // set fast PWM mode and non-inverting mode
TCCR0B |= (1 << CS02) | (1 << CS00); // set prescaler to 1024
while(1)
{
measuredValue = adc_read(4); // read ADC from channel 4
printf("hodnota: %04d \r", measuredValue);
OCR0A = measuredValue / 4; // adjust PWM duty cycle
}
return 0;
}
#include <avr/io.h>
void adc_init(void);
unsigned int adc_read(char a_pin);
#include <stdio.h>
#include "adc.h"
void adc_init(void) {
ADMUX = (1 << REFS0); // reference voltage set to AVcc
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // enable ADC and set prescaler to 128
}
unsigned int adc_read(char a_pin) {
a_pin &= 0x07; // limit input to 0-7
ADMUX = (ADMUX & 0xF8) | a_pin; // select ADC channel with safety mask
ADCSRA |= (1 << ADSC); // start conversion
while (ADCSRA & (1 << ADSC)); // wait for conversion to complete
return ADC; // return the ADC value
}
#ifndef UARTH_H
#define UARTH_H
#include <avr/io.h>
void uart_init(void);
int uart_putc(char c, FILE *stream);
int uart_getc(FILE *stream);
void uart_init(void) {
// Set baud rate
uint16_t baudrate = (F_CPU / (16UL * BAUDRATE)) - 1;
UBRR0H = (uint8_t)(baudrate >> 8);
UBRR0L = (uint8_t)baudrate;
// Enable transmitter and receiver
UCSR0B = (1 << TXEN0) | (1 << RXEN0);
// Set frame format: 8 data bits, 1 stop bit
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);
}
int uart_putc(char c, FILE *stream) {
if (c == '\n') {
uart_putc('\r', stream);
}
while (!(UCSR0A & (1 << UDRE0))); // Wait until the buffer is empty
UDR0 = c;
return 0;
}
int uart_getc(FILE *stream) {
while (!(UCSR0A & (1 << RXC0))); // Wait until data is received
return UDR0;
}
#endif // UARTH_H
Zdrojový kód: zdrojaky.zip
Overenie
![](/sensorwiki/images/thumb/6/6c/IMG_8668.jpg/400px-IMG_8668.jpg)
Výsledok merania
Reálna vzdialenosť a odmeraná sa zhodujú v menších vzdialenostiach, ale čím väčšia vzdialenosť, tým bola aj väčšia odchýlka. Toto spôsobuje číslo, ktorým delíme. V mojom prípade 41, kedy mi vychádzajú rovnako menšie vzdialenosti. Používateľ si musí zvoliť, aké dĺžky chce merať a podľa toho nastaviť dané číslo.
![](/sensorwiki/images/thumb/6/60/Vzdialenost.png/400px-Vzdialenost.png)
Video: