EncoderMotor Driver Unit

EncoderMotorDriverUnit 类通过 I2C 控制 Unit EncoderMotor Driver,支持电机正反转的开环 PWM 控制、位置控制、速度控制、编码器反馈、电机休眠、软启动和软停止、RGB LED 控制及输入电压和电流监测。

支持以下产品:

Unit EncoderMotor Driver

UiFlow2 应用示例

基本电机控制

在 UiFlow2 中打开 m5cores3_unit_encoder_motor_driver_basic_example.m5f2 项目。

选择 CoreS3 作为主机,将 Unit 连接到 Port A 端口(SDA=G2、SCL=G1,I2C 频率为 100 kHz)。Unit 的默认地址为 0x2F。

m5ui 页面提供三个触摸按键:

  • +:每按一次,PWM 控制值加 20;当前值为 80 时,再按一次归零。

  • -:每按一次,PWM 控制值减 20;当前值为 -80 时,再按一次归零。

  • STOP:将 PWM 控制值归零,停止电机。

PWM 控制值的正负表示相反的转动方向,绝对值表示占空比百分数。屏幕中央显示当前设置值,范围为 -80~80,初始值为 0;此处显示的是 PWM 设置值,而非转速或编码器计数。

备注

本示例使用 Unit 默认的开环模式,电机驱动需处于启用状态。若之前的程序切换到了闭环模式或禁用了驱动,请先调用 set_motor_mode(MODE_OPEN_LOOP) 切回开环模式,并调用 enable_motor() 启用驱动。重启 Unit 也可恢复这些默认设置。运行前请接好电机电源,结束示例前请按 STOP 停止电机。

UiFlow2 代码块:

m5cores3_unit_encoder_motor_driver_basic_example.png

示例输出:

CoreS3 屏幕显示当前的 PWM 设置值。例如,启动后连续按两次 +,屏幕显示 40;按 STOP 后显示 0。

MicroPython 应用示例

基本电机控制

按上述方式接线并设置 Unit 后,在 CoreS3 上运行以下示例。+、- 和 STOP 按键的功能与 UiFlow2 项目相同。

MicroPython 代码块:

  1# SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
  2#
  3# SPDX-License-Identifier: MIT
  4
  5import os, sys, io
  6import M5
  7from M5 import *
  8import m5ui
  9import lvgl as lv
 10from unit import EncoderMotorDriverUnit
 11from hardware import Pin
 12from hardware import I2C
 13
 14
 15page0 = None
 16label_title = None
 17button_speed_up = None
 18button_speed_down = None
 19label_speed = None
 20button_stop = None
 21i2c0 = None
 22encodermotordriver_0 = None
 23speed = None
 24
 25
 26def button_stop_short_clicked_event(event_struct):
 27    global \
 28        page0, \
 29        label_title, \
 30        button_speed_up, \
 31        button_speed_down, \
 32        label_speed, \
 33        button_stop, \
 34        i2c0, \
 35        encodermotordriver_0, \
 36        speed
 37    speed = 0
 38    encodermotordriver_0.set_motor_pwm_duty(speed)
 39    label_speed.set_text(str(speed))
 40
 41
 42def button_speed_up_short_clicked_event(event_struct):
 43    global \
 44        page0, \
 45        label_title, \
 46        button_speed_up, \
 47        button_speed_down, \
 48        label_speed, \
 49        button_stop, \
 50        i2c0, \
 51        encodermotordriver_0, \
 52        speed
 53    if speed < 80:
 54        speed = speed + 20
 55    else:
 56        speed = 0
 57    encodermotordriver_0.set_motor_pwm_duty(speed)
 58    label_speed.set_text(str(speed))
 59
 60
 61def button_speed_down_short_clicked_event(event_struct):
 62    global \
 63        page0, \
 64        label_title, \
 65        button_speed_up, \
 66        button_speed_down, \
 67        label_speed, \
 68        button_stop, \
 69        i2c0, \
 70        encodermotordriver_0, \
 71        speed
 72    if speed > -80:
 73        speed = speed - 20
 74    else:
 75        speed = 0
 76    encodermotordriver_0.set_motor_pwm_duty(speed)
 77    label_speed.set_text(str(speed))
 78
 79
 80def button_stop_event_handler(event_struct):
 81    global \
 82        page0, \
 83        label_title, \
 84        button_speed_up, \
 85        button_speed_down, \
 86        label_speed, \
 87        button_stop, \
 88        i2c0, \
 89        encodermotordriver_0, \
 90        speed
 91    event = event_struct.code
 92    if event == lv.EVENT.SHORT_CLICKED and True:
 93        button_stop_short_clicked_event(event_struct)
 94    return
 95
 96
 97def button_speed_up_event_handler(event_struct):
 98    global \
 99        page0, \
100        label_title, \
101        button_speed_up, \
102        button_speed_down, \
103        label_speed, \
104        button_stop, \
105        i2c0, \
106        encodermotordriver_0, \
107        speed
108    event = event_struct.code
109    if event == lv.EVENT.SHORT_CLICKED and True:
110        button_speed_up_short_clicked_event(event_struct)
111    return
112
113
114def button_speed_down_event_handler(event_struct):
115    global \
116        page0, \
117        label_title, \
118        button_speed_up, \
119        button_speed_down, \
120        label_speed, \
121        button_stop, \
122        i2c0, \
123        encodermotordriver_0, \
124        speed
125    event = event_struct.code
126    if event == lv.EVENT.SHORT_CLICKED and True:
127        button_speed_down_short_clicked_event(event_struct)
128    return
129
130
131def setup():
132    global \
133        page0, \
134        label_title, \
135        button_speed_up, \
136        button_speed_down, \
137        label_speed, \
138        button_stop, \
139        i2c0, \
140        encodermotordriver_0, \
141        speed
142
143    M5.begin()
144    Widgets.setRotation(0)
145    m5ui.init()
146    page0 = m5ui.M5Page(bg_c=0x000000)
147    label_title = m5ui.M5Label(
148        "Encoder Motor Control",
149        x=20,
150        y=5,
151        text_c=0x079EE1,
152        bg_c=0xFFFFFF,
153        bg_opa=0,
154        font=lv.font_montserrat_24,
155        parent=page0,
156    )
157    button_speed_up = m5ui.M5Button(
158        text="+",
159        x=50,
160        y=165,
161        bg_c=0x2196F3,
162        text_c=0xFFFFFF,
163        font=lv.font_montserrat_24,
164        parent=page0,
165    )
166    button_speed_down = m5ui.M5Button(
167        text="-",
168        x=230,
169        y=165,
170        bg_c=0x2196F3,
171        text_c=0xFFFFFF,
172        font=lv.font_montserrat_24,
173        parent=page0,
174    )
175    label_speed = m5ui.M5Label(
176        "00",
177        x=132,
178        y=75,
179        text_c=0x079EE1,
180        bg_c=0xFFFFFF,
181        bg_opa=0,
182        font=lv.font_montserrat_40,
183        parent=page0,
184    )
185    button_stop = m5ui.M5Button(
186        text="STOP",
187        x=112,
188        y=165,
189        bg_c=0xF32121,
190        text_c=0xFFFFFF,
191        font=lv.font_montserrat_24,
192        parent=page0,
193    )
194
195    button_stop.add_event_cb(button_stop_event_handler, lv.EVENT.ALL, None)
196    button_speed_up.add_event_cb(button_speed_up_event_handler, lv.EVENT.ALL, None)
197    button_speed_down.add_event_cb(button_speed_down_event_handler, lv.EVENT.ALL, None)
198
199    i2c0 = I2C(0, scl=Pin(1), sda=Pin(2), freq=100000)
200    encodermotordriver_0 = EncoderMotorDriverUnit(i2c0, 0x2F)
201    speed = 0
202    encodermotordriver_0.set_motor_pwm_duty(speed)
203    page0.screen_load()
204
205
206def loop():
207    global \
208        page0, \
209        label_title, \
210        button_speed_up, \
211        button_speed_down, \
212        label_speed, \
213        button_stop, \
214        i2c0, \
215        encodermotordriver_0, \
216        speed
217    M5.update()
218
219
220if __name__ == "__main__":
221    try:
222        setup()
223        while True:
224            loop()
225    except (Exception, KeyboardInterrupt) as e:
226        try:
227            m5ui.deinit()
228            from utility import print_error_msg
229
230            print_error_msg(e)
231        except ImportError:
232            print("please update to latest firmware")

示例输出:

屏幕中央显示当前的 PWM 设置值。未检测到 Unit 时,屏幕会提示检查连接。

API参考

EncoderMotorDriverUnit

class unit.encoder_motor_driver.EncoderMotorDriverUnit(i2c, address=micropython.const)

基类:object

通过 I2C 控制 Unit EncoderMotor Driver。

Unit 支持电机正反转的开环 PWM 控制、位置控制、速度控制、编码器反馈、电机休眠、软启动和软停止、RGB LED 控制及输入电压和电流监测。驱动使用传入的 I2C 总线,不会关闭该总线。未检测到指定地址时,请检查 Unit 的 Grove 接线、供电和 I2C 地址。

参数:
  • i2c (I2C | PAHUBUnit) – 已初始化的 I2C 总线或兼容的 PAHUB 端口。

  • address (int) – 7 位 I2C 地址,范围为 0x08~0x77,默认值为 0x2F。

UiFlow2 代码块:

init.png

MicroPython 代码块:

from hardware import I2C, Pin
from unit import EncoderMotorDriverUnit

i2c0 = I2C(0, scl=Pin(1), sda=Pin(2), freq=100000)
encodermotordriver_0 = EncoderMotorDriverUnit(i2c0, 0x2F)

电机控制模式常量:

  • MODE_OPEN_LOOP = 0:开环 PWM 控制。

  • MODE_POSITION = 1:位置控制。

  • MODE_SPEED = 2:速度控制。

编码器相位常量:

  • ENCODER_MODE_AB = 0:AB 相位顺序。

  • ENCODER_MODE_BA = 1:BA 相位顺序。

set_motor_mode(mode)

设置电机控制模式。

参数:

mode (int) – 使用 MODE_OPEN_LOOP、MODE_POSITION 或 MODE_SPEED。

返回:

None.

UiFlow2 代码块:

set_motor_mode.png

motor_mode_option.png

get_motor_mode()

获取当前电机控制模式。

返回:

当前模式,范围为 0~2。

返回类型:

int

UiFlow2 代码块:

get_motor_mode.png

set_motor_pwm_duty(percent)

设置电机在开环模式下的 PWM 控制值。

参数:

percent (int or float) – PWM 控制值,范围为 -100~100。正负表示相反的转动方向,绝对值表示占空比百分数。

返回:

None.

UiFlow2 代码块:

set_motor_pwm_duty.png

get_motor_pwm_duty()

获取电机当前的 PWM 控制值。

开环模式下返回设置的 PWM 控制值;闭环模式下,固件可能会根据实时电机输出更新该值。

返回:

PWM 控制值,范围为 -100~100。正负表示相反的转动方向,绝对值表示占空比百分数。

返回类型:

int

UiFlow2 代码块:

get_motor_pwm_duty.png

read_motor_speed()

读取电机当前的速度读数。

返回:

速度读数,可正可负,范围为 -127~127,固件每 20 ms 更新一次。该值未换算为转速(RPM),协议未提供相应的物理单位换算关系。

返回类型:

int

UiFlow2 代码块:

read_motor_speed.png

stop_motor()

停止电机,并将控制模式设为开环模式。

切换模式前后都会将 PWM 控制值清零,避免之前的闭环输出在切换后继续驱动电机。

返回:

None.

UiFlow2 代码块:

stop_motor.png

read_encoder_count()

读取当前编码器计数,读取操作不会将计数清零。

返回:

编码器计数,可正可负,范围为 -2147483648~2147483647。

返回类型:

int

UiFlow2 代码块:

read_encoder_count.png

set_encoder_count(count)

设置当前编码器计数。

参数:

count (int) – 编码器计数,可正可负,范围为 -2147483648~2147483647。

返回:

None.

UiFlow2 代码块:

set_encoder_count.png

clear_encoder_count()

将编码器计数清零。

返回:

None.

UiFlow2 代码块:

clear_encoder_count.png

set_encoder_mode(mode)

设置编码器 AB 或 BA 相位顺序。

修改相位顺序后,设置会保存到 Unit 的 Flash 中,并立即触发 Unit 重启。本方法会等待 Unit 重新响应当前 I2C 地址后返回。请避免重复写入相同设置,以减少 Flash 写入次数。

参数:

mode (int) – 使用 ENCODER_MODE_AB 或 ENCODER_MODE_BA。

返回:

None.

UiFlow2 代码块:

set_encoder_mode.png

encoder_mode_option.png

get_encoder_mode()

获取编码器相位顺序。

返回:

使用 ENCODER_MODE_AB 或 ENCODER_MODE_BA。

返回类型:

int

UiFlow2 代码块:

get_encoder_mode.png

set_position_pid(kp, ki, kd)

设置位置环 PID 系数。

参数:
  • kp (int) – 比例系数,范围为 0~255。

  • ki (int) – 积分系数,范围为 0~255。

  • kd (int) – 微分系数,范围为 0~255。

返回:

None.

UiFlow2 代码块:

set_position_pid.png

get_position_pid()

获取位置环 PID 系数。

返回:

PID 系数元组 (kp, ki, kd),依次为比例、积分、微分系数,每项范围均为 0~255。

返回类型:

tuple

UiFlow2 代码块:

get_position_pid.png

set_position_target_count(count)

设置位置控制的目标位置,以编码器计数为单位。

参数:

count (int) – 目标位置,以编码器计数为单位,可正可负,范围为 -2147483648~2147483647。

返回:

None.

UiFlow2 代码块:

set_position_target_count.png

get_position_target_count()

获取已设置的目标位置,以编码器计数为单位。

返回:

目标位置,以编码器计数为单位,可正可负,范围为 -2147483648~2147483647。

返回类型:

int

UiFlow2 代码块:

get_position_target_count.png

set_position_speed_limit(speed_limit)

设置位置控制时的速度上限。

位置控制使用该设置值的绝对值作为速度上限。该值为设备使用的速度数值,协议未提供其与转速(RPM)的换算关系。

参数:

speed_limit (int) – 速度上限设置值,范围为 -127~127,实际限速取该值的绝对值。

返回:

None.

UiFlow2 代码块:

set_position_speed_limit.png

get_position_speed_limit()

获取位置控制时的速度上限设置。

返回:

速度上限设置值,范围为 -127~127,实际限速取该值的绝对值。该值为设备使用的速度数值,单位不是转速(RPM)。

返回类型:

int

UiFlow2 代码块:

get_position_speed_limit.png

set_speed_pid(kp, ki, kd)

设置速度环 PID 系数。

参数:
  • kp (int) – 比例系数,范围为 0~255。

  • ki (int) – 积分系数,范围为 0~255。

  • kd (int) – 微分系数,范围为 0~255。

返回:

None.

UiFlow2 代码块:

set_speed_pid.png

get_speed_pid()

获取速度环 PID 系数。

返回:

PID 系数元组 (kp, ki, kd),依次为比例、积分、微分系数,每项范围均为 0~255。

返回类型:

tuple

UiFlow2 代码块:

get_speed_pid.png

set_speed_target(speed)

设置闭环速度控制的目标值。

参数:

speed (int) – 目标速度设置值,可正可负,范围为 -127~127。该值为设备使用的速度数值,单位不是转速(RPM)。

返回:

None.

UiFlow2 代码块:

set_speed_target.png

get_speed_target()

获取已设置的闭环速度控制目标。

返回:

目标速度设置值,可正可负,范围为 -127~127。该值为设备使用的速度数值,单位不是转速(RPM)。

返回类型:

int

UiFlow2 代码块:

get_speed_target.png

enable_soft_start()

在开环模式下启用软启动和软停止。

设置保存在 Unit 的 Flash 中。已启用时重复调用,不会再次写入 Flash。

返回:

None.

UiFlow2 代码块:

enable_soft_start.png

disable_soft_start()

在开环模式下禁用软启动和软停止。

设置保存在 Unit 的 Flash 中。已禁用时重复调用,不会再次写入 Flash。

返回:

None.

UiFlow2 代码块:

disable_soft_start.png

is_soft_start_enabled()

检查软启动和软停止是否已启用。

返回:

软启动和软停止已启用时返回 True。

返回类型:

bool

UiFlow2 代码块:

is_soft_start_enabled.png

enable_motor()

启用电机驱动,将 Motor nSleep 切换到运行状态。

返回:

None.

UiFlow2 代码块:

enable_motor.png

disable_motor()

禁用电机驱动,将 Motor nSleep 切换到休眠状态。

返回:

None.

UiFlow2 代码块:

disable_motor.png

is_motor_enabled()

检查电机驱动是否处于运行状态(Motor nSleep)。

返回:

电机驱动已启用时返回 True。

返回类型:

bool

UiFlow2 代码块:

is_motor_enabled.png

set_rgb_color(color)

设置板载 RGB LED 颜色。

参数:

color (int) – 0xRRGGBB 格式的 RGB888 颜色,范围为 0x000000~0xFFFFFF。

返回:

None.

UiFlow2 代码块:

set_rgb_color.png

get_rgb_color()

获取板载 RGB LED 颜色。

返回:

0xRRGGBB 格式的 RGB888 颜色,范围为 0x000000~0xFFFFFF。

返回类型:

int

UiFlow2 代码块:

get_rgb_color.png

set_rgb_brightness(percent)

设置板载 RGB LED 亮度。

参数:

percent (int or float) – 亮度,单位为百分比,范围为 0~100。

返回:

None.

UiFlow2 代码块:

set_rgb_brightness.png

get_rgb_brightness()

获取板载 RGB LED 亮度。

返回:

亮度,单位为百分比,范围为 0~100。

返回类型:

int

UiFlow2 代码块:

get_rgb_brightness.png

read_input_voltage()

读取电机供电输入电压。

返回:

输入电压,单位为 V,范围取决于供电。

返回类型:

float

UiFlow2 代码块:

read_input_voltage.png

read_input_voltage_adc()

读取电机供电电压的原始 12 位 ADC 采样值。

返回:

原始 ADC 采样值,范围为 0~4095。如需读取以 V 为单位的电压,请使用 read_input_voltage()。

返回类型:

int

UiFlow2 代码块:

read_input_voltage_adc.png

read_input_current()

读取电机供电输入电流。

返回:

输入电流,单位为 A,范围取决于负载。

返回类型:

float

UiFlow2 代码块:

read_input_current.png

get_firmware_version()

读取 Unit 的固件版本值。

返回:

固件版本值,范围为 0~255。

返回类型:

int

UiFlow2 代码块:

get_firmware_version.png

get_uid()

获取设备的 12 字节 STM32 唯一标识符。

返回:

设备 UID,按协议顺序返回,长度固定为 12 字节。

返回类型:

bytes

UiFlow2 代码块:

get_uid.png

get_i2c_address()

从设备获取 Unit I2C 地址。

返回:

7 位 I2C 地址,范围为 0x08~0x77。

返回类型:

int

UiFlow2 代码块:

get_i2c_address.png

set_i2c_address(address)

修改 Unit 的 I2C 地址,并更新当前驱动对象使用的地址。

新地址会保存到 Unit 的 Flash 中。根据协议,Unit 随后会重启,约 300 ms 后在新地址恢复响应。本方法会等待并检测新地址,确认响应后再更新驱动对象的地址。请避免不必要的调用,以减少 Flash 写入次数。

参数:

address (int) – 新的 7 位 I2C 地址,范围为 0x08~0x77。

返回:

None.

UiFlow2 代码块:

set_i2c_address.png