English
English
简体中文
日本語

Arduino Quick Start

2. Devices & Examples

5. Extensions

6. Applications

Unit DoF6 Arduino Tutorial

1. Preparations

2. Example Program

  • This tutorial uses a CoreS3 as the main controller with a Unit DoF6. The Unit DoF6 communicates over I2C. The default BMI270 address is 0x69, and it can be switched to 0x68 using the onboard switch (the BMI270_ADDRESS in the program must be changed accordingly after switching). After connecting the device, the corresponding pins are G2 (SDA) and G1 (SCL). The example program reads the BMI270's three-axis acceleration, three-axis angular velocity, and temperature data every 500 ms, displays the acceleration, angular velocity, and temperature on the CoreS3 screen as a dashboard, and outputs the same data through the serial port.
cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
#include <M5Unified.h>
#include <M5UnitUnified.h>
#include <M5UnitUnifiedIMU.h>

constexpr uint8_t BMI270_ADDRESS = 0x69;

m5::unit::UnitUnified units;
m5::unit::UnitDoF6 dof6{BMI270_ADDRESS};
m5::imu::imu_convert_param_t convert_param{};

void drawHeader(bool connected) {
    M5.Display.fillScreen(TFT_BLACK);
    M5.Display.setTextSize(1);
    M5.Display.setTextColor(TFT_CYAN, TFT_BLACK);
    M5.Display.setCursor(12, 8);
    M5.Display.print("UNIT DoF6");
    M5.Display.setTextSize(1);
    M5.Display.setTextColor(connected ? TFT_GREEN : TFT_ORANGE, TFT_BLACK);
    M5.Display.setCursor(240, 8);
    M5.Display.print(connected ? "READY" : "WAIT");
}

void drawStatus(const char* message, uint16_t color) {
    M5.Display.fillScreen(TFT_BLACK);
    drawHeader(false);
    M5.Display.setTextSize(1);
    M5.Display.setTextColor(color, TFT_BLACK);
    M5.Display.setCursor(12, 72);
    M5.Display.print(message);
    M5.Display.setTextSize(1);
    M5.Display.setTextColor(TFT_DARKGREY, TFT_BLACK);
    M5.Display.setCursor(12, 108);
    M5.Display.print("I2C 400 kHz");
}

void drawVectorCard(int x, int y, const char* title, const char* unit,
                    float x_value, float y_value, float z_value) {
    // Clear the whole card before redrawing, otherwise old glyphs remain.
    M5.Display.fillRect(x, y - 4, 148, 88, TFT_BLACK);
    M5.Display.setTextSize(1);
    M5.Display.setTextColor(TFT_CYAN, TFT_BLACK);
    M5.Display.setCursor(x + 10, y + 8);
    M5.Display.printf("%s  (%s)   ", title, unit);
    M5.Display.setTextColor(TFT_WHITE, TFT_BLACK);
    M5.Display.setCursor(x + 10, y + 28);
    M5.Display.printf("X  %+8.2f   ", x_value);
    M5.Display.setCursor(x + 10, y + 48);
    M5.Display.printf("Y  %+8.2f   ", y_value);
    M5.Display.setCursor(x + 10, y + 68);
    M5.Display.printf("Z  %+8.2f   ", z_value);
}

void drawData(float ax, float ay, float az, float gx, float gy, float gz, float temperature) {
    M5.Display.startWrite();
    drawVectorCard(8, 48, "ACCEL", "g", ax, ay, az);
    drawVectorCard(164, 48, "GYRO", "dps", gx, gy, gz);
    M5.Display.setTextSize(1);
    M5.Display.setTextColor(TFT_CYAN, TFT_BLACK);
    M5.Display.setCursor(8, 138);
    M5.Display.print("TEMPERATURE");
    M5.Display.setTextColor(TFT_WHITE, TFT_BLACK);
    M5.Display.setTextSize(1);
    M5.Display.setCursor(8, 158);
    M5.Display.printf("%+7.1f C", temperature);
    M5.Display.setTextSize(1);
    M5.Display.setTextColor(TFT_DARKGREY, TFT_BLACK);
    M5.Display.setCursor(12, 218);
    M5.Display.print("LIVE  |  500 ms  |  I2C");
    M5.Display.endWrite();
}

void setup() {
    Serial.begin(115200);
    const uint32_t serial_start = millis();
    while (!Serial && millis() - serial_start < 3000) {
        delay(10);
    }
    Serial.println("Starting Unit DoF6...");

    auto config = M5.config();
    M5.begin(config);
    M5.Display.setFont(&fonts::FreeSansBold9pt7b);
    M5.Display.setTextSize(1);
    M5.Display.setRotation(1);
    M5.Display.setTextWrap(false, false);
    drawStatus("Initializing...", TFT_YELLOW);

    auto cfg = dof6.component_config();
    cfg.clock = 400000;
    dof6.component_config(cfg);

    if (!M5.Ex_I2C.begin() || !units.add(dof6, M5.Ex_I2C) || !units.begin()) {
        while (true) {
            Serial.println("Unit DoF6 not found. Check wiring and BMI270 address.");
            drawStatus("Sensor not found", TFT_ORANGE);
            delay(1000);
        }
    }

    dof6.imuConvertParam(convert_param);
    Serial.printf("Unit DoF6 ready, BMI270 address: 0x%02X\n", BMI270_ADDRESS);
    drawHeader(true);
}

void loop() {
    M5.update();
    units.update();

    static uint32_t last_output = 0;
    if (millis() - last_output < 500) {
        return;
    }
    last_output = millis();

    m5::imu::imu_raw_data_t raw{};
    static bool waiting_shown = false;
    if (m5::imu::any(dof6.readImuRaw(raw))) {
        waiting_shown = false;
        const float ax = raw.accel[0] * convert_param.accel_res;
        const float ay = raw.accel[1] * convert_param.accel_res;
        const float az = raw.accel[2] * convert_param.accel_res;
        const float gx = raw.gyro[0] * convert_param.gyro_res;
        const float gy = raw.gyro[1] * convert_param.gyro_res;
        const float gz = raw.gyro[2] * convert_param.gyro_res;
        const float temperature = raw.temp * convert_param.temp_res + convert_param.temp_offset;

        Serial.printf("Accel: %.3f, %.3f, %.3f g\n",
                      ax, ay, az);
        Serial.printf("Gyro:  %.3f, %.3f, %.3f dps\n",
                      gx, gy, gz);
        Serial.printf("Temperature: %.2f C\n\n", temperature);

        drawData(ax, ay, az, gx, gy, gz, temperature);
    } else {
        if (!waiting_shown) {
            waiting_shown = true;
            Serial.println("Waiting for Unit DoF6 data...");
            drawStatus("Waiting for data...", TFT_YELLOW);
        }
    }
}

3. Compile and Upload

  • Copy and paste the example code above into the project code area, select the device port (for details, refer to Compile and Upload the Program), click the compile and upload button in the upper-left corner of the Arduino IDE, and wait for the program to compile and upload to the device.

4. Attitude Data Reading

  • After the program starts, the screen refreshes the three-axis acceleration, three-axis angular velocity, and temperature data every 500 ms, and the serial monitor outputs the corresponding values at the same time.
Page Tools
PDF
On This Page