本篇文章將先前撰寫的 Python 元件整合至單一指令碼,實作根據 Raspberry Pi 的遙控潛水器控制。文章首先介紹瞭如何使用 raspistillraspivid 指令擷取靜態圖片和錄製影片,並詳細說明瞭主程式迴圈的邏輯,包含操作桿輸入處理、馬達控制和按鍵功能。接著,文章逐步指導讀者完成潛水器的硬體組裝,涵蓋 PVC 框架搭建、Raspberry Pi 防水外殼製作、馬達防水處理、Wii Nunchuck 連線以及電源管理等關鍵步驟。同時,文章也提供了組裝過程中的注意事項,例如密封劑的使用、電源電壓的選擇等,並列舉了一些常見問題及解決方案,例如電池續航力不足、攝影機故障等。

完全自主潛水器控制程式

在完成所有 Python 元件的編寫後,接下來要做的就是將它們整合成一個完整的指令碼。我們已經確定了運動引數,因此我們需要編寫一些函式,這些函式將從主程式迴圈中呼叫,以回應操作桿的移動和按鍵的按壓。最簡單的部分是攝影機的功能。

擷取靜態圖片與錄製影片

首先,讓我們來看看擷取靜態圖片的函式。當 C 鍵被按下時,會執行以下函式:

def take_still_pic(pic_num):
    "當 C 按鈕被按下時擷取靜態圖片"
    subprocess.call(["raspistill -o image" + str(pic_num) + ".jpg"], shell=True)

這個函式使用系統呼叫 raspistill 來擷取圖片,並將其命名為 pic_num 的引數。接著,我們來看看錄製影片的函式:

def take_video():
    "當 Z 按鈕被按下時錄製影片"
    subprocess.call(["raspivid -o video.mp4"], shell=True)

這個函式使用 raspivid 系統呼叫來錄製影片,並將其儲存為 video.mp4

內容解密:

  • take_still_pic(pic_num) 函式:這個函式接受一個整數引數 pic_num,用於命名擷取的圖片。例如,如果 pic_num 是 4,那麼擷取的圖片將被命名為 image4.jpg。這樣可以避免每次按下 C 按鈕時都覆寫之前的圖片。
  • take_video() 函式:這個函式不接受任何引數,它會直接呼叫 raspivid 系統命令來錄製影片並儲存為 video.mp4
  • 程式碼中的 subprocess.call 是 Python 的一個模組,用於執行外部命令。這裡我們使用它來呼叫 Raspberry Pi 上的攝影機指令。

主程式迴圈

在主程式迴圈中,我們需要設定馬達控制針腳、讀取操作桿資料並根據操作桿和按鍵狀態執行相應的動作。以下是完整的主程式碼:

import time
import smbus
import RPi.GPIO as GPIO
import subprocess

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)

# 擷取靜態圖片的函式
def take_still_pic(num):
    subprocess.call(["raspistill -o image" + str(num) + ".jpg"], shell=True)

# 前進函式
def go_forward():
    GPIO.output(19, 1)  # IN1 on
    GPIO.output(23, 0)  # IN2 off
    GPIO.output(11, 1)  # IN3 on
    GPIO.output(15, 0)  # IN4 off

# 倒退函式
def go_backward():
    GPIO.output(19, 0)  # IN1 off
    GPIO.output(23, 1)  # IN2 on
    GPIO.output(11, 0)  # IN3 off
    GPIO.output(15, 1)  # IN4 on

# 右轉函式
def go_right():
    GPIO.output(19, 1)  # IN1 on
    GPIO.output(23, 0)  # IN2 off
    GPIO.output(11, 0)  # IN3 off
    GPIO.output(15, 1)  # IN4 on

# 左轉函式
def go_left():
    GPIO.output(19, 0)  # IN1 off
    GPIO.output(23, 1)  # IN2 on
    GPIO.output(11, 1)  # IN3 on
    GPIO.output(15, 0)  # IN4 off

# 啟用馬達控制針腳設定
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)

# 啟用兩個馬達
GPIO.output(13, 1)
GPIO.output(21, 1)

# 初始化操作桿讀取器(nunchuk)
bus = smbus.SMBus(0)
bus.write_byte_data(0x52, 0x40, 0x00)
time.sleep(0.5)

x = 1

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) or (buttons == 2)
        button_z = (buttons == 0) or (buttons == 2)

        if joy_x > 200:     # 操作桿向右
            go_right()
        elif joy_x < 35:     # 操作桿向左
            go_left()
        elif joy_y > 200:     # 操作桿向前
            go_forward()
        elif joy_y < 35:     # 操作桿向後
            go_backward()
        elif button_c == True:
            x += x+ x+ x+ x+ x+ x+ x+ x+ x+ x+ x+ x+ x+
            take_still_pic(x)
        elif button_z == True:
            print("Z 按鈕被按下!")
        else:   # 操作桿在中立位置且沒有按鍵被按下時停止馬達執行
            GPIO.output([], [])
            pass

   except IOError as e:
       print(e)

內容解密:

  • 首先我們初始化了兩個馬達和操作桿讀取器(nunchuk)。然後進入無限迴圈中持續讀取操作桿和按鍵狀態。
  • 操作桿的 X 與 Y 值分別對應到不同的方向移動。例如,當操作桿向右移動時 (joy_x > 超過某個值) 則會呼叫 go_right() 函式。
  • 按鍵部分則根據不同按鍵狀態執行不同動作。例如,當 C 按鈕被按下時 (button_c == True) 則會呼叫 take_still_pic(x) 函式來擷取靜態圖片。
  • 主程式迴圈中使用了例外處理機制來捕捉可能發生的 I/O 錯誤。

構建潛水器

現在我們已經完成了控制程式碼,接下來就是實際構建潛水器。以下是構建步驟:

構建框架

使用 PVC 塑膠管和彎頭構建一個大約正方形的框架,大小足夠放置 Raspberry Pi 的防水外殼。使用 PVC 膠水或螺絲固定所有部件。接著切割塑膠網以適合正方形並用塑膠扎帶固定到框架上,最終你應該得到一個類別似圖示中的塑膠「託盤」。

此圖示顯示了潛水器平台:

  graph TD;
A[PVC Frame] --> B[Plastic Netting];
B --> C[Zip Ties];
C --> D[Raspberry Pi Enclosure];

建立 Raspberry Pi 的防水外殼

選擇一個透明的塑膠容器來放置所有電子元件,因為你的攝影機需要能夠透過它拍攝照片。選定容器後,在其中打三個小孔:兩個用於連線馬達的線繩和一個用於連線操作桿(nunchuk)的線繩。

防水化馬達外殼

防水化馬達可能是這個專案的最困難部分。玄貓建議使用藥瓶來放置馬達:

  • 首先使用電工膠帶將馬達完全包裹起來以封住馬達殼上的大洞。
  • 接著剝去一小段乙太網線的線皮並將其中兩根線焊接到馬達線上。將所有線纏好後在藥瓶上打兩個孔:一個在蓋子上用於連線螺旋槳;另一個在底部用於穿過控制線。
  • 在藥瓶內倒入蠟油(如石蠟)以防水處理馬達和線路。蠟油在加熱後會融化並充滿藥瓶中的空隙。
  • 在蠟油完全固化後檢查電機轉軸是否能自由旋轉,然後安裝蓋子並穿過預先打好的孔安裝螺旋槳。
  graph TD;
A[Motor] --> B[Electrical Tape];
B --> C[Ethernet Cable];
C --> D[Wax Filling];
D --> E[Motor Shaft with Propeller];

改進與最佳化建議

  • 乘載平衡:在實際應用中可能需要調整潛水器的浮力以確保其穩定性和運動效能。
  • 錯誤處理:進一步最佳化錯誤處理機制以提高系統穩定性。
  • 延展功能:可考慮增加更多感測器或功能模組以增強潛水器的能力。

常見問題及解決方案

玄貓經常遇到以下問題:

問題:電池壽命不足以支援長時間任務。

解決方案:考慮增加更多電池模組或選擇高容量電池以延長執行時間。

問題:攝影機拍攝不清晰或無法正常工作。

解決方案:檢查攝影機連線是否穩固以及防水外殼內是否有液體進入。

透過以上詳細說明和實際案例分析,玄貓希望能夠幫助你順利完成完全自主潛水器專案並提供一些改進建議及常見問題解決方案。

連線Wii Nunchuck及組裝潛艇

在這篇文章中,玄貓將詳細介紹如何連線Wii Nunchuck控制器,並組裝一個潛艇。這個潛艇將使用Raspberry Pi(以下簡稱Pi)作為核心控制單元,並透過Ethernet電纜與Nunchuck進行無線通訊。

連線Nunchuck

首先,我們需要準備一段Ethernet電纜來連線潛艇與Nunchuck控制器。由於Nunchuck將放置在船上,而潛艇將在水下執行,因此我們需要確保電纜的長度足夠並且能夠穩定地傳輸資料。

  1. 剝除Ethernet電纜兩端的保護層,露出內部的四根線。
  2. 焊接這四根線到Nunchuck控制器上。這需要一些基本的電子焊接技能。
  3. 將電纜的另一端穿過潛艇機身頂部的孔洞,並將四根線分別連線到Pi的GPIO引腳上。

組裝最終產品

當馬達已經防水處理完成後,我們可以開始組裝潛艇的最終版本。以下是具體步驟:

  1. 將每個馬達的線路穿過容器上的孔洞,並像測試時一樣連線到馬達控制板上。
  2. 使用海洋環氧樹脂封住所有孔洞,確保水無法進入容器內部。這裡要特別注意5200密封劑非常粘膩且難以清理,建議穿戴手套並在室外操作。

封孔注意事項

  • 密封劑非常粘膩且難以清理,請務必穿戴手套並在室外操作。
  • 不要吝惜密封劑的使用,因為我們需要確保所有電子元件都得到充分保護。
  1. 檢查所有電子連線是否牢固,然後將Pi和馬達控制板放入容器內。
  2. 使用小塊膠帶或海報膠泥將攝像頭固定在容器前壁上,並確保各個板卡都固定牢靠。
  3. 使用小型麵包板連線地線,並新增兩個電池:一個為Pi供電,另一個為馬達控制板供電。

電源管理

當使用電池為Pi供電時,必須確保電壓為5V,因為Pi沒有內建電壓調節器。玄貓建議使用USB車充,它能提供穩定的5V和約1安培的電流。你也可以尋找其他電池組合來實作這一目的。

電源管理

  1. 開啟車充的外殼,使用USB到micro-USB線將車充的USB輸出連線到Pi的電源輸入。
  2. 將電池的電源連線到車充的輸入端,這樣就能提供穩定的5V電壓給Pi。

完成組裝

當所有元件都放置好並檢查無誤後,我們可以關閉容器並檢查是否有類別似圖12-17中的效果。如果一切正常,你現在應該擁有一個能夠透過Wii Nunchuck進行遠端控制的Pi潛艇。

潛艇操作

  • 按下Nunchuck上的按鈕可以拍攝照片,並將其傳輸到家中的電腦上進行檢視。

潛艇拍攝範例

根據不同地區的水域環境,潛艇拍攝到的照片也會有所不同。例如,如果你住在澳洲,可能會拍攝到類別似圖12-19中的海洋生物;而如果你住在阿拉斯加,可能會拍攝到更多湖泊景觀如圖12-20和圖12-21所示。