这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » M5STACKTAB5开发指南【IMU开发之屏幕旋转自适应】

共1条 1/1 1 跳转至

M5STACKTAB5开发指南【IMU开发之屏幕旋转自适应】

助工
2026-01-13 22:33:49   被打赏 50 分(兑奖)     打赏

一、硬件介绍

Tab5 集成了双芯片架构和丰富的硬件资源,其主控采用基于 RISC‑V 架构的 ESP32‑P4 SoC,并配备 16MB Flash 与 32MB PSRAM,无线模块则选用 ESP32-C6-MINI-1U,支持 Wi-Fi 6;

还配备5英寸(1280×720 IPS)触控屏幕,以及2MP摄像头(1600×1200)、双麦克风阵列,3.5mm耳机孔与扬声器;


内置BMI270六轴传感器、实时时钟,板载HY2.0-4P,M5-Bus,GPIO_EXT排母和microSD卡槽等;

底部兼容NP‑F550可拆卸锂电池(具备充放电与实时监测电路);


image-20260104213126322.png


image-20260104213126322

系统框图

image-20260104223329802.png


image-20260104223329802

二、功能实现





1、硬件介绍

BMI270 六轴姿态传感器

BMI270 是一款超低功耗惯性测量单元(IMU),集成了加速度计和陀螺仪的小型传感器芯片;



BMI270 是一个 6轴传感器,包含:


3轴加速度计: 测量物体在X、Y、Z三个方向上的加速度,用于检测运动、倾斜和震动;

3轴陀螺仪: 测量物体围绕X、Y、Z三个轴旋转的角速度,用于检测旋转和姿态变化;

支持中断唤醒




特性


image-20260109211132951.png



硬件引脚连接


image.png



原理图


image-20260109193942533.png


image-20260109193942533

2、功能效果



在LCD屏幕上显示BMI270传感器获取到的相关数值(加速度计 / 陀螺仪),并根据当前IMU的方向,屏幕显示方向进行自动旋转,当静止一段时间(5s)后关闭屏幕(睡眠模式),当再次检测到有运动时,屏幕才重新点亮;


静止休眠 / 运动唤醒:当静止一段时间后关闭屏幕,当再次检测到有运动时,屏幕重新点亮;

自动旋转:根据设备的握持方向(横屏、竖屏、倒立),自动调整屏幕内容的显示方向;


Accel (加速度计): 测量受力;


Gyro (陀螺仪): 测量旋转角速度;



三、代码编写


读取加速度计的 X 和 Y 轴分量:

  • x > 0.7 或 x < -0.7:判断左右倾斜;

  • y > 0.7 或 y < -0.7:判断上下倾斜;



#include <M5Unified.h>

// 创建画布
M5Canvas canvas(&M5.Display); 
m5::imu_data_t imuData;

// 记录当前的旋转方向
int currentRotation = -1; 

// 休眠功能相关变量
float lastAccX = 0, lastAccY = 0, lastAccZ = 0; // 上一次的加速度值
unsigned long lastActivityTime = 0;             // 最后一次检测到运动的时间
bool isScreenOn = true;                         // 当前屏幕状态

// 参数设置
const float MOVEMENT_THRESHOLD = 0.15;          // 灵敏度:0.15g (自定义)
const unsigned long SLEEP_TIMEOUT_MS = 5000;    // 超时时间:5秒 (自定义)

void setup() {
  M5.begin();
  
  // 初始时 默认方向
  M5.Display.setRotation(1);
  currentRotation = 1;

  // 初始化画布
  canvas.createSprite(M5.Display.width(), M5.Display.height());
  
  // 设置字体和对齐方式
  canvas.setFont(&fonts::FreeMonoBold24pt7b); 
  canvas.setTextDatum(middle_center);
  canvas.setTextColor(WHITE); 

  lastActivityTime = millis();
}

// 自动旋转函数
void autoRotate() {
  float x = imuData.accel.x;
  float y = imuData.accel.y;
  
  int newRotation = currentRotation; 

  if (x > 0.7)       newRotation = 3; 
  else if (x < -0.7) newRotation = 1; 
  else if (y > 0.7)  newRotation = 0; 
  else if (y < -0.7) newRotation = 2; 

  // 重新绘制文本
  if (newRotation != currentRotation) {
    M5.Display.setRotation(newRotation);
    currentRotation = newRotation;
    canvas.deleteSprite(); 
    canvas.createSprite(M5.Display.width(), M5.Display.height());
    canvas.setFont(&fonts::FreeMonoBold24pt7b);
    canvas.setTextDatum(middle_center);
    canvas.setTextColor(WHITE);
  }
}

// 屏幕休眠函数
void checkSleep() {
  // 计算三个轴的变化量
  float deltaX = abs(imuData.accel.x - lastAccX);
  float deltaY = abs(imuData.accel.y - lastAccY);
  float deltaZ = abs(imuData.accel.z - lastAccZ);
  
  // 计算总变化量
  float totalChange = deltaX + deltaY + deltaZ;

  // 判断是否在动
  if (totalChange > MOVEMENT_THRESHOLD) {
    lastActivityTime = millis(); // 刷新计时器

    // 屏幕状态
    if (!isScreenOn) {
      M5.Display.wakeup(); // 唤醒屏幕
      M5.Display.setBrightness(128); // 恢复亮度 (自定义)
      isScreenOn = true;
    }

    lastAccX = imuData.accel.x;
    lastAccY = imuData.accel.y;
    lastAccZ = imuData.accel.z;

  } else {
    if (isScreenOn && (millis() - lastActivityTime > SLEEP_TIMEOUT_MS)) {
      M5.Display.sleep(); // 熄灭屏幕
      isScreenOn = false;
    }
  }
}

void loop() {
  M5.Imu.update();
  imuData = M5.Imu.getImuData();    //获取IMU数值

  // 唤醒检测
  checkSleep();

  // 屏幕亮时,才绘制
  if (isScreenOn) {
    
    // 检查旋转
    autoRotate();

    //屏幕显示 IMU数值
    canvas.fillSprite(BLUE);

    int midX = canvas.width() / 2;
    int midY = canvas.height() / 2;
    int lh = 50; 
    int startY = midY - (lh * 3); 

    char buf[32];

    sprintf(buf, "Acc X: %7.2f", imuData.accel.x);
    canvas.drawString(buf, midX, startY);

    sprintf(buf, "Acc Y: %7.2f", imuData.accel.y);
    canvas.drawString(buf, midX, startY + lh);

    sprintf(buf, "Acc Z: %7.2f", imuData.accel.z);
    canvas.drawString(buf, midX, startY + lh * 2);

    sprintf(buf, "Gyr X: %7.2f", imuData.gyro.x);
    canvas.drawString(buf, midX, startY + lh * 4); 

    sprintf(buf, "Gyr Y: %7.2f", imuData.gyro.y);
    canvas.drawString(buf, midX, startY + lh * 5);

    sprintf(buf, "Gyr Z: %7.2f", imuData.gyro.z);
    canvas.drawString(buf, midX, startY + lh * 6);

    canvas.pushSprite(0, 0);
  }

  delay(100); 
}




四、程序烧录



1、连接USB数据线至开发板;

2、选择端口号对应的开发板;

3、点击 上传 烧录程序到开发板上;


image-20260105170611018.png


image-20260105170611018

五、效果演示


Tab5_IMU.gif











关键词: M5STACK    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]