Servo Shield

Servo Shield, bir PCA9685 servo / PWM denetleyicisi kullanarak OpenMV Cam’den I2C üzerinden en fazla sekiz hobi servosunu paralel olarak sürer.

Servo Shield

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ışı

Servo Shield 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)