在嵌入式系統開發中,經常需要與各種硬體互動,例如鍵盤、感測器和 GPS 模組。本文將示範如何使用 Python 在 Raspberry Pi 上操作這些裝置。首先,我們將介紹如何使用 RPi.GPIO 函式庫控制矩陣鍵盤,讀取使用者輸入。接著,我們將說明如何使用 gpiozero 函式庫操作 PIR 動作感測器,偵測物體移動。最後,我們將探討如何連線和讀取序列 GPS 模組的資料,並使用 Python-GPS 函式庫解析 GPS 資訊。這些範例將涵蓋硬體連線、程式碼撰寫以及相關函式庫的使用,讓讀者能夠快速上手嵌入式系統開發。

12.8 使用矩陣按鍵盤

問題

您想要在 Python 中偵測矩陣按鍵盤的按鍵。

解決方案

使用 SparkFun 矩陣按鍵盤模組,並編寫 Python 程式碼來偵測按鍵。

程式碼

import time
import RPi.GPIO as GPIO

# 定義按鍵盤的行和列
rows = [17, 25, 23, 22]
cols = [26, 19, 13, 6]

# 定義按鍵的對映
keys = [
    ['1', '2', '3', '*'],
    ['4', '5', '6', '#'],
    ['7', '8', '9', '0']
]

def get_key():
    key = None
    for col_num, col_pin in enumerate(cols):
        GPIO.output(col_pin, GPIO.HIGH)
        for row_num, row_pin in enumerate(rows):
            if GPIO.input(row_pin) == 0:
                key = keys[row_num][col_num]
                break
        GPIO.output(col_pin, GPIO.LOW)
        if key is not None:
            break
    return key

while True:
    key = get_key()
    if key:
        print(key)
    time.sleep(0.3)

討論

這個程式碼使用 RPi.GPIO 函式庫來控制按鍵盤的行和列。get_key 函式迴圈遍歷每個列,然後檢查每個行是否被按下。如果一個行被按下,則傳回對應的按鍵名稱。主迴圈呼叫 get_key 函式並列印傳回的按鍵名稱。

圖表翻譯

  flowchart TD
    A[開始] --> B[初始化GPIO]
    B --> C[定義按鍵盤的行和列]
    C --> D[定義按鍵的對映]
    D --> E[迴圈遍歷每個列]
    E --> F[檢查每個行是否被按下]
    F --> G[傳回對應的按鍵名稱]
    G --> H[列印傳回的按鍵名稱]

內容解密

這個程式碼使用 RPi.GPIO 函式庫來控制按鍵盤的行和列。get_key 函式迴圈遍歷每個列,然後檢查每個行是否被按下。如果一個行被按下,則傳回對應的按鍵名稱。主迴圈呼叫 get_key 函式並列印傳回的按鍵名稱。

圖表翻譯

  flowchart TD
    A[開始] --> B[初始化GPIO]
    B --> C[定義按鍵盤的行和列]
    C --> D[定義按鍵的對映]
    D --> E[迴圈遍歷每個列]
    E --> F[檢查每個行是否被按下]
    F --> G[傳回對應的按鍵名稱]
    G --> H[列印傳回的按鍵名稱]

相關內容

您也可以使用 USB 按鍵盤來簡化程式碼,並使用 Recipe 12.11 中的方法來偵測按鍵。

12.9 使用 PIR 動作偵測模組

介紹

PIR 動作偵測模組是一種常見的感測器,能夠偵測到物體的運動。這個模組通常使用於安全系統、自動控制系統等領域。

硬體連線

如圖 12-14 所示,PIR 動作偵測模組可以透過以下步驟連線到 Raspberry Pi:

  • 將 PIR 模組的 VCC 腳連線到 Raspberry Pi 的 5V 電源。
  • 將 PIR 模組的 GND 腳連線到 Raspberry Pi 的 GND。
  • 將 PIR 模組的 OUT 腳連線到 Raspberry Pi 的 GPIO 18 腳。

程式碼

以下是使用 PIR 動作偵測模組的 Python 程式碼:

from gpiozero import MotionSensor

pir = MotionSensor(18)
while True:
    pir.wait_for_motion()
    print("偵測到運動!")

這個程式碼使用 gpiozero 函式庫來控制 PIR 動作偵測模組。當偵測到運動時,程式碼會印出 “偵測到運動!” 的訊息。

討論

gpiozero 函式庫提供了一個 MotionSensor 類別來控制 PIR 動作偵測模組。這個類別可以監控 GPIO 腳的狀態,並在偵測到運動時觸發事件。

PIR 動作偵測模組的輸出會在偵測到運動時保持高電平一段時間。這個時間可以透過模組上的電位器進行調整。另外,模組上的第二個電位器(如果存在)可以設定光線強度的閾值,以便在光線強度低於閾值時啟動感應器。

相關資訊

更多關於 MotionSensor 類別的資訊可以在 gpiozero 函式庫的檔案中找到。你也可以將這個食譜與 Recipe 7.16 結合,當偵測到入侵者時傳送電子郵件通知。或者,你可以將其與 If This Then That (IFTTT) 整合,提供更多的通知方式(見 Recipe 16.4)。若要使用電腦視覺和網路攝影機來偵測運動,請參考 Recipe 8.6。

12.10 將 GPS 新增到 Raspberry Pi

問題

你想要將一個序列 GPS 模組連線到一個移動的 Raspberry Pi,並使用 Python 存取資料。

解決方案

一個具有 3.3V 輸出的序列 GPS 模組可以直接連線到 Raspberry Pi 的 RXD 連線。這意味著為了使其正常工作,你必須按照 Recipe 2.6 中的步驟進行。注意,雖然你想要啟用序列埠硬體,但你不應啟用序列控制檯選項。

圖 12-15 顯示瞭如何將模組連線。Raspberry Pi 的 RXD 連線到 GPS 模組的 Tx。其他連線只有 GND 和 5V,因此你可以使用三個母對母頭。

你可以使用 Minicom(見 Recipe 9.7)來檢視原始的 GPS 資料。使用以下命令:

minicom -b 9600 -o -D /dev/ttyUSB0

這個命令會以 9600 波特率啟動 Minicom,並連線到 /dev/ttyUSB0 埠。

程式碼

以下是使用 GPS 模組的 Python 程式碼:

import serial

ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=1)
while True:
    data = ser.readline()
    print(data.decode())

這個程式碼使用 serial 函式庫來讀取 GPS 模組的資料。它會不斷地讀取資料,並印出解碼後的資料。

討論

GPS 模組會以 NMEA 0183 格式輸出資料,這是一種標準的 GPS 資料格式。這個格式包含了多行資料,每行代表不同的資訊,例如位置、速度、方向等。

你可以使用 serial 函式庫來讀取這些資料,並進行解析以提取有用的資訊。

使用Minicom觀察GPS訊息

使用Minicom命令觀察GPS訊息:

$ minicom -b 9600 -o -D /dev/ttyS0

Older版本的Raspbian可能會將 /dev/ttyAMA0 與TTL序列埠相關聯,因此如果您無法看到資料,請嘗試使用 /dev/ttyAMA0 代替 /dev/ttyS0

GPS訊息格式

GPS訊息格式如下:

$GPRMC,095509.090,V,,,,,0.00,0.00,040619,,,N*4E
$GPVTG,0.00,T,,M,0.00,N,0.00,K,N*32
$GPGGA,095510.090,,,,,0,0,,,M,,M,,*49

這些訊息需要解碼。

安裝GPS工具

安裝GPS工具:

$ sudo apt-get install gpsd
$ sudo apt-get install gpsd-clients

其中,gpsd 是一個工具,可以從序列或USB連線(以及其他來源)讀取GPS資料,並使其可供客戶端程式使用。

組態GPSD

組態GPSD:

$ sudo nano /etc/default/gpsd

刪除檔案中的所有內容,並替換為以下內容:

START_DAEMON="true"
USBAUTO="false"
DEVICES="/dev/ttyS0"
GPSD_OPTIONS="-n"
GPSD_SOCKET="/var/run/gpsd.sock"

儲存檔案並啟動gpsd服務:

$ sudo gpsd /dev/ttyS0

您可以使用以下命令檢查是否正常運作:

$ cgps -s

使用Python-GPS函式庫

安裝python-gps函式庫:

$ sudo apt-get install python-gps

使用以下程式碼建立一個簡短的測試程式,以顯示緯度、經度和時間:

from gps import *

session = gps()

將此程式碼儲存為 ch_12_gps_test.py 檔案(請勿將其命名為 gps.py,因為這將與Python GPS函式庫發生衝突)。

GPS 資料讀取與處理

在本文中,我們將探討如何使用 Python 讀取 GPS 資料並進行處理。首先,我們需要建立一個 session 並啟用 WATCH_ENABLE 和 WATCH_NEWSTYLE 的旗標,以便接收 GPS 資料。

session.stream(WATCH_ENABLE|WATCH_NEWSTYLE)
while True:
    report = session.next()
    if report.keys()[0] == 'epx' :
        lat = float(report['lat'])
        lon = float(report['lon'])
        print("lat=%f\tlon=%f\ttime=%s" % (lat, lon, report['time']))
    time.sleep(0.5)

這段程式碼會不斷地讀取 GPS 資料,並將經度、緯度和時間印出來。

使用 xgps 工具顯示 GPS 資料

除了使用 Python 處理 GPS 資料外,我們也可以使用 xgps 工具來顯示 GPS 資料。只需在終端機中輸入 $ xgps 即可啟動 xgps 工具。

解決方案:攔截鍵盤按鍵

如果您想要攔截個別鍵盤按鍵,可以使用 sys.stdin.read 函式。這個方法的優點是無需啟動圖形使用者介面 (GUI),因此可以從 SSH 會話中執行程式。

import sys, tty, termios

內容解密:

上述程式碼使用 sys.stdin.read 函式來讀取鍵盤按鍵。tty 和 termios 模組用於控制終端機的設定。

圖表翻譯:

  flowchart TD
    A[開始] --> B[建立 session]
    B --> C[啟用 WATCH_ENABLE 和 WATCH_NEWSTYLE]
    C --> D[讀取 GPS 資料]
    D --> E[處理 GPS 資料]
    E --> F[顯示 GPS 資料]
    F --> G[攔截鍵盤按鍵]
    G --> H[結束]

這個流程圖描述了 GPS 資料讀取和處理的流程,包括建立 session、啟用 WATCH_ENABLE 和 WATCH_NEWSTYLE、讀取 GPS 資料、處理 GPS 資料、顯示 GPS 資料和攔截鍵盤按鍵。

使用Python偵測按鍵事件

簡介

在許多應用中,偵測按鍵事件是一個重要的功能,特別是在遊戲開發或需要即時反應的程式中。Python提供了多種方法來實作按鍵偵測,本文將介紹兩種常見的方法:使用termios模組和使用pygame函式庫。

方法一:使用termios模組

termios模組提供了一種方式來控制終端的行為,包括偵測按鍵事件。以下是一個簡單的範例程式,展示如何使用termios來偵測按鍵:

import sys
import termios
import tty

def read_ch():
    fd = sys.stdin.fileno()
    old_settings = termios.tcgetattr(fd)
    try:
        tty.setraw(sys.stdin.fileno())
        ch = sys.stdin.read(1)
    finally:
        termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
    return ch

while True:
    ch = read_ch()
    if ch == 'x':
        break
    print("按下的鍵是:", ch)

這個程式使用termios模組來設定終端為 raw 模式,然後讀取按下的鍵。當按下x鍵時,程式會離開迴圈。

方法二:使用pygame函式庫

pygame是一個Python函式庫,主要用於開發遊戲,但也可以用來偵測按鍵事件。以下是一個簡單的範例程式,展示如何使用pygame來偵測按鍵:

import pygame
import sys

from pygame.locals import *

pygame.init()

screen = pygame.display.set_mode((640, 480))

pygame.mouse.set_visible(0)

while True:
    for event in pygame.event.get():
        if event.type == KEYDOWN:
            print("按下的鍵是:", event.key)

這個程式使用pygame函式庫來初始化一個視窗,然後偵測按鍵事件。當按下任意鍵時,程式會印出按下的鍵。

比較兩種方法

兩種方法都可以用來偵測按鍵事件,但是有以下不同:

  • termios模組需要設定終端為 raw 模式,而pygame函式庫不需要。
  • termios模組只能偵測按鍵事件,而pygame函式庫可以偵測多種事件,包括滑鼠移動、滑鼠按下等。
  • pygame函式庫需要初始化一個視窗,而termios模組不需要。

因此,選擇哪種方法取決於具體的需求。如果只需要偵測按鍵事件,且不需要視窗,則可以使用termios模組。如果需要偵測多種事件,且需要視窗,則可以使用pygame函式庫。

圖表翻譯:

  graph LR
    A[程式啟動] -->|初始化終端|> B[設定終端為raw模式]
    B -->|讀取按下的鍵|> C[印出按下的鍵]
    C -->|按下x鍵|> D[離開迴圈]

這個圖表展示了使用termios模組偵測按鍵事件的流程。

內容解密:

上述程式使用termios模組來設定終端為 raw 模式,然後讀取按下的鍵。當按下x鍵時,程式會離開迴圈。這個程式可以用來偵測按鍵事件,但是需要注意終端的設定和還原。

嵌入式系統開發對於硬體周邊的整合需求日益增長,如何有效且簡潔地控制這些元件成為開發者關注的焦點。本文探討了矩陣按鍵盤、PIR 動作偵測模組和 GPS 模組的 Python 控制方法,涵蓋了硬體連線、程式碼實作以及資料處理等環節。分析顯示,使用如 RPi.GPIOgpiozeroserial 等 Python 函式庫能有效簡化開發流程,降低程式碼複雜度。然而,直接使用底層函式庫需要開發者對硬體和通訊協定有更深入的理解,也可能需要自行處理訊號幹擾和錯誤處理等問題。

技術限制深析顯示,雖然 gpiozero 等高階函式庫簡化了 PIR 感測器的使用,但對於更進階的功能,例如調整感測器靈敏度和光線閾值,仍需深入底層設定。此外,GPS 模組的資料解析和應用也需要開發者具備 NMEA 0183 格式的知識,並根據應用場景選擇合適的解析方法和資料過濾策略。值得注意的是,序列通訊的穩定性和資料完整性也需要額外關注,特別是在移動環境中。

展望未來,隨著物聯網技術的發展,嵌入式系統將整合更多種類別的感測器和通訊模組。玄貓認為,開發更易用、更抽象化的 Python 函式庫,以及提供更完善的範例程式碼和教學資源,將有助於降低開發門檻,加速物聯網應用創新。對於開發者而言,深入理解硬體原理和通訊協定,並掌握各種 Python 工具和函式庫的使用技巧,將成為未來嵌入式系統開發的關鍵競爭力。