Shield Servo¶
Le shield Servo pilote jusqu’à huit servomoteurs de modélisme en parallèle depuis l’OpenMV Cam via I2C, à l’aide d’un contrôleur de servo / PWM PCA9685.
Pour la fiche technique complète, les photos et les commandes, consultez la page produit du shield Servo.
Points forts¶
Contrôleur de servo / PWM PCA9685
Huit canaux de servo indépendants via I2C
Empilable avec le shield Moteur et le shield Pan and Tilt
Brochage¶
Référence des broches¶
Broche |
Fonction |
|---|---|
P4 |
I²C SCL — horloge vers le PCA9685 |
P5 |
I²C SDA — données vers le PCA9685 |
Rail VIN |
Alimente les servos (depuis la broche VIN de la caméra) |
Rail 3,3 V |
Alimente la logique du PCA9685 |
Rail GND |
Masse commune des servos et de la caméra |
L’adresse I²C par défaut est 0x40. Connectez le pont à souder intégré pour faire passer l’adresse à 0x60.
Note
Le shield prélève l’alimentation des servos directement sur la broche VIN de la caméra. L’USB n’alimente VIN sur aucune OpenMV Cam, VIN doit donc être fournie en externe (batterie, alimentation d’établi ou similaire) — choisissez une source dimensionnée pour le courant de blocage cumulé de tous les servos que vous prévoyez de piloter.
Utilisation¶
Pilotez les huit canaux de servo via le PCA9685 sur I²C. La plage de largeur d’impulsion varie d’un servo à l’autre, ajustez donc MIN_US et MAX_US aux vôtres — les valeurs typiques se situent autour de 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)
Le PCA9685 gère aussi du PWM 12 bits général à n’importe quelle fréquence — réutilisez la même classe avec set_duty (0–4095) pour, par exemple, faire varier la luminosité d’une LED sur le canal 0 à 1 kHz. La fonction auxiliaire ci-dessous met à l’échelle un flottant 0,0–100,0 % sur la plage de rapport cyclique 0–4095 de la puce
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)