Servo Shield¶
De Servo Shield stuurt tot acht hobbyservo’s parallel aan vanaf de OpenMV Cam via I2C, met behulp van een PCA9685 servo- / PWM-controller.
Voor de volledige datasheet, foto’s en bestelinformatie, zie de productpagina van de Servo Shield.
Hoogtepunten¶
PCA9685 servo- / PWM-controller
Acht onafhankelijke servokanalen via I2C
Stapelbaar met de Motor Shield en de Pan and Tilt Shield
Pinout¶
Pinreferentie¶
Pin |
Functie |
|---|---|
P4 |
I²C SCL — klok naar de PCA9685 |
P5 |
I²C SDA — data naar de PCA9685 |
VIN-rail |
Voedt de servo’s (vanaf de VIN-pin van de camera) |
3.3V-rail |
Voedt de logica van de PCA9685 |
GND-rail |
Gemeenschappelijke massa van servo en camera |
Het standaard I²C-adres is 0x40. Verbind de soldeerbrug aan boord om het adres naar 0x60 te verplaatsen.
Notitie
De shield trekt servovoeding rechtstreeks van de VIN-pin van de camera. USB voedt VIN niet op enige OpenMV Cam, dus VIN moet extern worden geleverd (batterij, labvoeding of dergelijke) — kies een bron die geschikt is voor de gecombineerde blokkeerstroom van elke servo die je van plan bent aan te sturen.
Gebruik¶
Stuur de acht servokanalen aan via de PCA9685 over I²C. Het pulsbreedtebereik varieert per servo, dus stem MIN_US en MAX_US af op de jouwe — typische waarden liggen rond 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)
De PCA9685 verwerkt ook algemene 12-bit PWM op elke frequentie — hergebruik dezelfde klasse met set_duty (0–4095) om bijvoorbeeld een LED op kanaal 0 te dimmen bij 1 kHz. De helper hieronder schaalt een 0,0–100,0%-float naar het 0–4095 duty-bereik van de chip:
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)