[ Preparation ]
開始之前先將硬體及周邊電子零組件準備完成!
硬體部分:
1. Raspberry Pi 3 Model B
2. HC-SR04 (超音波距離感測模組)
3. 麵包版 x 1
4. LED x 3 (紅黃綠)
5. 1 K 歐姆 電阻 x 4、2 K 歐姆 電阻 x 1
6. 他激式蜂鳴器 x 1 (可發出不同頻率的聲音)
7. 杜邦線 公/母 數條 (約10-15條)
軟體部分:
首先說明一下,因為原本後期就會用到較多 GPIO 來做較多的控制,而在 Raspberry Pi 2 時似乎只有一個 GPIO 的 pin 腳能當作 PWM 使用,而在 Pi 3 似乎就沒這個限制,我就順便測試了將 GPIO 中 SPI 的模組關掉 來當作一般的 GPIO 且使用PWM來當作不同音調的控制!
1. 所以一開始要先確定關掉 GPIO 的 SPI 模組(如要使用一般GPIO pin 腳則可省略此步驟)
打開終端機打上下列指令 (也可以直接開啟桌面圖示調整)
$ sudo raspi-config選擇 7 Advanced Option → A6 SPI → 是否 enable → <No>
這樣就可以確定 SPI 模組為關閉的了
2. 這裡我使用 Python 來完成此次小專題
[ Purpose ]
雖然此次小專題只是將基本所學的及練習的GPIO設置及相關硬體結合起來,但是在兜電路及撰寫程式前也是要先想想我們的目的及需要的功能!
既然是倒車雷達,也就是要偵測到特定距離範圍時會有不同的警示燈及聲音提示!
以下我們用流程圖作為程式草稿比較淺而易懂
程式流程圖 |
[ Hardware information ]
但是架設電路前要先了解到所使用到的硬體及模組資訊
才能正確連接以及依所需功能作調整!
LED及電阻就不多作介紹,特別要說明的是下列兩個:
1. 他激式蜂鳴器 (無源,底部有綠色電路板,腳位等長但有正負之分)
2. HC-SR04
他激式蜂鳴器:
需要震盪方波當作輸入,可發出不同頻率的聲音
這裡我們在 Raspberry Pi 上以 PWM (Pulse Width Modulation) 來實現方波
將 Duty cycle 設定為 50% 就能達成方波的效果,並將頻率設定為自己想要的音調
(會在 coding 部分再詳細說明如何設定)
HC-SR04:
四腳位 (Vcc, Trig, Echo, Gnd) 依照下列電子參數表來連接
Working Voltage (Vcc) | DC 5 V |
Working Current | 15 mA |
Working Frequency | 40 Hz |
Max Range | 4 m |
Min Range | 2 cm |
Measuring Angle | 15 degree |
Trigger Input Signal (Trig) | 10 uS TTL pulse |
Echo Output Signal (Echo) | Input TTL lever signal and the range in proportion |
Dimension | 45*20*15 mm |
也看到其工作電壓為 5 V,所以在 trigger 收到高電位 (Pi 的 GPIO 輸出及容忍電壓都為 3.3 V) 後會發射超音波及接收,而 Echo 隨後會從低電位提升到高電位 (HC-SR04 的工作電壓),但 Pi 容忍電壓僅為 3.3 V 所以我們要將 Echo 接上分壓電路降壓至3.3 V 左右,分壓電路說明如下,而後兩張則為 HC-SR04 的工作示意圖及時序圖:
分壓電路圖 |
工作示意圖 (圖片來源) |
時序圖 (圖片來源) |
[ Setting ]
接下來將電路都兜起來後再開始撰寫程式
實際接線示意圖 |
電路概要圖 |
接腳示意圖 (參考圖片網址) |
實際接線圖 1 (麵包版部分) |
實際接線圖 2 (Raspberry Pi 部分) |
實際接線圖 3 (整體) |
因為我後來會將這距離感測安裝在遙控車專題上所以就直接安裝在車體上了!
電路圖時 2.2 K 電阻代替 2 K 電阻,實際仍以 2 K 電阻為連接
這樣接完硬體部分就大功告成準備撰寫code來控制~
[ Coding-Python ]
這裡主要使用 Python 作為程式控制 (GitHub連結)
#Project: Parking sensors #RaspberryyPi 3 Model B+ #Hardware: LED*3(green,yellow,red), 1K-resistance*4, 2K-resistance*1, buzzer*1 #IC: HC-SR04 Ultrasonic Ranging Module #Editor: NORTHPC import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BOARD) echo_pin=22 trigger_pin=24 BUZZER_pin=26 LED1_pin=19 #GREEN LED2_pin=21 #YELLOW LED3_pin=23 #RED GPIO.setup(trigger_pin, GPIO.OUT,initial=GPIO.LOW) GPIO.setup(echo_pin, GPIO.IN) GPIO.setup(BUZZER_pin, GPIO.OUT) pwm_buzzer = GPIO.PWM(BUZZER_pin,523) #freq=523 Melody DO pwm_buzzer.start(0) #pwm start as dutycycle=0 GPIO.setup(LED1_pin, GPIO.OUT,initial=GPIO.LOW) GPIO.setup(LED2_pin, GPIO.OUT,initial=GPIO.LOW) GPIO.setup(LED3_pin, GPIO.OUT,initial=GPIO.LOW) v=343 #331+0.6T, T=Celsius def detection(): GPIO.output(trigger_pin, GPIO.HIGH) time.sleep(0.00001)#10u seconds TTL Trigger Single GPIO.output(trigger_pin, GPIO.LOW) pulse_start=0 #---Response level output have proportional with detection to the distance--- while GPIO.input(echo_pin)==0: #wait for the echo pin turns high pulse_start=time.time() #record the time point before echo pin turns high while GPIO.input(echo_pin)==1: #wait for the echo pin turns low pulse_end=time.time() #record the time point before echo pin turns low #----------------------------------------------------------------------------- t=pulse_end-pulse_start d=(t*v)/2 return d*100 def detection_average(): d1=detection() time.sleep(0.065) d2=detection() time.sleep(0.065) d3=detection() time.sleep(0.065) distance = (d1+d2+d3)/3 return distance def alarm(distance): if distance>12: warning=0 pwm_buzzer.ChangeDutyCycle(0) GPIO.output(LED3_pin, GPIO.LOW) GPIO.output(LED1_pin, GPIO.HIGH) time.sleep(0.6) GPIO.output(LED1_pin, GPIO.LOW) elif distance<=12 and distance>7: warning=0 pwm_buzzer.ChangeDutyCycle(0) GPIO.output(LED3_pin, GPIO.LOW) pwm_buzzer.ChangeDutyCycle(50) GPIO.output(LED2_pin, GPIO.HIGH) time.sleep(0.3) pwm_buzzer.ChangeDutyCycle(0) GPIO.output(LED2_pin, GPIO.LOW) elif distance<=7 and distance>2: GPIO.output(LED3_pin, GPIO.HIGH) pwm_buzzer.ChangeDutyCycle(50) try: while True: for i in xrange(0,4,1): distance=detection_average() alarm(distance) print "Distance = %.1f cm\n" % distance except KeyboardInterrupt: print "\nException: KeyboardInterrupt\n" finally: pwm_buzzer.stop() GPIO.cleanup()
程式解說:
7~26: 都是在前置初始設定,此次專題使用實體腳位
28: 音速約為 331+0.6T m/s,T 為攝氏溫度,而預設為 T = 20
30~43: 偵測距離的 function,監聽 Echo pin 的變化並計算距離
45~56: 偵測三次取平均值增加準確度,間隔為建議時間差 60ms 以上
58~77: 警示判斷觸發 LED 及蜂鳴器
Distance (D, cm) | LED | BUZZER |
D > 12 | Green (slow) | X |
12 ≥ D > 7 | Yellow (fast) | O (fast) |
7 ≥ D > 2 | Red (continuously) | O (continuously) |
86~87: 接住例外,這程式主要以鍵盤中斷為終止指令 (Ctrl+c)
89~91: 最後停止 PWM 並清空 GPIO
特別說明:Pulse Width Modulation (PWM)
先將 PWM 相關程式都寫在一起
BUZZER_pin=26 GPIO.setup(BUZZER_pin, GPIO.OUT) pwm_buzzer=GPIO.PWM(BUZZER_pin,523) #freq=523 Melody Do pwm_buzzer.satrt(0) #pwm start as dutycycle=0 pwm_buzzer.ChangeDutyCycle(50) pwm_buzzer.stop()第三行: 將已設為輸出的 pin 腳指定為 PWM 並名為 pwm_buzzer,並設定頻率為 523
第四行: 啟動 PWM 並設定 Duty cycle 為 0 (0 < Duty Cycle < 100)
第五行: 改變 PWM 的 Duty cycle 為 50
第六行: 停止 PWM
PWM 是藉由改變工作週期以達到改變電壓如下圖
圖片來源 |
而變化的電壓算法就為高電位乘上 Duty Cycle
圖片來源 |
[ Results ]
硬體設置完成,程式撰寫完畢,那就來執行看看我們的倒車雷達囉!
為了比較準確度順便用尺做了距離示意圖如下
這樣就完成簡易型的倒車雷達啦~
看起來真的是蠻準的!
[ 參考網站 ]
[產品] GPIO 遊戲機學習套件
(不是葉佩雯XD,只是裡面的投影片讓我了解不少程式的概念及樹梅派的相關資訊)
Ultrasonic Ranging Module HC - SR04
HC-SR04 超音波感測器介紹
ATmega168A Pulse Width Modulation – PWM
SCHEMATICS - HOW H-BRIDGES WORK
為了比較準確度順便用尺做了距離示意圖如下
先用尺量好並繪好圖 |
黏在桌上準備 DEMO |
示範影片
這樣就完成簡易型的倒車雷達啦~
看起來真的是蠻準的!
[ 參考網站 ]
[產品] GPIO 遊戲機學習套件
(不是葉佩雯XD,只是裡面的投影片讓我了解不少程式的概念及樹梅派的相關資訊)
Ultrasonic Ranging Module HC - SR04
HC-SR04 超音波感測器介紹
ATmega168A Pulse Width Modulation – PWM
SCHEMATICS - HOW H-BRIDGES WORK
沒有留言:
張貼留言