Atomic Motion Base

Atomic Motion Base is a servo and DC motor driver designed specifically for the ATOM series controllers. It integrates an STM32 control chip internally and uses I2C communication for control. Atomic Motion Base provides 4 servo channels and 2 DC motor interfaces, offering convenience for scenarios that require control of multiple servos or motor drivers, such as multi-axis servo robotic arms or small car motor control.

Atomic Motion Base v1.1 adds INA226 to implement current and voltage detection.

Support the following products:

Motion

Motion Base v1.1

UiFlow2 Example:

Motion Base

Open the atoms3_lite_motion_base_example.m5f2 project in UiFlow2.

This example controls the servo to rotate to a specified angle and sets the motor to rotate.

UiFlow2 Code Block:

example.png

Example output:

None

Motion Base v1.1

Open the atoms3_motion_base_v1.1_example.m5f2 project in UiFlow2.

The example program switches the motor’s running speed when the screen button is pressed, and the screen displays the current, voltage, and power.

UiFlow2 Code Block:

motion_base_v1.1_example.png

Example output:

None

MicroPython Example:

Motion Base

This example controls the servo to rotate to a specified angle and sets the motor to rotate.

MicroPython Code Block:

 1# SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD
 2#
 3# SPDX-License-Identifier: MIT
 4
 5import os, sys, io
 6import M5
 7from M5 import *
 8from hardware import *
 9from base import Motion
10
11
12i2c0 = None
13motion = None
14
15
16def setup():
17    global i2c0, motion
18
19    M5.begin()
20    i2c0 = I2C(0, scl=Pin(39), sda=Pin(38), freq=100000)
21    motion = Motion(i2c0, 0x38)
22    motion.set_servo_angle(1, 70)
23    motion.set_motor_speed(1, 46)
24    print(motion.get_servo_angle(1))
25
26
27def loop():
28    global i2c0, motion
29    M5.update()
30
31
32if __name__ == "__main__":
33    try:
34        setup()
35        while True:
36            loop()
37    except (Exception, KeyboardInterrupt) as e:
38        try:
39            from utility import print_error_msg
40
41            print_error_msg(e)
42        except ImportError:
43            print("please update to latest firmware")

Example output:

None

Motion Base v1.1

The example program switches the motor’s running speed when the screen button is pressed, and the screen displays the current, voltage, and power.

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 hardware import I2C
  9from hardware import Pin
 10from base import Motion
 11import time
 12
 13
 14label_speed = None
 15title_e = None
 16label_vol = None
 17label_cur = None
 18label_pow = None
 19i2c0 = None
 20motion = None
 21speed = None
 22voltage = None
 23curent = None
 24last_time = None
 25power = None
 26
 27
 28def btnA_wasClicked_event(state):
 29    global \
 30        label_speed, \
 31        title_e, \
 32        label_vol, \
 33        label_cur, \
 34        label_pow, \
 35        i2c0, \
 36        motion, \
 37        speed, \
 38        voltage, \
 39        curent, \
 40        last_time, \
 41        power
 42    speed = speed + 20
 43    if speed > 120:
 44        speed = 0
 45    motion.set_motor_speed(1, speed)
 46    label_speed.setText(str((str("speed: ") + str(speed))))
 47
 48
 49def setup():
 50    global \
 51        label_speed, \
 52        title_e, \
 53        label_vol, \
 54        label_cur, \
 55        label_pow, \
 56        i2c0, \
 57        motion, \
 58        speed, \
 59        voltage, \
 60        curent, \
 61        last_time, \
 62        power
 63    M5.begin()
 64    label_speed = Widgets.Label("speed:", 5, 27, 1.0, 0xFFFFFF, 0x000000, Widgets.FONTS.DejaVu18)
 65    title_e = Widgets.Title("Motor Ctrl", 3, 0xFFFFFF, 0x0000FF, Widgets.FONTS.DejaVu18)
 66    label_vol = Widgets.Label("vol:", 5, 55, 1.0, 0xFFFFFF, 0x000000, Widgets.FONTS.DejaVu18)
 67    label_cur = Widgets.Label("cur:", 5, 75, 1.0, 0xFFFFFF, 0x000000, Widgets.FONTS.DejaVu18)
 68    label_pow = Widgets.Label("pow:", 5, 95, 1.0, 0xFFFFFF, 0x000000, Widgets.FONTS.DejaVu18)
 69    BtnA.setCallback(type=BtnA.CB_TYPE.WAS_CLICKED, cb=btnA_wasClicked_event)
 70    i2c0 = I2C(0, scl=Pin(39), sda=Pin(38), freq=100000)
 71    motion = Motion(i2c0, 0x38)
 72    last_time = time.ticks_us()
 73    speed = 0
 74    label_speed.setText(str((str("speed: ") + str(speed))))
 75
 76
 77def loop():
 78    global \
 79        label_speed, \
 80        title_e, \
 81        label_vol, \
 82        label_cur, \
 83        label_pow, \
 84        i2c0, \
 85        motion, \
 86        speed, \
 87        voltage, \
 88        curent, \
 89        last_time, \
 90        power
 91    M5.update()
 92    voltage = motion.read_voltage()
 93    curent = motion.read_current()
 94    power = motion.read_power()
 95    label_vol.setText(str((str("vol: ") + str(voltage))))
 96    label_cur.setText(str((str("cur: ") + str(curent))))
 97    label_pow.setText(str((str("pow: ") + str(power))))
 98
 99
100if __name__ == "__main__":
101    try:
102        setup()
103        while True:
104            loop()
105    except (Exception, KeyboardInterrupt) as e:
106        try:
107            from utility import print_error_msg
108
109            print_error_msg(e)
110        except ImportError:
111            print("please update to latest firmware")

Example output:

None

API

Motion

class base.motion.Motion(i2c, address=0x38)

Create an Motion object.

Parameters:
  • i2c (I2C) – The I2C port to use.

  • address (int) – The device address. Default is 0x38.

UiFlow2 Code Block:

__init__.png

MicroPython Code Block:

from base import Motion
from machine import I2C

i2c0 = I2C(0, scl=Pin(39), sda=Pin(38), freq=100000)
motion = Motion(i2c0, 0x38)
get_servo_angle(ch)

Get the angle of the servo.

Parameters:

ch (int) – The servo channel. Range: 1~4.

Returns:

Specify the servo angle for the specified channel. Range: 0~180.

Return type:

int

UiFlow2 Code Block:

get_servo_angle.png

MicroPython Code Block:

motion.get_servo_angle()
set_servo_angle(ch, angle)

Set the angle of the servo.

Parameters:
  • ch (int) – The servo channel. Range: 1~4.

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

UiFlow2 Code Block:

set_servo_angle.png

MicroPython Code Block:

motion.set_servo_angle()
get_servo_pulse(ch)

Get the pulse of the servo.

Parameters:

ch (int) – The servo channel. Range: 1~4.

Returns:

Specify the servo pulse for the specified channel. Range: 500~2500.

Return type:

int

UiFlow2 Code Block:

get_servo_pulse.png

MicroPython Code Block:

motion.get_servo_pulse()
write_servo_pulse(ch, pulse)

Write the pulse of the servo.

Parameters:
  • ch (int) – The servo channel. Range: 1~4.

  • pulse (int) – The servo pulse. Range: 500~2500.

UiFlow2 Code Block:

write_servo_pulse.png

MicroPython Code Block:

motion.write_servo_pulse()
get_motor_speed(ch)

Get the speed of the motor.

Parameters:

ch (int) – The motor channel. Range: 1~2.

Returns:

Specify the speed for the specified channel. Range: -127~127.

Return type:

int

UiFlow2 Code Block:

get_motor_speed.png

MicroPython Code Block:

motion.get_motor_speed()
set_motor_speed(ch, speed)

Set motor speed.

Parameters:
  • ch (int) – The motor channel. Range: 1~2.

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

UiFlow2 Code Block:

set_motor_speed.png

MicroPython Code Block:

motion.set_motor_speed()
read_voltage()

Read voltage (unit: V).

Returns:

The voltage value in volts.

Return type:

float

Note

This method is supported only on Motion Base v1.1 and later versions.

UiFlow2 Code Block:

read_voltage.png

MicroPython Code Block:

motion.read_voltage()
read_current()

Read current (unit: A).

Returns:

The current value in amperes.

Return type:

float

Note

This method is supported only on Motion Base v1.1 and later versions.

UiFlow2 Code Block:

read_current.png

MicroPython Code Block:

motion.read_current()
read_power()

Read power (unit: W).

Returns:

The power value in watts.

Return type:

float

Note

This method is supported only on Motion Base v1.1 and later versions.

UiFlow2 Code Block:

read_power.png

MicroPython Code Block:

motion.read_power()