[SOLVED] M5StickCPlus and BMM150 (ENV II Hat) do not work

  • Hi all,

    I'm working on getting magnetometer data with a M5StickC Plus and ENV II Hat.
    I found that I2C communication between M5StickC Plus and BMM150 is not working as expected, and am wondering if you can provide some guidance to make it work.

    I'm using a sample code at

    I tried it as is. It did not work (the code stopped running somewhere)
    I added Wire.begin(0, 26) in the setup function since the hat is connected to G0 and G26. This got the same result.

    Then, I dug into where the code stopped.
    It stopped at BMM150::initialize > set_op_mode > suspend_to_sleep_mode > set_power_control_bit > i2c_read
    In i2c_read, when the code called Wire.requestFrom(BMM150_I2C_Address, 1), it did not return.
    How can I fix the issue?

    Here is a minimal code to reproduce the issue.

    #include <M5StickCPlus.h>
    #define BMM150_I2C_Address  0x10  // These are copied from bmm150_defs.h
    #define BMM150_POWER_CONTROL_ADDR 0x4B
    void setup() {
      Wire.begin(0, 26);
      delay(3000);  // Make sure to avoid any race conditions
      Serial.println("Start setup");
      uint8_t reg_data = i2c_read(BMM150_POWER_CONTROL_ADDR);
    void loop() {
    uint8_t i2c_read(short address)
        uint8_t byte;
        int result;
        result = Wire.endTransmission();
        Serial.printf("%d\n", result); // This sometimes gets 2: NACK, which is a bit strange
        result = Wire.endTransmission();
        Serial.printf("%d\n", result);  // This gets 0: Success
        result = Wire.endTransmission();
        Serial.printf("%d\n", result); // This gets 0: Success
        Serial.println("call Wire.requestFrom");
        Wire.requestFrom(BMM150_I2C_Address, 1, 0);
        Serial.println("call returned"); // This is never called
        byte = Wire.read();
        return byte;

  • @eulic_ Could be related to these includes and begins:

    #include "bmm150.h"
    #include "bmm150_defs.h"
    SHT3X sht3x;
    BMM150 bmm = BMM150();
    bmm150_mag_data value_offset;
    Adafruit_BMP280 bme;

    With the StickCPlus include you should not need to add Wire.begin(0, 26);

    Also I don't understand the three



  • @teastain Thank you for your comment Terry!
    I initially had all variables and, unfortunately, it did not work either.
    Wire.begin(0, 26) is necessary because I'm using Hat that connects to GPIO pins not Grove port. Wire.begin start I2C communications using the Grove port by default not G0 and 26 on the Hat connecter side.

    When I checked I2C addresses with I2C_Tester example, With Wire.begin(), it listed only three internal devices. With Wire.begin(0, 26), it listed three additional devices in ENV III Hat including BMM150 at 0x10.

    Btw, sht3x has Wire.begin() in its constructer. So, it's better not to have the sht3x instance if not necessary. It could lead to confusing results.

  • @eulic_,

    I adapted what is below from the M5Stack examples for StickC (non-Plus) and ENVII hat to work on an Atom. The only real changes I made were to write out to serial instead of LCD and use the LEDs of the Atom, so it might help you fault find. NB Library and pins need changed to suit your StickC Plus. It's a bit rough and ready, but it certainly worked on ENVII with Atom and StickC.

    #include <M5Atom.h> // Swap out for StickC library
    #include "M5_ENV.h"
    #include <Adafruit_BMP280.h>
    #include "Adafruit_Sensor.h"
    SHT3X sht30; // SHT3X sht30;
    Adafruit_BMP280 bme; // Adafruit_BMP280 bme;
    float tmp      = 0.0;
    float hum      = 0.0;
    float pressure = 0.0;
    void setup() {
        M5.begin(true, false, true);             // Init M5Atom
        // M5.Lcd.setRotation(3);  // Rotate the screen.
        // M5.dis.fillpix(0xFF0000); //LEDs of atom to black
        Wire.begin(19, 22); // Swap out for StickC 0, 26
        Serial.println(F("ENVII Unit(SHT30 and BMP280) test...\n"));
    void loop() {
        while (!bme.begin(0x76)) {  // Init the sensor of bme
            Serial.println("Could not find a valid BMP280 sensor, check wiring!");
        // M5.dis.fillpix(0x00FF00); // Turns atom leds green
        pressure = bme.readPressure();  // Stores the pressure gained by BMP.
        sht30.get();           // Obtain the data of shT30.
        tmp = sht30.cTemp;     // Store the temperature obtained from shT30
        hum = sht30.humidity;  // Store the humidity obtained from the SHT30
        // M5.Lcd.setCursor(0, 20);
        // M5.Lcd.fillRect(0, 20, 100, 60,
                      //  BLACK);  // Fill the screen with black (to clear the screen).
        Serial.printf("Temp: %2.1f  \r\nHumi: %2.0f%%  \r\nPressure:%2.0fPa\r\n",
                      tmp, hum, pressure);

  • Thanks @gavin67890 !
    Yes. We can make the SHT30 and BMP280 in that way, but not BMM150 unfortunately.
    I think the example code for BMM150 is fundamentally broken and M5Stack does not plan to fix it since ENV II Hat is EOL. I will look into an example code from Bosch, which is the manufacture of the BMM150 chip.

  • I found a solution.
    An example you can find at https://www.waveshare.com/wiki/BMM150_3-Axis_Magnetometer_Sensor (the one linked from Example Demo) with a proper modification worked with BMM150 in Env II Hat. Here is the procedure.

    • Download the zip file from the Example Demo link.
    • Open bmm150_Arduino.ino under Arduino > bmm150_Arduino
    • Search Wire.begin() in the code (you can find one in the line 149)
    • Change it to Wire.begin(0, 26)
      This is necessary if you are using a Hat version of ENV II HAT, which is connected to the GPIO pin side of the M5Stick variants. If you are using ENV II Hat connected the Grove port, you don't need to change it.

    After this modification, the code should work.