M5Stack Cardputer Zero · Volume 7
M5Stack Cardputer Zero Volume 7 — Programming Environments
Arduino + M5Cardputer library, PlatformIO Zero env, MicroPython, UiFlow, ESP-IDF — the developer paths
Contents
| Section | Topic |
|---|---|
| 1 | About this volume |
| 2 | Arduino IDE + M5Cardputer library |
| 3 | PlatformIO + Zero-specific env |
| 4 | MicroPython |
| 5 | UiFlow visual programming |
| 6 | ESP-IDF (low-level) |
| 7 | Common Zero-specific code patterns |
| 8 | Resources |
1. About this volume
Vol 7 covers programming environments for Cardputer Zero. The Cardputer family shares libraries (M5Cardputer, M5Unified) and the Zero is expected to be compatible once a Zero board target is added. Most developer workflows look identical to the ADV; the deltas are:
- PlatformIO env: a Zero-specific env file is needed (or Zero target in upstream)
- Pin maps: any code that references EXT pins or audio pins needs handling for Zero
- Capability checks at compile time: code that uses Cap modules or audio needs conditional compilation
Cross-reference: ../../../M5Stack Cardputer ADV/03-outputs/Cardputer_ADV_Complete.html Vol 8 covers programming environments for the ADV. This volume captures the Zero deltas.
2. Arduino IDE + M5Cardputer library
2.1 Standard setup
1. Install Arduino IDE 2.x (or 1.8.x; both work)
2. Add ESP32 board package via Boards Manager:
- Boards URL: https://espressif.github.io/arduino-esp32/package_esp32_index.json
- Install "esp32 by Espressif Systems"
3. Install libraries:
- M5Cardputer (search in Library Manager)
- M5Unified (search in Library Manager)
4. Select board: "M5Stack-Cardputer" (until Zero target appears)
5. Set port to detected COM port
6. Compile + upload
2.2 Zero-specific considerations
Until M5Cardputer library includes a Zero target:
- Pin mapping: code referencing M5.Cardputer pins works on Zero if pins are unchanged (presumed match for keyboard / display)
- Cap module pins: code that uses Cap pins (EXT bus) will NOT work on Zero
- Audio: code using M5.Speaker / M5.Microphone may behave differently or not at all
- IMU: code calling BMI270 functions will fail (no sensor)
For Zero-specific sketches, until the library updates: hand-edit any pins, capability-check at compile time.
2.3 Minimal example
#include "M5Cardputer.h"
void setup() {
auto cfg = M5.config();
M5Cardputer.begin(cfg, true);
M5Cardputer.Display.setTextSize(2);
M5Cardputer.Display.println("Hello, Cardputer Zero!");
}
void loop() {
M5Cardputer.update();
if (M5Cardputer.Keyboard.isChange()) {
// Read keyboard state
}
}
This works on Zero if the M5Cardputer abstraction covers basic display + keyboard. Audio/IMU calls would need conditional checks.
3. PlatformIO + Zero-specific env
3.1 Until Zero is in mainline support
Add a Zero-specific env to platformio.ini:
[env:m5stack-cardputer-zero]
platform = espressif32
board = esp32-s3-devkitc-1
framework = arduino
board_build.mcu = esp32s3
board_build.f_cpu = 240000000L
board_build.flash_size = 8MB
board_build.psram = no
board_upload.flash_size = 8MB
board_upload.maximum_size = 8388608
board_upload.use_1200bps_touch = no
board_upload.wait_for_upload_port = no
build_flags =
-DBOARD_HAS_PSRAM=0
-DARDUINO_USB_CDC_ON_BOOT=1
-DCONFIG_FREERTOS_HZ=1000
-DM5_CARDPUTER_ZERO ; custom flag for code differentiation
lib_deps =
m5stack/M5Cardputer
m5stack/M5Unified
monitor_speed = 115200
upload_speed = 921600
3.2 Conditional compilation pattern
For code that should work on both ADV and Zero:
#include "M5Cardputer.h"
void doAudioOutput() {
#if defined(M5_CARDPUTER_ZERO)
// Zero: PWM-driven speaker only
speaker_pwm_play(440, 100);
#else
// ADV: full audio codec available
M5.Speaker.tone(440, 100);
#endif
}
void readIMU() {
#if defined(M5_CARDPUTER_ZERO)
// Zero: no internal IMU; fail silently or read Grove IMU
#else
// ADV: BMI270 internal
M5.Imu.update();
#endif
}
This pattern is essential for libraries that support both variants. Maintain it carefully as Zero-specific code paths land.
4. MicroPython
Standard MicroPython for ESP32-S3 works on Zero unchanged. Flashing follows the standard pattern (Vol 8 § 4 for esptool.py).
4.1 Hello world
from machine import Pin
from time import sleep
# Built-in LED (if Zero has one)
led = Pin(2, Pin.OUT)
while True:
led.toggle()
sleep(0.5)
4.2 Display + keyboard via MicroHydra
MicroHydra (github.com/echo-lalia/MicroHydra) provides a high-level Cardputer-aware MicroPython API:
from microhydra import Display, Keyboard
d = Display()
k = Keyboard()
d.clear()
d.print("Press any key:")
while True:
if k.is_pressed():
d.print(f"Got: {k.get_char()}")
MicroHydra works on Zero if it adds Zero target; otherwise build from source.
5. UiFlow visual programming
UiFlow (flow.m5stack.com) — Scratch-style visual programming for M5Stack devices. Zero compatibility:
- Block library: ESP32-S3 family supported
- Cardputer Zero target: TBD when product ships
- Drag-and-drop: keyboard input + display output blocks
- Code generation: outputs Python (UiFlow 2) or block-driven runtime
For non-programmers / classroom use: this is the right entry point.
6. ESP-IDF (low-level)
ESP-IDF (Espressif IoT Development Framework) is the low-level C/C++ framework underneath Arduino-ESP32. For tjscientist’s expected use, Arduino + PlatformIO covers everything; ESP-IDF only matters when you need:
- Lower-level access to silicon features
- Larger projects (no Arduino sketch size limit)
- Real-time scheduling (Arduino is single-thread-ish)
- BLE GATT server with multiple services (deep integration)
- Custom partition tables (over-the-air, dual-bank)
Standard ESP-IDF setup applies for Zero (ESP32-S3 target). Cross-ref ESP-IDF docs.
7. Common Zero-specific code patterns
7.1 Detect Zero at runtime (without conditional compilation)
Some firmware might want to detect the device at runtime:
// Hypothetical detection — verify on hardware
bool isCardputerZero() {
// Method 1: Check for IMU presence
Wire.beginTransmission(0x68); // BMI270 default address
return Wire.endTransmission() != 0; // True if no IMU = Zero
}
// Method 2: Check ESP-IDF efuse for chip variant
bool isS3FN8() {
// Read efuse; ESP32-S3 PICO vs S3FN8 may differ
// (implementation depends on actual chip)
}
7.2 Graceful degradation pattern
void scanForFeatures() {
bool hasIMU = false;
bool hasAudioCodec = false;
bool hasMicrophone = false;
// Try IMU
Wire.beginTransmission(0x68);
hasIMU = (Wire.endTransmission() == 0);
// Try audio codec
Wire.beginTransmission(0x18); // ES8311 default
hasAudioCodec = (Wire.endTransmission() == 0);
// Adjust UI / features accordingly
if (!hasIMU) showMessage("No IMU; using compass workaround");
if (!hasAudioCodec) disableAudioMenu();
}
This pattern makes a single firmware build work on both ADV and Zero.
7.3 Grove peripheral handling
// Grove I2C scanner
void scanGroveI2C() {
Wire.setPins(GROVE_SDA, GROVE_SCL);
Wire.begin();
for (int addr = 1; addr < 128; addr++) {
Wire.beginTransmission(addr);
if (Wire.endTransmission() == 0) {
Serial.printf("Found Grove device at 0x%02X\n", addr);
}
}
}
8. Resources
- Cardputer ADV Vol 8 (programming envs canonical):
../../../M5Stack Cardputer ADV/03-outputs/Cardputer_ADV_Complete.html - M5Cardputer library: https://github.com/m5stack/M5Cardputer
- M5Unified library: https://github.com/m5stack/M5Unified
- Arduino ESP32 board package: https://github.com/espressif/arduino-esp32
- PlatformIO docs (ESP32-S3): https://docs.platformio.org/en/latest/boards/espressif32/esp32-s3-devkitc-1.html
- MicroPython for ESP32: https://micropython.org/download/ESP32_GENERIC_S3/
- UiFlow: https://flow.m5stack.com/
- ESP-IDF: https://docs.espressif.com/projects/esp-idf/
End of Vol 7. Next: Vol 8 covers firmware flashing workflows — M5Burner, web flashers, esptool.py manual flash, factory backup.