Xây dựng Rada trên board arduino và hiển thị trên LCD - Dự án RADUINO

Mô tả dự án: 

Đã 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).

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: 

NOKIA5110 | Hướng dẫn sử dụng và chia sẻ thư viện HOÀNG SA

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.

Youtube: 
It works ! Test arduino rada with SRF04, SRF05 ,lcd NOKIA 5110 and lcd ST7565 homephone.
Next! Lcd st7565 rada arduino
Part 2: RADA with arduino, lcd nokia5110 (PCD8544), SRF04
lên
14 thành viên đã đánh giá bài viết này hữu ích.
Chuyên mục: 
Các dự án được truyền cảm hứng

Bộ điều khiển PID - ứng dụng phần 2 - xe dò line dùng thuật toán PID

Tiép nối bài viết về xe dò line cảm ơn Đỗ Hữu Toàn đã viết hộ mình phần 4. hôm nay mình sẽ làm cho chiếc xe dò line đi mượt và có hồn hơn 

lên
34 thành viên đã đánh giá bài viết này hữu ích.
Các bài viết cùng tác giả

ST7565 | Hướng dẫn sử dụng glcd ST7565 homephone và chia sẻ thư viện

LCD chip st7565 có kích thước màn hình 128x64 pixel, là loại lcd graphic đa dụng cho nhiều dự án. Ở nước ta việc mua mới lcd này khá khó do không được ưa chuộng, sở dĩ có chuyện này có lẽ là do thiếu các tài liệu và hướng dẫn liên quan. Hiện lcd loại này chỉ có thể vọc từ các điện thoại homephone hoặc mua cũ. Nếu bạn đang có trong tay lcd này, thì bài viết dưới sẽ giúp bạn sử dụng nó với arduino.

lên
18 thành viên đã đánh giá bài viết này hữu ích.

Sử dụng Ic SRAM 23LC1024 bằng Driver với thư viện SRAM_MANAGER cho arduino

Ở 2 bài trước, chúng ta đã biết cách giao tiếp và lưu trữ cơ bản trên 2 loại SRAM. Sau gần 6 tháng làm việc với SRAM trong các dự án, hôm nay mình sẽ chia sẻ 1 driver do mình thiết kế, nó dùng để hỗ trợ quản lý SRAM 23lc1024, đem đến cách dùng RAM ngoài thân thiện hơn cho lập trình viên.

lên
7 thành viên đã đánh giá bài viết này hữu ích.