[SOLVED] GNSS on Core2: BMM150 issue when using M5 events



  • Hello,

    I'm developing a program that uses the GPS and the Magnetometer (BMM150) of the GNSS Module.
    It works fine, but as soon as functions such as M5.BtnA.wasPressed(), screen touch or M5.Axp.GetBatVoltage(), the BMM150 communication seems broken.

    I tried with address 0x68 and 0x69 -> same problem.
    I tried running the task on core 1 or core 0 -> same problem.

    DO YOU HAVE AN IDEA OF WHAT I'M DOING WRONG HERE?

    Examples of error displayed on the monitor.

    After M5.Axp.GetBatVoltage() called:
    11:59:50.763 -> E (22261) IMU: P:0 R 68 7C E:263

    After M5.BtnA.wasPressed() called:
    12:00:33.754 -> E (16003) IMU: P:0 R 68 7C E:-1
    12:00:34.119 -> E (16025) IMU: P:0 R 68 03 E:263
    12:00:34.149 -> E (16038) IMU: P:0 R 68 03 E:263

    Source code to reproduce the issue.

    M5Module_GNSS.h is available here: https://github.com/m5stack/M5Module-GNSS/tree/main/src

    #include <M5Core2.h>
    #include <Arduino.h>
    #include <TinyGPS++.h>
    #include <Wire.h>
    #include "M5Module_GNSS.h"

    #define BIM270_SENSOR_ADDR 0x68
    BMI270::BMI270 bmi270;

    #define WATCHDOG_TIMER 2000UL // ms
    #define BATT_CHECK 20000UL // ms - interval to check battery status

    // variables
    uint32_t last_battery_check = 0;
    uint32_t last_json = 0;

    bool isGPS = false;

    // GPS & Magnetometer
    float biasX, biasY, rangeX, rangeY;
    int16_t magX, magY, magZ;
    int16_t minMagX, minMagY, maxMagX, maxMagY;
    // The TinyGPS++ object
    TinyGPSPlus gps;

    // functions
    void gps_task(void *pvParameters);
    void magneto_task(void *pvParameters);

    void updateBatteryLevel (void) {

    float batVoltage = M5.Axp.GetBatVoltage();
    float batPercentage = ( batVoltage < 3.2 ) ? 0 : ( batVoltage - 3.2 ) * 100;
    Serial.printf("Battery %d\n", batPercentage);
    }

    // ------------------------------------------------ SETUP -----------------------------------------------

    void setup() {

    magX = 0;
    magY = 0;

    M5.begin(true, true, true, false, kMBusModeOutput);
    M5.Axp.SetLed(0);
    M5.Lcd.begin();

    xTaskCreatePinnedToCore(gps_task,
    "gps_task",
    10000,
    NULL,
    25,
    NULL,
    0); // running on core 0

    xTaskCreatePinnedToCore(magneto_task,
    "magneto_task",
    10000,
    NULL,
    25,
    NULL,
    1); // running on core 0

    return;
    }

    void magneto_task(void *pvParameters) {

    static int data, cpmt = 100;

    Serial.print("MAGNETO TASK STARTS\n");
    Wire.begin(21, 22, 100000);
    bmi270.init(I2C_NUM_0, BIM270_SENSOR_ADDR);

    while (1) {
    // DEBUG
    cpmt++;
    if ( cpmt > 100 ) {
    Serial.print("•");
    cpmt = 0;
    };
    // Get Magnetometer data
    if (bmi270.magneticFieldAvailable()) {
    bmi270.readMagneticField(magX, magY, magZ);
    }
    if (cpmt ==0) Serial.printf("x %d y %d\n", magX, magY);
    delay(10);
    }
    }

    void gps_task(void *pvParameters) {

    static int data, cpmt = 100;
    Serial.print("GPS TASK STARTS\n");
    Serial2.begin(38400, SERIAL_8N1, 13, 14);

    while (1) {
    // DEBUG
    cpmt++;
    if ( cpmt > 100 ) {
    Serial.print("+");
    cpmt = 0;
    };
    // Get GPS data
    while (Serial2.available() > 0) {
    data = Serial2.read();
    //Serial.printf("%c", data);
    gps.encode(data);
    }
    isGPS = gps.location.isValid();
    delay(10);
    }
    }

    // ------------------------------------------------ LOOP -----------------------------------------------

    void loop() {

    static char text[256];
    static uint32_t msecs;

    M5.update();
    msecs = millis();

    // WATCHDOG
    if ((msecs - last_json) > WATCHDOG_TIMER) {
    if (isGPS) sprintf(text, "GPS %d - ", gps.satellites.value());
    else sprintf(text, "Sat %d - ", gps.satellites.value());
    Serial.println(text);
    last_json = msecs;
    }

    // battery timer
    if ((msecs - last_battery_check) > BATT_CHECK) {
    updateBatteryLevel();
    last_battery_check = msecs;
    }

    if (M5.BtnA.wasPressed()) {
    Serial.println("BtnA pressed");
    }

    if (M5.BtnB.wasPressed()) {
    Serial.println("BtnB pressed");
    }

    if (M5.BtnC.wasPressed()) {
    Serial.println("BtnB pressed");
    }

    return;
    }



  • Hello @UnumDesignum

    the issue is probably that the internal I2C of M5Core2 library uses Wire1 (and not Wire). See here.

    In your magneto_task you initialize Wire with the same GPIOs (21, 22) so you end up with two I2C instances (Wire and Wire1) fighting for the same GPIOs.

    Try the following and see if that helps:

    //Wire.begin(21, 22, 100000);
    //bmi270.init(I2C_NUM_0, BIM270_SENSOR_ADDR);
    bmi270.init(I2C_NUM_1, BIM270_SENSOR_ADDR);
    

    Thanks
    Felix



  • @felmue A million thanks!

    This was my issue. Your solution works like a charm.

    Thank you!