How can we help you today?
【制動】DC馬達 | dual2s-mini | MPY-LLM
簡介
我們無法使用微處理器、單晶片(MCU)等可程式微控器單元,直接控制致動器(電機、電磁閥…)或是較大功率元件,原因在於MCU的GPIO控制腳位是一種通用型的輸出輸入訊號處理設計思維,GPIO腳位對外的電流輸出能力(fan out)都相當微小,不足以驅動致動器等需要較大功率的元件。如下圖。解決的方法就是透過專化的處理電路,對應被控制元件(如直流電機、BLDC…)的特性進行功率放大、訊號回授、電路保護…等處裡。
準備
材料與工具
本文範例使用【dual2s-mini】為示範。如圖標註,每個DC電機接口可提供max 10V/ 800mA的推動能力。此電機接口可使用N20-6V/12V、TT馬達…等,或其他符合推動規格以內之電機。
延伸應用部分,由於此四組電機接口為獨立控制,是以也可以滿足全向輪的控制需求。
韌體範例
注意:驅動電機需要的電流較大些,請將鋰電池依規範極性方向安裝,方能正常驅動電機。
DC電機規格限制:10V以下、耗電流800mA以下、瞬時堵轉電流1A以下。
單顆DC馬達正反轉與調速控制
from machine import Pin, PWM
import time
# 馬達引腳設定
M1A = PWM(Pin(14), freq=1000) # G14 控制正轉
M1B = PWM(Pin(32), freq=1000) # G32 控制反轉
def set_motor(speed, direction):
"""
控制單顆馬達的速度與方向。
參數:
- speed: 轉速 (0 到 1023,1023為最高速)
- direction: 方向 (1為正轉, -1為反轉, 0為停止)
"""
#duty_cycle = int((speed / 100) * 1023) # 將速度轉換為 0 到 1023 的 PWM 值
if direction == 1: # 正轉
M1A.duty(speed)
M1B.duty(0)
elif direction == -1: # 反轉
M1A.duty(0)
M1B.duty(speed)
else: # 停止
M1A.duty(0)
M1B.duty(0)
# 測試程式
if __name__ == "__main__":
print("Testing single motor...")
# 正轉,
set_motor(300, 1)
print("Motor forward at 50% speed")
time.sleep(2)
# 反轉
set_motor(300, -1)
print("Motor backward at 75% speed")
time.sleep(2)
# 停止
set_motor(0, 0)
print("Motor stopped")
time.sleep(2)
print("Test complete.")
from machine import Pin, PWM
import time
# 馬達引腳設定
M1A = PWM(Pin(14), freq=1000) # 馬達 1 正轉
M1B = PWM(Pin(32), freq=1000) # 馬達 1 反轉
M2A = PWM(Pin(12), freq=1000) # 馬達 2 正轉
M2B = PWM(Pin(33), freq=1000) # 馬達 2 反轉
def set_motor(motor, speed, direction):
"""
參數:
- motor: 選擇 "M1" 或 "M2"。
- speed: 速度 (0 到 1023)。
- direction: 方向 (1: 正轉, -1: 反轉, 0: 停止)。
"""
if motor == "M1":
forward, backward = M1A, M1B
elif motor == "M2":
forward, backward = M2A, M2B
else:
raise ValueError("Invalid motor. Use 'M1' or 'M2'.")
if direction == 1: # 正轉
forward.duty(speed)
backward.duty(0)
elif direction == -1: # 反轉
forward.duty(0)
backward.duty(speed)
else: # 停止
forward.duty(0)
backward.duty(0)
def stop():
"""停止車體。"""
set_motor("M1", 0, 0)
set_motor("M2", 0, 0)
def forward(speed):
"""車體前進。"""
set_motor("M1", speed, 1)
set_motor("M2", speed, -1)
def backward(speed):
"""車體後退。"""
set_motor("M1", speed, -1)
set_motor("M2", speed, 1)
def turn_left(speed):
"""車體左旋轉 (原地旋轉)。"""
set_motor("M1", speed, 1)
set_motor("M2", speed, 1)
def turn_right(speed):
"""車體右旋轉 (原地旋轉)。"""
set_motor("M1", speed, -1)
set_motor("M2", speed, -1)
# 測試程式
if __name__ == "__main__":
print("Testing vehicle motion...")
print("Forward...")
forward(800) # 50% 速度前進
time.sleep(2)
stop()
print("Backward...")
backward(500) # 50% 速度後退
time.sleep(2)
stop()
print("Turn left...")
turn_left(500) # 50% 速度左旋轉
time.sleep(2)
stop()
print("Turn right...")
turn_right(500) # 50% 速度右旋轉
time.sleep(2)
stop()
print("Test complete.")
from machine import Pin, PWM, time_pulse_us
import time
# 馬達引腳設定
M1A = PWM(Pin(14), freq=1000) # 馬達 1 正轉
M1B = PWM(Pin(32), freq=1000) # 馬達 1 反轉
M2A = PWM(Pin(12), freq=1000) # 馬達 2 正轉
M2B = PWM(Pin(33), freq=1000) # 馬達 2 反轉
#--------------------------------------------
# 超音波模組引腳設定
TRIG = Pin(27, Pin.OUT)
ECHO = Pin(13, Pin.IN)
def measure_distance():
"""
使用超音波模組測量距離。
返回距離值(單位:cm),若測量失敗則返回 -1。
"""
# 發送觸發信號
TRIG.off()
time.sleep_us(2)
TRIG.on()
time.sleep_us(10)
TRIG.off()
# 計算回波時間
duration = time_pulse_us(ECHO, 1, 30000) # 最多等待30ms
if duration < 0:
return 500 # 無有效回波
# 計算距離 (cm)
distance = (duration / 2) * 0.0343 # 回波時間轉換為距離
return round(distance, 2)
#--------------------------------------------
def set_motor(motor, speed, direction):
"""
控制單顆馬達的速度與方向。
參數:
- motor: 選擇 "M1" 或 "M2"。
- speed: 速度 (0 到 1023)。
- direction: 方向 (1: 正轉, -1: 反轉, 0: 停止)。
"""
if motor == "M1":
forward, backward = M1A, M1B
elif motor == "M2":
forward, backward = M2A, M2B
else:
raise ValueError("Invalid motor. Use 'M1' or 'M2'.")
if direction == 1: # 正轉
forward.duty(speed)
backward.duty(0)
elif direction == -1: # 反轉
forward.duty(0)
backward.duty(speed)
else: # 停止
forward.duty(0)
backward.duty(0)
def stop():
"""停止車體。"""
set_motor("M1", 0, 0)
set_motor("M2", 0, 0)
def forward(speed):
"""車體前進。"""
set_motor("M1", speed, 1)
set_motor("M2", speed, -1)
def backward(speed):
"""車體後退。"""
set_motor("M1", speed, -1)
set_motor("M2", speed, 1)
def turn_left(speed):
"""車體左旋轉 (原地旋轉)。"""
set_motor("M1", speed, 1)
set_motor("M2", speed, 1)
def turn_right(speed):
"""車體右旋轉 (原地旋轉)。"""
set_motor("M1", speed, -1)
set_motor("M2", speed, -1)
# 測試程式-------------------------------------
if __name__ == "__main__":
while True:
distance = measure_distance()
if distance <= 30:
print("Distance: {} cm".format(distance))
forward(300)
else:
stop()
time.sleep(0.1)
from machine import Pin, PWM, time_pulse_us
import time
# 馬達引腳設定
M1A = PWM(Pin(14), freq=1000) # 馬達 1 正轉
M1B = PWM(Pin(32), freq=1000) # 馬達 1 反轉
M2A = PWM(Pin(12), freq=1000) # 馬達 2 正轉
M2B = PWM(Pin(33), freq=1000) # 馬達 2 反轉
#--------------------------------------------
# 超音波模組引腳設定
TRIG = Pin(27, Pin.OUT)
ECHO = Pin(13, Pin.IN)
def measure_distance():
"""
使用超音波模組測量距離。
返回距離值(單位:cm),若測量失敗則返回 -1。
"""
# 發送觸發信號
TRIG.off()
time.sleep_us(2)
TRIG.on()
time.sleep_us(10)
TRIG.off()
# 計算回波時間
duration = time_pulse_us(ECHO, 1, 30000) # 最多等待30ms
if duration < 0:
return 500 # 無有效回波
# 計算距離 (cm)
distance = (duration / 2) * 0.0343 # 回波時間轉換為距離
return round(distance, 2)
#--------------------------------------------
def set_motor(motor, speed, direction):
"""
控制單顆馬達的速度與方向。
參數:
- motor: 選擇 "M1" 或 "M2"。
- speed: 速度 (0 到 1023)。
- direction: 方向 (1: 正轉, -1: 反轉, 0: 停止)。
"""
if motor == "M1":
forward, backward = M1A, M1B
elif motor == "M2":
forward, backward = M2A, M2B
else:
raise ValueError("Invalid motor. Use 'M1' or 'M2'.")
if direction == 1: # 正轉
forward.duty(speed)
backward.duty(0)
elif direction == -1: # 反轉
forward.duty(0)
backward.duty(speed)
else: # 停止
forward.duty(0)
backward.duty(0)
def stop():
"""停止車體。"""
set_motor("M1", 0, 0)
set_motor("M2", 0, 0)
def forward(speed):
"""車體前進。"""
set_motor("M1", speed, 1)
set_motor("M2", speed, -1)
def backward(speed):
"""車體後退。"""
set_motor("M1", speed, -1)
set_motor("M2", speed, 1)
def turn_left(speed):
"""車體左旋轉 (原地旋轉)。"""
set_motor("M1", speed, 1)
set_motor("M2", speed, 1)
def turn_right(speed):
"""車體右旋轉 (原地旋轉)。"""
set_motor("M1", speed, -1)
set_motor("M2", speed, -1)
# 測試程式-------------------------------------
if __name__ == "__main__":
myCnt = 0
while True:
distance = measure_distance()
if distance <= 30:
myCnt = 0
print("Distance: {} cm".format(distance))
forward(300)
else:
myCnt += 1
if(myCnt > 2):
myCnt = 0
turn_left(250)
time.sleep(0.1)
stop()
stop()
time.sleep(0.1)
from machine import Pin, PWM, time_pulse_us
import time
# 馬達引腳設定
M1A = PWM(Pin(14), freq=1000) # 馬達 1 正轉
M1B = PWM(Pin(32), freq=1000) # 馬達 1 反轉
M2A = PWM(Pin(12), freq=1000) # 馬達 2 正轉
M2B = PWM(Pin(33), freq=1000) # 馬達 2 反轉
M3A = PWM(Pin(25), freq=1000)
M3B = PWM(Pin(26), freq=1000)
M4A = PWM(Pin(22), freq=1000)
M4B = PWM(Pin(23), freq=1000)
#--------------------------------------------
# 超音波模組引腳設定
TRIG = Pin(27, Pin.OUT)
ECHO = Pin(13, Pin.IN)
def measure_distance():
"""
使用超音波模組測量距離。
返回距離值(單位:cm),若測量失敗則返回 -1。
"""
# 發送觸發信號
TRIG.off()
time.sleep_us(2)
TRIG.on()
time.sleep_us(10)
TRIG.off()
# 計算回波時間
duration = time_pulse_us(ECHO, 1, 30000) # 最多等待30ms
if duration < 0:
return 500 # 無有效回波
# 計算距離 (cm)
distance = (duration / 2) * 0.0343 # 回波時間轉換為距離
return round(distance, 2)
# -------------------------------------------
def boxing(speed):
M3A.duty(speed)
M3B.duty(0)
M4A.duty(speed)
M4B.duty(0)
def stop_boxing():
M3A.duty(0)
M3B.duty(0)
M4A.duty(0)
M4B.duty(0)
#--------------------------------------------
def set_motor(motor, speed, direction):
"""
控制單顆馬達的速度與方向。
參數:
- motor: 選擇 "M1" 或 "M2"。
- speed: 速度 (0 到 1023)。
- direction: 方向 (1: 正轉, -1: 反轉, 0: 停止)。
"""
if motor == "M1":
forward, backward = M1A, M1B
elif motor == "M2":
forward, backward = M2A, M2B
else:
raise ValueError("Invalid motor. Use 'M1' or 'M2'.")
if direction == 1: # 正轉
forward.duty(speed)
backward.duty(0)
elif direction == -1: # 反轉
forward.duty(0)
backward.duty(speed)
else: # 停止
forward.duty(0)
backward.duty(0)
def stop():
"""停止車體。"""
set_motor("M1", 0, 0)
set_motor("M2", 0, 0)
def forward(speed):
"""車體前進。"""
set_motor("M1", speed, 1)
set_motor("M2", speed, -1)
def backward(speed):
"""車體後退。"""
set_motor("M1", speed, -1)
set_motor("M2", speed, 1)
def turn_left(speed):
"""車體左旋轉 (原地旋轉)。"""
set_motor("M1", speed, 1)
set_motor("M2", speed, 1)
def turn_right(speed):
"""車體右旋轉 (原地旋轉)。"""
set_motor("M1", speed, -1)
set_motor("M2", speed, -1)
# 測試程式-------------------------------------
if __name__ == "__main__":
myCnt = 0
while True:
distance = measure_distance()
if distance <= 30:
myCnt = 0
print("Distance: {} cm".format(distance))
forward(800)
if distance <= 10:
boxing(1000)
else:
myCnt += 1
if(myCnt > 1):
myCnt = 0
turn_left(300)
time.sleep(0.1)
stop()
stop()
stop_boxing()
time.sleep(0.1)