HS-F27-L 4路電機8路舵機擴展板

HS-F27-L 4路電機8路舵機擴展板

1、介紹

實現電機控制:通過 I2C 接口與外部微控制器相連,利用 PCA9685 芯片輸出 PWM 信號,實現對四路 MOC PF 電機的速度等參數的控制。8PIN 接口:提供 8 個引腳接口,可用於連接感應器、其他控制器或擴展更多功能,方便系統的進一步擴展和集成。
電源管理:通常會集成電源接口,為連接的電機和晶片本身提供合適的電源。部分擴展板還具備反接保護電路,防止因電源正負極接反而損壞電路。

2、原理圖

3、模組參數

引腳名稱

描述

G

GND(電源輸入負極)

V

VCC(電源輸入正極)

SDA

數據引腳

SCL

時鐘引腳

  • 供電電壓: 3.3V-5V

  • 連接方式:PH2.0 4P端子線

  • 安裝方式:樂高搭建

4、電路板尺寸

5、添加Arduino庫文件

Arduino環境庫文件安裝步驟:參考連結

Arduino環境庫文件:點擊下載

米思齊UNO開發板庫文件安裝步驟(使用代碼前先下載安裝米思齊庫文件):參考連結

6、加入MicroPython環境庫檔案

米思齊ESP32開發板庫檔案下載安裝步驟(使用代碼前先下載安裝米思齊庫檔案):參考連結

7、Arduino IDE範例程式

範例程式(UNO開發板):點擊下載

#include "Wire.h"
#include "Adafruit_PWMServoDriver.h"
Adafruit_PWMServoDriver PWM = Adafruit_PWMServoDriver(0x40);

void setup(){
  PWM.begin();
  PWM.setPWMFreq(85);
}

void loop(){
  PWM.setPWM(0,0,0);
  PWM.setPWM(1,0,2048);
  PWM.setPWM(2,0,0);
  PWM.setPWM(3,0,2048);
  PWM.setPWM(4,0,0);
  PWM.setPWM(5,0,2048);
  PWM.setPWM(6,0,0);
  PWM.setPWM(7,0,2048);
  for (int i = 0; i <= 180; i = i + (1)) {
    PWM.setPWM(8,0,(map(i, 0, 180, 140, 680)));
    PWM.setPWM(9,0,(map(i, 0, 180, 140, 680)));
    PWM.setPWM(10,0,(map(i, 0, 180, 140, 680)));
    PWM.setPWM(11,0,(map(i, 0, 180, 140, 680)));
    delay(50);
  }

}

示例程式(ESP32開發板):

from machine import I2C, Pin
import time
from mixpy import math_map


PCA9685_MODE1      = 0x00
PCA9685_MODE2      = 0x01
PCA9685_LED0_ON_L  = 0x06
PCA9685_LED0_ON_H  = 0x07
PCA9685_LED0_OFF_L = 0x08
PCA9685_LED0_OFF_H = 0x09
PCA9685_ALLLED_ON_L  = 0xFA
PCA9685_ALLLED_ON_H  = 0xFB
PCA9685_ALLLED_OFF_L = 0xFC
PCA9685_ALLLED_OFF_H = 0xFD
PCA9685_PRESCALE     = 0xFE

MODE1_ALLCAL  = 0x01
MODE1_SUB3    = 0x02
MODE1_SUB2    = 0x04
MODE1_SUB1    = 0x08
MODE1_SLEEP   = 0x10
MODE1_AI      = 0x20
MODE1_EXTCLK  = 0x40
MODE1_RESTART = 0x80

MODE2_OUTNE_0 = 0x01
MODE2_OUTNE_1 = 0x02
MODE2_OUTDRV  = 0x04
MODE2_OCH     = 0x08
MODE2_INVRT   = 0x10


PCA9685_I2C_ADDRESS       = 0x40
FREQUENCY_OSCILLATOR_HZ   = 25_000_000
PRESCALE_MIN = 3
PRESCALE_MAX = 255


class PCA9685:
    def __init__(self, i2c: I2C, addr: int = PCA9685_I2C_ADDRESS):
        self.i2c = i2c
        self.addr = addr
        self._oscillator_freq = FREQUENCY_OSCILLATOR_HZ

    def _write8(self, reg: int, val: int):
        self.i2c.writeto_mem(self.addr, reg, bytes([val & 0xFF]))

    def _read8(self, reg: int) -> int:
        return self.i2c.readfrom_mem(self.addr, reg, 1)[0]

    def _write4(self, base_reg: int, on: int, off: int):
        buf = bytearray(4)
        buf[0] = on & 0xFF
        buf[1] = (on >> 8) & 0x0F
        buf[2] = off & 0xFF
        buf[3] = (off >> 8) & 0x0F
        self.i2c.writeto_mem(self.addr, base_reg, buf)

    def begin(self):
        self.reset()
        mode1 = self._read8(PCA9685_MODE1)
        self._write8(PCA9685_MODE1, mode1 | MODE1_AI)
        self.set_output_mode(True)

    def reset(self):
        self._write8(PCA9685_MODE1, MODE1_RESTART)  # 写 RESTART
        time.sleep_ms(10)

    def sleep(self):
        m1 = self._read8(PCA9685_MODE1)
        self._write8(PCA9685_MODE1, m1 | MODE1_SLEEP)
        time.sleep_ms(5)

    def wakeup(self):
        m1 = self._read8(PCA9685_MODE1)
        self._write8(PCA9685_MODE1, m1 & (~MODE1_SLEEP))
        time.sleep_ms(5)

    def set_output_mode(self, totempole: bool = True):
        m2 = self._read8(PCA9685_MODE2)
        if totempole:
            m2 |= MODE2_OUTDRV
        else:
            m2 &= ~MODE2_OUTDRV
        self._write8(PCA9685_MODE2, m2)

    def set_oscillator_frequency(self, freq_hz: int):
        self._oscillator_freq = int(freq_hz)

    def get_oscillator_frequency(self) -> int:
        return self._oscillator_freq

    def set_pwm_freq(self, freq_hz: float):
        if freq_hz < 1.0:
            freq_hz = 1.0
        if freq_hz > 3500.0:
            freq_hz = 3500.0

        prescaleval = ((self._oscillator_freq / (freq_hz * 4096.0)) + 0.5) - 1.0
        if prescaleval < PRESCALE_MIN:
            prescaleval = PRESCALE_MIN
        if prescaleval > PRESCALE_MAX:
            prescaleval = PRESCALE_MAX
        prescale = int(prescaleval)

        oldmode = self._read8(PCA9685_MODE1)
        newmode = (oldmode & ~MODE1_RESTART) | MODE1_SLEEP
        self._write8(PCA9685_MODE1, newmode)
        self._write8(PCA9685_PRESCALE, prescale)
        self._write8(PCA9685_MODE1, oldmode)
        time.sleep_ms(5)
        self._write8(PCA9685_MODE1, oldmode | MODE1_RESTART | MODE1_AI)

    def read_prescale(self) -> int:
        return self._read8(PCA9685_PRESCALE)

    def set_pwm(self, ch: int, on: int, off: int):
        base = PCA9685_LED0_ON_L + 4 * ch
        self._write4(base, on & 0x1FFF, off & 0x1FFF)

    def set_pin(self, ch: int, val: int, invert: bool = False):
        if val < 0:
            val = 0
        if val > 4095:
            val = 4095

        if invert:
            if val == 0:
                self.set_pwm(ch, 4096, 0)   # fully ON
            elif val == 4095:
                self.set_pwm(ch, 0, 4096)  # fully OFF
            else:
                self.set_pwm(ch, 0, 4095 - val)
        else:
            if val == 4095:
                self.set_pwm(ch, 4096, 0)  # fully ON
            elif val == 0:
                self.set_pwm(ch, 0, 4096)  # fully OFF
            else:
                self.set_pwm(ch, 0, val)

    def write_microseconds(self, ch: int, us: int):
        prescale = self.read_prescale() + 1
        us_per_bit = (1_000_000.0 * prescale) / float(self._oscillator_freq)
        ticks = int(us / us_per_bit + 0.5)
        if ticks < 0:
            ticks = 0
        if ticks > 4095:
            ticks = 4095
        self.set_pwm(ch, 0, ticks)


i2c = I2C(0, scl=Pin(22), sda=Pin(21), freq=400000)

PWM = PCA9685(i2c, addr=0x40)

PWM.begin()

PWM.set_pwm_freq(50)
while True:
    PWM.set_pwm(0,1,4095)
    PWM.set_pwm(1,1,2000)
    PWM.set_pwm(2,1,4095)
    PWM.set_pwm(3,1,2000)
    PWM.set_pwm(4,1,4095)
    PWM.set_pwm(5,1,2000)
    PWM.set_pwm(6,1,4095)
    PWM.set_pwm(7,1,2000)
    PWM.set_pwm(8,  0, int(math_map(90, 0, 180, 140, 680)))
    time.sleep(5)
    PWM.set_pwm(0,1,2000)
    PWM.set_pwm(1,1,2000)
    PWM.set_pwm(2,1,2000)
    PWM.set_pwm(3,1,2000)
    PWM.set_pwm(4,1,2000)
    PWM.set_pwm(5,1,2000)
    PWM.set_pwm(6,1,2000)
    PWM.set_pwm(7,1,2000)
    PWM.set_pwm(8,  0, int(math_map(0, 0, 180, 140, 680)))
    time.sleep(5)

8、米思齊 Mixly 示例程式(圖形化語言)

示例程式(UNO開發板):點擊下載

示例程序(ESP32開發板):點擊下載

9、測試環境搭建

Arduino UNO 測試環境搭建

準備配件:

  • UNO-R3 開發板 *1

  • UNO-R3 EXP 開放板 *1

  • USB type-c 資料線 *1

  • HS-F27 4路電機8路舵機擴展板*1

  • PH2.0 4P雙頭端子線 *1

  • 6-9V電池盒*1

  • 樂高電機*4

  • 舵機*4

電路接線圖:

ESP32 Python 測試環境搭建

10、視頻教學

Arduino UNO視頻教學:按鈕查看

ESP32 Python視頻教學:

11、測試結論

Arduino UNO測試結論:

下載程式,接上對應模組,上電之後,電機和舵機會同時轉動。