Chain 8Servos2

The Servos8V2Chain class controls the Unit 8Servos2-Chain through a ChainBus. The device provides eight configurable channels for GPIO input, GPIO output, ADC, servo, RGB, and PWM operation. It also provides power monitoring, UID, firmware, bootloader, and device type APIs.

Support the following products:

Unit 8Servos2-Chain

Constants

Use the following constants with set_channel_mode():

  • MODE_INPUT: GPIO input mode.

  • MODE_OUTPUT: GPIO output mode.

  • MODE_ADC: ADC input mode.

  • MODE_SERVO: Servo control mode.

  • MODE_RGB: RGB output mode for WS2812 LEDs.

  • MODE_PWM: PWM duty output mode.

Use PULL_NONE, PULL_UP, or PULL_DOWN with set_input_pull().

备注

Channels 0-3 share one PWM frequency, and channels 4-7 share another. Setting the frequency of one channel changes every channel in the same group. Selecting servo mode sets the channel’s shared group to 50 Hz.

UiFlow2 Example

Servo control

Initialize Unit 8Servos2-Chain, set a channel to servo mode, and set its angle.

UiFlow2 Code Block:

example.png

Example output:

The selected servo moves to the configured angle.

MicroPython Example

Basic control

This example reads device information and power values from Unit 8Servos2-Chain, then moves each servo channel between 0 and 180 degrees.

MicroPython Code Block:

  1# SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
  2#
  3# SPDX-License-Identifier: MIT
  4
  5import M5
  6from M5 import *
  7from chain import ChainBus
  8from chain import Servos8V2Chain
  9import time
 10
 11
 12title = None
 13label_angle = None
 14label_timer = None
 15label_power = None
 16label_state = None
 17bus2 = None
 18servos8v2_0 = None
 19last_move = 0
 20position = 0
 21
 22ANGLES = (45, 135)
 23
 24
 25def require_ok(result, action):
 26    if not result:
 27        raise RuntimeError(action + " failed")
 28
 29
 30def setup():
 31    global title, label_angle, label_timer, label_power, label_state
 32    global bus2, servos8v2_0, last_move
 33
 34    M5.begin()
 35    Widgets.setRotation(1)
 36    Widgets.fillScreen(0x222222)
 37    title = Widgets.Title("Chain 8Servos2 Servo", 3, 0xFFFFFF, 0x0055AA, Widgets.FONTS.DejaVu18)
 38    label_angle = Widgets.Label(
 39        "All channels: 90 deg", 10, 58, 1.0, 0x17E6CF, 0x222222, Widgets.FONTS.DejaVu18
 40    )
 41    label_timer = Widgets.Label(
 42        "Servo PWM: 50 Hz", 10, 98, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18
 43    )
 44    label_power = Widgets.Label(
 45        "Use external servo power", 10, 138, 1.0, 0xFFD166, 0x222222, Widgets.FONTS.DejaVu18
 46    )
 47    label_state = Widgets.Label(
 48        "Sweeps 45 <-> 135 deg", 10, 178, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18
 49    )
 50
 51    bus2 = ChainBus(2, tx=21, rx=22)
 52    servos8v2_0 = Servos8V2Chain(bus2, 1)
 53    for channel in range(8):
 54        require_ok(
 55            servos8v2_0.set_channel_mode(channel, Servos8V2Chain.MODE_SERVO),
 56            "set IO%d servo mode" % channel,
 57        )
 58    for channel in range(8):
 59        require_ok(servos8v2_0.set_servo_angle(channel, 90), "center servo %d" % channel)
 60    modes = tuple(servos8v2_0.get_channel_mode(channel) for channel in range(8))
 61    freqs = (
 62        servos8v2_0.get_pwm_freq(0),
 63        servos8v2_0.get_pwm_freq(4),
 64    )
 65    label_timer.setText("PWM groups: %d / %d Hz" % freqs)
 66    label_state.setText("Mode: %s" % ("OK" if modes == (3,) * 8 else str(modes)))
 67    last_move = time.ticks_ms()
 68    print("Chain 8Servos2: modes =", modes, "PWM groups =", freqs)
 69    print("Chain 8Servos2: all channels centered at 90 degrees")
 70
 71
 72def loop():
 73    global last_move, position
 74
 75    M5.update()
 76    if time.ticks_diff(time.ticks_ms(), last_move) < 1500:
 77        return
 78    last_move = time.ticks_ms()
 79    angle = ANGLES[position]
 80    position = (position + 1) % len(ANGLES)
 81    for channel in range(8):
 82        require_ok(servos8v2_0.set_servo_angle(channel, angle), "set servo %d angle" % channel)
 83    label_angle.setText("All channels: %d deg" % angle)
 84    print("Servo angle:", angle)
 85
 86
 87if __name__ == "__main__":
 88    try:
 89        setup()
 90        while True:
 91            loop()
 92    except (Exception, KeyboardInterrupt) as e:
 93        try:
 94            if bus2 is not None:
 95                bus2.deinit()
 96            from utility import print_error_msg
 97
 98            print_error_msg(e)
 99        except ImportError:
100            print("please update to latest firmware")

Example output:

Device information and power values are printed to the serial console, and each connected servo moves through the test sequence.

API

Servos8V2Chain

class chain.servos8_v2.Servos8V2Chain(bus, device_id)

基类:KeyChain

Unit 8Servos2 Chain device.

参数:
  • bus (ChainBus) – The Chain bus instance.

  • device_id (int) – The device ID on the Chain bus.

UiFlow2 Code Block:

init.png

MicroPython Code Block:

from chain import ChainBus
from chain import Servos8V2Chain

bus2 = ChainBus(2, tx=21, rx=22)
servos8v2_0 = Servos8V2Chain(bus2, 1)

For general Chain device methods, refer to KeyChain.

get_channel_mode(channel)

Get the current mode of a specific channel.

The channel mode values:

  • MODE_INPUT: 0x00

  • MODE_OUTPUT: 0x01

  • MODE_ADC: 0x02

  • MODE_SERVO: 0x03

  • MODE_RGB: 0x04

  • MODE_PWM: 0x05

参数:

channel (int) – The channel number (0 to 7).

返回:

The mode of the specified channel.

返回类型:

int

UiFlow2 Code Block:

get_channel_mode.png

MicroPython Code Block:

mode = servos8v2_0.get_channel_mode(0)
set_channel_mode(channel, mode)

Set the mode of a specific channel.

The channel mode values:

  • MODE_INPUT: 0x00

  • MODE_OUTPUT: 0x01

  • MODE_ADC: 0x02

  • MODE_SERVO: 0x03

  • MODE_RGB: 0x04

  • MODE_PWM: 0x05

When a channel is set to MODE_SERVO, the driver automatically sets its shared frequency group to 50 Hz. Channels 0-3 share one frequency, and channels 4-7 share another frequency.

参数:
  • channel (int) – The channel number (0 to 7).

  • mode (int) – The channel mode to set.

返回:

True if the operation was successful, False otherwise.

返回类型:

bool

UiFlow2 Code Block:

set_channel_mode.png

MicroPython Code Block:

servos8v2_0.set_channel_mode(0, Servos8V2Chain.MODE_SERVO)
set_input_pull(channel, pull)

Set the input pull configuration of a specific channel.

参数:
  • channel (int) – The channel number (0 to 7).

  • pull (int) – Pull configuration. Use PULL_NONE, PULL_UP, or PULL_DOWN.

返回:

True if the operation was successful, False otherwise.

返回类型:

bool

UiFlow2 Code Block:

set_input_pull.png

MicroPython Code Block:

servos8v2_0.set_input_pull(0, Servos8V2Chain.PULL_UP)
get_input_pull(channel)

Get the input pull configuration of a specific channel.

参数:

channel (int) – The channel number (0 to 7).

返回:

Pull configuration of the specified channel.

返回类型:

int

UiFlow2 Code Block:

get_input_pull.png

MicroPython Code Block:

pull = servos8v2_0.get_input_pull(0)
get_gpio_input_value(channel)

Get the GPIO input value of a specific channel.

参数:

channel (int) – The channel number (0 to 7).

返回:

True for high level, False for low level.

返回类型:

bool

UiFlow2 Code Block:

get_gpio_input_value.png

MicroPython Code Block:

level = servos8v2_0.get_gpio_input_value(0)
set_gpio_output_value(channel, value)

Set the GPIO output value of a specific channel.

参数:
  • channel (int) – The channel number (0 to 7).

  • value (bool) – Output value, False for low level or True for high level.

返回:

True if the operation was successful, False otherwise.

返回类型:

bool

UiFlow2 Code Block:

set_gpio_output_value.png

MicroPython Code Block:

servos8v2_0.set_gpio_output_value(0, True)
get_gpio_output_value(channel)

Get the GPIO output value of a specific channel.

参数:

channel (int) – The channel number (0 to 7).

返回:

True for high level, False for low level.

返回类型:

bool

UiFlow2 Code Block:

get_gpio_output_value.png

MicroPython Code Block:

level = servos8v2_0.get_gpio_output_value(0)
get_adc_input(channel)

Get the 12-bit ADC input value of a specific channel.

参数:

channel (int) – The channel number (0 to 7).

返回:

ADC value, range 0 to 4095.

返回类型:

int

UiFlow2 Code Block:

get_adc_input.png

MicroPython Code Block:

adc = servos8v2_0.get_adc_input(0)
set_servo_angle(channel, angle)

Set the servo angle of a specific channel.

参数:
  • channel (int) – The channel number (0 to 7).

  • angle (int) – Servo angle, range 0 to 180.

返回:

True if the operation was successful, False otherwise.

返回类型:

bool

UiFlow2 Code Block:

set_servo_angle.png

MicroPython Code Block:

servos8v2_0.set_servo_angle(0, 90)
get_servo_angle(channel)

Get the servo angle of a specific channel.

参数:

channel (int) – The channel number (0 to 7).

返回:

Servo angle, range 0 to 180.

返回类型:

int

UiFlow2 Code Block:

get_servo_angle.png

MicroPython Code Block:

angle = servos8v2_0.get_servo_angle(0)
set_rgb_config(channel, count, refresh=False)

Set the WS2812 LED count and refresh flag of a specific channel.

参数:
  • channel (int) – The channel number (0 to 7).

  • count (int) – WS2812 LED count, range 0 to 16.

  • refresh (bool) – Whether to trigger an RGB refresh. Default is False.

返回:

True if the operation was successful, False otherwise.

返回类型:

bool

UiFlow2 Code Block:

set_rgb_config.png

MicroPython Code Block:

servos8v2_0.set_rgb_config(0, 4, refresh=True)
get_rgb_config(channel)

Get the raw WS2812 config value of a specific channel.

参数:

channel (int) – The channel number (0 to 7).

返回:

Raw RGB config byte.

返回类型:

int

UiFlow2 Code Block:

get_rgb_config.png

MicroPython Code Block:

config = servos8v2_0.get_rgb_config(0)
get_rgb_count(channel)

Get the configured WS2812 LED count of a specific channel.

参数:

channel (int) – The channel number (0 to 7).

返回:

WS2812 LED count, range 0 to 16.

返回类型:

int

UiFlow2 Code Block:

get_rgb_count.png

MicroPython Code Block:

count = servos8v2_0.get_rgb_count(0)
refresh_rgb(channel)

Trigger WS2812 refresh for a specific channel.

参数:

channel (int) – The channel number (0 to 7).

返回:

True if the operation was successful, False otherwise.

返回类型:

bool

UiFlow2 Code Block:

refresh_rgb.png

MicroPython Code Block:

servos8v2_0.refresh_rgb(0)
set_rgb_buffer(index, color)

Set one WS2812 color buffer entry.

参数:
  • index (int) – WS2812 color buffer index, range 0 to 15.

  • color (int) – RGB888 color value in 0xRRGGBB format.

返回:

True if the operation was successful, False otherwise.

返回类型:

bool

UiFlow2 Code Block:

set_rgb_buffer.png

MicroPython Code Block:

servos8v2_0.set_rgb_buffer(0, 0xFF0000)
get_rgb_buffer(index)

Get one WS2812 color buffer entry.

参数:

index (int) – WS2812 color buffer index, range 0 to 15.

返回:

RGB888 color value in 0xRRGGBB format.

返回类型:

int

UiFlow2 Code Block:

get_rgb_buffer.png

MicroPython Code Block:

color = servos8v2_0.get_rgb_buffer(0)
set_pwm_duty(channel, duty)

Set the PWM duty of a specific channel.

参数:
  • channel (int) – The channel number (0 to 7).

  • duty (int) – PWM duty, range 0 to 100.

返回:

True if the operation was successful, False otherwise.

返回类型:

bool

UiFlow2 Code Block:

set_pwm_duty.png

MicroPython Code Block:

servos8v2_0.set_pwm_duty(0, 50)
get_pwm_duty(channel)

Get the PWM duty of a specific channel.

参数:

channel (int) – The channel number (0 to 7).

返回:

PWM duty, range 0 to 100.

返回类型:

int

UiFlow2 Code Block:

get_pwm_duty.png

MicroPython Code Block:

duty = servos8v2_0.get_pwm_duty(0)
set_pwm_freq(channel, freq)

Set the PWM frequency of a specific channel.

Channels 0-3 share one frequency, and channels 4-7 share another frequency. Setting the frequency of any channel changes the frequency of every channel in the same group.

参数:
  • channel (int) – The channel number (0 to 7).

  • freq (int) – PWM frequency in Hz, range 1 to 65535.

返回:

True if the operation was successful, False otherwise.

返回类型:

bool

UiFlow2 Code Block:

set_pwm_freq.png

MicroPython Code Block:

servos8v2_0.set_pwm_freq(0, 1000)
get_pwm_freq(channel)

Get the PWM frequency of a specific channel.

Channels 0-3 share one frequency, and channels 4-7 share another frequency. The returned value is the shared frequency of the channel’s group.

参数:

channel (int) – The channel number (0 to 7).

返回:

PWM frequency in Hz.

返回类型:

int

UiFlow2 Code Block:

get_pwm_freq.png

MicroPython Code Block:

freq = servos8v2_0.get_pwm_freq(0)
get_reference_voltage()

Get the reference voltage.

返回:

Reference voltage in mV.

返回类型:

int

UiFlow2 Code Block:

get_reference_voltage.png

MicroPython Code Block:

voltage = servos8v2_0.get_reference_voltage()
get_grove_voltage()

Get the Grove port voltage.

返回:

Grove port voltage in mV.

返回类型:

int

UiFlow2 Code Block:

get_grove_voltage.png

MicroPython Code Block:

voltage = servos8v2_0.get_grove_voltage()
get_dc_voltage()

Get the DC input voltage.

返回:

DC input voltage in mV.

返回类型:

int

UiFlow2 Code Block:

get_dc_voltage.png

MicroPython Code Block:

voltage = servos8v2_0.get_dc_voltage()
get_current()

Get the system current.

返回:

System current in mA.

返回类型:

int

UiFlow2 Code Block:

get_current.png

MicroPython Code Block:

current = servos8v2_0.get_current()
get_uid(uid_type=0)

Get the device UID.

参数:

uid_type (int) – UID type. Use 0 for 4-byte UID or 1 for 12-byte UID. Default is 0.

返回:

Tuple of UID bytes. Returns an empty tuple if failed.

返回类型:

tuple

UiFlow2 Code Block:

get_uid.png

MicroPython Code Block:

uid = servos8v2_0.get_uid(0)
get_bootloader_version()

Get the bootloader version.

返回:

Bootloader version, or None if failed.

返回类型:

int

UiFlow2 Code Block:

get_bootloader_version.png

MicroPython Code Block:

version = servos8v2_0.get_bootloader_version()
get_firmware_version()

Get the firmware version.

返回:

Firmware version.

返回类型:

int

UiFlow2 Code Block:

get_firmware_version.png

MicroPython Code Block:

version = servos8v2_0.get_firmware_version()
get_device_type()

Get the Chain device type.

返回:

Device type. Unit 8Servos2 Chain is 0x000C.

返回类型:

int

UiFlow2 Code Block:

get_device_type.png

MicroPython Code Block:

device_type = servos8v2_0.get_device_type()