Operácie

Meranie vzdialenosti ultrazvukovým snímačom HC-SR04: Rozdiel medzi revíziami

Z SensorWiki

(Revízia 15456 používateľa StudentMIPS (diskusia) bola vrátená)
(Jedna medziľahlá úprava od rovnakého používateľa nie je zobrazená.)
Riadok 7: Riadok 7:
  
 
[[Obrázok:arduino_nano.jpg|400px|thumb|center|Vývojová doska ARDUINO-NANO.]]
 
[[Obrázok:arduino_nano.jpg|400px|thumb|center|Vývojová doska ARDUINO-NANO.]]
 
=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°.
 
 
[[Obrázok:dsaf-5.jpg|400px|thumb|center|HC-SR04.]]
 
  
 
'''Literatúra:'''  
 
'''Literatúra:'''  
Riadok 36: Riadok 31:
  
 
<tabs>
 
<tabs>
<tab name="semestralny-projekt"><source lang="c++" style="background: LightYellow;">
+
<tab name="main.c"><source lang="c++" style="background: LightYellow;">
 
#include <avr/io.h>
 
#include <avr/io.h>
#include <util/delay.h>
+
#include "uarth.h"
 +
#define F_CPU 16000000UL
 +
#define BAUDRATE 9600
 
#include <stdio.h>
 
#include <stdio.h>
#include "uart.h"
 
volatile uint16_t distance = 0; //tu budeme ukladat vzdialenost, ako cele cislo o velkosti 16 bitov
 
 
FILE mystdout = FDEV_SETUP_STREAM(uart_putc, NULL, _FDEV_SETUP_WRITE);
 
FILE mystdout = FDEV_SETUP_STREAM(uart_putc, NULL, _FDEV_SETUP_WRITE);
  
void UART_Transmit(unsigned char data) {
+
int main(void)
    while (!(UCSR0A & (1<<UDRE0))); // Caka na prazdny buffer
+
{
    UDR0 = data;
+
  adc_init();
}
+
  hw_init();
 
+
  uart_init();
void trigger_pulse() {
+
  stdout = &mystdout;        
    PORTB |= (1 << PB1); // Nastavi Trig pin na vysoku uroven
+
  unsigned int measuredValue;
    _delay_us(10);             // Caka 10 mikrosekund
 
    PORTB &= ~(1 << PB1); // Nastavi Trig pin na nizku uroven
 
}
 
  
uint16_t measure_pulse_width() {
+
  DDRD |= (1 << PD6); // PD6 as output (OC0A)
    uint16_t pulse_width = 0;
 
    uint16_t timeout = 50000; // Aby sme nesli donekonecna
 
  
    // Caka na Echo pin, kym bude na vysokej urovni
+
  TCNT0 = 0; // initialize counter value
    while (!(PINB & (1 << PB2)) && timeout--) {
 
        _delay_us(1);
 
    }
 
  
    // Mera dlzku signalu
+
  OCR0A = 0; // initialize OCR0A value
    while ((PINB & (1 << PB2)) && timeout--) {
+
                             
        _delay_us(1);
+
  TCCR0A |= (1 << COM0A1) | (1 << COM0B1) | (1 << WGM01) | (1 << WGM00); // set fast PWM mode and non-inverting mode
        pulse_width++;
+
  TCCR0B |= (1 << CS02) | (1 << CS00); // set prescaler to 1024
    }
+
 
 
+
  while(1)
     // Vypocitame vzdialenost v cm
+
  {
     uint16_t distance = pulse_width / 41;
+
     measuredValue = adc_read(4); // read ADC from channel 4
    return distance;
+
    printf("hodnota: %04d \r", measuredValue);
 +
      
 +
    OCR0A = measuredValue / 4; // adjust PWM duty cycle
 +
  }
 +
 
 +
  return 0;
 
}
 
}
 +
</source></tab>
  
int main(void) {
+
<tab name="adc.h"><source lang="c++" style="background: LightYellow;">
    DDRB |= (1 << PB1); // Nastavi Trig pin ako vystup
+
#include <avr/io.h>
    DDRB &= ~(1 << PB2); // Nastavi Echo pin ako vstup
 
PORTB |= (1 << PB2); // Ovladanie pull-up rezistoru
 
 
hw_init();
 
    uart_init();
 
    stdout= &mystdout;
 
 
    while (1) {
 
        trigger_pulse(); // Posle signal na senzor
 
uint16_t distance = measure_pulse_width(); // Merame vzdialenost a vypocitame ju v cm
 
        printf("Vzdialenost: %d cm\n", distance); // Vypiseme vzdialenost cez napr. Putty
 
        _delay_ms(500); // Pockame pred dalsim meranim
 
    }
 
    return 0;
 
}
 
  
 +
void adc_init(void);                                 
 +
unsigned int adc_read(char a_pin);
 
</source></tab>
 
</source></tab>
<tab name="uart.h"><source lang="c++" style="background: LightYellow;">
 
/* ************************************************************************* */
 
/* FileName:            uart.h                                              */
 
/* ************************************************************************* */
 
 
#define LED PB5  // internal on-board LED
 
 
/* na testovanie su uz zadefinovane */
 
// bit_is_set(PINB, SW1)
 
// bit_is_clear(PINB, SW1)
 
 
/* na cakanie su preddefinovane slucky */
 
// loop_until_bit_is_set(PINB, SW1);    // cakanie na uvolnenie tlacitka
 
// loop_until_bit_is_clear(PINB, SW1);  // cakanie na stlacenie tlacitka
 
 
 
#define set_bit(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
 
#define clear_bit(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
 
 
#ifndef UART_H_
 
#define UART_H_
 
  
 +
<tab name="adc.c"><source lang="c++" style="background: LightYellow;">
 
#include <stdio.h>
 
#include <stdio.h>
 +
#include "adc.h"
  
#define BAUD_PRESCALE  (((F_CPU / (BAUDRATE * 16UL))) - 1) // vzor?ek z datasheetu
+
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
 +
}
  
void hw_init( void );
+
unsigned int adc_read(char a_pin) {
void uart_init( void );
+
  a_pin &= 0x07; // limit input to 0-7
   
+
  ADMUX = (ADMUX & 0xF8) | a_pin; // select ADC channel with safety mask
/* Following definition is compatible with STDIO.H, for more
+
  ADCSRA |= (1 << ADSC); // start conversion
* information see https://www.appelsiini.net/2011/simple-usart-with-avr-libc/
+
  while (ADCSRA & (1 << ADSC)); // wait for conversion to complete
*/
+
  return ADC; // return the ADC value
+
}
int uart_putc( char c, FILE *stream );
+
</source></tab>
void uart_puts( const char *s );
 
  
char uart_getc( void );
+
<tab name="uarth.h"><source lang="c++" style="background: LightYellow;">
 
+
#ifndef UARTH_H
void delay(int delay);
+
#define UARTH_H
 
 
#endif /* UART_H_ */
 
 
 
</source></tab>
 
<tab name="uart.c"><source lang="c++" style="background: LightYellow;">
 
/* ************************************************************************* */
 
/* FileName:            uart.c                                              */
 
/* ************************************************************************* */
 
  
 
#include <avr/io.h>
 
#include <avr/io.h>
#include <util/delay.h>
 
#include "uart.h"
 
  
void hw_init( void )
+
void uart_init(void);
{
+
int uart_putc(char c, FILE *stream);
  DDRB |= (1<<LED);   // PORTB.5 kde je LED ma byt OUTPUT
+
int uart_getc(FILE *stream);
  /* sem si mozete dopisat svoje vlastne inicializacne prikazy */
 
}
 
  
void uart_init( void )  
+
void uart_init(void) {
{
+
  // Set baud rate
// for different BAUD rate change the project settings, or uncomment
+
  uint16_t baudrate = (F_CPU / (16UL * BAUDRATE)) - 1;
//  following two lines:
+
  UBRR0H = (uint8_t)(baudrate >> 8);
// #undef  BAUD          // avoid compiler warning
+
  UBRR0L = (uint8_t)baudrate;
//  #define BAUD 115200
 
 
  #include <util/setbaud.h>  // requires defined BAUD
 
 
 
  UBRR0H = UBRRH_VALUE;
 
  UBRR0L = UBRRL_VALUE;
 
  #if USE_2X                // defined in setbaud.h
 
    UCSR0A |= (1 << U2X0);
 
  #else
 
    UCSR0A &= ~(1 << U2X0);
 
  #endif
 
 
 
 
 
    UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); /* 8-bit data */
 
    UCSR0B = _BV(RXEN0) | _BV(TXEN0);   /* Enable RX and TX */
 
}
 
  
 +
  // Enable transmitter and receiver
 +
  UCSR0B = (1 << TXEN0) | (1 << RXEN0);
  
int uart_putc( char c, FILE *stream )
+
  // Set frame format: 8 data bits, 1 stop bit
{
+
  UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);
  if (c == '\n')
 
      uart_putc('\r',stream);
 
 
 
  loop_until_bit_is_set(UCSR0A, UDRE0); /* Wait until data register empty. */
 
  UDR0 = c;
 
  return 0;
 
 
}
 
}
  
 
+
int uart_putc(char c, FILE *stream) {
void uart_puts(const char *s)
+
  if (c == '\n') {
{
+
    uart_putc('\r', stream);
   /* toto je vasa uloha */
+
   }
 +
  while (!(UCSR0A & (1 << UDRE0))); // Wait until the buffer is empty
 +
  UDR0 = c;
 +
  return 0;
 
}
 
}
  
char uart_getc(void)  
+
int uart_getc(FILE *stream) {
{
+
  while (!(UCSR0A & (1 << RXC0))); // Wait until data is received
    loop_until_bit_is_set(UCSR0A, RXC0); /* Wait until data exists. */
+
  return UDR0;
    return UDR0;
 
 
}
 
}
  
void delay(int delay)      // vlastna funkcia pre dlhsie casy
+
#endif // UARTH_H
{
 
  for (int i=1; i<=delay; i++)
 
  _delay_ms(1);
 
}
 
 
 
 
 
 
</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 ===
Riadok 214: Riadok 141:
  
  
[[Súbor:IMG_8668.jpg|400px|thumb|center|Zapojenie.]]
+
[[Súbor:IMG_8668.jpg|400px|thumb|center|Aplikácia.]]
 
==Výsledok merania==
 
==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.
 
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.
[[Súbor:vzdialenost.png|400px|thumb|center|Meranie.]]
+
[[Súbor:vzdialenost.png|400px|thumb|center|Aplikácia.]]
  
  

Verzia zo dňa a času 18:15, 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.

Vývojová doska ARDUINO-NANO.

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.

Schéma zapojenia HC-SR04 senzora.


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

Aplikácia.

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.

Aplikácia.


Video: