M5.begin() had different parameters and counts for different device libraries. To unify them, M5Unified uses a structure as a parameter to pass various configuration information.SD.h is not used by default, and SD.begin() is not executed internally.BtnA instead of Btn.M5), leading to the following compilation error:error: reference to 'jpeg_div_t' is ambiguous jpeg_div_t scale = JPEG_DIV_NONE); error: conflicting declaration 'M5Stack M5' extern M5Stack M5;M5.beginIn earlier driver libraries, M5.begin() had different parameters for each device, as shown below:
// M5Stack M5.begin(bool LCDEnable = true, bool SDEnable = true, bool SerialEnable = true, bool I2CEnable = false); // M5Core2 M5.begin(bool LCDEnable = true, bool SDEnable = true, bool SerialEnable = true, bool I2CEnable = false, mbus_mode_t mode = KMBusModeOutput); // M5StickC M5.begin(bool LCDEnable = true, bool PowerEnable = true, bool SerialEnable = true); // M5StickCPlus M5.begin(bool LCDEnable = true, bool PowerEnable = true, bool SerialEnable = true); // M5Atom M5.begin(bool SerialEnable = true, bool I2CEnable = true, bool DisplayEnable = false);After switching to M5Unified, some initialization configuration information is implemented in a cfg structure:
auto cfg = M5.config(); // Set the items you want to configure. Omit the following two lines if you use the default settings. cfg.serial_baudrate = 115200; cfg.output_power = true; M5.begin(cfg);- M5.begin(true, true, true, true); + auto cfg = M5.config(); + cfg.internal_imu = true; + + M5.begin(cfg); M5.BtnThe number of available buttons varies by M5Stack product, primarily using the following naming conventions:
BtnA, BtnB, BtnCBtnPWRBtnEXTChange example: Display the message "BtnA isPressed" when Button A is pressed, and "BtnA isReleased" when released.
#include <M5Unified.h> void setup() { auto cfg = M5.config(); cfg.clear_display = true; M5.begin(cfg); M5.Lcd.setTextSize(2); M5.Lcd.println("Press BtnA"); } void loop() { // update the button state. M5.update(); if (M5.BtnA.isPressed()) { M5.Display.setCursor(0, 16); M5.Display.println("BtnA isPressed "); } else { M5.Display.setCursor(0, 16); M5.Display.println("BtnA isReleased"); } }To update the button state, execute M5.update():
#include <M5Unified.h> uint32_t loop_count = 0; void setup() { auto cfg = M5.config(); cfg.clear_display = true; M5.begin(cfg); M5.Lcd.setTextSize(2); M5.Lcd.println("Press BtnA"); } void loop() { M5.update(); // update the button state. if (M5.BtnA.wasPressed()) { M5.Display.fillScreen(TFT_BLACK); M5.Display.setCursor(0, 0); M5.Display.println("BtnA wasPressed"); M5.Display.println("Press BtnA Stop Count"); while (true) { M5.update(); // update the button state within the subloop. M5.Display.setCursor(0, 32); M5.Display.printf("count: %10d\n", loop_count); if (M5.BtnA.wasPressed()) { M5.Display.println("Count Stop"); loop_count = 0; break; } loop_count++; } } }For more information, refer to the M5Unified Button Class.
M5.LcdM5Unified relies on the M5GFX library. When installing M5Unified in the Arduino IDE, a popup will prompt you to install this dependency; please install all of them.
Change example: This example program supports M5Stack controllers with LCD or e-Ink displays, using the same set of drawing APIs regardless of screen type.
#include <M5Unified.h> void setup() { auto cfg = M5.config(); M5.begin(cfg); M5.Display.setTextSize(3); M5.Display.println("HelloWorld!"); } void loop() { }After switching to M5Unified.h, SD.h is no longer included by default. You must manually add #include <SD.h>:
- #include <M5Stack.h> + #include <SD.h> + #include <M5Unified.h> Add SD.begin():
+ while (false == SD.begin(GPIO_NUM_4, SPI, 25000000)) + { + delay(500); + } M5Unified initializes the internal I2C by default. For devices like Basic/Gray/Fire, where PORT.A is reused for internal I2C, call M5.In_I2C.release() if PORT.A is mapped to other functions.
auto cfg = M5.config(); . . . M5.begin(cfg); M5.In_I2C.release();If you convert the FactoryTest.ino example from the M5Stack library to M5Unified, it will look like this:
SD.beginSPEAKER_PINM5.Btn.pressedFordiff --git a/src/main.cpp b/src/main.cpp index b735e30..dae9b99 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,10 +1,10 @@ #include <Arduino.h> -#include <M5Stack.h> +#include <SD.h> +#include <M5Unified.h> #include <stdlib.h> //#include "FastLED.h" #include "WiFi.h" -#include "utility/MPU9250.h" extern const unsigned char gImage_logoM5[]; extern const unsigned char m5stack_startup_music[]; @@ -13,7 +13,8 @@ extern const unsigned char m5stack_startup_music[]; #define min(a, b) (((a) < (b)) ? (a) : (b)) #endif -MPU9250 IMU; + +#define SPEAKER_PIN 25 // #define LEDS_PIN 15 // #define LEDS_NUM 10 @@ -127,15 +128,15 @@ void writeFile(fs::FS &fs, const char *path, const char *message) { } void buttons_test() { - if (M5.BtnA.wasReleased() || M5.BtnA.pressedFor(1000, 200)) { + if (M5.BtnA.wasReleased() || M5.BtnA.pressedFor(1000)) { M5.Lcd.printf("A"); Serial.printf("A"); } - if (M5.BtnB.wasReleased() || M5.BtnB.pressedFor(1000, 200)) { + if (M5.BtnB.wasReleased() || M5.BtnB.pressedFor(1000)) { M5.Lcd.printf("B"); Serial.printf("B"); } - if (M5.BtnC.wasReleased() || M5.BtnC.pressedFor(1000, 200)) { + if (M5.BtnC.wasReleased() || M5.BtnC.pressedFor(1000)) { M5.Lcd.printf("C"); Serial.printf("C"); } @@ -475,8 +476,11 @@ void setup() { // GPIO_test(); // } + auto cfg = M5.config(); + cfg.internal_imu = true; + // initialize the M5Stack object - M5.begin(); + M5.begin(cfg); /* Power chip connected to gpio21, gpio22, I2C device @@ -484,6 +488,10 @@ void setup() { If used battery, please call this function in your project */ M5.Power.begin(); + while (false == SD.begin(GPIO_NUM_4, SPI, 25000000)) + { + delay(500); + } // dac test // if (gpio_test_flg) @@ -492,7 +500,6 @@ void setup() { // } startupLogo(); // ledBar(); - Wire.begin(); // Lcd display M5.Lcd.setBrightness(100); @@ -609,54 +616,33 @@ void setup() { M5.Lcd.setBrightness(i); delay(2); } - - byte c = IMU.readByte(MPU9250_ADDRESS, WHO_AM_I_MPU9250); - Serial.print("MPU9250 "); - Serial.print("I AM "); - Serial.print(c, HEX); - Serial.print(" I should be "); - Serial.println(0x71, HEX); - Serial.println(""); - M5.Lcd.setCursor(20, 0); - M5.Lcd.print("MPU9250"); - M5.Lcd.setCursor(0, 10); - M5.Lcd.print("I AM"); - M5.Lcd.setCursor(0, 20); - M5.Lcd.print(c, HEX); - M5.Lcd.setCursor(0, 30); - M5.Lcd.print("I Should Be"); - M5.Lcd.setCursor(0, 40); - M5.Lcd.println(0x71, HEX); - M5.Lcd.println(); - delay(100); - - IMU.initMPU9250(); - // Initialize device for active mode read of acclerometer, gyroscope, and - // temperature - Serial.println("MPU9250 initialized for active data mode...."); - - // Read the WHO_AM_I register of the magnetometer, this is a good test of - // communication - byte d = IMU.readByte(AK8963_ADDRESS, WHO_AM_I_AK8963); - Serial.print("AK8963 "); - Serial.print("I AM "); - Serial.print(d, HEX); - Serial.print(" I should be "); - Serial.println(0x48, HEX); - - // M5.Lcd.fillScreen(BLACK); - M5.Lcd.setCursor(20, 100); - M5.Lcd.print("AK8963"); - M5.Lcd.setCursor(0, 110); - M5.Lcd.print("I AM"); - M5.Lcd.setCursor(0, 120); - M5.Lcd.print(d, HEX); - M5.Lcd.setCursor(0, 130); - M5.Lcd.print("I Should Be"); - M5.Lcd.setCursor(0, 140); - M5.Lcd.print(0x48, HEX); + const char* name; + // run-time branch : imu model check + switch (M5.Imu.getType()) + { + case m5::imu_t::imu_mpu6050: + name = "MPU6050"; + break; + case m5::imu_t::imu_mpu6886: + name = "MPU6886"; + break; + case m5::imu_t::imu_mpu9250: + name = "MPU9250"; + break; + case m5::imu_t::imu_sh200q: + name = "SH200Q"; + break; + default: + name = "none"; + break; + } + M5.Display.print("IMU:"); + M5.Display.println(name); + M5.Display.endWrite(); + ESP_LOGI("setup", "imu:%s", name); delay(1000); + M5.Lcd.setCursor(0, 0); M5.Lcd.println("wifi test:"); M5.Lcd.fillScreen(BLACK);