🤖Have you ever tried Chat.M5Stack.com before asking??😎
    M5Stack Community
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Register
    • Login

    M5Atom and Grove Sensors

    Units
    2
    5
    13.1k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • M
      MadGeometer
      last edited by

      I'm trying to use M5Atom with any Grove sensor, and aren't making any progress.

      An I2C scan finds one address in use (0x68). This is returned even when no sensors are plugged into the Grove port, and plugging in a sensor does not return any additional addresses.

      1. What exactly is the device on 0x68?
      2. Can the Grove port be used with I2C sensors? If so, how?

      Thanks in advance for any help!

      liemphL 3 Replies Last reply Reply Quote 0
      • liemphL
        liemph @MadGeometer
        last edited by liemph

        @madgeometer

        1. The device on 0x68 is MPU6886 (gyro, accelerometer).
          I have checked the sample program for the MPU6886 (it worked):
          https://github.com/m5stack/M5Atom/blob/master/examples/Basics/MPU6886/MPU6886.ino
        2. The Atom grove port is for I2C devices (similar to other M5 cores, for example, M5Stack Fire is Port A). So you can connect any I2C Unit to this port. There is no Arduino example available for connecting an I2C M5 Unit to an Atom but the main difference is only in the GPIO Pin definition. The Atom I2C uses GPIO Pin 26 and 32. These are different with for example M5Stack Fire Port A use GPIO Pin 21 and 22.
          I do not have time to try connecting a Unit to an Atom, but I will share my test in the future.
          https://github.com/m5stack/M5Atom
        1 Reply Last reply Reply Quote 2
        • liemphL
          liemph @MadGeometer
          last edited by liemph

          @madgeometer I have just tried to connect a TOF Unit to my Atom Matrix via its grove port. Since the Atom Matrix does not have LCD than the distance measurement results are sent via the serial port. The code is taken from the TOF Unit example for M5 Stack. I modified:

          1. Wire.begin() -> Wire.begin(26,32)
          2. M5.begin() is moved BEFORE the Wire.begin(26,32)

          Check this list:

          //  the original code by Ted Meyers
          //  posted here: https://groups.google.com/d/msg/diyrovers/lc7NUZYuJOg/ICPrYNJGBgAJ
          //  if your tof have some problem, please see https://docs.m5stack.com/#/en/unit/tof
          //
          //  Modified by from M5Stack Fire Example to be suited for M5 Atom Matrix (liemph, 2020)
          //
          #include "M5Atom.h"
          #include <Wire.h>
          
          #define VL53L0X_REG_IDENTIFICATION_MODEL_ID         0xc0
          #define VL53L0X_REG_IDENTIFICATION_REVISION_ID      0xc2
          #define VL53L0X_REG_PRE_RANGE_CONFIG_VCSEL_PERIOD   0x50
          #define VL53L0X_REG_FINAL_RANGE_CONFIG_VCSEL_PERIOD 0x70
          #define VL53L0X_REG_SYSRANGE_START                  0x00
          #define VL53L0X_REG_RESULT_INTERRUPT_STATUS         0x13
          #define VL53L0X_REG_RESULT_RANGE_STATUS             0x14
          #define address 0x29
          
          byte gbuf[16];
          
          void setup() {
            // put your setup code here, to run once:
            M5.begin();            // Wire.begin() must be after M5.begin()
            Wire.begin(26, 32);    // Atom Matrix I2C GPIO Pin is 26 and 32 <- Important
            Serial.begin(115200);  // start serial for output
            Serial.println("VLX53LOX test started.");
          }
          
          void loop() {
            Serial.println("----- START TEST ----");
            test();
            Serial.println("----- END TEST ----");
            Serial.println("");
            delay(500);
          }
          
          void test() {
            byte val1 = read_byte_data_at(VL53L0X_REG_IDENTIFICATION_REVISION_ID);
            Serial.print("Revision ID: "); Serial.println(val1);
          
            val1 = read_byte_data_at(VL53L0X_REG_IDENTIFICATION_MODEL_ID);
            Serial.print("Device ID: "); Serial.println(val1);
          
            val1 = read_byte_data_at(VL53L0X_REG_PRE_RANGE_CONFIG_VCSEL_PERIOD);
            Serial.print("PRE_RANGE_CONFIG_VCSEL_PERIOD="); Serial.println(val1);
            Serial.print(" decode: "); Serial.println(VL53L0X_decode_vcsel_period(val1));
          
            val1 = read_byte_data_at(VL53L0X_REG_FINAL_RANGE_CONFIG_VCSEL_PERIOD);
            Serial.print("FINAL_RANGE_CONFIG_VCSEL_PERIOD="); Serial.println(val1);
            Serial.print(" decode: "); Serial.println(VL53L0X_decode_vcsel_period(val1));
          
            write_byte_data_at(VL53L0X_REG_SYSRANGE_START, 0x01);
          
            byte val = 0;
            int cnt = 0;
            while (cnt < 100) { // 1 second waiting time max
              delay(10);
              val = read_byte_data_at(VL53L0X_REG_RESULT_RANGE_STATUS);
              if (val & 0x01) break;
              cnt++;
            }
            if (val & 0x01) Serial.println("ready"); else Serial.println("not ready");
          
            read_block_data_at(0x14, 12);
            uint16_t acnt = makeuint16(gbuf[7], gbuf[6]);
            uint16_t scnt = makeuint16(gbuf[9], gbuf[8]);
            uint16_t dist = makeuint16(gbuf[11], gbuf[10]);
            byte DeviceRangeStatusInternal = ((gbuf[0] & 0x78) >> 3);
          
            Serial.print("ambient count: "); Serial.println(acnt);
            Serial.print("signal count: ");  Serial.println(scnt);
            Serial.print("distance ");       Serial.println(dist);
            Serial.print("status: ");        Serial.println(DeviceRangeStatusInternal);
          }
          
          uint16_t bswap(byte b[]) {
            // Big Endian unsigned short to little endian unsigned short
            uint16_t val = ((b[0] << 8) & b[1]);
            return val;
          }
          
          uint16_t makeuint16(int lsb, int msb) {
            return ((msb & 0xFF) << 8) | (lsb & 0xFF);
          }
          
          void write_byte_data(byte data) {
            Wire.beginTransmission(address);
            Wire.write(data);
            Wire.endTransmission();
          }
          
          void write_byte_data_at(byte reg, byte data) {
            // write data word at address and register
            Wire.beginTransmission(address);
            Wire.write(reg);
            Wire.write(data);
            Wire.endTransmission();
          }
          
          void write_word_data_at(byte reg, uint16_t data) {
            // write data word at address and register
            byte b0 = (data & 0xFF);
            byte b1 = ((data >> 8) && 0xFF);
          
            Wire.beginTransmission(address);
            Wire.write(reg);
            Wire.write(b0);
            Wire.write(b1);
            Wire.endTransmission();
          }
          
          byte read_byte_data() {
            Wire.requestFrom(address, 1);
            while (Wire.available() < 1) delay(1);
            byte b = Wire.read();
            return b;
          }
          
          byte read_byte_data_at(byte reg) {
            //write_byte_data((byte)0x00);
            write_byte_data(reg);
            Wire.requestFrom(address, 1);
            while (Wire.available() < 1) delay(1);
            byte b = Wire.read();
            return b;
          }
          
          uint16_t read_word_data_at(byte reg) {
            write_byte_data(reg);
            Wire.requestFrom(address, 2);
            while (Wire.available() < 2) delay(1);
            gbuf[0] = Wire.read();
            gbuf[1] = Wire.read();
            return bswap(gbuf);
          }
          
          void read_block_data_at(byte reg, int sz) {
            int i = 0;
            write_byte_data(reg);
            Wire.requestFrom(address, sz);
            for (i = 0; i < sz; i++) {
              while (Wire.available() < 1) delay(1);
              gbuf[i] = Wire.read();
            }
          }
          
          uint16_t VL53L0X_decode_vcsel_period(short vcsel_period_reg) {
            // Converts the encoded VCSEL period register value into the real
            // period in PLL clocks
            uint16_t vcsel_period_pclks = (vcsel_period_reg + 1) << 1;
            return vcsel_period_pclks;
          }
          
          1 Reply Last reply Reply Quote 1
          • liemphL
            liemph @MadGeometer
            last edited by liemph

            @madgeometer
            It worked perfectly. This is the serial log I had:

            ----- START TEST ----
            Revision ID: 16
            Device ID: 238
            PRE_RANGE_CONFIG_VCSEL_PERIOD=7
             decode: 16
            FINAL_RANGE_CONFIG_VCSEL_PERIOD=5
             decode: 12
            ready
            ambient count: 46
            signal count: 7
            distance 1854
            status: 11
            ----- END TEST ----
            
            1 Reply Last reply Reply Quote 1
            • M
              MadGeometer
              last edited by

              Thanks for your help guys, I'll give this all a shot!

              1 Reply Last reply Reply Quote 0
              • First post
                Last post