USB Module
The USB Module is a module that uses the SPI interface to expand USB functionality, implemented with the MAX3421E.
Support the following products:
Micropython Example
Note
Before using the following examples, please check the DIP switches on the module to ensure that the pins used in the example match the DIP switch positions. For specific configurations, please refer to the product manual page. The SPI configuration has been implemented internally, so users do not need to worry about it.
Input/Output Pin Control
The module exposes 5 IN (input) pins and 5 OUT (output) pins through headers. This example demonstrates controlling the high and low level switching of the output pins, as well as reading and printing the level status of the input pins.
1# SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD 2# 3# SPDX-License-Identifier: MIT 4import os, sys, io 5import M5 6from M5 import * 7from module import USBModule 8import time 9 10 11module_usb_0 = None 12last_time = None 13i = None 14last_set_time = None 15value = None 16state = None 17toggle = None 18 19 20def setup(): 21 global module_usb_0, last_time, last_set_time, value, state, toggle, i 22 M5.begin() 23 Widgets.fillScreen(0x222222) 24 module_usb_0 = USBModule(pin_cs=1, pin_int=10) 25 module_usb_0.write_gpout(0, 0) 26 module_usb_0.write_gpout(1, 1) 27 module_usb_0.write_gpout(2, 0) 28 module_usb_0.write_gpout(3, 1) 29 module_usb_0.write_gpout(4, 0) 30 state = [0] * 5 31 toggle = True 32 33 34def loop(): 35 global module_usb_0, last_time, last_set_time, value, state, toggle, i 36 M5.update() 37 module_usb_0.poll_data() 38 if (time.ticks_diff((time.ticks_ms()), last_time)) > 200: 39 last_time = time.ticks_ms() 40 for i in range(5): 41 value = module_usb_0.read_gpin(i) 42 state[int((i + 1) - 1)] = value 43 print(state) 44 if (time.ticks_diff((time.ticks_ms()), last_set_time)) > 1000: 45 last_set_time = time.ticks_ms() 46 if toggle: 47 for i in range(5): 48 module_usb_0.write_gpout(i, 1) 49 else: 50 for i in range(5): 51 module_usb_0.write_gpout(i, 0) 52 toggle = not toggle 53 54 55if __name__ == "__main__": 56 try: 57 setup() 58 while True: 59 loop() 60 except (Exception, KeyboardInterrupt) as e: 61 try: 62 from utility import print_error_msg 63 64 print_error_msg(e) 65 except ImportError: 66 print("please update to latest firmware")
Mouse
Implementing USB host to capture mouse input
1# SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD 2# 3# SPDX-License-Identifier: MIT 4import os, sys, io 5import M5 6from M5 import * 7from module import USBModule 8 9 10title0 = None 11label_x = None 12label_y = None 13module_usb_0 = None 14x = None 15y = None 16mouse_move = None 17dx = None 18dy = None 19 20 21def setup(): 22 global title0, label_x, label_y, module_usb_0, x, y, mouse_move, dx, dy 23 M5.begin() 24 Widgets.fillScreen(0x222222) 25 title0 = Widgets.Title( 26 "Module USB Example mouse", 3, 0xFFFFFF, 0x0000FF, Widgets.FONTS.DejaVu18 27 ) 28 label_x = Widgets.Label("x", 130, 90, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18) 29 label_y = Widgets.Label("y", 180, 90, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18) 30 module_usb_0 = USBModule(pin_cs=1, pin_int=10) 31 x = 0 32 y = 0 33 34 35def loop(): 36 global title0, label_x, label_y, module_usb_0, x, y, mouse_move, dx, dy 37 module_usb_0.poll_data() 38 if module_usb_0.is_left_btn_pressed(): 39 print("click left") 40 if module_usb_0.is_right_btn_pressed(): 41 print("click right") 42 if module_usb_0.is_middle_btn_pressed(): 43 print("click middle") 44 mouse_move = module_usb_0.read_mouse_move() 45 dx = mouse_move[0] 46 dy = mouse_move[1] 47 if dx != 0 or dy != 0: 48 print((str("move: ") + str((str(dx) + str((str(", ") + str(dy))))))) 49 x = min(max(x + dx, 0), 320) 50 y = min(max(y + dy, 0), 240) 51 label_x.setText(str(x)) 52 label_y.setText(str(y)) 53 54 55if __name__ == "__main__": 56 try: 57 setup() 58 while True: 59 loop() 60 except (Exception, KeyboardInterrupt) as e: 61 try: 62 from utility import print_error_msg 63 64 print_error_msg(e) 65 except ImportError: 66 print("please update to latest firmware")
Keyboard
Implementing USB host to capture keyboard input
1# SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD 2# 3# SPDX-License-Identifier: MIT 4import os, sys, io 5import M5 6from M5 import * 7from module import USBModule 8 9 10module_usb_0 = None 11modifier = None 12indata = None 13 14 15def setup(): 16 global module_usb_0, modifier, indata 17 M5.begin() 18 Widgets.fillScreen(0x222222) 19 module_usb_0 = USBModule(pin_cs=1, pin_int=10) 20 21 22def loop(): 23 global module_usb_0, modifier, indata 24 M5.update() 25 module_usb_0.poll_data() 26 modifier = module_usb_0.read_kb_modifier() 27 if modifier & 0x01: 28 print("Left Control pressed") 29 if modifier & 0x02: 30 print("Left Shift pressed") 31 if modifier & 0x04: 32 print("Left Alt pressed") 33 if modifier & 0x08: 34 print("Left GUI pressed") 35 if modifier & 0x10: 36 print("Right Control pressed") 37 if modifier & 0x20: 38 print("Right Shift pressed") 39 if modifier & 0x40: 40 print("Right Alt pressed") 41 if modifier & 0x80: 42 print("Right GUI pressed") 43 indata = module_usb_0.read_kb_input(True) 44 if indata: 45 print(indata) 46 47 48if __name__ == "__main__": 49 try: 50 setup() 51 while True: 52 loop() 53 except (Exception, KeyboardInterrupt) as e: 54 try: 55 from utility import print_error_msg 56 57 print_error_msg(e) 58 except ImportError: 59 print("please update to latest firmware")
UIFlow2.0 Example
Input/Output Pin Control
Mouse
Keyboard
class USBModule
Constructors
- poll_data()
poll data
Note: It needs to be called in the main loop
UIFlow2.0
- read_mouse_move() tuple[int, int]
Read Mouse Cursor Movement
Returns a tuple (x, y) containing the horizontal displacement x and vertical displacement y of the mouse; x range: -127 to 127; 0 indicates no movement, negative values indicate movement to the left, and positive values indicate movement to the right; y range: -127 to 127; 0 indicates no movement, negative values indicate movement upward, and positive values indicate movement downward.
Example:
move = usb_module.read_mouse_move() x = move[0] y = move[1]
UIFlow2.0
- read_wheel_move() int
Read Mouse Wheel Movement
Returns a value in the range of -127 to 127, 0 indicates no movement, Positive values indicate forward scrolling, Negative values indicate backward scrolling.
UIFlow2.0
- read_kb_input(convert: bool = True) list
Read keyboard input
convert
Whether to convert HID Keycode to the corresponding string.
Returns a list containing keyboard inputs (up to 6 elements, meaning a maximum of 6 key values can be input at once).
Example:
res = usb_module.read_kb_input(convert=True) # output ['a', 'b', 'Enter'] res = usb_module.read_kb_input(convert=False) # output [0x04, 0x05, 0x28]
UIFlow2.0
- read_kb_modifier() int
Read the keyboard modifier keys, namely “Ctrl”, “Shift”, “Alt”, and “Win” keys.
Return
: The status of the keyboard modifier keys, usually represented by a bit mask to indicate the status of different modifier keys.0x01: Left Control key
0x02: Left Shift key
0x04: Left Alt key
0x08: Left Windows key (Left GUI)
0x10: Right Control key
0x20: Right Shift key
0x40: Right Alt key
0x80: Right Windows key (Right GUI)
Example:
modifier = module_usb.read_kb_modifier() if modifier & 0x01: print("left ctrl key pressed")
UIFlow2.0
- read_gpin(pin) int
Read input pin value
pin
pin numberReturn
1 represents high level, and 0 represents low level.
UIFlow2.0
- write_gpout(pin, value)
Write output pin value
pin
pin numberReturn
1 represents high level, and 0 represents low level.
UIFlow2.0