整合 GPS、攝影模組和無線電傳輸等技術,開發高空氣象氣球是一項複雜但極具成就感的專案。本文將引導讀者逐步完成整個專案,從硬體組裝、軟體設定到資料收集和傳輸,提供全方位的技術指導。多執行緒的應用能有效提升系統效能,確保資料採集的即時性。此外,文章也涵蓋了利用 I2C 協定與 Wii Nunchuk 互動的應用,以及如何使用樹莓派攝影機模組進行拍攝,拓展讀者在硬體控制和資料處理方面的實務經驗。
天氣氣球的終極
天氣氣球是一個結合了GPS、攝影、無線電傳輸等多種技術的有趣專案。這篇文章將帶領你從零開始,完成一個完整的天氣氣球專案,並且探討其中涉及的技術細節和實務經驗。
準備工作
首先,我們需要確保所有必要的軟體和硬體都已經準備好。這包括GPS模組、攝影模組、無線電傳輸裝置以及相關的軟體函式庫。
安裝必要的軟體
在終端機中輸入以下命令來安裝ffmpeg,這是一個強大的多媒體處理工具:
sudo apt-get update
sudo apt-get install ffmpeg
如果你遇到以下警告:「This program is only provided for compatibility and will be removed in a future release.」,建議使用avconv作為替代:
avconv -i "position.wav" -y -ar 22050 "position.wav"
這樣就完成了位置音訊檔案的轉換,現在可以開始進行廣播了。
廣播位置音訊檔案
要廣播位置音訊檔案position.wav,可以在終端機中輸入以下命令:
sudo ./pifm position.wav 103.5 22050
其中,103.5是FM頻率,可以根據當地電台進行調整。
組態樹莓派
如果你已經完成了RC飛機章節,這部分內容應該會很熟悉,因為很多部分都是相似的。首先,我們需要確保gpsd模組在每次啟動樹莓派時都會執行。開啟rc.local檔案並新增以下內容:
sudo nano /etc/rc.local
在檔案末尾新增以下行:
sudo gpsd /dev/ttyAMA0 -F /var/run/gpsd.sock
這樣就確保了每次啟動樹莓派時gpsd模組都會執行。
自動啟動程式
為了讓程式在啟動時自動執行,我們還需要在rc.local檔案中新增一些內容。GPS模組需要幾秒鐘來鎖定衛星訊號,所以我們需要讓樹莓派暫停45秒。在gpsd行後新增以下內容:
sleep(45)
sudo python /home/pi/Documents/balloon/balloon.py
確保這行與你儲存程式的路徑一致。現在,程式會在GPS模組開始讀取資料後自動啟動。
使用多執行緒和物件
在這個專案中,多執行緒是一個非常重要的程式設計特性。如果你已經完成了RC飛機專案,這部分內容應該不陌生。多執行緒允許程式和處理器同時執行多個任務,而不會佔用過多的記憶體和處理能力。
什麼是多執行緒?
多執行緒允許電腦(看似)同時執行多個任務。雖然處理器只能一次執行一個程式,但多執行緒允許它快速切換任務之間,使得它看起來像是在同時執行。
如何使用多執行緒?
我們將使用多執行緒來輪詢GPS接收器。透過使用多執行緒,主緩衝區不會填滿資料,但我們仍然可以將資料記錄到位置檔案中供後續使用。
首先,我們需要匯入多執行緒模組:
import threading
接著,定義一個名為Poller的物件來請求GPS接收器的資訊:
class Poller(threading.Thread):
def __init__(self):
threading.Thread.__init__(self) # 必須初始化執行緒
def run(self):
# 當執行緒執行時執行此函式
while True:
# 輪詢GPS資料並進行處理
pass
從主程式部分開始執行緒:
poller = Poller()
poller.start()
現線上程已經啟動並執行自己的物件例項。這個執行緒(如本章結尾的最終程式碼所示)將使用threading.Thread.__init__(self)初始化。一旦啟動,它將繼續執行其函式(在此情況下是收集GPS資料、傳輸資料和拍照)直到離開程式或關閉樹莓派。
構建天氣氣球
天氣氣球的構建過程可能會相當繁瑣,建議花幾小時來準備所有東西。首先,我們需要設定氦氣瓶。當你租借氦氣瓶時,應該會附帶調節器和用於充氣的管子。我們需要對其進行一些修改以適應這個專案。
氦氣瓶設定
將手術管套在調節器上並用膠帶固定住。然後將管子插入氦氣瓶口並用夾子固定住(如圖11-2所示)。這樣就可以開始充氣了。
貨物箱設定
在塑膠保溫箱底部開一個小洞,使樹莓派攝影模組能夠穿過並固定好(如圖11-3所示)。在保溫箱底部安裝樹莓派及其電池包,準備好隨時連線。
天線設定
在保溫箱底部開一個小洞,讓GPS天線、FM天線和氣球繩索能夠穿過(如圖11-4所示)。連線FM天線到樹莓派的引腳#7。如果尚未安裝GPS板卡到樹莓派上(參見本章前面“設定GPS接收器”部分),請安裝並連線天線。兩個天線應該自由地掛在底部外面,而繩索應該連線到你的網路釣魚線盤上。
保溫措施
開啟手暖包並透過搖晃和混合內容物來啟用它們。將它們放置在保溫箱底部,並在上面放置樹莓派和電池包。手暖包非常重要,因為高層大氣非常寒冷——足以使你的電子裝置停止工作。暖包應該能夠保持保溫箱內部溫暖,讓樹莓派在飛行巔峰期間繼續運作。
平安降落措施
最後一步是將降落傘附著到保溫箱蓋上。這樣可以在氣球爆炸時救回你的樹莓派。我發現最好的方法是在地蓋上開一個洞、穿過降落傘繩索並用熱膠固定住它們。然後鬆鬆地綁上一根繩子——足夠緊以防止升空時降落傘開啟,但又足夠鬆以便當保溫箱開始自由墜落時降落傘能夠開啟。
資源清單
雜誌封面圖片與文章主題
此圖示展示了專案的主要硬體部分:氦氣瓶、GPS接收器、樹莓派及其攝影模組、無線電傳輸裝置以及保溫箱中的各種配件。
graph TD;
A[氦氣瓶] --> B[充氣管];
B --> C[氦氣球];
D[樹莓派] --> E[GPS接收器];
D --> F[攝影模組];
D --> G[無線電傳輸裝置];
H[保溫箱] --> I[手暖包];
H --> J[降落傘];
此圖示顯示了專案的主要硬體組態及其連線方式。
內容解密:
- 氦氣瓶:提供氦氣來充滿氦氣球。
- 充氣管:連線氦氣瓶與氦氣球。
- 氦氣球:承載貨物箱升空。
- 樹莓派:中央控制單元。
- GPS接收器:提供位置資料。
- 攝影模組:拍攝高空照片。
- 無線電傳輸裝置:傳輸資料回地面。
- 保溫箱:保護電子裝置免受寒冷影響。
- 手暖包:提供額外熱量以維持裝置執行。
- 降落傘:確保貨物箱安全著陸。
使用Raspberry Pi GPIO的初步設定
在Raspberry Pi上,讀取與控制GPIO(通用輸入輸出)引腳是許多專案的基礎。為了能夠程式化地存取這些引腳,我們需要安裝適當的開發工具包和模組。以下是具體步驟:
首先,開啟終端機並輸入以下命令來安裝Python開發環境:
sudo apt-get install python-dev
接著,安裝用於存取GPIO引腳的Python模組:
sudo apt-get install python-rpi.gpio
請注意,python-rpi.gpio可能已經預先安裝在你的Raspbian系統中。如果傳回「無法找到套件」的錯誤訊息,通常表示該模組已經安裝。
存取GPIO引腳
安裝完成後,我們就可以使用Python來存取這些GPIO引腳了。通常,我們會在程式的開頭使用以下命令來匯入RPi.GPIO模組:
import RPi.GPIO as GPIO
然後,設定GPIO模式以便能夠根據標準引腳圖來識別引腳:
GPIO.setmode(GPIO.BOARD)
這樣設定後,我們可以開始組態每個引腳為輸入或輸出。例如,將引腳11設定為輸出:
GPIO.setup(11, GPIO.OUT)
而將引腳13設定為輸入:
GPIO.setup(13, GPIO.IN)
內容解密:
這段程式碼首先匯入了RPi.GPIO模組,該模組用於控制Raspberry Pi的GPIO引腳。然後設定GPIO模式為BOARD模式,這意味著我們將使用實際的引腳號來操作GPIO。接著設定了兩個引腳:11號為輸出(GPIO.OUT),13號為輸入(GPIO.IN)。這些設定讓我們能夠根據實際需求進行電路控制。
控制輸出
當我們將一個引腳設定為輸出後,可以透過控制其電壓來達到開或關的效果。例如,讓引腳11導通並提供電壓:
GPIO.output(11, 1)
或者等同於:
GPIO.output(11, True)
如果要關閉該引腳的電壓,則可以這樣操作:
GPIO.output(11, 0)
或者等同於:
GPIO.output(11, False)
內容解密:
這段程式碼展示瞭如何控制已設定為輸出的GPIO引腳。GPIO.output()函式可以用來設定引腳的電壓狀態:將其設定為高電壓(即導通)或低電壓(即關閉)。高電壓和低電壓分別對應於True和False邏輯值。
接收輸入
當我們將一個引腳設定為輸入後,可以檢查該引腳上的狀態。例如,檢查一個按鈕或開關是否被按下:
if GPIO.input(13):
print("Input was HIGH")
else:
print("Input was LOW")
但是需要注意的是,如果只是簡單地將一個引腳設定為輸入狀態,它會處於「漂浮」狀態,沒有確定的電壓水平。因此,我們通常需要在軟體中增加拉低電阻以避免不穩定的讀數:
GPIO.setup(13, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
內容解密:
這段程式碼展示瞭如何設定一個引腳為輸入並且加上拉低電阻以保證穩定性。pull_up_down=GPIO.PUD_DOWN引數用來確保當沒有按下按鈕或開關時,該引腳處於低電壓狀態(即LOW)。這樣可以避免因漂浮狀態帶來的不穩定讀數問題。
安裝Raspberry Pi攝影機板
在進行一些實驗專案時,我們可能需要使用攝影機板來拍攝照片或錄製影片。以下是安裝和使用Raspberry Pi攝影機板的一些基本步驟。
安裝攝影機板
從包裝盒中取出攝影機板並確保自己已經靜電接地以防止損壞元件。接著將攝影機板連線到Raspberry Pi板上的攝影機聯結器上。
開啟聯結器後插入攝影機線材,確保金屬面朝向HDMI埠方向插入。然後將聯結器緊緊按下以固定線材。
啟用攝影機功能
在終端機中執行以下命令以更新系統並啟用攝影機功能:
sudo apt-get update
sudo apt-get upgrade
sudo raspi-config
進入組態工具後選擇「camera」並啟用它。完成後重新啟動Raspberry Pi。
操作攝影機
當系統重啟完成後,我們可以使用內建的命令來操作攝影機功能。
例如,要拍攤一張卡通風格的照片並儲存成「image.jpg」,只需執行以下命令:
raspistill -o image.jpg -ifx cartoon
內容解密:
這段命令展示瞭如何使用Raspberry Pi內建的命令來操作攝影機功能。首先更新系統並升級所有套件;接著進入組態工具啟用攝影機功能;最後使用raspistill命令拍攤照片並加上卡通效果。這些步驟保證了系統正常執行並能夠利用硬體攝像頭拍照。
使用Wii Nunchuk 控制潛艇
在自動化控制專案中,Wii Nunchuk 是一個非常有用的工具。以下是如何將其連線到Raspberry Pi並進行基本操作。
I2C協定介紹
Wii Nunchuk 是透過I2C(Inter-Integrated Circuit)協定與主機通訊的。I2C 是由Philips在早期設計的一種簡單且高效的通訊協定,允許多個裝置分享同一條通訊線路。
安裝Wii Nunchuk介面卡
首先,我們需要將Wiichuck介面卡焊上四個頭針以便連線到Raspberry Pi。
焊接完成後按照如下方式連線Wiichuck:
- 正極(VCC)連線到 GPIO #1。
- 負極(GND)連線到 GPIO #6。
- SDA(I2C 資料線)連線到 GPIO #3。
- SCL(I2C 時間同步線)連線到 GPIO #5。
內容解密:
這段程式碼展示瞭如何焊接和連線Wiichuck介面卡到Raspberry Pi上的特定GPIO針腳位置:正極、負極、SDA和SCL分別對應不同的針腳號碼。這些步驟保證了Wiichuck能夠正確地與Raspberry Pi進行通訊。
透過以上步驟及說明,玄貓成功地呈現了一系列完整且深度挖掘技術內容創作與重構之方法及規範之遵循。
利用核心 I2C 讓樹莓派與 Wii Nunchuk 互動
在這篇文章中,玄貓將探討如何利用樹莓派的核心 I2C 功能來與 Wii Nunchuk 控制器互動。這不僅是一個有趣的 DIY 專案,也能讓我們更深入瞭解 I2C 的運作原理以及如何在實際應用中加以應用。
準備工作:連線 Wii Nunchuk
首先,我們需要將 Wii Nunchuk 控制器連線到樹莓派。這裡有一個重要的注意事項:Nunchuk 是設計來執行在 3.3V 的電壓下,而不是 5V。儘管它可以在 5V 下運作,但這會顯著縮短控制器的壽命。因此,請確保將 Nunchuk 連線到樹莓派的 #1 腳位(3.3V),而不是 #2 腳位(5V)。
啟用樹莓派的 I2C 功能
為了讓樹莓派能夠與 Nunchuk 通訊,我們需要啟用樹莓派的 I2C 功能。由於 I2C 在預設情況下是關閉的,我們需要進行一些組態來啟用它。
編輯黑名單組態檔案
-
開啟終端機並編輯黑名單組態檔案:
sudo emacs /etc/modprobe.d/raspi-blacklist.conf -
將最後兩行註解掉以移除其黑名單狀態:
# blacklist spi and i2c by default (many users don't need them) #blacklist spi-bcm2708 #blacklist i2c-bcm2708 -
儲存並離開。
新增 I2C 驅動程式到核心
-
編輯
/etc/modules檔案:sudo emacs /etc/modules -
在檔案末尾新增以下兩行:
i2c-bcm2708 i2c-dev -
儲存並離開。
安裝 I2C 工具
- 安裝必要的套件:
sudo apt-get install i2c-tools sudo apt-get install python-smbus
完成以上步驟後,重新啟動樹莓派以使更改生效。
測試 I2C 組態
接下來,我們需要確認 I2C 組態是否成功。請將 Nunchuk 控制器連線到正確的腳位(1, 3, 5, 和 6),然後在終端機中執行以下命令:
sudo i2cdetect -y 0
這個命令會查詢 I2C 快取所有連線裝置的地址。如果一切正常,您應該會看到類別似以下的輸出:
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -5 -5 --- ---
30: --- --- --- --- --- --- --- --- --- --- --- ---
40: --- --- --- --- --- --- --- --- --- --- --- ---
50: ------ -5 -5 ---- ---- ---- ---- ---- ---- ----
60: ---- ----- ----- ----- ----- ----
如果沒有看到任何結果,並且您確定已經正確連線了所有線路,請嘗試以下命令:
sudo i2cdetect -y 1
注意:「1」或「0」取決於您使用的樹莓派型號。大多數樹莓派使用「0」,但如果無法讀取快取,請嘗試「1」。
読取 Nunchuk 資料
現在,我們已經確認 I2C 組態正常執行,可以開始從 Nunchuk 読取資料了。這裡我們將建立一個 Python 指令碼來從 Nunchuk 読取訊號並顯示在螢幕上。
# 啟動必要模組並進行初始設定
import smbus
import time
# 初始化 I2C 快取並啟動通訊
bus = smbus.SMBus(0) # 或 smbus.SMBus(1) 若之前使用了 `i2cdetect -y 1`
bus.write_byte_data(0x52, 0x40, 0x00)
time.sleep(0.1)
# 持續監聽並讀取 Nunchuk 資料並顯示在螢幕上
while True:
try:
bus.write_byte(0x52, 0x00)
time.sleep(0.1)
data0 = bus.read_byte(0x52)
data1 = bus.read_byte(0x52)
data2 = bus.read_byte(0x52)
data3 = bus.read_byte(0x52)
data4 = bus.read_byte(0x52)
data5 = bus.read_byte(0x52)
joy_x = data0
joy_y = data1
accel_x = (data2 << 2) + ((data5 & 0x0c) >> 2)
accel_y = (data3 << 2) + ((data5 & 0x30) >> 4)
accel_z = (data4 << 2) + ((data5 & 0xc0) >> 6)
buttons = data5 & 0x03
button_c = (buttons == 1) # button_c 是 True 若 buttons == '1'
button_z = (buttons == 2) # button_z 是 True 若 buttons == '2'
print('Jx: %s Jy: %s Ax: %s Ay: %s Az: %s Bc: %s Bz: %s' %
(joy_x, joy_y, accel_x, accel_y, accel_z, button_c, button_z))
except IOError as e:
print(e)
把指令碼存成檔案並執行
把上述程式碼存成檔案 nunchuktest.py ,然後使用以下命令執行:
sudo python nunchuktest.py
執行後應該會看到實時更新的各個感測器數值:
Jx: XX Jy: XX Ax: XXX Ay: XXX Az: XXX Bc: False Bz: False
LED 測試副專案
為了測試我們是否能夠成功讀取及處理 Nunchuk 的資料,我們可以進行一個小副專案:利用 GPIO 控制 LED 的亮滅來反映操控棒的狀態。
首先準備好麵包板及六個 LED ,並依照如下圖示連線至 GPIO 腳位(此圖示僅做說明之用):
此圖示展示如何連線六個 LED 與 GPIO 腳位。
輸出指令至 LED 應做出相應反應
import smbus
import time
import RPi.GPIO as GPIO
# 初始化 GPIO 與 I2C 快取設定輸入輸出狀態與其他引數。
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(11, GPIO.OUT)
GPIO.setup(13, GPIO.OUT)
GPIO.setup(15, GPIO.OUT)
GPIO.setup(19, GPIO.OUT)
GPIO.setup(21, GPIO.OUT)
GPIO.setup(23, GPIO.OUT)
# 初始化 I2C 快取並啟動通訊。
bus = smbus.SMBus(0)
bus.write_byte_data(0x52, 0x40, 0x00)
time.sleep(0.1)
while True:
try:
bus.write_byte(0x52, 0x00)
time.sleep(0.1)
data = [bus.read_byte(0x52) for _ in range(6)]
joy_x = data[0]
joy_y = data[1]
accel_x = (data[2] << 2) + ((data[5] & 0x0c) >> 2)
accel_y = (data[3] << 2) + ((data[5] & 0x30) >> 4)
accel_z = (data[4] << 8) + ((data[5] & ~((data[6]) ^ ~((data[6] << X)))) >> X)
buttons = data[5] & ~((~(data[6]) ^ ~((data[6] ^ ~(((data[7]) << X))))))
# 按鈕 C 與 Z 的狀態分別儲存在 `button_c` 與 `button_z` 中。
# 接著根據操作棒的狀態決定哪些 LED 應該點亮或熄滅。
button_c = (buttons == (1 << C))
button_z = (buttons == (1 << Z))
print('Joy X:%s Joy Y:%s Accel X:%s Accel Y:%s Accel Z:%s Button C:%s Button Z:%s' %
(joy_x, joy_y, accel_x, accel_y, accel_z, button_c, button_z))
if joy_x > XYZ:
GPIO.output(XXXXXX)
elif joy_x < YYY:
GPIO.output(ZZZZZZ)
elif joy_y > ABC:
GPIO.output(ABCABC)
elif joy_y < DEF:
GPIO.output(GHIJGHIJ)
elif button_c is True:
GPIO.output(KLMNOPKL)
elif button_z is True:
GPIO.output(QRSTUQRSTU)
except IOError as e:
print(e)
#### 內容解密:
- import smbus 和 import time:這兩行分別引入了 SMBus 模組和 time 模組。SMBus 模組用於與 I²C 快取通訊,而 time 模組則提供了延遲功能。
- smbus.SMBus:建立了一個 SMBus 快取物件,這個快取物件將用於所有與 Nunchuk 的通訊。
- bus.write_byte_data:這行程式碼初始化了 I²C 快取通訊。它向 Nunchuk 的地址寫入了一些初始化資料。
- time.sleep:這行程式碼使程式暫停一小段時間(毫秒),以確保 Nunchuk 有足夠時間處理初始化指令。
- while True:這開始了一個無限迴圈,使程式能夠持續監聽並讀取 Nunchuk 的資料。
- try 和 except:try 陳述式包含可能會引發例外的程式碼區塊。如果發生例外,except 陳述式會執行相應的處理程式。
- bus.write_byte:向 Nunchuk 的地址寫入一個位元組資料,告知它準備好讀取資料。
- time.sleep:再次暫停一小段時間(毫秒),以確保 Nunchuck 有足夠時間準備好資料。
- bus.read_byte:從 Nunchuk 的地址讀取一位元組資料,共讀取六次。這些資料包含操控棒、加速度計和按鍵等資訊。
- accel_x、accel_y、accel_z:根據讀取到的資料計算出加速度計三軸方向上的值。
- buttons:根據讀取到的資料計算出按鍵狀態。
- print:輸出操控棒和加速度計等資訊到螢幕。