BaseX Module

BaseX is an M5Stack stackable module with 4 DC motor channels and 2 servo channels. It communicates with the host via I2C address 0x22. The onboard controller handles motor PWM output, motor encoder count, position/speed mode configuration, and servo output.

Support the following products:

BaseXModule

UiFlow2 Example

Servo control

Open the m5core_basex_servo_control_example.m5f2 project in UiFlow2.

Control two servos by button. Button A changes Servo1 angle, Button B changes Servo2 angle, and Button C resets both servos to 0 degrees.

UiFlow2 Code Block:

servo_control_example.png

Example output:

None

Motor normal control

Open the m5core_basex_motor_normal_control_example.m5f2 project in UiFlow2.

Set all motors to Normal mode and control PWM duty by button.

UiFlow2 Code Block:

motor_normal_control_example.png

Example output:

None

Motor position control

Open the m5basic_basex_motor_position_control_example.m5f2 project in UiFlow2.

Button A sets position target to 720, Button B sets target to -720, and Button C sets target to 0.

UiFlow2 Code Block:

motor_position_control_example.png

Example output:

None

Motor speed control

Open the m5basic_basex_motor_speed_control_example.m5f2 project in UiFlow2.

Button A increases speed target, Button B decreases speed target, and Button C sets speed target to 0.

UiFlow2 Code Block:

motor_speed_control_example.png

Example output:

None

Read encoder

Open the m5basic_basex_encoder_display_example.m5f2 project in UiFlow2.

Display encoder values for four motor channels. Button B clears all encoder values.

UiFlow2 Code Block:

encoder_display_example.png

Example output:

None

MicroPython Example

Servo control

Control two servos by button.

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 module import ModuleBaseX
  9
 10
 11label_title = None
 12label_angle1 = None
 13label_angle2 = None
 14label_btn1 = None
 15label_btn2 = None
 16label_btn3 = None
 17basex_0 = None
 18angle1 = None
 19agnle2 = None
 20
 21
 22def btna_was_clicked_event(state):
 23    global \
 24        label_title, \
 25        label_angle1, \
 26        label_angle2, \
 27        label_btn1, \
 28        label_btn2, \
 29        label_btn3, \
 30        basex_0, \
 31        angle1, \
 32        agnle2
 33    angle1 = angle1 + 30
 34    if angle1 > 180:
 35        angle1 = 0
 36    basex_0.set_servo_angle(1, angle1)
 37    label_angle1.setText(str((str("Servo1 Angle: ") + str(angle1))))
 38
 39
 40def btnb_was_clicked_event(state):
 41    global \
 42        label_title, \
 43        label_angle1, \
 44        label_angle2, \
 45        label_btn1, \
 46        label_btn2, \
 47        label_btn3, \
 48        basex_0, \
 49        angle1, \
 50        agnle2
 51    agnle2 = agnle2 + 30
 52    if agnle2 > 180:
 53        agnle2 = 0
 54    basex_0.set_servo_angle(2, agnle2)
 55    label_angle2.setText(str((str("Servo2 Angle: ") + str(agnle2))))
 56
 57
 58def btnc_was_clicked_event(state):
 59    global \
 60        label_title, \
 61        label_angle1, \
 62        label_angle2, \
 63        label_btn1, \
 64        label_btn2, \
 65        label_btn3, \
 66        basex_0, \
 67        angle1, \
 68        agnle2
 69    angle1 = 0
 70    agnle2 = 0
 71    basex_0.set_servo_angle(1, 0)
 72    basex_0.set_servo_angle(2, 0)
 73    label_angle1.setText(str("Servo1 Angle:  0"))
 74    label_angle2.setText(str("Servo2 Angle:  0"))
 75
 76
 77def setup():
 78    global \
 79        label_title, \
 80        label_angle1, \
 81        label_angle2, \
 82        label_btn1, \
 83        label_btn2, \
 84        label_btn3, \
 85        basex_0, \
 86        angle1, \
 87        agnle2
 88
 89    M5.begin()
 90    Widgets.setRotation(1)
 91    Widgets.fillScreen(0x000000)
 92    label_title = Widgets.Label(
 93        "BaseX Servo Control", 36, 1, 1.0, 0x12DEEE, 0x000000, Widgets.FONTS.Montserrat24
 94    )
 95    label_angle1 = Widgets.Label(
 96        "Servo1 Angle: --", 20, 70, 1.0, 0x1AE179, 0x000000, Widgets.FONTS.Montserrat24
 97    )
 98    label_angle2 = Widgets.Label(
 99        "Servo2 Angle: --", 20, 110, 1.0, 0x1AE179, 0x000000, Widgets.FONTS.Montserrat24
100    )
101    label_btn1 = Widgets.Label(
102        "Servo1", 38, 205, 1.0, 0xFFFFFF, 0x000000, Widgets.FONTS.Montserrat18
103    )
104    label_btn2 = Widgets.Label(
105        "Servo2", 124, 205, 1.0, 0xFFFFFF, 0x000000, Widgets.FONTS.Montserrat18
106    )
107    label_btn3 = Widgets.Label(
108        "Reset", 219, 205, 1.0, 0xFFFFFF, 0x000000, Widgets.FONTS.Montserrat18
109    )
110
111    BtnA.setCallback(type=BtnA.CB_TYPE.WAS_CLICKED, cb=btna_was_clicked_event)
112    BtnB.setCallback(type=BtnB.CB_TYPE.WAS_CLICKED, cb=btnb_was_clicked_event)
113    BtnC.setCallback(type=BtnC.CB_TYPE.WAS_CLICKED, cb=btnc_was_clicked_event)
114
115    basex_0 = ModuleBaseX()
116    angle1 = 0
117    agnle2 = 0
118    label_angle1.setText(str("Servo1 Angle:  0"))
119    label_angle2.setText(str("Servo2 Angle:  0"))
120
121
122def loop():
123    global \
124        label_title, \
125        label_angle1, \
126        label_angle2, \
127        label_btn1, \
128        label_btn2, \
129        label_btn3, \
130        basex_0, \
131        angle1, \
132        agnle2
133    M5.update()
134
135
136if __name__ == "__main__":
137    try:
138        setup()
139        while True:
140            loop()
141    except (Exception, KeyboardInterrupt) as e:
142        try:
143            from utility import print_error_msg
144
145            print_error_msg(e)
146        except ImportError:
147            print("please update to latest firmware")

Example output:

None

Motor normal control

Set all motors to Normal mode and control PWM duty by button.

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 module import ModuleBaseX
  9
 10
 11label_title = None
 12label_speed = None
 13label_btn1 = None
 14label_btn2 = None
 15label_mode = None
 16label_btn3 = None
 17basex_0 = None
 18pwm = None
 19i = None
 20
 21
 22def btna_was_clicked_event(state):
 23    global \
 24        label_title, \
 25        label_speed, \
 26        label_btn1, \
 27        label_btn2, \
 28        label_mode, \
 29        label_btn3, \
 30        basex_0, \
 31        pwm, \
 32        i
 33    pwm = pwm + 20
 34    if pwm > 120:
 35        pwm = 0
 36    for i in range(4):
 37        basex_0.set_motor_pwm(i + 1, pwm)
 38
 39    label_speed.setText(str((str("motor pwm: ") + str(pwm))))
 40
 41
 42def btnb_was_clicked_event(state):
 43    global \
 44        label_title, \
 45        label_speed, \
 46        label_btn1, \
 47        label_btn2, \
 48        label_mode, \
 49        label_btn3, \
 50        basex_0, \
 51        pwm, \
 52        i
 53    pwm = pwm - 20
 54    if pwm < -120:
 55        pwm = 0
 56    for i in range(4):
 57        basex_0.set_motor_pwm(i + 1, pwm)
 58
 59    label_speed.setText(str((str("motor pwm: ") + str(pwm))))
 60
 61
 62def btnc_was_clicked_event(state):
 63    global \
 64        label_title, \
 65        label_speed, \
 66        label_btn1, \
 67        label_btn2, \
 68        label_mode, \
 69        label_btn3, \
 70        basex_0, \
 71        pwm, \
 72        i
 73    pwm = 0
 74    for i in range(4):
 75        basex_0.set_motor_pwm(i + 1, 0)
 76
 77    label_speed.setText(str("motor pwm: "))
 78
 79
 80def setup():
 81    global \
 82        label_title, \
 83        label_speed, \
 84        label_btn1, \
 85        label_btn2, \
 86        label_mode, \
 87        label_btn3, \
 88        basex_0, \
 89        pwm, \
 90        i
 91
 92    M5.begin()
 93    Widgets.setRotation(1)
 94    Widgets.fillScreen(0x000000)
 95    label_title = Widgets.Label(
 96        "BaseX Motor Control", 34, 0, 1.0, 0x12DEEE, 0x000000, Widgets.FONTS.Montserrat24
 97    )
 98    label_speed = Widgets.Label(
 99        "motor pwm: 0", 20, 105, 1.0, 0x1AE179, 0x000000, Widgets.FONTS.Montserrat24
100    )
101    label_btn1 = Widgets.Label("+20", 50, 205, 1.0, 0xFFFFFF, 0x000000, Widgets.FONTS.Montserrat18)
102    label_btn2 = Widgets.Label(
103        "-20", 140, 205, 1.0, 0xFFFFFF, 0x000000, Widgets.FONTS.Montserrat18
104    )
105    label_mode = Widgets.Label(
106        "control mode: normal", 20, 70, 1.0, 0x1AE179, 0x000000, Widgets.FONTS.Montserrat24
107    )
108    label_btn3 = Widgets.Label("0", 238, 205, 1.0, 0xFFFFFF, 0x000000, Widgets.FONTS.Montserrat18)
109
110    BtnA.setCallback(type=BtnA.CB_TYPE.WAS_CLICKED, cb=btna_was_clicked_event)
111    BtnB.setCallback(type=BtnB.CB_TYPE.WAS_CLICKED, cb=btnb_was_clicked_event)
112    BtnC.setCallback(type=BtnC.CB_TYPE.WAS_CLICKED, cb=btnc_was_clicked_event)
113
114    basex_0 = ModuleBaseX()
115    pwm = 0
116    label_speed.setText(str("motor pwm: 0"))
117    for i in range(4):
118        basex_0.set_motor_mode(i + 1, ModuleBaseX.MOTOR_MODE_NORMAL)
119        basex_0.set_motor_pwm(i + 1, 0)
120
121
122def loop():
123    global \
124        label_title, \
125        label_speed, \
126        label_btn1, \
127        label_btn2, \
128        label_mode, \
129        label_btn3, \
130        basex_0, \
131        pwm, \
132        i
133    M5.update()
134
135
136if __name__ == "__main__":
137    try:
138        setup()
139        while True:
140            loop()
141    except (Exception, KeyboardInterrupt) as e:
142        try:
143            from utility import print_error_msg
144
145            print_error_msg(e)
146        except ImportError:
147            print("please update to latest firmware")

Example output:

None

Motor position control

Use position mode to move Motor1 between fixed target positions.

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 module import ModuleBaseX
  9import time
 10
 11
 12label_title = None
 13label_mode = None
 14label_target = None
 15label_encoder = None
 16label_btn1 = None
 17label_btn2 = None
 18label_btn3 = None
 19basex_0 = None
 20
 21
 22position_target = None
 23
 24
 25def btna_was_clicked_event(state):
 26    global \
 27        label_title, \
 28        label_mode, \
 29        label_target, \
 30        label_encoder, \
 31        label_btn1, \
 32        label_btn2, \
 33        label_btn3, \
 34        basex_0, \
 35        position_target
 36    position_target = 720
 37    basex_0.set_motor_mode(1, ModuleBaseX.MOTOR_MODE_POSITION)
 38    basex_0.set_motor_position_pid(1, 3, 1, 15)
 39    basex_0.set_motor_position_max_speed(1, 80)
 40    basex_0.set_motor_position_target(1, position_target)
 41    label_target.setText(str((str("target pos: ") + str(position_target))))
 42
 43
 44def btnb_was_clicked_event(state):
 45    global \
 46        label_title, \
 47        label_mode, \
 48        label_target, \
 49        label_encoder, \
 50        label_btn1, \
 51        label_btn2, \
 52        label_btn3, \
 53        basex_0, \
 54        position_target
 55    position_target = -720
 56    basex_0.set_motor_mode(1, ModuleBaseX.MOTOR_MODE_POSITION)
 57    basex_0.set_motor_position_pid(1, 3, 1, 15)
 58    basex_0.set_motor_position_max_speed(1, 80)
 59    basex_0.set_motor_position_target(1, position_target)
 60    label_target.setText(str((str("target pos: ") + str(position_target))))
 61
 62
 63def btnc_was_clicked_event(state):
 64    global \
 65        label_title, \
 66        label_mode, \
 67        label_target, \
 68        label_encoder, \
 69        label_btn1, \
 70        label_btn2, \
 71        label_btn3, \
 72        basex_0, \
 73        position_target
 74    position_target = 0
 75    basex_0.set_motor_mode(1, ModuleBaseX.MOTOR_MODE_POSITION)
 76    basex_0.set_motor_position_pid(1, 3, 1, 15)
 77    basex_0.set_motor_position_max_speed(1, 80)
 78    basex_0.set_motor_position_target(1, position_target)
 79    label_target.setText(str((str("target pos: ") + str(position_target))))
 80
 81
 82def setup():
 83    global \
 84        label_title, \
 85        label_mode, \
 86        label_target, \
 87        label_encoder, \
 88        label_btn1, \
 89        label_btn2, \
 90        label_btn3, \
 91        basex_0, \
 92        position_target
 93
 94    M5.begin()
 95    Widgets.setRotation(1)
 96    Widgets.fillScreen(0x000000)
 97    label_title = Widgets.Label(
 98        "BaseX Position Control", 16, 0, 1.0, 0x12DEEE, 0x000000, Widgets.FONTS.Montserrat24
 99    )
100    label_mode = Widgets.Label(
101        "control mode: position", 20, 65, 1.0, 0x1AE179, 0x000000, Widgets.FONTS.Montserrat24
102    )
103    label_target = Widgets.Label(
104        "target pos: 0", 20, 105, 1.0, 0x1AE179, 0x000000, Widgets.FONTS.Montserrat24
105    )
106    label_encoder = Widgets.Label(
107        "encoder: 0", 20, 145, 1.0, 0x1AE179, 0x000000, Widgets.FONTS.Montserrat24
108    )
109    label_btn1 = Widgets.Label(
110        "+720", 45, 205, 1.0, 0xFFFFFF, 0x000000, Widgets.FONTS.Montserrat18
111    )
112    label_btn2 = Widgets.Label(
113        "-720", 136, 205, 1.0, 0xFFFFFF, 0x000000, Widgets.FONTS.Montserrat18
114    )
115    label_btn3 = Widgets.Label(
116        "Reset", 220, 205, 1.0, 0xFFFFFF, 0x000000, Widgets.FONTS.Montserrat18
117    )
118
119    BtnA.setCallback(type=BtnA.CB_TYPE.WAS_CLICKED, cb=btna_was_clicked_event)
120    BtnB.setCallback(type=BtnB.CB_TYPE.WAS_CLICKED, cb=btnb_was_clicked_event)
121    BtnC.setCallback(type=BtnC.CB_TYPE.WAS_CLICKED, cb=btnc_was_clicked_event)
122
123    basex_0 = ModuleBaseX()
124    position_target = 0
125    basex_0.set_motor_mode(1, ModuleBaseX.MOTOR_MODE_NORMAL)
126    basex_0.set_motor_pwm(1, 0)
127    basex_0.set_motor_encoder(1, 0)
128    basex_0.set_motor_position_pid(1, 3, 1, 15)
129    basex_0.set_motor_position_max_speed(1, 80)
130    basex_0.set_motor_position_target(1, 0)
131    basex_0.set_motor_mode(1, ModuleBaseX.MOTOR_MODE_POSITION)
132    label_target.setText(str("target pos: 0"))
133    label_encoder.setText(str("encoder: 0"))
134
135
136def loop():
137    global \
138        label_title, \
139        label_mode, \
140        label_target, \
141        label_encoder, \
142        label_btn1, \
143        label_btn2, \
144        label_btn3, \
145        basex_0, \
146        position_target
147    M5.update()
148    label_encoder.setText(str((str("encoder: ") + str((basex_0.get_motor_encoder(1))))))
149    time.sleep_ms(100)
150
151
152if __name__ == "__main__":
153    try:
154        setup()
155        while True:
156            loop()
157    except (Exception, KeyboardInterrupt) as e:
158        try:
159            from utility import print_error_msg
160
161            print_error_msg(e)
162        except ImportError:
163            print("please update to latest firmware")

Example output:

None

Motor speed control

Use speed mode to set Motor1 speed target.

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 module import ModuleBaseX
  9import time
 10
 11
 12label_title = None
 13label_mode = None
 14label_target = None
 15label_feedback = None
 16label_btn1 = None
 17label_btn2 = None
 18label_btn3 = None
 19basex_0 = None
 20speed_target = None
 21
 22
 23def btna_was_clicked_event(state):
 24    global \
 25        label_title, \
 26        label_mode, \
 27        label_target, \
 28        label_feedback, \
 29        label_btn1, \
 30        label_btn2, \
 31        label_btn3, \
 32        basex_0, \
 33        speed_target
 34    speed_target = speed_target + 5
 35    if speed_target > 20:
 36        speed_target = 20
 37    basex_0.set_motor_speed_target(1, speed_target)
 38    label_target.setText(str((str("target speed: ") + str(speed_target))))
 39
 40
 41def btnb_was_clicked_event(state):
 42    global \
 43        label_title, \
 44        label_mode, \
 45        label_target, \
 46        label_feedback, \
 47        label_btn1, \
 48        label_btn2, \
 49        label_btn3, \
 50        basex_0, \
 51        speed_target
 52    speed_target = speed_target - 5
 53    if speed_target < -20:
 54        speed_target = -20
 55    basex_0.set_motor_speed_target(1, speed_target)
 56    label_target.setText(str((str("target speed: ") + str(speed_target))))
 57
 58
 59def btnc_was_clicked_event(state):
 60    global \
 61        label_title, \
 62        label_mode, \
 63        label_target, \
 64        label_feedback, \
 65        label_btn1, \
 66        label_btn2, \
 67        label_btn3, \
 68        basex_0, \
 69        speed_target
 70    speed_target = 0
 71    basex_0.set_motor_speed_target(1, speed_target)
 72    label_target.setText(str((str("target speed: ") + str(speed_target))))
 73
 74
 75def setup():
 76    global \
 77        label_title, \
 78        label_mode, \
 79        label_target, \
 80        label_feedback, \
 81        label_btn1, \
 82        label_btn2, \
 83        label_btn3, \
 84        basex_0, \
 85        speed_target
 86
 87    M5.begin()
 88    Widgets.setRotation(1)
 89    Widgets.fillScreen(0x000000)
 90    label_title = Widgets.Label(
 91        "BaseX Speed Control", 34, 0, 1.0, 0x12DEEE, 0x000000, Widgets.FONTS.Montserrat24
 92    )
 93    label_mode = Widgets.Label(
 94        "control mode: speed", 20, 65, 1.0, 0x1AE179, 0x000000, Widgets.FONTS.Montserrat24
 95    )
 96    label_target = Widgets.Label(
 97        "target speed: 0", 20, 105, 1.0, 0x1AE179, 0x000000, Widgets.FONTS.Montserrat24
 98    )
 99    label_feedback = Widgets.Label(
100        "speed20ms: --", 20, 145, 1.0, 0x1AE179, 0x000000, Widgets.FONTS.Montserrat24
101    )
102    label_btn1 = Widgets.Label("+5", 55, 205, 1.0, 0xFFFFFF, 0x000000, Widgets.FONTS.Montserrat18)
103    label_btn2 = Widgets.Label("-5", 145, 205, 1.0, 0xFFFFFF, 0x000000, Widgets.FONTS.Montserrat18)
104    label_btn3 = Widgets.Label("0", 245, 205, 1.0, 0xFFFFFF, 0x000000, Widgets.FONTS.Montserrat18)
105
106    BtnA.setCallback(type=BtnA.CB_TYPE.WAS_CLICKED, cb=btna_was_clicked_event)
107    BtnB.setCallback(type=BtnB.CB_TYPE.WAS_CLICKED, cb=btnb_was_clicked_event)
108    BtnC.setCallback(type=BtnC.CB_TYPE.WAS_CLICKED, cb=btnc_was_clicked_event)
109
110    basex_0 = ModuleBaseX()
111    speed_target = 0
112    basex_0.set_motor_mode(1, ModuleBaseX.MOTOR_MODE_NORMAL)
113    basex_0.set_motor_pwm(1, 0)
114    basex_0.set_motor_encoder(1, 0)
115    basex_0.set_motor_speed_pid(1, 3, 1, 15)
116    basex_0.set_motor_speed_target(1, 0)
117    basex_0.set_motor_mode(1, ModuleBaseX.MOTOR_MODE_SPEED)
118    label_target.setText(str("target speed: 0"))
119    label_feedback.setText(str("speed20ms: --"))
120
121
122def loop():
123    global \
124        label_title, \
125        label_mode, \
126        label_target, \
127        label_feedback, \
128        label_btn1, \
129        label_btn2, \
130        label_btn3, \
131        basex_0, \
132        speed_target
133    M5.update()
134    label_feedback.setText(str((str("speed20ms: ") + str(basex_0.get_motor_speed_20ms(1)))))
135    time.sleep_ms(100)
136
137
138if __name__ == "__main__":
139    try:
140        setup()
141        while True:
142            loop()
143    except (Exception, KeyboardInterrupt) as e:
144        try:
145            from utility import print_error_msg
146
147            print_error_msg(e)
148        except ImportError:
149            print("please update to latest firmware")

Example output:

None

Read encoder

Display encoder values for four motor channels. Button B clears all encoder values.

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 module import ModuleBaseX
  9import time
 10
 11
 12label_title = None
 13label_encoder1 = None
 14label_encoder2 = None
 15label_encoder3 = None
 16label_encoder4 = None
 17label_btn2 = None
 18basex_0 = None
 19
 20
 21def btnb_was_clicked_event(state):
 22    global \
 23        label_title, \
 24        label_encoder1, \
 25        label_encoder2, \
 26        label_encoder3, \
 27        label_encoder4, \
 28        label_btn2, \
 29        basex_0
 30    basex_0.set_motor_encoder(1, 0)
 31    basex_0.set_motor_encoder(2, 0)
 32    basex_0.set_motor_encoder(3, 0)
 33    basex_0.set_motor_encoder(4, 0)
 34
 35
 36def setup():
 37    global \
 38        label_title, \
 39        label_encoder1, \
 40        label_encoder2, \
 41        label_encoder3, \
 42        label_encoder4, \
 43        label_btn2, \
 44        basex_0
 45
 46    M5.begin()
 47    Widgets.setRotation(1)
 48    Widgets.fillScreen(0x000000)
 49    label_title = Widgets.Label(
 50        "BaseX Encoder", 58, 0, 1.0, 0x12DEEE, 0x000000, Widgets.FONTS.Montserrat24
 51    )
 52    label_encoder1 = Widgets.Label(
 53        "M1 encoder: --", 20, 45, 1.0, 0x1AE179, 0x000000, Widgets.FONTS.Montserrat18
 54    )
 55    label_encoder2 = Widgets.Label(
 56        "M2 encoder: --", 20, 75, 1.0, 0x1AE179, 0x000000, Widgets.FONTS.Montserrat18
 57    )
 58    label_encoder3 = Widgets.Label(
 59        "M3 encoder: --", 20, 105, 1.0, 0x1AE179, 0x000000, Widgets.FONTS.Montserrat18
 60    )
 61    label_encoder4 = Widgets.Label(
 62        "M4 encoder: --", 20, 135, 1.0, 0x1AE179, 0x000000, Widgets.FONTS.Montserrat18
 63    )
 64    label_btn2 = Widgets.Label(
 65        "B: Clear All", 108, 205, 1.0, 0xFFFFFF, 0x000000, Widgets.FONTS.Montserrat18
 66    )
 67
 68    BtnB.setCallback(type=BtnB.CB_TYPE.WAS_CLICKED, cb=btnb_was_clicked_event)
 69
 70    basex_0 = ModuleBaseX()
 71    basex_0.set_motor_mode(1, ModuleBaseX.MOTOR_MODE_NORMAL)
 72    basex_0.set_motor_pwm(1, 0)
 73    basex_0.set_motor_mode(2, ModuleBaseX.MOTOR_MODE_NORMAL)
 74    basex_0.set_motor_pwm(2, 0)
 75    basex_0.set_motor_mode(3, ModuleBaseX.MOTOR_MODE_NORMAL)
 76    basex_0.set_motor_pwm(3, 0)
 77    basex_0.set_motor_mode(4, ModuleBaseX.MOTOR_MODE_NORMAL)
 78    basex_0.set_motor_pwm(4, 0)
 79    basex_0.set_motor_encoder(1, 0)
 80    basex_0.set_motor_encoder(2, 0)
 81    basex_0.set_motor_encoder(3, 0)
 82    basex_0.set_motor_encoder(4, 0)
 83
 84
 85def loop():
 86    global \
 87        label_title, \
 88        label_encoder1, \
 89        label_encoder2, \
 90        label_encoder3, \
 91        label_encoder4, \
 92        label_btn2, \
 93        basex_0
 94    M5.update()
 95    label_encoder1.setText(str((str("M1 encoder: ") + str((basex_0.get_motor_encoder(1))))))
 96    label_encoder2.setText(str((str("M2 encoder: ") + str((basex_0.get_motor_encoder(2))))))
 97    label_encoder3.setText(str((str("M3 encoder: ") + str((basex_0.get_motor_encoder(3))))))
 98    label_encoder4.setText(str((str("M4 encoder: ") + str((basex_0.get_motor_encoder(4))))))
 99    time.sleep_ms(200)
100
101
102if __name__ == "__main__":
103    try:
104        setup()
105        while True:
106            loop()
107    except (Exception, KeyboardInterrupt) as e:
108        try:
109            from utility import print_error_msg
110
111            print_error_msg(e)
112        except ImportError:
113            print("please update to latest firmware")

Example output:

None

API

ModuleBaseX

class module.ModuleBaseX

Create a BaseX module object.

UiFlow2 Code Block:

init.png

MicroPython Code Block:

from module import ModuleBaseX

basex_0 = ModuleBaseX()
MOTOR_MODE_NORMAL

Normal PWM mode.

MOTOR_MODE_POSITION

Position control mode.

MOTOR_MODE_SPEED

Speed target control mode.

set_servo_angle(channel, angle)

Set servo angle.

Parameters:
  • channel (int) – Servo channel. Range: 1 ~ 2.

  • angle (int) – Servo angle. Range: 0 ~ 180.

UiFlow2 Code Block:

set_servo_angle.png

MicroPython Code Block:

basex_0.set_servo_angle(1, 90)
set_servo_pulse(channel, pulse_us)

Set servo pulse width.

Parameters:
  • channel (int) – Servo channel. Range: 1 ~ 2.

  • pulse_us (int) – Pulse width in microseconds. Range: 500 ~ 2500.

The servo PWM frequency is 50Hz, with a period of 20ms. The pulse range 500 ~ 2500us corresponds to about 2.5% ~ 12.5% duty.

UiFlow2 Code Block:

set_servo_pulse.png

MicroPython Code Block:

basex_0.set_servo_pulse(1, 1500)
set_motor_pwm(channel, duty)

Set motor PWM duty.

Parameters:
  • channel (int) – Motor channel. Range: 1 ~ 4.

  • duty (int) – PWM duty. Range: -127 ~ 127.

The sign indicates direction. abs(duty) 0 ~ 127 maps to 0% ~ 100% duty.

UiFlow2 Code Block:

set_motor_pwm.png

MicroPython Code Block:

basex_0.set_motor_pwm(1, 80)
get_motor_speed_20ms(channel)

Get motor speed feedback over 20ms.

Parameters:

channel (int) – Motor channel. Range: 1 ~ 4.

Returns:

Encoder delta over 20ms.

Return type:

int

UiFlow2 Code Block:

get_motor_speed_20ms.png

MicroPython Code Block:

speed = basex_0.get_motor_speed_20ms(1)
get_motor_encoder(channel)

Get motor encoder value.

Parameters:

channel (int) – Motor channel. Range: 1 ~ 4.

Returns:

Encoder count as signed 32-bit integer.

Return type:

int

UiFlow2 Code Block:

get_motor_encoder.png

MicroPython Code Block:

encoder = basex_0.get_motor_encoder(1)
set_motor_encoder(channel, value)

Set motor encoder value.

Parameters:
  • channel (int) – Motor channel. Range: 1 ~ 4.

  • value (int) – Encoder count as signed 32-bit integer.

UiFlow2 Code Block:

set_motor_encoder.png

MicroPython Code Block:

basex_0.set_motor_encoder(1, 0)
set_motor_mode(channel, mode)

Set motor control mode.

Parameters:
  • channel (int) – Motor channel. Range: 1 ~ 4.

  • mode (int) – Motor mode. MOTOR_MODE_NORMAL, MOTOR_MODE_POSITION or MOTOR_MODE_SPEED.

UiFlow2 Code Block:

set_motor_mode.png

MicroPython Code Block:

basex_0.set_motor_mode(1, ModuleBaseX.MOTOR_MODE_NORMAL)
set_motor_position_pid(channel, p=3, i=1, d=15)

Set motor position mode PID parameters.

Parameters:
  • channel (int) – Motor channel. Range: 1 ~ 4.

  • p (int) – Position P parameter. Default is 3.

  • i (int) – Position I parameter. Default is 1.

  • d (int) – Position D parameter. Default is 15.

UiFlow2 Code Block:

set_motor_position_pid.png

MicroPython Code Block:

basex_0.set_motor_position_pid(1)
set_motor_position_target(channel, position)

Set motor position mode target.

Parameters:
  • channel (int) – Motor channel. Range: 1 ~ 4.

  • position (int) – Position target as signed 32-bit integer.

UiFlow2 Code Block:

set_motor_position_target.png

MicroPython Code Block:

basex_0.set_motor_position_target(1, 720)
set_motor_position_max_speed(channel, speed)

Set motor position mode max speed.

Parameters:
  • channel (int) – Motor channel. Range: 1 ~ 4.

  • speed (int) – Max speed. Range: -127 ~ 127.

The sign indicates direction.

UiFlow2 Code Block:

set_motor_position_max_speed.png

MicroPython Code Block:

basex_0.set_motor_position_max_speed(1, 80)
set_motor_speed_pid(channel, p=3, i=1, d=15)

Set motor speed mode PID parameters.

Parameters:
  • channel (int) – Motor channel. Range: 1 ~ 4.

  • p (int) – Speed P parameter. Default is 3.

  • i (int) – Speed I parameter. Default is 1.

  • d (int) – Speed D parameter. Default is 15.

UiFlow2 Code Block:

set_motor_speed_pid.png

MicroPython Code Block:

basex_0.set_motor_speed_pid(1)
set_motor_speed_target(channel, speed)

Set motor speed mode target.

Parameters:
  • channel (int) – Motor channel. Range: 1 ~ 4.

  • speed (int) – Speed target. Range: -20 ~ 20.

The sign indicates direction. The target controls the feedback value returned by get_motor_speed_20ms().

UiFlow2 Code Block:

set_motor_speed_target.png

MicroPython Code Block:

basex_0.set_motor_speed_target(1, 20)