درع المؤازر

يقود درع المؤازر ما يصل إلى ثمانية مؤازرات هواة بالتوازي من كاميرا OpenMV Cam عبر I2C، باستخدام متحكّم مؤازر/PWM من نوع PCA9685.

Servo Shield

للاطلاع على ورقة البيانات الكاملة والصور وطلب الشراء، راجع صفحة منتج درع المؤازر.

أبرز الميزات

  • متحكّم مؤازر/PWM من نوع PCA9685

  • ثماني قنوات مؤازر مستقلة عبر I2C

  • قابل للتكديس مع درع المحرك ودرع الدوران والميل

مخطط الأطراف

Servo Shield Pinout

مرجع الأطراف

الطرف

الوظيفة

P4

I²C SCL — ساعة إلى PCA9685

P5

I²C SDA — بيانات إلى PCA9685

خط VIN

يغذّي المؤازرات (من طرف VIN الخاص بالكاميرا)

خط 3.3V

يغذّي منطق PCA9685

خط GND

أرضي مشترك للمؤازر والكاميرا

عنوان I²C الافتراضي هو 0x40. صِل وصلة اللَحم المدمجة على اللوحة لنقل العنوان إلى 0x60.

ملاحظة

يسحب الدرع طاقة المؤازر مباشرة من طرف VIN الخاص بالكاميرا. لا يغذّي USB طرف VIN على أي كاميرا OpenMV Cam، لذا يجب توفير VIN خارجياً (بطارية أو مصدر مختبري أو ما شابه) — اختر مصدراً مصنّفاً لتيار التوقف المجمّع لكل مؤازر تخطط لقيادته.

الاستخدام

قُد قنوات المؤازر الثمانية عبر PCA9685 من خلال I²C. يختلف مدى عرض النبضة بين المؤازرات، لذا اضبط MIN_US و MAX_US لمطابقة مؤازراتك — القيم النموذجية تقع حول 1000–2000 ميكروثانية:

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 كيلوهرتز. تقوم الدالة المساعدة أدناه بمعايرة قيمة عشرية بمدى 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)