2018年7月2日 星期一

Arduino:超音波量測與LCD距離顯示

老是指導自家儍花兒子進行 Arduino 模組學習,讓小誌心癢癢、手癢癢的也想 DIY 動手實作一下。先前儍花哥已經完成超音波量測距模組 HC-SR04R 的基礎學習,雖然是以ardublock 圖形化來學習,但程式觀念也學習得不錯,小誌則想以純程式碼的方式來實際演練一下。

[演練功能]
利用 HC-SR04R模組測量物體距離,並將量測得知的距離數據顯示於LCD模組中;當超出量測範圍 2cm< 或 >300cm 時,LCD 顯示 Out of Range!! 並亮起警示的紅色 LED。


[模組材料]
• Arduino Uno  x 1
• Uno 擴張板  x 1
• HC-SR04R超音波測距模組  x1
• LCD模組1602A  x1
• I2C匯流排  x1(簡化LCD模組控制線路)
• 紅色LED  x1(作為超過量測範圍警示燈)
• 杜邦連接線 x 10條



[[超音波測距模組]]
超音波測距模組一般都是用HC-SR04,小誌這次使用HC-SR04P。
1.最低工作電壓3V,與3.3V供電的MCU可以直接連接。
2.探測距離5V時:2cm~450cm
3. 探測距離3.3V時:2cm~400cm
4.探測角度:小於15度
5.工作溫度:-20度C~+80度C
HC-SR04R 超音波模組
Arduino 腳位對應
1 - VCC
VCC
2 - Trig – Trigger
DPin X S
3 - Echo
DPin X S
4 - GND
GND


HC-SR04與HC-SR04外觀比較圖來源:https://docs.labs.mediatek.com/linkit-7697-blocklyduino/a24-hc-sr04p-12882982.html?selectedPageVersions=5&selectedPageVersions=6

 [[LCD模組]]

  • 此次實驗的顯示模組採用1602A,此款LCD模組是最基本、常見的字元型LCD,使用的電壓為5V,2行顯示,每行可顯示16個字元。
  • 為了簡化顯示模組配線,另配合I2C匯流排來通訊傳輸,因此最終的LCD顯示模組只有四隻接腳,分別為Vcc、GND、SDA、SCL。
  • I2C匯流排能夠讓兩個裝置之間以穩定、高速、雙向的方式只使用兩條線來進行通訊,一條時脈線(SCL)和一條數據線(SDA),所以I2C匯流排所使用的通訊協定也被稱之為「雙線」通訊協定。


LCD接腳
功能
1 (VSS)
電源負極
2 (VCC)
電源正極
3 (Vo)
調整對比
4 (RS)
D0~D7放入資料暫存器 (1) 或指令資料暫存器 (0)
5 (RW)
讀取 (1) 或寫入 (0) LCD
6 (E)
可寫入 (1) 或不可寫入 (0) LCD
7 (D0)
資料位元 0
8 (D1)
資料位元 1
9 (D2)
資料位元 2
10 (D3)
資料位元 3
11 (D4)
資料位元 4
12 (D5)
資料位元 5
13 (D6)
資料位元 6
14 (D7)
資料位元 7
15 (A+)
背光電源正極
16 (-K)
背光電源負極
[程式碼]
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>

// 設定 LCD I2C 位址
// addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

  long duration;
  int intCM;
  const byte trigPin=10;
  const int echoPin=11;
  const int LED=3;
  
void setup() {
// 初始化 LCD,一行 16 的字元,共 2 行,預設開啟背光
lcd.begin(16, 2);
//接腳IO定義
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(LED, OUTPUT);
  digitalWrite(LED, HIGH);
// 輸出啟動訊息
lcd.setCursor(0, 0); // 設定游標位置在第一行行首
lcd.print("SYSTEM START!!");
delay(3000);
lcd.clear(); //顯示清除
}

//測距計算
void GeneratedReturnCM()
{
  //digitalWrite(trigPin, LOW);
  //delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(20);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  duration = duration / 59;
  if ((duration < 2) || (duration > 300)) {
    digitalWrite(LED, LOW); //超出量測範圍亮燈
    intCM = 0;
  }else  {
    digitalWrite(LED, HIGH);
    intCM = duration; //正常量測範圍熄燈
  }
}

void loop() {
//LCD訊息輸出  
lcd.clear(); //顯示清除
lcd.setCursor(0, 0); // 設定游標位置在第一行行首
lcd.print("Object Detection");
lcd.setCursor(0, 1); // 設定游標位置在第二行行首

GeneratedReturnCM(); //呼叫測距計算

//輸出超音波量測距離
if (intCM!=0){
  lcd.print("Distance:");
  lcd.print(intCM);
  lcd.print("cm");
}else{
  lcd.print("Out of Range!!");
}
//0.5秒後重複量測
delay(500); 
}