亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Manufacturing Technology >> 制造工艺

互动陀螺仪 LED 显示:NeoPixel Ring + Arduino Pro Mini

元器件与物料

元器件数量备注
SparkFun Arduino Pro Mini 328 (5V/16MHz)1需 FTDI 下载器
Adafruit NeoPixel Ring (24×WS2812)1单数据线控制
MPU-9250 IMU 模块 (或 MPU6050)1I2C 接口,9 轴/6 轴
面包板1
公公/公母杜邦线若干U 型排线更整洁
4×AA 电池盒+电池1便携供电

项目简介

利用 MPU6050/MPU9250 陀螺仪读取姿态角 (Roll/Pitch/Yaw),在 24 颗 NeoPixel 环上点亮对应倾斜方向的 LED,实现“气泡水平仪”式视觉反馈。适合学习 IMU 姿态解算、DMP 数据融合、NeoPixel 驱动及三角函数映射。

硬件连接 (Fritzing 原理图见附件)

  1. NeoPixel Ring 焊三针:VCC、GND、DIN → Arduino D6。
  2. 电池盒焊两根公头杜邦线接面包板电源轨。
  3. 面包板布局:MPU SDA→A4, SCL→A5;NeoPixel DIN→D6;共地共电。
  4. 可选:双面胶/扎带固定电池盒于面包板背面,便于手持。
互动陀螺仪 LED 显示:NeoPixel Ring + Arduino Pro Mini
互动陀螺仪 LED 显示:NeoPixel Ring + Arduino Pro Mini

软件准备

  1. 安装库:Adafruit_NeoPixel、MPU6050_6Axis_MotionApps20 (含 I2Cdev)。
  2. 代码见 GitHub 或下文完整列出。

校准关键参数

LED_OFFSET (0-23) 决定 0° 方向对应哪颗 LED。上电后观察灯环亮灯方向,调整该值使亮灯方向与板载 IMU 坐标系对齐。

核心代码

#include "I2Cdev.h"
#include <Adafruit_NeoPixel.h>
#include "MPU6050_6Axis_MotionApps20.h"
#include "Wire.h"

#define NEOPIXEL_PIN 6
#define NUM_LEDS 24
const int MAX_ANGLE = 45;
const int LED_OFFSET = 12;  // 需校准

MPU6050 mpu;
Adafruit_NeoPixel strip(NUM_LEDS, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);

unsigned long lastPrint = 0;
bool dmpReady = false;
uint8_t mpuIntStatus, devStatus;
uint16_t packetSize, fifoCount;
uint8_t fifoBuffer[64];
Quaternion q; VectorFloat gravity; float ypr[3];
volatile bool mpuInterrupt = false;

void setup() {
  Serial.begin(9600); Serial.println(F("Program started"));
  dmpReady = initializeGyroscope();
  strip.begin();
}

void loop() {
  if (!dmpReady) return;
  mpuInterrupt = false;
  mpuIntStatus = mpu.getIntStatus();
  fifoCount = mpu.getFIFOCount();
  if (hasFifoOverflown(mpuIntStatus, fifoCount)) { mpu.resetFIFO(); return; }
  if (mpuIntStatus & 0x02) {
    while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
    mpu.getFIFOBytes(fifoBuffer, packetSize);
    fifoCount -= packetSize;
    mpu.dmpGetQuaternion(&q, fifoBuffer);
    mpu.dmpGetGravity(&gravity, &q);
    mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
    redrawLeds(ypr[0]*180/M_PI, ypr[1]*180/M_PI, ypr[2]*180/M_PI);
  }
}

bool hasFifoOverflown(int st, int cnt) { return (st & 0x10) || cnt == 1024; }

void redrawLeds(int yaw, int pitch, int roll) {
  pitch = constrain(pitch, -MAX_ANGLE, MAX_ANGLE);
  roll  = constrain(roll,  -MAX_ANGLE, MAX_ANGLE);
  if (pitch < 0 && roll > 0) lightLeds(pitch, roll, 0,  5, 0, 89);
  else if (pitch < 0 && roll < 0) lightLeds(pitch, roll, 6, 12, 89, 0);
  else if (pitch > 0 && roll < 0) lightLeds(pitch, roll, 13, 19, 0, 89);
  else if (pitch > 0 && roll > 0) lightLeds(pitch, roll, 20, 23, 89, 0);
}

void lightLeds(int p, int r, int fromLed, int toLed, int fromAng, int toAng) {
  double angle = atan(abs(p)/abs(r)) * 4068 / 71; // 近似 180/π * 1000/1000
  int led = map(angle, fromAng, toAng, fromLed, toLed);
  printDebug(p, r, led, angle);
  for (int i=0; i= NUM_LEDS) ? p - NUM_LEDS : p;
}

void printDebug(int p, int r, int led, int ang) {
  if (millis() - lastPrint < 500) return;
  Serial.print(F("a=")); Serial.print(ang); Serial.print(F("; ll=")); Serial.print(led);
  Serial.print(F("; y=")); Serial.print(p); Serial.print(F("; z=")); Serial.println(r);
  lastPrint = millis();
}

bool initializeGyroscope() {
  Wire.begin(); TWBR = 24; // 400kHz I2C
  mpu.initialize();
  Serial.println(mpu.testConnection() ? F("MPU6050 OK") : F("MPU6050 FAIL"));
  Serial.println(F("Init DMP..."));
  devStatus = mpu.dmpInitialize();
  // 以下偏移值需按自校准结果修改
  mpu.setXGyroOffset(220); mpu.setYGyroOffset(76); mpu.setZGyroOffset(-85);
  mpu.setZAccelOffset(1788);
  if (devStatus != 0) { Serial.print(F("DMP fail ")); Serial.println(devStatus); return false; }
  mpu.setDMPEnabled(true);
  attachInterrupt(0, dmpDataReady, RISING); // INT0 = D2
  mpuIntStatus = mpu.getIntStatus();
  Serial.println(F("DMP ready!"));
  packetSize = mpu.dmpGetFIFOPacketSize();
  return true;
}

void dmpDataReady() { mpuInterrupt = true; }

原理深度解析

MPU6050 与 DMP

MEMS 陀螺仪利用科里奥利效应检测角速度,原始数据含噪声与零漂。DMP (Digital Motion Processor) 内置四元数融合算法,输出重力向量与欧拉角,大幅简化主控负担。

NeoPixel 通信

WS2812 单线零码/一码协议,Adafruit 库封装了时序细节,仅需一根数据线即可驱动级联 LED。

角度到 LED 的映射数学

互动陀螺仪 LED 显示:NeoPixel Ring + Arduino Pro Mini

将 Roll-Pitch 平面划分四象限,每象限映射 6 颗 LED (共 24)。在象限内,倾斜向量与轴夹角 θ = atan(|Pitch|/|Roll|),经 map() 线性映射至 LED 索引区间。normalize() 引入 LED_OFFSET 修正安装旋转误差。相邻 LED 微亮实现视觉平滑过渡。

原理图文件

Fritzing 源文件:sketch_gMlSrk3rCX.fzz

制造工艺

  1. Arduino Nano 与 MPU-6050 构建实时陀螺仪游戏
  2. 用 Adafruit 60 LED NeoPixel 环形灯和 Arduino 制作时尚挂钟
  3. K30 CO₂ 传感器:室内空气质量实时监测
  4. 基于 1Sheeld 与 Arduino 的盲聋人士沟通辅助系统
  5. DIY Arduino USB 游戏手柄 — 自制高性能游戏手柄
  6. 智能存钱罐:Arduino Nano 控制硬币识别器实现余额显示
  7. Pixie:基于 Arduino Pro Mini 的 NeoPixel 智能腕表 - 极简 DIY LED 时钟
  8. Arduino + HC-05 蓝牙控制 LED:MIT App Inventor 手机 App 开发全攻略
  9. DFRobot 电容指纹传感器 (ID809) 接入 Arduino/ESP8266 完整教程
  10. 在 Arduino Due 上实现语音识别与语音合成 - BitVoicer Server 方案
  11. Arduino UNO + 以太网盾板实现低成本太阳辐射测量仪(热电堆原理)
  12. 智能手语手套:柔性传感器 + 加速度计 + 蓝牙将手势转文字/语音