互动陀螺仪 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) | 1 | I2C 接口,9 轴/6 轴 |
| 面包板 | 1 | |
| 公公/公母杜邦线 | 若干 | U 型排线更整洁 |
| 4×AA 电池盒+电池 | 1 | 便携供电 |
项目简介
利用 MPU6050/MPU9250 陀螺仪读取姿态角 (Roll/Pitch/Yaw),在 24 颗 NeoPixel 环上点亮对应倾斜方向的 LED,实现“气泡水平仪”式视觉反馈。适合学习 IMU 姿态解算、DMP 数据融合、NeoPixel 驱动及三角函数映射。
硬件连接 (Fritzing 原理图见附件)
- NeoPixel Ring 焊三针:VCC、GND、DIN → Arduino D6。
- 电池盒焊两根公头杜邦线接面包板电源轨。
- 面包板布局:MPU SDA→A4, SCL→A5;NeoPixel DIN→D6;共地共电。
- 可选:双面胶/扎带固定电池盒于面包板背面,便于手持。


软件准备
- 安装库:
Adafruit_NeoPixel、MPU6050_6Axis_MotionApps20(含 I2Cdev)。 - 代码见 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 的映射数学

将 Roll-Pitch 平面划分四象限,每象限映射 6 颗 LED (共 24)。在象限内,倾斜向量与轴夹角 θ = atan(|Pitch|/|Roll|),经 map() 线性映射至 LED 索引区间。normalize() 引入 LED_OFFSET 修正安装旋转误差。相邻 LED 微亮实现视觉平滑过渡。
原理图文件
Fritzing 源文件:sketch_gMlSrk3rCX.fzz
制造工艺
- Arduino Nano 与 MPU-6050 构建实时陀螺仪游戏
- 用 Adafruit 60 LED NeoPixel 环形灯和 Arduino 制作时尚挂钟
- K30 CO₂ 传感器:室内空气质量实时监测
- 基于 1Sheeld 与 Arduino 的盲聋人士沟通辅助系统
- DIY Arduino USB 游戏手柄 — 自制高性能游戏手柄
- 智能存钱罐:Arduino Nano 控制硬币识别器实现余额显示
- Pixie:基于 Arduino Pro Mini 的 NeoPixel 智能腕表 - 极简 DIY LED 时钟
- Arduino + HC-05 蓝牙控制 LED:MIT App Inventor 手机 App 开发全攻略
- DFRobot 电容指纹传感器 (ID809) 接入 Arduino/ESP8266 完整教程
- 在 Arduino Due 上实现语音识别与语音合成 - BitVoicer Server 方案
- Arduino UNO + 以太网盾板实现低成本太阳辐射测量仪(热电堆原理)
- 智能手语手套:柔性传感器 + 加速度计 + 蓝牙将手势转文字/语音