Servo Shield¶
Servo Shield, bir PCA9685 servo / PWM denetleyicisi kullanarak OpenMV Cam’den I2C üzerinden en fazla sekiz hobi servosunu paralel olarak sürer.
Tam veri sayfası, fotoğraflar ve sipariş bilgileri için Servo Shield ürün sayfasına bakın.
Öne çıkanlar¶
PCA9685 servo / PWM denetleyicisi
I2C üzerinden sekiz bağımsız servo kanalı
Motor Shield ve Pan and Tilt Shield ile istiflenebilir
Pin Çıkışı¶
Pin referansı¶
Pin |
İşlev |
|---|---|
P4 |
I²C SCL — PCA9685’e saat sinyali |
P5 |
I²C SDA — PCA9685’e veri |
VIN hattı |
Servolara güç verir (kameranın VIN pininden) |
3.3V hattı |
PCA9685 mantığına güç verir |
GND hattı |
Servo ve kamera ortak toprağı |
Varsayılan I²C adresi 0x40‘tır. Adresi 0x60‘a taşımak için kart üzerindeki lehim köprüsünü bağlayın.
Not
Shield, servo gücünü doğrudan kameranın VIN pininden çeker. USB hiçbir OpenMV Cam’de VIN’i beslemez; bu nedenle VIN harici olarak sağlanmalıdır (pil, tezgah güç kaynağı veya benzeri) — sürmeyi planladığınız her servonun toplam durma akımına uygun bir kaynak seçin.
Kullanım¶
Sekiz servo kanalını I²C üzerinden PCA9685 aracılığıyla sürün. Darbe genişliği aralığı servolar arasında değişir; bu nedenle MIN_US ve MAX_US değerlerini kendi servonuza uyacak şekilde ayarlayın — tipik değerler yaklaşık 1000–2000 µs civarındadır:
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 ayrıca herhangi bir frekansta genel 12 bit PWM’i de işler — örneğin kanal 0’daki bir LED’i 1 kHz’de soldurmak için aynı sınıfı set_duty (0–4095) ile yeniden kullanın. Aşağıdaki yardımcı işlev, 0.0–100.0% bir float değerini çipin 0–4095 görev döngüsü aralığına ölçekler:
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)