8Servos2 Unit
The Servos8V2Unit class controls the Unit 8Servos2-I2C over I2C. The
device provides eight configurable channels for GPIO input, GPIO output, ADC,
servo, RGB, and PWM operation. It also provides power monitoring and device
information APIs.
Support the following products:
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().
Note
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
Open the basic_8servos_v2_servo_control_example.m5f2 project in UiFlow2.
This example initializes Unit 8Servos2-I2C for servo control. Button A selects a channel or the all-channel option. Buttons B and C increase or decrease the servo angle in 10-degree steps. The screen displays the selected channel and current angle.
UiFlow2 Code Block:
Example output:
The selected servo output moves to the angle shown on the screen.
MicroPython Example
Servo control
This example initializes Unit 8Servos2-I2C for servo control. Button A selects a channel or the all-channel option. Buttons B and C increase or decrease the servo angle in 10-degree steps.
MicroPython Code Block:
1# SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD 2# 3# SPDX-License-Identifier: MIT 4 5import os, sys, io 6import M5 7from M5 import * 8from hardware import Pin 9from hardware import I2C 10from unit import Servos8V2Unit 11 12 13label_title = None 14label_channel = None 15label_angle = None 16label_sel = None 17label_increase = None 18label_decrease = None 19i2c0 = None 20servos8v2_0 = None 21channel = None 22angle = None 23i = None 24 25 26def btna_was_clicked_event(state): 27 global \ 28 label_title, \ 29 label_channel, \ 30 label_angle, \ 31 label_sel, \ 32 label_increase, \ 33 label_decrease, \ 34 i2c0, \ 35 servos8v2_0, \ 36 channel, \ 37 angle, \ 38 i 39 channel = (channel if isinstance(channel, (int, float)) else 0) + 1 40 if channel >= 9: 41 channel = 0 42 if channel == 8: 43 label_channel.setText(str("Channel: all")) 44 for i in range(7): 45 servos8v2_0.set_servo_angle(i, angle) 46 else: 47 label_channel.setText(str((str("Channel: ") + str(channel)))) 48 servos8v2_0.set_servo_angle(channel, angle) 49 50 51def btnb_was_clicked_event(state): 52 global \ 53 label_title, \ 54 label_channel, \ 55 label_angle, \ 56 label_sel, \ 57 label_increase, \ 58 label_decrease, \ 59 i2c0, \ 60 servos8v2_0, \ 61 channel, \ 62 angle, \ 63 i 64 angle = angle + 10 65 if angle >= 180: 66 angle = 0 67 if channel == 8: 68 for i in range(7): 69 servos8v2_0.set_servo_angle(i, angle) 70 else: 71 servos8v2_0.set_servo_angle(channel, angle) 72 label_angle.setText(str((str("Angle: ") + str(angle)))) 73 74 75def btnc_was_clicked_event(state): 76 global \ 77 label_title, \ 78 label_channel, \ 79 label_angle, \ 80 label_sel, \ 81 label_increase, \ 82 label_decrease, \ 83 i2c0, \ 84 servos8v2_0, \ 85 channel, \ 86 angle, \ 87 i 88 angle = angle - 10 89 if angle <= 0: 90 angle = 180 91 if channel == 8: 92 for i in range(7): 93 servos8v2_0.set_servo_angle(i, angle) 94 else: 95 servos8v2_0.set_servo_angle(channel, angle) 96 label_angle.setText(str((str("Angle: ") + str(angle)))) 97 98 99def setup(): 100 global \ 101 label_title, \ 102 label_channel, \ 103 label_angle, \ 104 label_sel, \ 105 label_increase, \ 106 label_decrease, \ 107 i2c0, \ 108 servos8v2_0, \ 109 channel, \ 110 angle, \ 111 i 112 113 M5.begin() 114 Widgets.setRotation(1) 115 Widgets.fillScreen(0x000000) 116 label_title = Widgets.Label( 117 "Servo Control", 76, 2, 1.0, 0x1393E8, 0x000000, Widgets.FONTS.Montserrat24 118 ) 119 label_channel = Widgets.Label( 120 "Channel: 1", 36, 77, 1.0, 0xFFFFFF, 0x000000, Widgets.FONTS.Montserrat24 121 ) 122 label_angle = Widgets.Label( 123 "Angle: 0", 40, 112, 1.0, 0xFFFFFF, 0x000000, Widgets.FONTS.Montserrat24 124 ) 125 label_sel = Widgets.Label( 126 "select", 43, 210, 1.0, 0xFFFFFF, 0x000000, Widgets.FONTS.Montserrat16 127 ) 128 label_increase = Widgets.Label( 129 "+10", 143, 210, 1.0, 0xFFFFFF, 0x000000, Widgets.FONTS.Montserrat16 130 ) 131 label_decrease = Widgets.Label( 132 "-10", 233, 210, 1.0, 0xFFFFFF, 0x000000, Widgets.FONTS.Montserrat16 133 ) 134 135 BtnA.setCallback(type=BtnA.CB_TYPE.WAS_CLICKED, cb=btna_was_clicked_event) 136 BtnB.setCallback(type=BtnB.CB_TYPE.WAS_CLICKED, cb=btnb_was_clicked_event) 137 BtnC.setCallback(type=BtnC.CB_TYPE.WAS_CLICKED, cb=btnc_was_clicked_event) 138 139 i2c0 = I2C(0, scl=Pin(22), sda=Pin(21), freq=100000) 140 servos8v2_0 = Servos8V2Unit(i2c0, 0x25) 141 channel = 0 142 angle = 0 143 for i in range(7): 144 servos8v2_0.set_channel_mode(i, Servos8V2Unit.MODE_SERVO) 145 servos8v2_0.set_servo_angle(i, 0) 146 147 148def loop(): 149 global \ 150 label_title, \ 151 label_channel, \ 152 label_angle, \ 153 label_sel, \ 154 label_increase, \ 155 label_decrease, \ 156 i2c0, \ 157 servos8v2_0, \ 158 channel, \ 159 angle, \ 160 i 161 M5.update() 162 163 164if __name__ == "__main__": 165 try: 166 setup() 167 while True: 168 loop() 169 except (Exception, KeyboardInterrupt) as e: 170 try: 171 from utility import print_error_msg 172 173 print_error_msg(e) 174 except ImportError: 175 print("please update to latest firmware")
Example output:
The screen displays the selected channel and angle, and the selected servo output moves when the angle is changed.
API
Servos8V2Unit
- class unit.servos8_v2.Servos8V2Unit(i2c, address=37)
Bases:
objectCreate a Unit 8Servos2 object.
- Parameters:
i2c (machine.I2C | PAHUBUnit) – The I2C bus the Unit 8Servos2 is connected to.
address (int | list | tuple) – The I2C address of the device, range 0x25 to 0x34. Default is 0x25.
i2c
address
- Raises:
UnitError – If the Unit 8Servos2 is not connected.
UiFlow2 Code Block:

MicroPython Code Block:
from hardware import I2C, Pin from unit import Servos8V2Unit i2c0 = I2C(0, scl=Pin(22), sda=Pin(21), freq=100000) servos8v2_0 = Servos8V2Unit(i2c0, 0x25)
- get_channel_mode(channel)
Get the current mode of a specific channel.
The channel mode values:
MODE_INPUT:0x00MODE_OUTPUT:0x01MODE_ADC:0x02MODE_SERVO:0x03MODE_RGB:0x04MODE_PWM:0x05
- Parameters:
channel (int) – The channel number (0 to 7).
- Returns:
The mode of the specified channel.
- Return type:
UiFlow2 Code Block:

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:0x00MODE_OUTPUT:0x01MODE_ADC:0x02MODE_SERVO:0x03MODE_RGB:0x04MODE_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.- Parameters:
- Return type:
None
UiFlow2 Code Block:

MicroPython Code Block:
servos8v2_0.set_channel_mode(0, Servos8V2Unit.MODE_SERVO)
- set_input_pull(channel, pull)
Set the input pull configuration of a specific channel.
- Parameters:
- Return type:
None
UiFlow2 Code Block:

MicroPython Code Block:
servos8v2_0.set_input_pull(0, Servos8V2Unit.PULL_UP)
- get_input_pull(channel)
Get the input pull configuration of a specific channel.
- Parameters:
channel (int) – The channel number (0 to 7).
- Returns:
Pull configuration of the specified channel.
- Return type:
UiFlow2 Code Block:

MicroPython Code Block:
pull = servos8v2_0.get_input_pull(0)
- get_gpio_input_value(channel)
Get the GPIO input value of a specific channel.
- Parameters:
channel (int) – The channel number (0 to 7).
- Returns:
True for high level, False for low level.
- Return type:
UiFlow2 Code Block:

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.
- Parameters:
- Return type:
None
UiFlow2 Code Block:

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.
- Parameters:
channel (int) – The channel number (0 to 7).
- Returns:
True for high level, False for low level.
- Return type:
UiFlow2 Code Block:

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.
- Parameters:
channel (int) – The channel number (0 to 7).
- Returns:
ADC value, range 0 to 4095.
- Return type:
UiFlow2 Code Block:

MicroPython Code Block:
adc = servos8v2_0.get_adc_input(0)
- set_servo_angle(channel, angle)
Set the servo angle of a specific channel.
- Parameters:
- Return type:
None
UiFlow2 Code Block:

MicroPython Code Block:
servos8v2_0.set_servo_angle(0, 90)
- get_servo_angle(channel)
Get the servo angle of a specific channel.
- Parameters:
channel (int) – The channel number (0 to 7).
- Returns:
Servo angle, range 0 to 180.
- Return type:
UiFlow2 Code Block:

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.
- Parameters:
- Return type:
None
UiFlow2 Code Block:

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.
- Parameters:
channel (int) – The channel number (0 to 7).
- Returns:
Raw RGB config byte.
- Return type:
UiFlow2 Code Block:

MicroPython Code Block:
config = servos8v2_0.get_rgb_config(0)
- get_rgb_count(channel)
Get the configured WS2812 LED count of a specific channel.
- Parameters:
channel (int) – The channel number (0 to 7).
- Returns:
WS2812 LED count, range 0 to 16.
- Return type:
UiFlow2 Code Block:

MicroPython Code Block:
count = servos8v2_0.get_rgb_count(0)
- refresh_rgb(channel)
Trigger WS2812 refresh for a specific channel.
- Parameters:
channel (int) – The channel number (0 to 7).
- Return type:
None
UiFlow2 Code Block:

MicroPython Code Block:
servos8v2_0.refresh_rgb(0)
- set_rgb_buffer(index, color)
Set one WS2812 color buffer entry.
- Parameters:
- Return type:
None
UiFlow2 Code Block:

MicroPython Code Block:
servos8v2_0.set_rgb_buffer(0, 0xFF0000)
- get_rgb_buffer(index)
Get one WS2812 color buffer entry.
- Parameters:
index (int) – WS2812 color buffer index, range 0 to 15.
- Returns:
RGB888 color value in
0xRRGGBBformat.- Return type:
UiFlow2 Code Block:

MicroPython Code Block:
color = servos8v2_0.get_rgb_buffer(0)
- set_pwm_duty(channel, duty)
Set the PWM duty of a specific channel.
- Parameters:
- Return type:
None
UiFlow2 Code Block:

MicroPython Code Block:
servos8v2_0.set_pwm_duty(0, 50)
- get_pwm_duty(channel)
Get the PWM duty of a specific channel.
- Parameters:
channel (int) – The channel number (0 to 7).
- Returns:
PWM duty, range 0 to 100.
- Return type:
UiFlow2 Code Block:

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.
- Parameters:
- Return type:
None
UiFlow2 Code Block:

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.
- Parameters:
channel (int) – The channel number (0 to 7).
- Returns:
PWM frequency in Hz.
- Return type:
UiFlow2 Code Block:

MicroPython Code Block:
freq = servos8v2_0.get_pwm_freq(0)
- get_reference_voltage()
Get the reference voltage.
- Returns:
Reference voltage in mV.
- Return type:
UiFlow2 Code Block:

MicroPython Code Block:
voltage = servos8v2_0.get_reference_voltage()
- get_grove_voltage()
Get the Grove port voltage.
- Returns:
Grove port voltage in mV.
- Return type:
UiFlow2 Code Block:

MicroPython Code Block:
voltage = servos8v2_0.get_grove_voltage()
- get_dc_voltage()
Get the DC input voltage.
- Returns:
DC input voltage in mV.
- Return type:
UiFlow2 Code Block:

MicroPython Code Block:
voltage = servos8v2_0.get_dc_voltage()
- get_current()
Get the system current.
- Returns:
System current in mA.
- Return type:
UiFlow2 Code Block:

MicroPython Code Block:
current = servos8v2_0.get_current()
- get_firmware_version()
Get the firmware version.
- Returns:
Firmware version.
- Return type:
UiFlow2 Code Block:

MicroPython Code Block:
version = servos8v2_0.get_firmware_version()
- get_i2c_address()
Get the current I2C address.
- Returns:
Current I2C address.
- Return type:
UiFlow2 Code Block:

MicroPython Code Block:
address = servos8v2_0.get_i2c_address()


