Bala2 Module
The Bala2 Module is part of the M5Stack stackable module series. The module communicates with the host via the I2C interface, and its built-in microcontroller manages PWM control for the motor, reads the encoder count, and outputs control signals for the servo.
Support the following products:
UiFlow2 Example
Servo control
Open the servo_control_example.m5f2 project in UiFlow2.
Control the servo to swing back and forth between 0° and 180°.
UiFlow2 Code Block:
Example output:
None
Motor control
Open the motor_control_example.m5f2 project in UiFlow2.
Run the program, and the car’s motors will first rotate forward, gradually accelerating to the maximum speed, then gradually decelerating to a stop. Next, the motors will reverse, similarly accelerating to the maximum speed before gradually slowing down to a stop. Finally, the car will come to a complete stop, with the motor speed returning to zero.
UiFlow2 Code Block:
Example output:
None
Read encoder
Open the read_encoder_example.m5f2 project in UiFlow2.
Run the program and manually rotate the wheels to observe the screen display.
UiFlow2 Code Block:
Example output:
None
Car control
Open the car_control_example.m5f2 project in UiFlow2.
Save the program to the controller, place the car on its side, and turn it on. After the gyroscope calibration is complete, the car will automatically stand upright and maintain balance. It will then perform a series of actions, including turning left, turning right, moving forward, and moving backward. Finally, it will stop and return to the balanced state.
UiFlow2 Code Block:
Example output:
None
MicroPython Example
Servo control
Control the servo to swing back and forth between 0° and 180°.
MicroPython Code Block:
1# SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD 2# 3# SPDX-License-Identifier: MIT 4 5import os, sys, io 6import M5 7from M5 import * 8from module import Bala2Module 9import time 10 11 12title0 = None 13label_servo1 = None 14label_servo1_val = None 15module_bala2_0 = None 16t_dir = None 17last_time = None 18angle = None 19 20 21def setup(): 22 global title0, label_servo1, label_servo1_val, module_bala2_0, t_dir, last_time, angle 23 M5.begin() 24 Widgets.fillScreen(0x222222) 25 title0 = Widgets.Title("Bala2 Servo Control", 3, 0xFFFFFF, 0x0000FF, Widgets.FONTS.DejaVu24) 26 label_servo1 = Widgets.Label("Angle:", 54, 85, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18) 27 label_servo1_val = Widgets.Label("0", 125, 85, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18) 28 module_bala2_0 = Bala2Module(0) 29 t_dir = True 30 angle = 0 31 last_time = time.ticks_ms() 32 33 34def loop(): 35 global title0, label_servo1, label_servo1_val, module_bala2_0, t_dir, last_time, angle 36 M5.update() 37 if (time.ticks_diff((time.ticks_ms()), last_time)) > 10: 38 last_time = time.ticks_ms() 39 angle = angle + 1 40 if angle > 180: 41 angle = 0 42 t_dir = not t_dir 43 if t_dir: 44 module_bala2_0.set_servo_angle(1, angle) 45 else: 46 module_bala2_0.set_servo_angle(1, 180 - angle) 47 label_servo1_val.setText(str(angle)) 48 49 50if __name__ == "__main__": 51 try: 52 setup() 53 while True: 54 loop() 55 except (Exception, KeyboardInterrupt) as e: 56 try: 57 from utility import print_error_msg 58 59 print_error_msg(e) 60 except ImportError: 61 print("please update to latest firmware")
Example output:
None
Motor control
Run the program, and the car’s motors will first rotate forward, gradually accelerating to the maximum speed, then gradually decelerating to a stop. Next, the motors will reverse, similarly accelerating to the maximum speed before gradually slowing down to a stop. Finally, the car will come to a complete stop, with the motor speed returning to zero.
MicroPython Code Block:
1# SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD 2# 3# SPDX-License-Identifier: MIT 4 5import os, sys, io 6import M5 7from M5 import * 8from module import Bala2Module 9import time 10 11 12title0 = None 13module_bala2_0 = None 14i = None 15 16 17def setup(): 18 global title0, module_bala2_0, i 19 M5.begin() 20 Widgets.fillScreen(0x222222) 21 title0 = Widgets.Title("Bala2 Motor Control", 3, 0xFFFFFF, 0x0000FF, Widgets.FONTS.DejaVu24) 22 23 module_bala2_0 = Bala2Module(0) 24 for i in range(1, 1001): 25 module_bala2_0.set_motor_speed(i, i) 26 time.sleep_ms(10) 27 for i in range(1, 1001): 28 module_bala2_0.set_motor_speed(1000 - i, 1000 - i) 29 time.sleep_ms(10) 30 for i in range(1, 1001): 31 module_bala2_0.set_motor_speed(0 - i, 0 - i) 32 time.sleep_ms(10) 33 for i in range(-1000, 1): 34 module_bala2_0.set_motor_speed(i, i) 35 time.sleep_ms(10) 36 module_bala2_0.set_motor_speed(0, 0) 37 38 39def loop(): 40 global title0, module_bala2_0, i 41 M5.update() 42 43 44if __name__ == "__main__": 45 try: 46 setup() 47 while True: 48 loop() 49 except (Exception, KeyboardInterrupt) as e: 50 try: 51 from utility import print_error_msg 52 53 print_error_msg(e) 54 except ImportError: 55 print("please update to latest firmware")
Example output:
None
Read encoder
Run the program and manually rotate the wheels to observe the screen display.
MicroPython Code Block:
1# SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD 2# 3# SPDX-License-Identifier: MIT 4 5import os, sys, io 6import M5 7from M5 import * 8from module import Bala2Module 9import time 10 11 12title0 = None 13label_enc1 = None 14label_enc2 = None 15label_enc1_val = None 16label_enc2_val = None 17module_bala2_0 = None 18last_time = None 19enc_value = None 20enc1 = None 21enc2 = None 22 23 24def setup(): 25 global \ 26 title0, \ 27 label_enc1, \ 28 label_enc2, \ 29 label_enc1_val, \ 30 label_enc2_val, \ 31 module_bala2_0, \ 32 last_time, \ 33 enc_value, \ 34 enc1, \ 35 enc2 36 M5.begin() 37 Widgets.fillScreen(0x222222) 38 title0 = Widgets.Title("Bala2 Encoder Read", 3, 0xFFFFFF, 0x0000FF, Widgets.FONTS.DejaVu24) 39 label_enc1 = Widgets.Label("Enc1", 54, 85, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18) 40 label_enc2 = Widgets.Label("Enc2", 208, 85, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18) 41 label_enc1_val = Widgets.Label("0", 50, 125, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18) 42 label_enc2_val = Widgets.Label("0", 202, 125, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18) 43 module_bala2_0 = Bala2Module(0) 44 module_bala2_0.set_encoder_value(0, 0) 45 last_time = time.ticks_ms() 46 47 48def loop(): 49 global \ 50 title0, \ 51 label_enc1, \ 52 label_enc2, \ 53 label_enc1_val, \ 54 label_enc2_val, \ 55 module_bala2_0, \ 56 last_time, \ 57 enc_value, \ 58 enc1, \ 59 enc2 60 M5.update() 61 if (time.ticks_diff((time.ticks_ms()), last_time)) > 100: 62 last_time = time.ticks_ms() 63 enc_value = module_bala2_0.get_encoder_value() 64 enc1 = enc_value[0] 65 enc2 = enc_value[1] 66 label_enc1_val.setText(str(enc1)) 67 label_enc2_val.setText(str(enc2)) 68 69 70if __name__ == "__main__": 71 try: 72 setup() 73 while True: 74 loop() 75 except (Exception, KeyboardInterrupt) as e: 76 try: 77 from utility import print_error_msg 78 79 print_error_msg(e) 80 except ImportError: 81 print("please update to latest firmware")
Example output:
None
Car control
Save the program to the controller, place the car on its side, and turn it on. After the gyroscope calibration is complete, the car will automatically stand upright and maintain balance. It will then perform a series of actions, including turning left, turning right, moving forward, and moving backward. Finally, it will stop and return to the balanced state.
MicroPython Code Block:
1# SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD 2# 3# SPDX-License-Identifier: MIT 4 5import os, sys, io 6import M5 7from M5 import * 8from module import Bala2Module 9import time 10 11 12title0 = None 13module_bala2_0 = None 14i = None 15 16 17def setup(): 18 global title0, module_bala2_0, i 19 M5.begin() 20 Widgets.fillScreen(0x222222) 21 title0 = Widgets.Title("Self-Balancing Robot", 3, 0xFFFFFF, 0x0000FF, Widgets.FONTS.DejaVu24) 22 module_bala2_0 = Bala2Module(0) 23 module_bala2_0.calibrate() 24 module_bala2_0.start() 25 time.sleep_ms(2000) 26 module_bala2_0.set_turn_speed(-100) 27 time.sleep_ms(1000) 28 module_bala2_0.set_turn_speed(100) 29 time.sleep_ms(1000) 30 module_bala2_0.set_turn_speed(0) 31 time.sleep_ms(2000) 32 for i in range(20): 33 module_bala2_0.set_angle_pid_target(0 - i) 34 time.sleep_ms(100) 35 time.sleep_ms(2000) 36 for i in range(20): 37 module_bala2_0.set_angle_pid_target(i - 20) 38 time.sleep_ms(100) 39 for i in range(20): 40 module_bala2_0.set_angle_pid_target(i) 41 time.sleep_ms(100) 42 time.sleep_ms(2000) 43 for i in range(20): 44 module_bala2_0.set_angle_pid_target(20 - i) 45 time.sleep_ms(100) 46 module_bala2_0.set_angle_pid_target(0) 47 48 49def loop(): 50 global title0, module_bala2_0, i 51 M5.update() 52 53 54if __name__ == "__main__": 55 try: 56 setup() 57 while True: 58 loop() 59 except (Exception, KeyboardInterrupt) as e: 60 try: 61 from utility import print_error_msg 62 63 print_error_msg(e) 64 except ImportError: 65 print("please update to latest firmware")
Example output:
None
API
Bala2Module
- class module.bala2.Bala2Module(timer_id=0)
Create an Bala2Module object.
- Parameters:
timer_id (int) – Timer ID from 0 to 3 (Use a timer to periodically call the balance control program.)
UiFlow2 Code Block:
MicroPython Code Block:
from module import Bala2Module module_bala2_0 = Bala2Module(timer_id = 0)
- calibrate()
Calibrate sensor
UiFlow2 Code Block:
MicroPython Code Block:
module_bala2_0.calibrate()
- set_motor_speed(left, right)
Set motor speed
- Parameters:
UiFlow2 Code Block:
MicroPython Code Block:
module_bala2_0.set_motor_speed(left, right)
- set_encoder_value(left, right)
Set encoder value
- Parameters:
UiFlow2 Code Block:
MicroPython Code Block:
module_bala2_0.set_encoder_value(left, right)
- get_encoder_value()
The left, right encoder value returned in a 2-tuple
UiFlow2 Code Block:
MicroPython Code Block:
module_bala2_0.get_encoder_value()
- set_servo_angle(pos, angle)
Set servo angle
- Parameters:
UiFlow2 Code Block:
MicroPython Code Block:
module_bala2_0.set_servo_angle(pos, angle)
- start()
Start the balance car (car upright balance)
UiFlow2 Code Block:
MicroPython Code Block:
module_bala2_0.start()
- stop()
Stop the balance car (stop the balance control of the car)
UiFlow2 Code Block:
MicroPython Code Block:
module_bala2_0.stop()
- get_angle()
Get the tilt angle of the balance car
- Returns:
The angle of the car
- Return type:
Data is valid only when the car is running (start() is called).
UiFlow2 Code Block:
MicroPython Code Block:
module_bala2_0.get_angle()
- set_angle_pid(kp, ki, kd)
Set angle PID parameters
UiFlow2 Code Block:
MicroPython Code Block:
module_bala2_0.set_angle_pid(kp, ki, kd)
- get_angle_pid()
The angle loop PID parameters returned in a 3-tuple
UiFlow2 Code Block:
MicroPython Code Block:
module_bala2_0.get_angle_pid()
- set_angle_pid_target(angle=0)
Set angle loop PID control target.
- Parameters:
angle (float) – The angle of the angle loop PID control target. Default is 0.
UiFlow2 Code Block:
MicroPython Code Block:
module_bala2_0.set_angle_pid_target(angle)
- get_angle_pid_target()
Get angle loop PID control target
- Returns:
The angle loop PID control target
- Return type:
UiFlow2 Code Block:
MicroPython Code Block:
module_bala2_0.get_angle_pid_target()
- set_speed_pid(kp, ki, kd)
Set speed loop PID parameters.
UiFlow2 Code Block:
MicroPython Code Block:
module_bala2_0.set_speed_pid(kp, ki, kd)
- get_speed_pid()
The speed loop PID parameters returned in a 3-tuple
UiFlow2 Code Block:
MicroPython Code Block:
module_bala2_0.get_speed_pid()
- set_speed_pid_target(speed=0)
Set speed loop PID control target.
- Parameters:
speed (float) – The speed of the speed loop PID control target. Default is 0.
UiFlow2 Code Block:
MicroPython Code Block:
module_bala2_0.set_speed_pid_target(speed)
- get_speed_pid_target()
Get speed loop PID control target
- Returns:
The speed loop PID control target
- Return type:
UiFlow2 Code Block:
MicroPython Code Block:
module_bala2_0.get_speed_pid_target()