Servo Shield¶
Servo Shield ขับเซอร์โว hobby ได้สูงสุดแปดตัวพร้อมกันจาก OpenMV Cam ผ่าน I2C โดยใช้คอนโทรลเลอร์เซอร์โว/PWM แบบ PCA9685
สำหรับข้อมูลจำเพาะเต็ม ภาพถ่าย และการสั่งซื้อ ดูที่ หน้าผลิตภัณฑ์ Servo Shield
จุดเด่น¶
คอนโทรลเลอร์เซอร์โว/PWM แบบ PCA9685
แปดช่องเซอร์โวอิสระผ่าน I2C
เสียบซ้อนกับ Motor Shield และ Pan and Tilt Shield ได้
แผนผังพิน¶
อ้างอิงพิน¶
พิน |
หน้าที่ |
|---|---|
P4 |
I²C SCL — สัญญาณนาฬิกาไปยัง PCA9685 |
P5 |
I²C SDA — สัญญาณข้อมูลไปยัง PCA9685 |
ขา VIN |
จ่ายไฟให้เซอร์โว (จากพิน VIN ของกล้อง) |
ขา 3.3V |
จ่ายไฟให้ลอจิก PCA9685 |
ขา GND |
กราวด์ร่วมเซอร์โวและกล้อง |
ที่อยู่ I²C ค่าเริ่มต้นคือ 0x40 ต่อสะพานบัดกรีบนบอร์ดเพื่อเปลี่ยนที่อยู่เป็น 0x60
Note
shield ดึงไฟเซอร์โวโดยตรงจากพิน VIN ของกล้อง USB ไม่จ่ายไฟ VIN บน OpenMV Cam ใดๆ ดังนั้นต้องจ่าย VIN จากภายนอก (แบตเตอรี่ แหล่งจ่ายไฟตั้งโต๊ะ หรือที่คล้ายกัน) — เลือกแหล่งจ่ายที่รับกระแส stall รวมของเซอร์โวทุกตัวที่วางแผนจะขับ
การใช้งาน¶
ขับแปดช่องเซอร์โวผ่าน PCA9685 บน I²C ช่วง pulse-width แตกต่างกันระหว่างเซอร์โว ดังนั้นปรับ MIN_US และ MAX_US ให้ตรงกับของคุณ — ค่าทั่วไปอยู่ที่ประมาณ 1000–2000 µs:
import time
from machine import SoftI2C, Pin
class PCA9685:
"""Minimal PCA9685 driver — 12-bit PWM on any of 8 channels."""
def __init__(self, bus, address=0x40, freq=50):
self._bus = bus
self._addr = address
bus.writeto_mem(address, 0x00, b"\x00") # reset Mode1
prescale = round(25_000_000 / (4096 * freq)) - 1
bus.writeto_mem(address, 0x00, b"\x10") # sleep
bus.writeto_mem(address, 0xFE, bytes([prescale])) # prescale
bus.writeto_mem(address, 0x00, b"\x00") # wake
time.sleep_us(5)
bus.writeto_mem(address, 0x00, b"\xA1") # restart + AI + allcall
self._period_us = 1_000_000 // freq
def set_duty(self, channel, duty):
duty &= 0xFFF # 12-bit
if duty == 0:
on, off = 0, 0x1000 # FULL_OFF
elif duty == 0xFFF:
on, off = 0x1000, 0 # FULL_ON
else:
on, off = 0, duty
self._bus.writeto_mem(
self._addr, 0x06 + 4 * channel,
bytes([on & 0xFF, on >> 8, off & 0xFF, off >> 8]))
def set_us(self, channel, pulse_us):
self.set_duty(channel, (pulse_us * 4096) // self._period_us)
MIN_US = 1000 # full-left pulse width (microseconds)
MAX_US = 2000 # full-right pulse width
bus = SoftI2C(scl=Pin("P4"), sda=Pin("P5"))
pca = PCA9685(bus, address=0x40, freq=50)
def angle(channel, deg):
pca.set_us(channel, MIN_US + (deg * (MAX_US - MIN_US)) // 180)
while True:
for ch in range(8):
angle(ch, 0)
time.sleep_ms(2000)
for ch in range(8):
angle(ch, 180)
time.sleep_ms(2000)
PCA9685 ยังจัดการ PWM 12 บิตทั่วไปที่ความถี่ใดก็ได้ — ใช้คลาสเดิมซ้ำกับ set_duty (0–4095) เพื่อ ตัวอย่างเช่น เฟดเอาต์ LED บนช่อง 0 ที่ 1 kHz ตัวช่วยด้านล่างปรับ float 0.0–100.0% ลงบนช่วงดิวตี้ 0–4095 ของชิป:
import time
from machine import SoftI2C, Pin
bus = SoftI2C(scl=Pin("P4"), sda=Pin("P5"))
pca = PCA9685(bus, address=0x40, freq=1000)
def brightness(channel, pct):
pca.set_duty(channel, int(pct * 4095 / 100))
while True:
# Ramp up 0 → 100%.
for pct in range(101):
brightness(0, float(pct))
time.sleep_ms(20)
# Ramp down 100 → 0%.
for pct in reversed(range(101)):
brightness(0, float(pct))
time.sleep_ms(20)