水下機器人控制系統需要整合多種硬體和軟體技術。本文以 Nunchuk 遊戲手把、Raspberry Pi 和 L298 馬達驅動器為例,講解如何搭建一個基本的水下機器人控制系統。透過 Python 程式碼讀取 Nunchuk 的搖桿和按鈕資料,進而控制馬達的轉速和方向,同時還能控制攝影機進行拍照和錄影。為了讓系統在離線環境下也能正常運作,文章也說明瞭如何使用 Cron 工作排程器設定程式自動啟動。
水下機器人控制系統
水下機器人是一種複雜且精密的機電整合系統,需要精確控制多個元件來實作功能。這篇文章將探討如何利用Nunchuk遊戲手把來控制水下機器人的馬達和攝影機,並介紹相關的技術細節。
構建基礎:Nunchuk與LED測試
首先,我們需要確保Nunchuk與Raspberry Pi之間的通訊正常。這裡簡單介紹如何利用Python程式碼來讀取Nunchuk的資料,並根據讀取的資料控制LED燈。
import smbus
import time
from time import sleep
import RPi.GPIO as GPIO
# 初始化GPIO
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(1)
address = 0x52
try:
bus.write_byte_data(address, 0xF0, 0x55)
bus.write_byte_data(address, 0xFB, 0x00)
while True:
data0 = bus.read_byte_data(address, 0x00)
data1 = bus.read_byte_data(address, 0x01)
data2 = bus.read_byte_data(address, 0x02)
data3 = bus.read_byte_data(address, 0x03)
data4 = bus.read_byte_data(address, 0x04)
# 操作LED燈
if data3 & 0x01: # 按鈕Z被按下
GPIO.output(11, 1)
else:
GPIO.output(11, 0)
if data3 & 0x02: # 按鈕C被按下
GPIO.output(13, 1)
else:
GPIO.output(13, 0)
if data2 > 128: # 搖桿向上
GPIO.output(15, 1)
else:
GPIO.output(15, 0)
if data2 < 128: # 搖桿向下
GPIO.output(19, 1)
else:
GPIO.output(19, 0)
if data4 > 128: # 搖桿向左
GPIO.output(21, 1)
else:
GPIO.output(21, 0)
if data4 < 128: # 搖桿向右
GPIO.output(23, 1)
else:
GPIO.output(23, 0)
except IOError as e:
print(e)
finally:
GPIO.cleanup()
內容解密:
- 初始化GPIO:首先,我們使用
RPi.GPIO函式庫來設定Raspberry Pi的GPIO引腳模式和輸出模式。這裡我們選擇了BOARD模式,並設定了六個引腳作為輸出。 - 初始化I2C匯流排:使用
smbus函式庫來初始化I2C匯流排,並設定Nunchuk的I2C地址。 - 讀取Nunchuk資料:在無限迴圈中,我們不斷從Nunchuk讀取五個位元組的資料。這些資料分別表示搖桿方向、加速度計讀數和按鈕狀態。
- 控制LED燈:根據讀取到的資料,我們控制相應的LED燈。例如,如果按鈕Z被按下,則點亮對應的LED燈。
- 錯誤處理:使用
try-except-finally結構來處理可能的IO錯誤,並在最後清理GPIO設定。
控制馬達與攝影機
接下來,我們將利用L298馬達驅動器來控制水下機器人的馬達,並使用Python程式碼來控制攝影機拍照和錄影。
L298馬達驅動器
L298是一款H橋馬達驅動器,能夠驅動大功率馬達。它可以接收外部電源,並由Raspberry Pi控制馬達的啟停和方向。
接線圖示
此圖示展示了Raspberry Pi、L298馬達驅動器和兩個直流馬達之間的連線方式。
graph LR;
A[Raspberry Pi] -->|IN1| B[L298]
A -->|IN2| B
A -->|ENA| B
A -->|IN3| C[L298]
A -->|IN4| C
A -->|ENB| C
B -->|Motor A+| D[Motor A]
B -->|Motor A-| D
C -->|Motor B+| E[Motor B]
C -->|Motor B-| E
控制邏輯
我們將修改之前的LED控制程式碼,使其能夠根據Nunchuk的輸入來控制馬達和攝影機。
import smbus
import time
import RPi.GPIO as GPIO
from subprocess import call
# 初始化GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setup(7, GPIO.OUT) # ENA (Motor A Enable)
GPIO.setup(11, GPIO.OUT) # IN1 (Motor A Input 1)
GPIO.setup(13, GPIO.OUT) # IN2 (Motor A Input 2)
GPIO.setup(15, GPIO.OUT) # ENB (Motor B Enable)
GPIO.setup(16, GPIO.OUT) # IN3 (Motor B Input 3)
GPIO.setup(18, GPIO.OUT) # IN4 (Motor B Input 4)
# 初始化I2C匯流排
bus = smbus.SMBus(1)
address = 0x52
def control_motor_a(direction):
if direction == 'forward':
GPIO.output(ENA_PIN, GPIO.HIGH)
GPIO.output(IN1_PIN, GPIO.HIGH)
GPIO.output(IN2_PIN, GPIO.LOW)
elif direction == 'backward':
GPIO.output(ENA_PIN, GPIO.HIGH)
GPIO.output(IN1_PIN, GPIO.LOW)
GPIO.output(IN2_PIN, GPIO.HIGH)
elif direction == 'stop':
GPIO.output(ENA_PIN, GPIO.LOW)
def control_motor_b(direction):
if direction == 'forward':
GPIO.output(ENB_PIN, GPIO.HIGH)
GPIO.output(IN3_PIN, GPIO.HIGH)
GPIO.output(IN4_PIN, GPIO.LOW)
elif direction == 'backward':
_GPIO_.output_(ENB_PIN_,_GPIOHIGH_)
_GPIO_.output_(IN3_PIN_,_GPIOLOW_)
_GPIO_.output_(IN4_PIN_,_GPIOHIGH_)
elif direction == 'stop':
_GPI_OPU_.output_(ENB_PIN_,_GPIOLOW_)
def take_photo():
call(["raspistill -o image.jpg"], shell=True)
def record_video():
call(["raspivid -o video.mp4"], shell=True)
try:
bus.write_byte_data(address, 0xF0, 0x55)
bus.write_byte_data(address, 0xFB, 0x00)
while True:
data3 = bus.read_byte_data(address, 0x03) # 按鈕狀態
data4 = bus.read_byte_data(address,_oXO_)_#_joshick_position_
_data5= _bus. read byte _data ( address , _oXO_5 _) _# accelometer_
if joystick_y > threshold_forward: control_motor_a('forward')
control_motor_b('forward')
elif joystick_y < threshold_backward: control_motor_a('backward')
control_motor_b('backward')
elif joystick_x > threshold_right: control_motor_a('stop')
control_motor_b('forward')
elif joystick_x < threshold_left: control_motor_a('forward')
control_motor_b('stop')
if button_c == True: take_photo()
if button_z == True: record_video()
except IOError as e:
print(e)
finally:
control_motor_a('stop')
control_motor_b('stop')
_GPI_OPU_.cleanup()
內容解密:
- 初始化GPIO:設定用於控制馬達A和馬達B的輸出引腳。
- 初始化I2C匯流排:設定Nunchuk的I2C地址。
- 控制馬達函式:定義兩個函式來控制馬達A和馬達B的前進、後退和停止。
- 攝影機函式:使用
subprocess函式庫呼叫系統命令來拍照和錄影。 - 主迴圈:在無限迴圈中讀取Nunchuk的資料,並根據搖桿方向和按鈕狀態控制馬達和攝影機。
- 錯誤處理:使用
try-except-finally結構處理可能的IO錯誤,並在最後停止馬達並清理GPIO設定。
離線啟動程式
在實際應用中,水下機器人通常無法連線到網路。因此,我們需要一種方法能夠在沒有鍵盤、滑鼠或顯示器的情況下啟動Python程式碼。這裡介紹如何利用Cron工作排程器自動啟動程式。
編輯Cron排程
編輯Cron排程檔案以便在系統啟動時自動執行Python指令碼。
sudo crontab -e
在檔案末尾新增以下行:
@reboot python /home/pi/Desktop/submersible/sub.py &
內容解密:
- 編輯Cron排程:使用
sudo crontab -e命令編輯root使用者的Cron排程檔案。 - 新增啟動指令:在檔案末尾新增一行指令,指定在系統啟動時執行Python指令碼
sub.py。 - 背景執行:使用
&符號使指令碼在背景執行,不影響系統正常啟動流程。
水下機器人的應用場景
水下機器人具有廣泛的應用場景,包括海洋探測、救援任務、環境監測等。透過合理設計和精確控制,可以實作多種複雜任務。例如:
海洋探測
水下機器人可以搭載各種感測器,用於海洋環境監測。例如,溫度感測器、鹽度計、氧氣計等可以提供豐富的海洋環境資料。
救援任務
在災難救援中,水下機器人可以進入危險區域進行探測和救援。例如,地震後的海底救援任務中,水下機器人可以幫助尋找倖存者並傳遞救援物資。
資源勘探
水下機器人可以用於海底資源勘探。例如,石油天然氣勘探、礦產資源勘探等。透過搭載高解析度攝影機和其他感測器,可以取得詳細的海底地形和資源分佈資訊。
未來趨勢與挑戰
隨著技術的進步,水下機器人的應用將越來越廣泛。然而也面臨一些挑戰:
技術挑戰
水下環境對電子裝置具有嚴格要求。需要開發更耐用、更高效的電子元件和電池技術。
安全性問題
水下機器人的操作需要高度安全性。需要開發更智慧、更可靠的人工智慧演算法來確保操作安全。
法規與倫理問題
隨著水下機器人的廣泛應用,法律法規和倫理問題也逐漸浮現。需要制定相關法規來規範水下機器人的使用。
對玄貓的一些建議
玄貓建議從以下幾個方面進行改進:
技術深度提升
繼續深入研究水下機器人的技術細節,掌握更多先進技術如自主導航、影像處理等。
與其他領域結合
將水下機器人技術與其他領域結合,例如智慧城市、環保等領域進行創新應用。
強化實際操作經驗
透過更多實際操作經驗來提升技術能力,解決實際問題中的技術難題。
錯誤教訓與反思
在開發過程中遇到的一些錯誤教訓值得反思:
電路設計錯誤
最初設計中的一些電路連線不夠穩定,導致系統經常出現故障。後來透過改進電路設計和增加保護措施解決了這個問題。
軟體除錯困難
由於硬體與軟體之間存在耦合關係除錯過程中遇到一些困難。後來透過模組化設計軟體結構降低了除錯難度。
測試環境不足
缺乏完整測試環境影響了系統穩定性驗證工作進行多次實地測試提升了系統穩定性及可靠性