Nick Chung gửi vào
- 23437 lượt xem
Đã có nhiều bài viết về cách làm rada hiển thị lên màn hình máy tính. Tương tự, mình cũng sẽ làm một chiếc rada cảnh báo hiển thị lên một vài LCD thông dụng hiện nay.
Chuẩn bị
Mình viết cho 2 loại lcd là ST7565 (homephone) và PCB8540 (nokia5110).
- Hiển thị: 1 lcd st7565 hoặc nokia5110
- Điều khiển: arduino uno r3
- Cảm biến đo khoảng cách: 1 cảm biến siêu âm SHF04 hoặc HRF05
- Cổ xoay: 1 động cơ servo
- Thiết lập người dùng: 2 nút ấn.
- Cảnh báo: led + trở 220 ohm hoặc còi báo.
Ráp mạch
Với màn hình lcd nokia 5110

|
Arduino pin to..
|
Nokia5510
|
|
(3,4,5,6)
|
Lcd nokia (Rst,DC,Din,Clk), trên lcd còn chân CS bạn nối xuống 0v.
|
|
7
|
Còi báo hoặc đèn báo
|
|
8
|
Nút A
|
|
9
|
Nút B
|
|
11
|
Servo
|
|
12
|
Echo của cảm biến siêu âm
|
|
13
|
Trigger của cảm biến siêu âm
|
Bạn nào sử dụng module siêu âm SRF05 như của mình thì để hở chân “OUT”.
Lcd nokia 5110 sử dụng thư viện : PCD8544_hoangsa.h
Bạn hãy cài thư viện theo bài viết này:
Với màn hình lcd st7565 homephone

|
Arduino pin to..
|
LCD ST7565
|
|
(3,4,5,6)
|
Lcd ST7565 (RST,D/C, Din,CLK), trên lcd còn chân CS bạn nối xuống 0v.
|
|
7
|
Còi báo hoặc đèn báo
|
|
8
|
Nút A
|
|
9
|
Nút B
|
|
11
|
Servo
|
|
12
|
Echo của cảm biến siêu âm
|
|
13
|
Trigger của cảm biến siêu âm
|
Bạn nào sử dụng module siêu âm SRF05 như của mình thì để hở chân “OUT”.
LCD ST7565 sử dụng thư viện : st7565_homephone.h
Bạn hãy cài thư viện theo bài viết này:
ST7565 | Hướng dẫn sử dụng glcd ST7565 homephone và chia sẻ thư viện
Hiện cả hai thư viện đều đã được nâng cấp phiên bản V3.0 và V2.0 (16/12/2016) với nhiều tính năng mới.
Để cho hình đỡ rối, mình đã bỏ qua điện trở giảm áp cho lcd, các bạn hãy đọc 2 bài viết trên để có cách nối đúng hơn (nối như trên vẫn chạy).
CODE
LCD nokia5110
// Tác giả: Thái Sơn.<Nick_chung>
// code đăng lên arduino.vn . ngày 18/12/2016.
// phiên bản rada dành cho lcd nokia 5110
//CÁCH dùng:
// b1: sử dụng nút B để chọn cách vẽ vật cản,sau đó nhấn nút A để vào chương trình
// b2: sử dụng nút B để giảm khoảng cách phát hiện, nút A để tăng khoảng cách phát hiện
// đơn vị hiển thị là : cm.
#include "PCD8544_HOANGSA.h"
PCD8544 lcd(3, 4, 5, 6); //RST,D/C, Din,CLK
/*
#include <ST7565_homephone.h>
ST7565 lcd(3, 4, 5, 6); //RST, SCLK, A0, SID
*/
#ifdef __AVR__
#include <avr/io.h>
#include <avr/pgmspace.h>
#endif
const static unsigned char __attribute__ ((progmem)) logo_84x14[] = {
// 84, // width
// 14, // height
/* page 0 (lines 0-7) */
0x0, 0xfe, 0xfe, 0xfe, 0xc6, 0xc6, 0xc6, 0xfe, 0x7e, 0x7c, 0x0, 0x0, 0x0, 0xc0, 0xf0, 0xfe,
0x1e, 0xe, 0xfe, 0xfc, 0xf0, 0xc0, 0x0, 0x0, 0x0, 0xfe, 0xfe, 0xfe, 0x6, 0x6, 0x6, 0x6,
0xe, 0xfe, 0xfc, 0xf8, 0x0, 0x0, 0xfe, 0xfe, 0xfe, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xfe, 0xfe,
0xfe, 0xfe, 0x0, 0x0, 0xfe, 0xfe, 0xfe, 0x0, 0x0, 0xfe, 0xfe, 0xfe, 0xfe, 0x7e, 0xfc, 0xf8,
0xc0, 0x0, 0xfe, 0xfe, 0xfe, 0x0, 0x0, 0xf8, 0xfc, 0xfe, 0xe, 0x6, 0x6, 0x6, 0x6, 0x6,
0xfe, 0xfe, 0xfc, 0xf8,
/* page 1 (lines 8-15) */
0x0, 0x3f, 0x3f, 0x1f, 0x1, 0x1, 0x3, 0x3f, 0x3f, 0x3c, 0x38, 0x20, 0x3c, 0x3f, 0x7, 0x7,
0x7, 0x7, 0x7, 0x7, 0xf, 0x3f, 0x3c, 0x30, 0x0, 0x3f, 0x3f, 0x3f, 0x38, 0x38, 0x38, 0x38,
0x1c, 0x1f, 0xf, 0x7, 0x0, 0x0, 0x7, 0xf, 0x1f, 0x3f, 0x38, 0x38, 0x38, 0x38, 0x3f, 0x1f,
0xf, 0x7, 0x0, 0x0, 0x3f, 0x3f, 0x3f, 0x0, 0x0, 0x3f, 0x3f, 0x3f, 0x3f, 0x0, 0x0, 0x7,
0xf, 0x1f, 0x3f, 0x3f, 0x3f, 0x0, 0x0, 0x7, 0xf, 0x1f, 0x3c, 0x38, 0x38, 0x38, 0x38, 0x3c,
0x1f, 0xf, 0x7, 0x3,
};
#include <Servo.h>
#define CONST 58
#define loc_nhieu 1
// lọc nhiễu: đơn vị cm, thể hiện sự sai lệch 2 lần đo trước và sau
// nếu sai lệch <= loc_nhieu thì kết luận đó là vật cản
// loc_nhieu cầng nhỏ thì độ tin cậy kết luận có vật cản càng cao+
#define trig 13
// chân trig của HC-SR04
#define echo 12
// chân echo của HC-SR04
# define cong_xa 8
#define tru_xa 9
#define loa 7
#define tam_xa_max 250
#define Width_lcd 84
#define Height_lcd 48
const byte x0 = Width_lcd / 2;
const byte y0 = Height_lcd - 1 ;
const byte r_max = Width_lcd / 2; // tâm và bán kính hình tròn
int giao_dien = 0; //
// lựa chọn giao diện
Servo servo; // create servo object to control a servo
void setup()
{
Serial.begin(9600); // giao tiếp Serial với baudrate 9600
pinMode(trig, OUTPUT); // chân trig sẽ phát tín hiệu
pinMode(echo, INPUT); // chân echo sẽ nhận tín hiệu
pinMode(cong_xa, INPUT_PULLUP); // Tăng khoảng cách
pinMode(tru_xa, INPUT_PULLUP); // giam khoảng cách
pinMode(loa, OUTPUT);
servo.attach(11); // attaches the servo on pin 9 to the servo object
lcd.ON();
lcd.SET(23, 0, 0, 0, 4);
Serial.begin(9600);
cai_giao_dien();
}
void cai_giao_dien() {
bool state = digitalRead(tru_xa);
int plus = 0;
lcd.clear();
lcd.bitmap(0, 20, 84, 14, logo_84x14, BLACK);
lcd.display();
delay(5000);
lcd.clear();
lcd.uni_string( 0, 0, uni(u"V\x1EBD v\x1EADt \x63\x1EA3n"), BLACK);
lcd.display();
while (digitalRead(cong_xa) == 1) {
if ((state != digitalRead(tru_xa)) && (digitalRead(tru_xa) == 0)) {
// khi mà nút nhấn là thấp
plus++;
giao_dien = plus % 3;
if (giao_dien > 2) {
giao_dien = 2;
}
if (giao_dien < 0) {
giao_dien = 0;
}
state == digitalRead(tru_xa);
// bip bip
digitalWrite(loa, HIGH);
delay(30);
digitalWrite(loa, LOW);
//vẽ
lcd.fillrect( 0, 15, 100, 30, DELETE);
lcd.number_long(0, 15, giao_dien, STYLE_NUMBER , BLACK);
switch (giao_dien) {
case 0:
lcd.uni_string( 20, 19, uni(u"\x110\x1B0\x1EDDng"), BLACK); break;
case 1:
lcd.uni_string( 20, 19, uni(u"H tr\xF2n"), BLACK); break;
case 2:
lcd.uni_string( 20, 19, uni(u"H vu\xF4ng"), BLACK); break;
}
lcd.display();
delay(250);// làm trễ chống nhiễu
}
}
lcd.clear();
}
int k_cach(int tam_xa) {
/*
Tốc độ của âm thanh trong không khí là 340 m/s (hằng số vật lý), tương đương với 29,412 microSeconds/cm (106 / (340*100)). Khi đã tính được thời gian, ta sẽ chia cho 29,412 để nhận được khoảng cách.
*/
unsigned long duration; // Đo độ rộng xung HIGH ở chân echo.
int distance; // biến lưu khoảng cách
PORTB = PORTB & (~(1 << PB5));
//delayMicroseconds(4);
/* Phát xung từ chân trig */
PORTB = PORTB | (1 << PB5);
delayMicroseconds(10); // xung có độ dài 10 microSeconds
PORTB = PORTB & (~(1 << PB5));
/* Tính toán thời gian */
duration = pulseIn(echo, HIGH);
// Tính rồi trả về khoảng cách đến vật.
distance = int(duration / CONST);
distance = constrain(distance, 0, tam_xa);
//delay(20);
return distance;
}
int quet_k_cach( int goc, int tam_xa) {
servo.write(goc); // quay servo;
//delay(10);// đợi cho servo quay xong
return k_cach(tam_xa);
}
void in_distance( int distance) {
lcd.fillrect(Width_lcd - 19, 0, 19, 8, WHITE); // xóa ảnh cũ
lcd.number_long(Width_lcd - 19, 1, distance, ASCII_NUMBER, BLACK);
}
void in_tam_xa( int tam_xa) {
lcd.fillrect(0, 0, 19, 8, WHITE); // xóa ảnh cũ
lcd.number_long(1, 1, tam_xa, ASCII_NUMBER, BLACK);
}
void ve_vat_can(int x, int y, byte chon_giao_dien) {
switch ( chon_giao_dien) {
case 0:
//cách 1:
lcd.drawline(x0, y0, x, y, BLACK); // vẽ vật cản
lcd.drawline(x0 - 1, y0, x + 1, y, BLACK); // vẽ vật cản
lcd.drawline(x0 + 1, y0, x - 1, y, BLACK); // vẽ vật cản
break;
case 1:
//cách 2;
lcd.fillcircle(x, y, 2, BLACK);
break;
case 2:
lcd.rect( x - 2, y - 2, 4, 4, BLACK); // hình vuông
break;
default:
// mặc định
lcd.rect( x - 2, y - 2, 4, 4, BLACK); // hình vuông
break;
}
/*
*/
//cách 3:
/*
*/
}
void loop()
{
int distance; // biến lưu khoảng cách
int goc_quet;// góc quét: 0->180
int tam_xa = 50; // 50cm
in_tam_xa(tam_xa);
// tâm O(x0,y0)
int xB, yB; // điểm A(xA,yA), B(xB,Yb);
int x_cu, xA, y_cu, yA; // p1(x_cu,y_cu), p2(xA,yA);
int distance_cu, distance_moi;
// khi p1 sát p2 thì mới vẽ, p1 là điểm quét tước, p2 là điểm quét sau(điểm hiện tại)
int analog;
byte r = 250;
int distance_tb[3];// khoảng cách trung bình
while (1) {
for ( unsigned long goc = 0; goc < 361; goc++) { //180 quét đi + 180 quét về
// quay được 10 độ thì kiểm tra button 1 lần
if (digitalRead(cong_xa) == 0) {
tam_xa += 2;
if (tam_xa > tam_xa_max) {
tam_xa = tam_xa_max; // giới hạn cộng
}
in_tam_xa(tam_xa);
}
if (digitalRead(tru_xa) == 0) {
tam_xa -= 2;
if (tam_xa < 0) {
tam_xa = 0; //giới hạn trừ
}
in_tam_xa(tam_xa);
}
if ((goc < 181) && (goc >= 0)) {
goc_quet = goc; //quay thuận 0->180
} else if (goc < 361) {
goc_quet = 360 - goc; // quay ngược 180->0
}
//tìm điểm B
if (goc < 180) {
lcd.Find_XY_Elip(x0, y0, r_max, r_max, goc_quet + 10);
} else {
lcd.Find_XY_Elip(x0, y0, r_max, r_max, goc_quet - 10);
}
xB = lcd.X_Elip();
yB = lcd.Y_Elip();
lcd.drawline(x0, y0, xB, yB, BLACK); //vẽ thanh quét
lcd.display();
digitalWrite(loa, 0); // tắt loa
////////////////////////////
for (byte i = 0; i < 3; i++) {
distance_tb[i] = quet_k_cach(goc_quet, tam_xa);
// delay(50);// đợi
}
if ((abs(distance_tb[0] - distance_tb[1]) <= loc_nhieu) & (abs(distance_tb[1] - distance_tb[2]) <= loc_nhieu) & (abs(distance_tb[0] - distance_tb[2]) <= loc_nhieu)) {
distance_moi = (distance_tb[0] + distance_tb[1] + distance_tb[2]) / 3;
r = (r_max * distance_moi) / tam_xa;
//tìm Pmới (p2)
lcd.Find_XY_Elip(x0, y0, r, r, goc_quet);
xA = lcd.X_Elip();
yA = lcd.Y_Elip();
//delay(10); //dừng khung hình
if (distance_moi < tam_xa) {
if (goc < 180) {
ve_vat_can(xA, yA, giao_dien);
in_distance(distance_moi);
digitalWrite(loa, 1);
} else {
ve_vat_can(xA, yA, giao_dien);
in_distance(distance_moi);
digitalWrite(loa, 1);
}
}//if(distance<tam_xa)
}
lcd.drawline(x0, y0, xB, yB, DELETE); // xóa thanh quét
lcd.drawline(x0 + 1, y0, xB - 1, yB, DELETE); //vẽ thanh quét
lcd.drawline(x0 - 1, y0, xB + 1, yB, DELETE); //vẽ thanh quét
lcd.display();
}//for
}//while
}
ST7565-HOMEPHONE
// Tác giả: Thái Sơn.<Nick_chung>
// code đăng lên arduino.vn . ngày 18/12/2016.
// phiên bản rada dành cho lcd st7565 homephone 128x64
//CÁCH dùng:
// b1: sử dụng nút B để chọn cách vẽ vật cản,sau đó nhấn nút A để vào chương trình
// b2: sử dụng nút B để giảm khoảng cách phát hiện, nút A để tăng khoảng cách phát hiện
// đơn vị hiển thị là : cm.
/*
#include "PCD8544_HOANGSA.h"
PCD8544 lcd(3,4,5,6);//RST,D/C, Din,CLK
*/
#include <ST7565_homephone.h>
ST7565 lcd(3, 4, 5, 6); //RST, SCLK, A0, SID
#ifdef __AVR__
#include <avr/io.h>
#include <avr/pgmspace.h>
#endif
// file bitmap
const static unsigned char __attribute__ ((progmem)) logo_114x20[] = {
// 114, // width
// 20, // height
/* page 0 (lines 0-7) */
0x0, 0xfe, 0xfe, 0xfe, 0xfe, 0xe, 0xe, 0xe, 0xe, 0xbe, 0xfc, 0xfc, 0xf8, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0xc0, 0xf8, 0xfe, 0x7e, 0x1e, 0xfe, 0xfe, 0xf8, 0xc0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0xfe, 0xfe, 0xfe, 0xfe, 0xe, 0xe, 0xe, 0xe, 0xe, 0x1e, 0x3c, 0xfc, 0xf8, 0xf0,
0xc0, 0x0, 0x0, 0x0, 0xfe, 0xfe, 0xfe, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe,
0xfe, 0xfe, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xfe, 0xfe, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xfc, 0xfe,
0xfe, 0xfe, 0x7e, 0xfc, 0xf8, 0xe0, 0x80, 0x0, 0x0, 0x0, 0xfe, 0xfe, 0xfe, 0x0, 0x0, 0x0,
0x80, 0xf0, 0xf8, 0xfc, 0x3c, 0x1e, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0x3e, 0xfc, 0xfc, 0xf8,
0xe0, 0x0,
/* page 1 (lines 8-15) */
0x0, 0xff, 0xff, 0xff, 0xff, 0xe, 0xe, 0xe, 0x3f, 0xff, 0xfb, 0xf3, 0xc1, 0x0, 0x0, 0x0,
0x80, 0xf0, 0xfe, 0xff, 0x7f, 0x73, 0x70, 0x70, 0x70, 0x77, 0x7f, 0xff, 0xfe, 0xf0, 0xc0, 0x0,
0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0xc0, 0xff, 0xff, 0xff,
0x3f, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0xff,
0xff, 0xff, 0x7f, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
0xff, 0xff, 0x0, 0x1, 0x7, 0x1f, 0x7f, 0xfe, 0xf8, 0xe0, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0,
0x3f, 0xff, 0xff, 0xff, 0xc0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0xc0, 0xff, 0xff, 0xff,
0x3f, 0x0,
/* page 2 (lines 16-23) */
0x0, 0x7, 0x7, 0x7, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0x7, 0x7, 0x7, 0x0, 0x4,
0x7, 0x7, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x7, 0x7, 0x7, 0x6,
0x0, 0x0, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x3, 0x3, 0x3, 0x1, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x3, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x3,
0x3, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0x7, 0x7, 0x0, 0x0, 0x0, 0x0, 0x7, 0x7,
0x7, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x3, 0x7, 0x7, 0x7, 0x7, 0x0, 0x0, 0x0,
0x0, 0x0, 0x1, 0x3, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x3, 0x3, 0x1, 0x0,
0x0, 0x0,
};
#include <Servo.h>
#define CONST 58
#define loc_nhieu 1
// lọc nhiễu: đơn vị cm, thể hiện sự sai lệch 2 lần đo trước và sau
// nếu sai lệch <= loc_nhieu thì kết luận đó là vật cản
// loc_nhieu cầng nhỏ thì độ tin cậy kết luận có vật cản càng cao+
#define trig 13
// chân trig của HC-SR04
#define echo 12
// chân echo của HC-SR04
# define cong_xa 8
#define tru_xa 9
#define loa 7
#define tam_xa_max 250
#define Width_lcd 128
#define Height_lcd 64
const byte x0 = Width_lcd / 2;
const byte y0 = Height_lcd - 1 ;
const byte r_max = Width_lcd / 2; // tâm và bán kính hình tròn
int giao_dien = 0; //
// lựa chọn giao diện
Servo servo; // create servo object to control a servo
void setup()
{
Serial.begin(9600); // giao tiếp Serial với baudrate 9600
pinMode(trig, OUTPUT); // chân trig sẽ phát tín hiệu
pinMode(echo, INPUT); // chân echo sẽ nhận tín hiệu
pinMode(cong_xa, INPUT_PULLUP); // Tăng khoảng cách
pinMode(tru_xa, INPUT_PULLUP); // giam khoảng cách
pinMode(loa, OUTPUT);
servo.attach(11); // attaches the servo on pin 9 to the servo object
lcd.ON();
lcd.SET(23, 0, 0, 0, 4);
Serial.begin(9600);
cai_giao_dien();
}
void cai_giao_dien() {
bool state = digitalRead(tru_xa);
int plus = 0;
lcd.clear();
lcd.bitmap(10, 20, 114, 20, logo_114x20, BLACK);
lcd.display();
delay(5000);
lcd.clear();
lcd.uni_string( 0, 0, uni(u"V\x1EBD v\x1EADt \x63\x1EA3n"), BLACK);
lcd.display();
while (digitalRead(cong_xa) == 1) {
if ((state != digitalRead(tru_xa)) && (digitalRead(tru_xa) == 0)) {
// khi mà nút nhấn là thấp
plus++;
giao_dien = plus % 3;
if (giao_dien > 2) {
giao_dien = 2;
}
if (giao_dien < 0) {
giao_dien = 0;
}
state == digitalRead(tru_xa);
// bip bip
digitalWrite(loa, HIGH);
delay(30);
digitalWrite(loa, LOW);
//vẽ
lcd.fillrect( 0, 15, 100, 30, DELETE);
lcd.number_long(0, 15, giao_dien, STYLE_NUMBER , BLACK);
switch (giao_dien) {
case 0:
lcd.uni_string( 20, 19, uni(u"\x110\x1B0\x1EDDng th\x1EB3ng"), BLACK); break;
case 1:
lcd.uni_string( 20, 19, uni(u"H\xECnh tr\xF2n"), BLACK); break;
case 2:
lcd.uni_string( 20, 19, uni(u"H\xECnh vu\xF4ng"), BLACK); break;
}
lcd.display();
delay(250);// làm trễ chống nhiễu
}
}
lcd.clear();
}
int k_cach(int tam_xa) {
/*
Tốc độ của âm thanh trong không khí là 340 m/s (hằng số vật lý), tương đương với 29,412 microSeconds/cm (106 / (340*100)). Khi đã tính được thời gian, ta sẽ chia cho 29,412 để nhận được khoảng cách.
*/
unsigned long duration; // Đo độ rộng xung HIGH ở chân echo.
int distance; // biến lưu khoảng cách
PORTB = PORTB & (~(1 << PB5));
//delayMicroseconds(4);
/* Phát xung từ chân trig */
PORTB = PORTB | (1 << PB5);
delayMicroseconds(10); // xung có độ dài 10 microSeconds
PORTB = PORTB & (~(1 << PB5));
/* Tính toán thời gian */
duration = pulseIn(echo, HIGH);
// Tính rồi trả về khoảng cách đến vật.
distance = int(duration / CONST);
distance = constrain(distance, 0, tam_xa);
//delay(20);
return distance;
}
int quet_k_cach( int goc, int tam_xa) {
servo.write(goc); // quay servo;
//delay(10);// đợi cho servo quay xong
return k_cach(tam_xa);
}
void in_distance( int distance) {
lcd.fillrect(Width_lcd - 19, 0, 19, 8, WHITE); // xóa ảnh cũ
lcd.number_long(Width_lcd - 19, 1, distance, ASCII_NUMBER, BLACK);
}
void in_tam_xa( int tam_xa) {
lcd.fillrect(0, 0, 19, 8, WHITE); // xóa ảnh cũ
lcd.number_long(1, 1, tam_xa, ASCII_NUMBER, BLACK);
}
void ve_vat_can(int x, int y, byte chon_giao_dien) {
switch ( chon_giao_dien) {
case 0:
//cách 1:
lcd.drawline(x0, y0, x, y, BLACK); // vẽ vật cản
lcd.drawline(x0 - 1, y0, x + 1, y, BLACK); // vẽ vật cản
lcd.drawline(x0 + 1, y0, x - 1, y, BLACK); // vẽ vật cản
break;
case 1:
//cách 2;
lcd.fillcircle(x, y, 2, BLACK);
break;
case 2:
lcd.rect( x - 2, y - 2, 4, 4, BLACK); // hình vuông
break;
default:
// mặc định
lcd.rect( x - 2, y - 2, 4, 4, BLACK); // hình vuông
break;
}
/*
*/
//cách 3:
/*
*/
}
void loop()
{
int distance; // biến lưu khoảng cách
int goc_quet;// góc quét: 0->180
int tam_xa = 50; // 50cm
in_tam_xa(tam_xa);
// tâm O(x0,y0)
int xB, yB; // điểm A(xA,yA), B(xB,Yb);
int x_cu, xA, y_cu, yA; // p1(x_cu,y_cu), p2(xA,yA);
int distance_cu, distance_moi;
// khi p1 sát p2 thì mới vẽ, p1 là điểm quét tước, p2 là điểm quét sau(điểm hiện tại)
int analog;
byte r = 250;
int distance_tb[3];// khoảng cách trung bình
while (1) {
for ( unsigned long goc = 0; goc < 361; goc++) { //180 quét đi + 180 quét về
// quay được 10 độ thì kiểm tra button 1 lần
if (digitalRead(cong_xa) == 0) {
tam_xa += 2;
if (tam_xa > tam_xa_max) {
tam_xa = tam_xa_max; // giới hạn cộng
}
in_tam_xa(tam_xa);
}
if (digitalRead(tru_xa) == 0) {
tam_xa -= 2;
if (tam_xa < 0) {
tam_xa = 0; //giới hạn trừ
}
in_tam_xa(tam_xa);
}
if ((goc < 181) && (goc >= 0)) {
goc_quet = goc; //quay thuận 0->180
} else if (goc < 361) {
goc_quet = 360 - goc; // quay ngược 180->0
}
//tìm điểm B
if (goc < 180) {
lcd.Find_XY_Elip(x0, y0, r_max, r_max, goc_quet + 10);
} else {
lcd.Find_XY_Elip(x0, y0, r_max, r_max, goc_quet - 10);
}
xB = lcd.X_Elip();
yB = lcd.Y_Elip();
lcd.drawline(x0, y0, xB, yB, BLACK); //vẽ thanh quét
lcd.display();
digitalWrite(loa, 0); // tắt loa
////////////////////////////
for (byte i = 0; i < 3; i++) {
distance_tb[i] = quet_k_cach(goc_quet, tam_xa);
// delay(50);// đợi
}
if ((abs(distance_tb[0] - distance_tb[1]) <= loc_nhieu) & (abs(distance_tb[1] - distance_tb[2]) <= loc_nhieu) & (abs(distance_tb[0] - distance_tb[2]) <= loc_nhieu)) {
distance_moi = (distance_tb[0] + distance_tb[1] + distance_tb[2]) / 3;
r = (r_max * distance_moi) / tam_xa;
//tìm Pmới (p2)
lcd.Find_XY_Elip(x0, y0, r, r, goc_quet);
xA = lcd.X_Elip();
yA = lcd.Y_Elip();
//delay(10); //dừng khung hình
if (distance_moi < tam_xa) {
if (goc < 180) {
ve_vat_can(xA, yA, giao_dien);
in_distance(distance_moi);
digitalWrite(loa, 1);
} else {
ve_vat_can(xA, yA, giao_dien);
in_distance(distance_moi);
digitalWrite(loa, 1);
}
}//if(distance<tam_xa)
}
lcd.drawline(x0, y0, xB, yB, DELETE); // xóa thanh quét
lcd.drawline(x0 + 1, y0, xB - 1, yB, DELETE); //vẽ thanh quét
lcd.drawline(x0 - 1, y0, xB + 1, yB, DELETE); //vẽ thanh quét
lcd.display();
}//for
}//while
}
Cách sử dụng
- B1: sử dụng nút B để chọn cách vẽ vật cản, sau đó nhấn nút A để vào chương trình
- B2: sử dụng nút B để giảm khoảng cách phát hiện, nút A để tăng khoảng cách phát hiện
- Đơn vị hiển thị là: cm.
- Số bên góc trái màn hình hiển thị tầm quét xa nhất của rada.
- Số bên phải hiển thị khoảng cách của vật cản tới cảm biến.
- Bề mặt vật cản cần phải có tính phản xạ âm thanh tốt, mặt phản xạ song song với mặt cảm biến thì khả năng phát hiện ở đầu thu là cao nhất.
Tạm kết.
Phần khó nhất vẫn là khâu vẽ, khó thứ hai là lọc nhiễu… cứ luẩn quẩn mãi..
OK. Chúc mọi người có tuần làm việc mới hiệu quả.
Tác giả: Thái Sơn.


