Objectives
- Understand the M5Stack internal I2C bus: SDA = GPIO21, SCL = GPIO22, shared between Grove PORT.A (red), the IP5306 (address 0x75), and the IMU on Gray models.
- Write an I2C scanner to discover present peripherals.
- Read the battery level via the IP5306 power management chip (5-level voltage gauge, not a true fuel gauge).
- Recall variant pitfalls: Basic = no IMU; Gray = MPU6050+MAG3110, then MPU9250, then MPU6886+BMM150 depending on the manufacturing date.
Hardware
- 1 M5Stack Core (Basic or Gray).
- Optional: 1 Grove I2C sensor on PORT.A (red).
- 3.3 V pins only on the Grove connector.
Complete Code
#include <M5Unified.h>
#include <Wire.h>
void scannerI2C {
Serial.println("Scan I2C (SDA=21, SCL=22) :");
for (uint8_t a = 1; a < 127; a++) {
Wire.beginTransmission(a);
if (Wire.endTransmission == 0) Serial.printf(" trouve 0x%02X\n", a);
}
}
void setup {
Serial.begin(115200);
auto cfg = M5.config;
M5.begin(cfg); // M5Unified initialise I2C et l'IP5306
Wire.begin(21, 22); // SDA, SCL (PORT.A / M-BUS)
scannerI2C; // 0x75 = IP5306 ; 0x68 = IMU (Gray seulement)
M5.Display.setTextSize(2);
}
void loop {
int niveau = M5.Power.getBatteryLevel; // 0..100 par paliers IP5306
M5.Display.fillRect(0, 30, 320, 60, TFT_BLACK);
M5.Display.setCursor(10, 35);
M5.Display.printf("Batterie : %d %%", niveau);
M5.Display.drawRect(10, 100, 300, 30, TFT_WHITE);
M5.Display.fillRect(12, 102, 296 * constrain(niveau, 0, 100) / 100, 26,
niveau > 30 ? TFT_GREEN : TFT_RED);
Serial.printf("Batterie %d%%\n", niveau);
vTaskDelay(2000 / portTICK_PERIOD_MS);
}
Expected Verification
- The scan lists at least 0x75 (IP5306); on a Gray model, an IMU address (0x68, sometimes 0x10 for the BMM150 magnetometer) also appears.
- The screen displays a percentage and a colored bar; unplugging USB causes the voltage and the bar to drop in steps (the IP5306 gauge is coarse: 5 voltage levels).
- A Grove I2C sensor on PORT.A appears in the scan at its own address.
Common Errors
- Looking for an IMU on a Basic model: there isn't one (the IMU is a Gray feature) — the "IMU" code fails silently.
- Hardcoding an IMU address/chip: the manufacturer has changed sensors several times (MPU6050 → MPU9250 → MPU6886+BMM150, or SH200Q); you must detect it via scanning.
- Expecting gauge precision: the IP5306 % is a voltage level lookup table (e.g., 3.81-3.55 V = "50 %").
- Forgetting Wire.begin(21, 22) when using Wire directly: silent bus.
- Thinking 0 % = 0 V: the 110 mAh LiPo battery cuts off well before; do not drain the battery completely.