# 尋線、避障與測距

## 一、尋線與避障

要實作自走車，這三個電子模組元件：尋線、避障與測距，是非常重要的，尋線可以讓自走車沿車黑線行走，而避障與測距，則可以讓自走車不要撞到障礙物，適時的倒退或轉向。

事實上也不要被名字誤導，避障不一定是避障，它主要是測定前方是否有物體，比如廁所裡的自動沖水系統、洗手台的自動給水系統，也是類似的原理。

這二個電子模組元件尋線及避障，是利用發射紅外線，並且依據是否有接收反射回來的紅外線，來決定是不是在線上或是接近障礙物，它們的輸出都是高電位(1)或是低電位(0)，因此利用gpiozero來撰寫是輕而易舉的事。 另外gpiozero的輸出元件(如LED)可以設定來源source，也就是依據另外一個元件來決定LED的亮暗，很好用喔！

{% embed url="https://youtu.be/Sf1YUXOaOyY" %}

```python
from gpiozero import LED, LineSensor
from gpiozero.tools import negated
from signal import pause

led1 = LED(26)
led2 = LED(19)

ls1 = LineSensor(17)
ls2 = LineSensor(27)

def line():
    led1.on()

def no_line():
    led1.off()

ls1.when_line = line
ls1.when_no_line = no_line

led2.source = negated(ls2)

pause()

```

## 二、超音波測距

超音波測距是很常見的電子模組元件，常用來測量元件與物體之間的距離，比如自走車利用這個電子模組元件，偵測與障礙物間的距離，太靠近時就轉向或倒車，事實上現今很多車子都有配倒車偵測，原理是一樣的。 （影片最後一句口誤，是超音波測距不是雷射測距）

{% embed url="https://youtu.be/vrrFT8M-l0M" %}

使用Rpi GPIO的程式碼如下：

```python
import RPi.GPIO as gpio
import time

led = 26
trig = 17
echo = 27

gpio.setmode(gpio.BCM)

gpio.setup(led, gpio.OUT)
gpio.setup(trig, gpio.OUT)
gpio.setup(echo, gpio.IN)
gpio.output(trig, gpio.LOW)


def distance():
    gpio.output(trig, gpio.HIGH)
    time.sleep(0.00001)
    gpio.output(trig, gpio.LOW)

    start_time = time.time()
    end_time = 0
    while gpio.input(echo) == gpio.LOW:
        start_time = time.time()

    while gpio.input(echo) == gpio.HIGH:
        end_time = time.time()

    echo_time = end_time - start_time
    d = echo_time * 343
    d = d / 2
    return d * 100


try:
    while True:
        dis = distance()
        print('{0:.1f}cm'.format(distance()))
        if dis < 10:
            for i in range(3):
                gpio.output(led, gpio.HIGH)
                time.sleep(0.5)
                gpio.output(led, gpio.LOW)
                time.sleep(0.5)
        time.sleep(2)
except KeyboardInterrupt:
    pass
gpio.cleanup()

```

使用gpiozero的程式碼如下：

```python
from gpiozero import LED, DistanceSensor
from time import sleep

led = LED(26)
sensor = DistanceSensor(echo=27, trigger=17)

try:
    while True:
        dis = sensor.distance * 100
        print('{0:.1f}cm'.format(dis))
        if dis < 10:
            led.blink(1, 0.5, 3)
            sleep(5)
        sleep(1)
except KeyboardInterrupt:
    pass

```
