• Distance Measurement using HC-SR04 and AVR Microcontroller - Đo khoảng cách HC-SR04

QC

Distance Measurement using HC-SR04 and AVR Microcontroller - Đo khoảng cách HC-SR04

 Distance Measurement using HC-SR04 and AVR Microcontroller - Đo khoảng cách HC-SR04




Trong hướng dẫn này, chúng ta sẽ thảo luận và thiết kế một mạch để đo khoảng cách. Mạch này được phát triển bằng cảm biến siêu âm giao tiếp “HC-SR04” với vi điều khiển AVR. Cảm biến này sử dụng một kỹ thuật gọi là “ECHO”, một kỹ thuật mà bạn nhận được khi âm thanh phản xạ trở lại sau khi va chạm với một bề mặt.


Chúng ta biết rằng dao động âm thanh không thể xuyên qua chất rắn. Vì vậy, điều gì sẽ xảy ra, khi một nguồn âm thanh tạo ra dao động, chúng sẽ truyền trong không khí với tốc độ 220 mét / giây. Những rung động này khi chúng gặp tai chúng ta, chúng ta mô tả chúng như là âm thanh. Như đã nói ở trên, những dao động này không thể truyền qua vật rắn, vì vậy khi chúng va chạm với một bề mặt như tường, chúng bị phản xạ trở lại với cùng tốc độ tới nguồn, được gọi là tiếng vang.


Cảm biến siêu âm “HC-SR04” cung cấp tín hiệu đầu ra tỷ lệ với khoảng cách dựa trên tiếng vọng. Cảm biến ở đây tạo ra rung động âm thanh trong phạm vi siêu âm khi đưa ra một kích hoạt, sau đó nó sẽ đợi rung động âm thanh quay trở lại. Bây giờ dựa trên các thông số, tốc độ âm thanh (220m / s) và thời gian thực hiện để tiếng vang đến nguồn, nó cung cấp xung đầu ra tỷ lệ với khoảng cách.




Như trong hình, lúc đầu chúng ta cần khởi động cảm biến để đo khoảng cách, đó là tín hiệu logic CAO tại chân kích hoạt của cảm biến cho hơn 10uS, sau đó cảm biến sẽ gửi rung động âm thanh, sau một tiếng vang, cảm biến cung cấp tín hiệu tại chân đầu ra có chiều rộng tỷ lệ với khoảng cách giữa nguồn và vật cản.


Khoảng cách này được tính bằng, khoảng cách (tính bằng cm) = chiều rộng của đầu ra xung (tính bằng uS) / 58.


Ở đây độ rộng của tín hiệu phải được lấy theo bội số uS (micro giây hoặc 10 ^ -6).

Components Required

Hardware: ATMEGA32, Power supply (5v), AVR-ISP PROGRAMMER, JHD_162ALCD (16x2LCD), 1000uF capacitor, 10KΩ resistor (2 pieces) , HC-SR04 sensor.

Software: Atmel studio 6.1, progisp or flash magic.


Circuit Diagram and Working Explanation



Ở đây chúng tôi đang sử dụng PORTB để kết nối với cổng dữ liệu LCD (D0-D7). Bất kỳ ai không muốn làm việc với FUSE BITS của ATMEGA32A đều không thể sử dụng PORTC, vì PORTC chứa một loại giao tiếp đặc biệt chỉ có thể bị vô hiệu hóa bằng cách thay đổi FUSEBITS.


Trong mạch, bạn quan sát tôi chỉ lấy hai chân điều khiển, điều này cho sự linh hoạt dễ hiểu hơn. Bit tương phản và READ / WRITE không thường xuyên được sử dụng để chúng có thể được nối đất. Điều này đặt màn hình LCD ở chế độ đọc và độ tương phản cao nhất. Chúng ta chỉ cần điều khiển các chân ENABLE và RS để gửi các ký tự và dữ liệu cho phù hợp.


Các kết nối được thực hiện cho LCD được đưa ra dưới đây:


PIN1 hoặc VSS để nối đất


PIN2 hoặc VDD hoặc VCC đến nguồn + 5v


PIN3 hoặc VEE nối đất (mang lại độ tương phản tối đa tốt nhất cho người mới bắt đầu)


PIN4 hoặc RS (Lựa chọn đăng ký) đến PD6 của uC


PIN5 hoặc RW (Đọc / Ghi) nối đất (đặt màn hình LCD ở chế độ đọc giúp giảm bớt giao tiếp cho người dùng)


PIN6 hoặc E (Bật) đến PD5 của uC


PIN7 hoặc D0 đến PB0 của uC


PIN8 hoặc D1 đến PB1 của uC


PIN9 hoặc D2 đến PB2 của uC


PIN10 hoặc D3 đến PB3 của uC


PIN11 hoặc D4 đến PB4 của uC


PIN12 hoặc D5 đến PB5 của uC


PIN13 hoặc D6 đến PB6 của uC


PIN14 hoặc D7 đến PB7 của uC


Trong mạch các bạn có thể thấy chúng ta đã sử dụng giao tiếp 8bit (D0-D7) tuy nhiên đây không phải là điều bắt buộc và chúng ta có thể sử dụng giao tiếp 4bit (D4-D7) nhưng với 4 bit chương trình giao tiếp trở nên hơi phức tạp. Vì vậy, như trong bảng trên chúng ta đang kết nối 10 chân của LCD với bộ điều khiển trong đó 8 chân là chân dữ liệu và 2 chân để điều khiển.


Cảm biến siêu âm là một thiết bị bốn chân, PIN1- VCC hoặc + 5V; PIN2-TRIGGER; PIN3- ECHO; PIN4- MẶT BẰNG. Chân kích hoạt là nơi chúng tôi đưa ra kích hoạt để báo cho cảm biến đo khoảng cách. Echo là chân đầu ra nơi chúng ta nhận được khoảng cách dưới dạng độ rộng của xung. Chân echo ở đây được kết nối với bộ điều khiển như một nguồn ngắt bên ngoài. Vì vậy, để có được độ rộng của đầu ra tín hiệu, chân echo của cảm biến được kết nối với INT0 (ngắt 0) hoặc PD2.


Bây giờ để có được khoảng cách, chúng ta phải lập trình bộ điều khiển như sau:


1. Kích hoạt cảm biến bằng cách kéo chân kích hoạt lên cho 12uS ít nhất.


2. Khi tiếng vọng tăng cao, chúng ta nhận được một ngắt bên ngoài và chúng ta sẽ bắt đầu một bộ đếm (kích hoạt bộ đếm) trong ISR (Quy trình Dịch vụ Ngắt) được thực thi ngay sau khi một ngắt được kích hoạt.


3. Khi tiếng vọng xuống thấp một lần nữa, một ngắt được tạo ra, lần này chúng ta sẽ dừng bộ đếm (tắt bộ đếm).


4. Vì vậy, đối với một xung từ cao xuống thấp tại chân echo, chúng tôi đã bắt đầu một bộ đếm và dừng nó. Số lượng này được cập nhật vào bộ nhớ để nhận khoảng cách, vì chúng ta có độ rộng của tiếng vọng đang đếm.


5. Chúng ta sẽ tính toán thêm trong bộ nhớ để có khoảng cách tính bằng cm


6. Khoảng cách được hiển thị trên màn hình LCD 16x2.


Để thiết lập các tính năng trên, chúng ta sẽ thiết lập các thanh ghi sau:



Ba thanh ghi trên phải được đặt cho phù hợp để thiết lập hoạt động và chúng ta sẽ thảo luận ngắn gọn về chúng,


BLUE (INT0): bit này phải được đặt ở mức cao để kích hoạt ngắt ngoài0, khi chân này được đặt chúng ta sẽ cảm nhận được các thay đổi logic tại chân PIND2.


BROWN (ISC00, ISC01): hai bit này được điều chỉnh để thay đổi logic thích hợp tại PD2, được coi là ngắt.



Vì vậy, như đã nói trước đó, chúng ta cần một ngắt để bắt đầu đếm và dừng nó. Vì vậy, chúng tôi đặt ISC00 là một và chúng tôi nhận được một ngắt khi có logic LOW đến HIGH tại INT0; ngắt khác khi có logic CAO đến THẤP.


RED (CS10): Bit này chỉ đơn giản là để bật và tắt bộ đếm. Mặc dù nó hoạt động cùng với các bit khác CS10, CS12. Chúng tôi không thực hiện bất kỳ cài đặt trước nào ở đây, vì vậy chúng tôi không cần phải lo lắng về chúng.


Một số điều quan trọng cần nhớ ở đây là:


Chúng tôi đang sử dụng xung nhịp bên trong của ATMEGA32A là 1MHz. Không có cài đặt trước ở đây, chúng tôi không thực hiện quy trình tạo ngắt kết hợp so sánh, vì vậy không có cài đặt thanh ghi phức tạp.


Giá trị đếm sau khi đếm được lưu vào thanh ghi TCNT1 16bit.


Programming Explanation


Hoạt động của cảm biến đo khoảng cách được giải thích từng bước trong chương trình C bên dưới.
#include <avr/io.h>

//header to enable data flow control over pins

#define F_CPU 1000000      

//telling controller crystal frequency attached

#include <util/delay.h>

//header to enable delay function in program

#define    E   5

//giving name “enable”  to 5th pin of PORTD, since it Is connected to LCD enable pin

#define RS  6

//giving name “registerselection” to 6th pin of PORTD, since is connected to LCD RS pin

void send_a_command(unsigned char command);

void send_a_character(unsigned char character);

void send_a_string(char *string_of_characters);    

static volatile int pulse = 0;//interger  to access all though the program

static volatile int i = 0;// interger  to access all though the program

int main(void)

{

DDRB = 0xFF;

//putting portB output pins

DDRD = 00b11111011;

_delay_ms(50);//giving delay of 50ms

DDRA = 00FF;//Taking portA as output.

GICR|=(1<<INT0);//enabling interrupt0

MCUCR|=(1<<ISC00);//setting interrupt triggering logic change

int16_t COUNTA = 0;//storing digital output

char SHOWA [3];//displaying digital output as temperature in 16*2 lcd

send_a_command(0x01); //Clear Screen 0x01 = 00000001

_delay_ms(50);

send_a_command(0x38);//telling lcd we are using 8bit command /data mode

_delay_ms(50);

send_a_command(0b00001111);//LCD SCREEN ON and courser blinking

sei();// enabling global interrupts

while(1)

{

PORTD|=(1<<PIND0);

_delay_us(15);///triggering the sensor for 15usec

PORTD &=~(1<<PIND0);

COUNTA = pulse/58;//getting the distance based on formula on introduction

send_a_string ("CIRCUIT DIGEST ");//displaying name

send_a_command(0x80 + 0x40 + 0); // shifting cursor  to 1st  shell  of second line

send_a_string ("DISTANCE=");// displaying name

itoa(COUNTA,SHOWA,10); //command for putting variable number in LCD(variable number, in which character to replace, which base is variable(ten here as we are counting number in base10))

send_a_string(SHOWA); //telling the display to show character(replaced by variable number) after positioning the courser on LCD

send_a_string ("cm       ");

send_a_command(0x80 + 0); //retuning to first line first shell

}

}

ISR(INT0_vect)//interrupt service routine when there is a change in logic level

{

if (i==1)//when logic from HIGH to LOW

{

TCCR1B=0;//disabling counter

pulse=TCNT1;//count memory is updated to integer

TCNT1=0;//resetting the counter memory

i=0;

}

if (i==0)//when logic change from LOW to HIGH

{

TCCR1B|=(1<<CS10);//enabling counter

i=1;

}

}

void send_a_command(unsigned char command)

{

PORTA = command;

PORTD &= ~ (1<<RS); //putting 0 in RS to tell lcd we are sending command

PORTD |= 1<<E; //telling lcd to receive command /data at the port

_delay_ms(50);

PORTD &= ~1<<E;//telling lcd we completed sending data

PORTA= 0;

}

void send_a_character(unsigned char character)

{

PORTA= character;

PORTD |= 1<<RS;//telling LCD we are sending data not commands

PORTD |= 1<<E;//telling LCD to start receiving command/data

_delay_ms(50);

PORTD &= ~1<<E;//telling lcd we completed sending data/command

PORTA = 0;

}

void send_a_string(char *string_of_characters)

{

while(*string_of_characters > 0)

{

send_a_character(*string_of_characters++);

}

}

Code :

/*
C Program for Distance Measurement using Ultrasonic Sensor and AVR Microocntroller
 */ 

#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 1000000
#include <util/delay.h>
#include <stdlib.h>

#define enable            5
#define registerselection 6

void send_a_command(unsigned char command);
void send_a_character(unsigned char character);
void send_a_string(char *string_of_characters);

static volatile int pulse = 0;
static volatile int i = 0;

int main(void)
{
    DDRA = 0xFF;
    DDRB = 0xFF;
    DDRD = 0b11111011;
    _delay_ms(50);
    
    GICR|=(1<<INT0);
    MCUCR|=(1<<ISC00);
    
    TCCR1A = 0;
    
    int16_t COUNTA = 0;
    char SHOWA [16];
    

    send_a_command(0x01); //Clear Screen 0x01 = 00000001
    _delay_ms(50);
    send_a_command(0x38);
    _delay_ms(50);
    send_a_command(0b00001111);
    _delay_ms(50);
    
    sei();
    
    while(1)
    {
        PORTD|=(1<<PIND0);
        _delay_us(15);
        PORTD &=~(1<<PIND0);
        
        COUNTA = pulse/58;
        send_a_string ("CIRCUIT DIGEST");
        send_a_command(0x80 + 0x40 + 0);
        send_a_string ("DISTANCE=");
        itoa(COUNTA,SHOWA,10);
        send_a_string(SHOWA);
        send_a_string ("cm    ");
        send_a_command(0x80 + 0);

    }
}

ISR(INT0_vect)
{
    if (i==1)
    {
        TCCR1B=0;
        pulse=TCNT1;
        TCNT1=0;
        i=0;
    }
    if (i==0)
    {
        TCCR1B|=(1<<CS10);
        i=1;
    }
}

void send_a_command(unsigned char command)
{
    PORTB = command;
    PORTD &= ~ (1<<registerselection);
    PORTD |= 1<<enable;
    _delay_ms(8);
    PORTD &= ~1<<enable;
    PORTB = 0;
}

void send_a_character(unsigned char character)
{
    PORTB = character;
    PORTD |= 1<<registerselection;
    PORTD |= 1<<enable;
    _delay_ms(8);
    PORTD &= ~1<<enable;
    PORTB = 0;
}
void send_a_string(char *string_of_characters)
{
    while(*string_of_characters > 0)
    {
        send_a_character(*string_of_characters++);
    }
}





















Nap Code vào PY32F003 dùng Stlink

 Nap Code vào PY32F003 dùng Stlink Bước 1: Cài đặt  KeilC v5.39 theo link sau ( chú ý 5.39 keil c mới nạp ok). https://edge07.111.ir.cdn.ir/...