1. 项目概述当骰子“学会”自己报数几年前我在一个线下桌游吧里看到一群朋友为了一个骰子的点数争论不休——骰子滚到了沙发底下谁也不知道到底是几点。当时我就在想要是骰子自己能“告诉”我们结果就好了。这个念头加上手头闲置的Arduino和几个传感器就成了今天这个项目的起点一个能远程读取并物理指示点数的智能骰子。本质上这是一个典型的“感知-决策-执行”物联网闭环系统。核心逻辑很简单一个内置的陀螺仪我们选用常见的MPU-6050实时感知骰子在空间中的姿态一块微控制器这里用了性能更强的Teensy 3.2但原理通用解读这些数据判断出哪一面朝上最后通过继电器控制对应的微型电磁阀也叫螺线管从骰子外部将代表点数的柱塞推出来实现物理“报数”。比如如果朝上的是5点那么控制“2”和“3”点的两个电磁阀就会同时动作。这个项目麻雀虽小五脏俱全。它涵盖了嵌入式系统开发的多个核心环节传感器数据采集与融合、微控制器编程、功率驱动电路设计继电器控制电磁阀、以及结构设计与集成3D打印外壳。无论你是刚接触Arduino的新手想通过一个有趣的项目串联起知识点还是有一定经验的开发者希望探索传感器与执行器的联动这个“远程骰子读取器”都是一个绝佳的练手平台。下面我就把从电路焊接、代码调试到机械组装的所有细节和踩过的坑毫无保留地分享给你。2. 核心硬件选型与电路设计解析做硬件项目第一步永远是搞清楚你要用什么以及为什么用它们。盲目堆料只会增加成本和复杂度。这个项目的硬件清单不长但每一样都有其不可替代的作用。2.1 传感器与主控为什么是MPU-6050和Teensy 3.2MPU-6050陀螺仪几乎是入门姿态传感器的代名词。它集成了三轴陀螺仪和三轴加速度计能通过I2C总线提供物体的角速度和加速度原始数据。对于骰子这种需要检测静止姿态哪面朝上的应用加速度计的数据是关键——它能够感知重力加速度的方向。虽然MPU-6050本身不直接输出“欧拉角”即滚转、俯仰、偏航角但通过库函数如MPU6050_6Axis_MotionApps20.h可以获取解算后的四元数再转换成我们容易理解的姿态角。它的性价比和社区支持度资料、库极其丰富是选择它的首要原因。注意MPU-6050模块通常需要正确焊接或插接。其I2C接口的引脚SDA, SCL需要连接到微控制器对应的I2C引脚上VCC接3.3V或5V需与主控逻辑电平匹配GND接地。模块上的AD0引脚用于设置I2C地址悬空或接地时地址为0x68。主控芯片的选择上原项目使用了Arduino Teensy 3.2。Teensy是Arduino兼容板中的“性能小钢炮”基于ARM Cortex-M4内核主频高达72MHz远超普通的ATmega328P16MHz。为什么需要这么强的性能因为实时解算MPU-6050的原始数据尤其是使用DMP数字运动处理器功能并进行四元数运算需要一定的计算能力。Teensy能确保姿态解算的实时性和稳定性避免卡顿。当然如果你手头只有经典的Arduino Uno也是完全可以完成的只需注意代码效率避免使用过于复杂的滤波算法。2.2 执行机构电磁阀与继电器驱动电路详解这是将电信号转化为物理动作的关键一步。电磁阀螺线管我们选用的是Deltrol Controls 56597-60 INT这类微型推拉式电磁阀。它的工作原理是通电后线圈产生磁场吸合内部的铁芯柱塞产生直线运动。断电后依靠弹簧复位。我们需要用它来推动骰子表面的点数柱塞。选择时需关注几个参数工作电压需与驱动电压匹配、行程柱塞能伸出多长、以及力量能否可靠推动柱塞。核心问题Arduino不能直接驱动电磁阀。Arduino的GPIO引脚只能提供最大40mA的电流而电磁阀工作电流往往在几百毫安以上。直接连接会烧毁引脚甚至主控芯片。因此我们必须引入继电器作为驱动开关。继电器MEDER Electronic DIP05-1A57-BV350在这里扮演了“电子开关”的角色。它是一个利用小电流控制大电流通断的器件。我们的电路设计如下控制端线圈连接Arduino的数字输出引脚和地。当Arduino引脚输出高电平如5V时继电器线圈得电内部开关吸合。被控端触点这是一个独立的电路。一端连接外部电源如9V电池的正极另一端连接电磁阀的一端。电磁阀的另一端直接连到电源负极。工作原理当Arduino给继电器控制端高电平时继电器触点闭合外部电源-电磁阀-地的回路导通电磁阀动作。Arduino只负责提供几毫安的控制电流大电流由外部电源承担完美隔离。实操心得继电器有常开NO、常闭NC、公共端COM三个触点。我们通常使用常开端。接线时务必区分线圈引脚和触点引脚接反了无法工作。另外为保护Arduino引脚防止继电器线圈断电时产生的反向电动势冲击建议在线圈两端并联一个续流二极管如1N4007阴极接电源正阳极接地。电源方案电磁阀驱动电源选用9V电池方便独立供电。整个系统的电源管理可以这样设计9V电池单独为三个电磁阀供电同时可以通过一个降压模块如LM7805将9V降为5V为Arduino和MPU-6050供电。如果使用Teensy 3.2工作电压3.3V则需要使用降压到3.3V的模块。务必确保逻辑电平一致。3. 软件逻辑与代码实现深度剖析硬件是骨架软件才是灵魂。这个项目的代码核心在于姿态解算和状态映射。3.1 姿态感知从原始数据到骰子朝向MPU-6050输出的是原始的角速度和加速度数据。要得到稳定的姿态我们需要进行传感器数据融合。最便捷的方法是使用MPU-6050内置的DMP。DMP是一个专用于运动处理的微处理器它能直接在传感器内部完成复杂的四元数解算极大减轻主控的负担。在Arduino IDE中我们需要安装Adafruit MPU6050库以及Adafruit_Sensor库。初始化DMP后我们可以直接读取到四元数q.w, q.x, q.y, q.z。四元数是一种描述三维旋转的数学工具比欧拉角更能避免“万向节死锁”问题。接下来的关键是将四元数转换为骰子具体的“哪一面朝上”。骰子有6个面每个面对应一个唯一的空间法向量方向。例如当“1点”面朝上时该面的法向量垂直于面向外大致指向正上方。我们可以通过计算当前传感器坐标系下的“上”向量通常由加速度计数据或从四元数推导出的旋转矩阵的某一列表示与6个预设的法向量之间的夹角找到夹角最小的那个面即为朝上的面。// 伪代码示例简化版的方向判断思路 #include MPU6050_6Axis_MotionApps20.h MPU6050 mpu; void loop() { // ... 获取四元数 q ... // 将四元数转换为旋转矩阵或直接计算“上”向量 // 定义6个面的单位法向量基于你的骰子初始校准方向 float faceVectors[6][3] { {0, 0, 1}, {0, 0, -1}, {1, 0, 0}, {-1, 0, 0}, {0, 1, 0}, {0, -1, 0} }; float upVector[3]; // 根据四元数计算当前向上的向量 upVector computeUpVector(q, upVector); int faceUp 0; float maxDot -1; for (int i 0; i 6; i) { float dotProduct upVector[0]*faceVectors[i][0] upVector[1]*faceVectors[i][1] upVector[2]*faceVectors[i][2]; if (dotProduct maxDot) { maxDot dotProduct; faceUp i 1; // 假设i0对应1点面 } } // 此时 faceUp 存储了朝上的点数1-6 }3.2 执行控制点数到电磁阀的映射与驱动判断出点数后需要控制对应的电磁阀。一个标准的骰子其点数的布局是固定的相对两面点数之和为71-6, 2-5, 3-4。但我们只在外壳的特定位置安装了3个电磁阀如何表示6个数字这里用到了一个巧妙的二进制表示思路。我们使用三个电磁阀分别代表二进制权值1、2、4。通过它们的组合可以表示1到72^3 -1的所有数字。对于骰子点数1点仅电磁阀1动作 (001)2点仅电磁阀2动作 (010)3点电磁阀1和2动作 (011)4点仅电磁阀3动作 (100)5点电磁阀1和3动作 (101)6点电磁阀2和3动作 (110)这样我们只需要三个电磁阀就能覆盖所有情况。代码实现就是简单的位操作。// 定义电磁阀控制引脚 const int solenoidPin1 2; // 权值1 const int solenoidPin2 4; // 权值2 const int solenoidPin3 6; // 权值4 void activateSolenoidsForFace(int face) { // 先关闭所有电磁阀 digitalWrite(solenoidPin1, LOW); digitalWrite(solenoidPin2, LOW); digitalWrite(solenoidPin3, LOW); // 根据点数决定哪些引脚输出HIGH switch(face) { case 1: digitalWrite(solenoidPin1, HIGH); break; case 2: digitalWrite(solenoidPin2, HIGH); break; case 3: digitalWrite(solenoidPin1, HIGH); digitalWrite(solenoidPin2, HIGH); break; case 4: digitalWrite(solenoidPin3, HIGH); break; case 5: digitalWrite(solenoidPin1, HIGH); digitalWrite(solenoidPin3, HIGH); break; case 6: digitalWrite(solenoidPin2, HIGH); digitalWrite(solenoidPin3, HIGH); break; default: break; // 点数错误全部关闭 } // 电磁阀动作后需要保持一段时间再关闭以让用户看清 delay(1000); // 保持1秒 // 然后循环会再次执行关闭所有电磁阀等待下一次掷骰 }注意事项电磁阀是感性负载不宜长时间通电否则线圈会过热损坏。因此代码中采用触发后短时保持如1秒再关闭的策略。同时频繁开关也可能缩短寿命需根据实际使用频率权衡。4. 机械结构设计与3D打印实践硬件和软件需要在物理外壳内协同工作。这个外壳需要容纳Arduino、面包板、电池、三个电磁阀并且为骰子本身提供一个放置和自由滚动的空间。4.1 3D模型设计要点设计模型时我使用了Fusion 360。核心考虑以下几点分层结构外壳分为底座和上盖。底座用于固定所有电路和电源上盖则用于安装电磁阀和作为骰子的“舞台”。电磁阀安装位在上盖内侧需要精确设计三个圆柱形安装孔位置与骰子表面的点数位置对应。孔的大小需要与电磁阀壳体过盈配合可以用胶水加固。同时柱塞伸出的正前方需要开小孔让柱塞能刚好顶到骰子表面。骰子活动腔外壳内部需要有一个足够大的空腔让内置陀螺仪的骰子能自由滚动和稳定停驻。腔体顶部即上盖内侧应平整确保骰子停下时只有一个面完全贴合。走线与维护开口需要设计合理的线槽让陀螺仪的导线从骰子腔连接到底座电路区。底座侧面或底部应开孔用于USB编程线、电源开关如果添加的接入。防呆与固定设计卡扣或螺丝柱确保上盖和底座能牢固结合防止骰子滚动时震开。4.2 3D打印与后处理将设计好的模型导出为STL或3MF格式导入切片软件如Cura, PrusaSlicer。打印参数建议材料PLA即可强度足够易于打印。层高0.2mm在打印质量和时间间取得平衡。填充率15%-20%外壳不需要实心。支撑对于电磁阀安装孔等悬空结构需要生成支撑。记得在打印后仔细拆除。打印完成后后处理至关重要打磨用砂纸仔细打磨电磁阀柱塞伸出孔的内壁确保光滑减少柱塞运动时的摩擦阻力。试装配不要急着上胶水。先进行试装配确保骰子能在腔内自由滚动且不会卡住电磁阀柱塞能准确对准骰子点数位置。固定陀螺仪将MPU-6050模块用热熔胶或蓝丁胶固定在骰子模型内部中心位置。这里用蓝丁胶是个好选择既能固定又能缓冲震动。正如原项目提到的可以在骰子空腔内适当增加配重如粘土降低重心使骰子更容易稳定也减少连接线对骰子滚动的影响。5. 系统集成、校准与调试全记录这是将电子、代码和机械部分组装起来并让它“聪明”起来的过程也是最容易出问题的阶段。5.1 电路焊接与集成按照之前的电路图在面包板上搭建系统。建议遵循以下顺序先连接主控与传感器将MPU-6050的VCC、GND、SDA、SCL分别连接到Teensy的3.3V、GND、对应的I2C引脚Teensy 3.2的引脚17-SDA0, 18-SCL0。确保连接牢固。再搭建继电器驱动电路为每个继电器准备一个独立的驱动电路。以一路为例Arduino数字引脚 - 继电器模块信号输入引脚IN。继电器模块VCC接Arduino 5VGND接Arduino GND。继电器模块的常开NO和公共端COM接入电磁阀驱动回路9V电池正极 - COM端 - NO端 - 电磁阀线圈 - 9V电池负极。务必在继电器线圈两端并联续流二极管。最后连接电源确保逻辑电源给Arduino、传感器和驱动电源给电磁阀的“地”GND连接在一起即“共地”这是电路正常工作的基础。踩坑实录我第一次组装时电磁阀死活不动作。排查了半天发现是继电器模块的“高电平触发”和“低电平触发”模式没搞清。有些继电器模块有跳线帽选择务必根据说明书设置成与Arduino输出一致通常是高电平触发。用万用表通断档测试当给控制信号时听继电器是否有“咔嗒”声并测量触点是否导通这是最直接的排查方法。5.2 软件校准最关键的“教骰子认面”这是整个项目最精细的一步。你需要告诉系统当骰子以某个姿态静止时它对应的四元数数据是什么应该触发哪几个电磁阀。校准步骤上传基础代码先上传一个能读取MPU-6050四元数并通过串口打印出来的程序。确保传感器工作正常。固定初始姿态将骰子小心地以“1点”面朝上平稳地放在外壳腔体内。记录此时串口监视器打印出的稳定的四元数值q.w, q.x, q.y, q.z。这个姿态就是你的“参考零点”。修改判断逻辑在你的主代码中将读取到的实时四元数与这个“1点”面的参考四元数进行比较。但由于四元数表示旋转直接比较数值不直观。更实用的方法是像前面所述计算当前姿态的“上”向量。在校准阶段你需要记录六个面分别朝上时的“上”向量或对应的四元数。编写判断函数在代码中预设这六个参考向量。在循环中计算当前实时四元数对应的“上”向量然后计算这个向量与六个参考向量的点积夹角余弦。点积最大的那个参考向量对应的面就是当前朝上的面。映射测试依次将骰子每个面朝上放置观察串口输出的判断结果是否正确同时观察对应的电磁阀是否被触发。如果不正确检查参考向量数据是否记录准确或者传感器是否安装牢固、有无松动。高级技巧由于传感器安装偏差、骰子内部配重不均等因素实际静止时计算出的方向可能会有轻微波动。可以在代码中加入阈值判断和去抖。例如只有当某个方向持续稳定200毫秒以上才确认为最终结果并触发一次电磁阀动作避免在骰子翻滚过程中误触发。5.3 总装与功能测试当电路、代码、外壳都准备好后进行总装将面包板、电池等用尼龙扎带或双面胶固定在底座内。将电磁阀插入上盖的安装孔并用强力胶如环氧树脂从内部加固。连接电磁阀与底座内继电器的导线留出适当长度保证上盖能开合。将内置陀螺仪的骰子放入腔体并将其数据线穿过预留的线槽连接到底座的MPU-6050接口上。合上上盖紧固螺丝或卡扣。进行最终测试摇晃外壳让骰子滚动后静止观察对应的点数电磁阀是否迅速、准确地弹出。测试各个面。6. 常见问题排查与项目优化方向即使按照步骤操作你也可能会遇到一些问题。这里列出一些常见故障和解决方法问题现象可能原因排查步骤与解决方案电磁阀完全不动作1. 电源问题2. 继电器未吸合3. 控制信号问题1. 用万用表测量9V电池电压检查电磁阀回路通断。2. 给继电器控制脚直接接高电平听是否有“咔嗒”声测触点通断。3. 用digitalWrite和delay写一个简单测试程序用LED或万用表测量Arduino控制引脚是否有输出。电磁阀随机误动作1. 继电器控制线受到干扰2. 电源波动3. 代码逻辑错误1. 缩短连接线或使用双绞线。在继电器控制端和地之间加一个104瓷片电容滤波。2. 为驱动电源9V电池并联一个大电容如470uF稳压。3. 检查姿态判断代码加入稳定延时和阈值判断避免数据抖动导致误判。姿态判断不准1. MPU-6050未校准2. 参考姿态数据记录不准3. 骰子滚动未停止就判断1. 运行MPU-6050的校准例程获取偏移量并写入代码。2. 重新执行校准步骤确保骰子绝对静止时记录数据。3. 在代码中增加检测当角速度gyro读数连续若干次接近零时才认为骰子静止开始判断姿态。骰子滚动不自然或卡住1. 内部导线缠绕2. 腔体空间过小或不平3. 配重不当1. 重新整理和固定骰子内部的陀螺仪导线尽量短且不影响重心。2. 检查并打磨3D打印腔体内部确保光滑无毛刺。3. 调整骰子内的配重蓝丁胶使其重心居中滚动更随机。这个项目本身已经完成了一个完整的闭环但它还有巨大的扩展潜力无线化将Teensy换成ESP32或Arduino HC-05蓝牙模块通过蓝牙将骰子点数发送到手机APP或电脑上显示实现真正的“远程”读取而不仅仅是物理指示。多骰子与游戏逻辑扩展系统同时支持多个智能骰子并编写简单的游戏逻辑如骰子游戏“快艇骰子”自动计算分数。可视化与记录在上盖增加LED灯环根据点数点亮不同区域。或者将每次投掷的结果和时间戳通过Wi-Fi上传到服务器形成游戏记录。结构优化设计更精巧的磁吸充电接口解决骰子供电问题。或者尝试使用微型振动电机代替电磁阀实现更安静的“触觉反馈”式报数。这个项目最让我着迷的地方在于它用一个具体的、有趣的载体把嵌入式开发中那些抽象的概念——传感器采样、数据滤波、状态机、驱动电路——都串联了起来。调试过程中看着骰子终于能准确响应不同朝向那种成就感远超单纯点亮一个LED。硬件项目的魅力就在于你的代码和逻辑最终在物理世界得到了实实在在的回响。希望你在复现和改造这个项目的过程中也能体验到这种乐趣。如果在制作中遇到任何问题不妨回头检查一下电源、地线和传感器的校准这三个往往是大多数问题的根源。
基于MPU-6050与Arduino的智能骰子:嵌入式系统全栈开发实践
发布时间:2026/5/30 23:34:23
1. 项目概述当骰子“学会”自己报数几年前我在一个线下桌游吧里看到一群朋友为了一个骰子的点数争论不休——骰子滚到了沙发底下谁也不知道到底是几点。当时我就在想要是骰子自己能“告诉”我们结果就好了。这个念头加上手头闲置的Arduino和几个传感器就成了今天这个项目的起点一个能远程读取并物理指示点数的智能骰子。本质上这是一个典型的“感知-决策-执行”物联网闭环系统。核心逻辑很简单一个内置的陀螺仪我们选用常见的MPU-6050实时感知骰子在空间中的姿态一块微控制器这里用了性能更强的Teensy 3.2但原理通用解读这些数据判断出哪一面朝上最后通过继电器控制对应的微型电磁阀也叫螺线管从骰子外部将代表点数的柱塞推出来实现物理“报数”。比如如果朝上的是5点那么控制“2”和“3”点的两个电磁阀就会同时动作。这个项目麻雀虽小五脏俱全。它涵盖了嵌入式系统开发的多个核心环节传感器数据采集与融合、微控制器编程、功率驱动电路设计继电器控制电磁阀、以及结构设计与集成3D打印外壳。无论你是刚接触Arduino的新手想通过一个有趣的项目串联起知识点还是有一定经验的开发者希望探索传感器与执行器的联动这个“远程骰子读取器”都是一个绝佳的练手平台。下面我就把从电路焊接、代码调试到机械组装的所有细节和踩过的坑毫无保留地分享给你。2. 核心硬件选型与电路设计解析做硬件项目第一步永远是搞清楚你要用什么以及为什么用它们。盲目堆料只会增加成本和复杂度。这个项目的硬件清单不长但每一样都有其不可替代的作用。2.1 传感器与主控为什么是MPU-6050和Teensy 3.2MPU-6050陀螺仪几乎是入门姿态传感器的代名词。它集成了三轴陀螺仪和三轴加速度计能通过I2C总线提供物体的角速度和加速度原始数据。对于骰子这种需要检测静止姿态哪面朝上的应用加速度计的数据是关键——它能够感知重力加速度的方向。虽然MPU-6050本身不直接输出“欧拉角”即滚转、俯仰、偏航角但通过库函数如MPU6050_6Axis_MotionApps20.h可以获取解算后的四元数再转换成我们容易理解的姿态角。它的性价比和社区支持度资料、库极其丰富是选择它的首要原因。注意MPU-6050模块通常需要正确焊接或插接。其I2C接口的引脚SDA, SCL需要连接到微控制器对应的I2C引脚上VCC接3.3V或5V需与主控逻辑电平匹配GND接地。模块上的AD0引脚用于设置I2C地址悬空或接地时地址为0x68。主控芯片的选择上原项目使用了Arduino Teensy 3.2。Teensy是Arduino兼容板中的“性能小钢炮”基于ARM Cortex-M4内核主频高达72MHz远超普通的ATmega328P16MHz。为什么需要这么强的性能因为实时解算MPU-6050的原始数据尤其是使用DMP数字运动处理器功能并进行四元数运算需要一定的计算能力。Teensy能确保姿态解算的实时性和稳定性避免卡顿。当然如果你手头只有经典的Arduino Uno也是完全可以完成的只需注意代码效率避免使用过于复杂的滤波算法。2.2 执行机构电磁阀与继电器驱动电路详解这是将电信号转化为物理动作的关键一步。电磁阀螺线管我们选用的是Deltrol Controls 56597-60 INT这类微型推拉式电磁阀。它的工作原理是通电后线圈产生磁场吸合内部的铁芯柱塞产生直线运动。断电后依靠弹簧复位。我们需要用它来推动骰子表面的点数柱塞。选择时需关注几个参数工作电压需与驱动电压匹配、行程柱塞能伸出多长、以及力量能否可靠推动柱塞。核心问题Arduino不能直接驱动电磁阀。Arduino的GPIO引脚只能提供最大40mA的电流而电磁阀工作电流往往在几百毫安以上。直接连接会烧毁引脚甚至主控芯片。因此我们必须引入继电器作为驱动开关。继电器MEDER Electronic DIP05-1A57-BV350在这里扮演了“电子开关”的角色。它是一个利用小电流控制大电流通断的器件。我们的电路设计如下控制端线圈连接Arduino的数字输出引脚和地。当Arduino引脚输出高电平如5V时继电器线圈得电内部开关吸合。被控端触点这是一个独立的电路。一端连接外部电源如9V电池的正极另一端连接电磁阀的一端。电磁阀的另一端直接连到电源负极。工作原理当Arduino给继电器控制端高电平时继电器触点闭合外部电源-电磁阀-地的回路导通电磁阀动作。Arduino只负责提供几毫安的控制电流大电流由外部电源承担完美隔离。实操心得继电器有常开NO、常闭NC、公共端COM三个触点。我们通常使用常开端。接线时务必区分线圈引脚和触点引脚接反了无法工作。另外为保护Arduino引脚防止继电器线圈断电时产生的反向电动势冲击建议在线圈两端并联一个续流二极管如1N4007阴极接电源正阳极接地。电源方案电磁阀驱动电源选用9V电池方便独立供电。整个系统的电源管理可以这样设计9V电池单独为三个电磁阀供电同时可以通过一个降压模块如LM7805将9V降为5V为Arduino和MPU-6050供电。如果使用Teensy 3.2工作电压3.3V则需要使用降压到3.3V的模块。务必确保逻辑电平一致。3. 软件逻辑与代码实现深度剖析硬件是骨架软件才是灵魂。这个项目的代码核心在于姿态解算和状态映射。3.1 姿态感知从原始数据到骰子朝向MPU-6050输出的是原始的角速度和加速度数据。要得到稳定的姿态我们需要进行传感器数据融合。最便捷的方法是使用MPU-6050内置的DMP。DMP是一个专用于运动处理的微处理器它能直接在传感器内部完成复杂的四元数解算极大减轻主控的负担。在Arduino IDE中我们需要安装Adafruit MPU6050库以及Adafruit_Sensor库。初始化DMP后我们可以直接读取到四元数q.w, q.x, q.y, q.z。四元数是一种描述三维旋转的数学工具比欧拉角更能避免“万向节死锁”问题。接下来的关键是将四元数转换为骰子具体的“哪一面朝上”。骰子有6个面每个面对应一个唯一的空间法向量方向。例如当“1点”面朝上时该面的法向量垂直于面向外大致指向正上方。我们可以通过计算当前传感器坐标系下的“上”向量通常由加速度计数据或从四元数推导出的旋转矩阵的某一列表示与6个预设的法向量之间的夹角找到夹角最小的那个面即为朝上的面。// 伪代码示例简化版的方向判断思路 #include MPU6050_6Axis_MotionApps20.h MPU6050 mpu; void loop() { // ... 获取四元数 q ... // 将四元数转换为旋转矩阵或直接计算“上”向量 // 定义6个面的单位法向量基于你的骰子初始校准方向 float faceVectors[6][3] { {0, 0, 1}, {0, 0, -1}, {1, 0, 0}, {-1, 0, 0}, {0, 1, 0}, {0, -1, 0} }; float upVector[3]; // 根据四元数计算当前向上的向量 upVector computeUpVector(q, upVector); int faceUp 0; float maxDot -1; for (int i 0; i 6; i) { float dotProduct upVector[0]*faceVectors[i][0] upVector[1]*faceVectors[i][1] upVector[2]*faceVectors[i][2]; if (dotProduct maxDot) { maxDot dotProduct; faceUp i 1; // 假设i0对应1点面 } } // 此时 faceUp 存储了朝上的点数1-6 }3.2 执行控制点数到电磁阀的映射与驱动判断出点数后需要控制对应的电磁阀。一个标准的骰子其点数的布局是固定的相对两面点数之和为71-6, 2-5, 3-4。但我们只在外壳的特定位置安装了3个电磁阀如何表示6个数字这里用到了一个巧妙的二进制表示思路。我们使用三个电磁阀分别代表二进制权值1、2、4。通过它们的组合可以表示1到72^3 -1的所有数字。对于骰子点数1点仅电磁阀1动作 (001)2点仅电磁阀2动作 (010)3点电磁阀1和2动作 (011)4点仅电磁阀3动作 (100)5点电磁阀1和3动作 (101)6点电磁阀2和3动作 (110)这样我们只需要三个电磁阀就能覆盖所有情况。代码实现就是简单的位操作。// 定义电磁阀控制引脚 const int solenoidPin1 2; // 权值1 const int solenoidPin2 4; // 权值2 const int solenoidPin3 6; // 权值4 void activateSolenoidsForFace(int face) { // 先关闭所有电磁阀 digitalWrite(solenoidPin1, LOW); digitalWrite(solenoidPin2, LOW); digitalWrite(solenoidPin3, LOW); // 根据点数决定哪些引脚输出HIGH switch(face) { case 1: digitalWrite(solenoidPin1, HIGH); break; case 2: digitalWrite(solenoidPin2, HIGH); break; case 3: digitalWrite(solenoidPin1, HIGH); digitalWrite(solenoidPin2, HIGH); break; case 4: digitalWrite(solenoidPin3, HIGH); break; case 5: digitalWrite(solenoidPin1, HIGH); digitalWrite(solenoidPin3, HIGH); break; case 6: digitalWrite(solenoidPin2, HIGH); digitalWrite(solenoidPin3, HIGH); break; default: break; // 点数错误全部关闭 } // 电磁阀动作后需要保持一段时间再关闭以让用户看清 delay(1000); // 保持1秒 // 然后循环会再次执行关闭所有电磁阀等待下一次掷骰 }注意事项电磁阀是感性负载不宜长时间通电否则线圈会过热损坏。因此代码中采用触发后短时保持如1秒再关闭的策略。同时频繁开关也可能缩短寿命需根据实际使用频率权衡。4. 机械结构设计与3D打印实践硬件和软件需要在物理外壳内协同工作。这个外壳需要容纳Arduino、面包板、电池、三个电磁阀并且为骰子本身提供一个放置和自由滚动的空间。4.1 3D模型设计要点设计模型时我使用了Fusion 360。核心考虑以下几点分层结构外壳分为底座和上盖。底座用于固定所有电路和电源上盖则用于安装电磁阀和作为骰子的“舞台”。电磁阀安装位在上盖内侧需要精确设计三个圆柱形安装孔位置与骰子表面的点数位置对应。孔的大小需要与电磁阀壳体过盈配合可以用胶水加固。同时柱塞伸出的正前方需要开小孔让柱塞能刚好顶到骰子表面。骰子活动腔外壳内部需要有一个足够大的空腔让内置陀螺仪的骰子能自由滚动和稳定停驻。腔体顶部即上盖内侧应平整确保骰子停下时只有一个面完全贴合。走线与维护开口需要设计合理的线槽让陀螺仪的导线从骰子腔连接到底座电路区。底座侧面或底部应开孔用于USB编程线、电源开关如果添加的接入。防呆与固定设计卡扣或螺丝柱确保上盖和底座能牢固结合防止骰子滚动时震开。4.2 3D打印与后处理将设计好的模型导出为STL或3MF格式导入切片软件如Cura, PrusaSlicer。打印参数建议材料PLA即可强度足够易于打印。层高0.2mm在打印质量和时间间取得平衡。填充率15%-20%外壳不需要实心。支撑对于电磁阀安装孔等悬空结构需要生成支撑。记得在打印后仔细拆除。打印完成后后处理至关重要打磨用砂纸仔细打磨电磁阀柱塞伸出孔的内壁确保光滑减少柱塞运动时的摩擦阻力。试装配不要急着上胶水。先进行试装配确保骰子能在腔内自由滚动且不会卡住电磁阀柱塞能准确对准骰子点数位置。固定陀螺仪将MPU-6050模块用热熔胶或蓝丁胶固定在骰子模型内部中心位置。这里用蓝丁胶是个好选择既能固定又能缓冲震动。正如原项目提到的可以在骰子空腔内适当增加配重如粘土降低重心使骰子更容易稳定也减少连接线对骰子滚动的影响。5. 系统集成、校准与调试全记录这是将电子、代码和机械部分组装起来并让它“聪明”起来的过程也是最容易出问题的阶段。5.1 电路焊接与集成按照之前的电路图在面包板上搭建系统。建议遵循以下顺序先连接主控与传感器将MPU-6050的VCC、GND、SDA、SCL分别连接到Teensy的3.3V、GND、对应的I2C引脚Teensy 3.2的引脚17-SDA0, 18-SCL0。确保连接牢固。再搭建继电器驱动电路为每个继电器准备一个独立的驱动电路。以一路为例Arduino数字引脚 - 继电器模块信号输入引脚IN。继电器模块VCC接Arduino 5VGND接Arduino GND。继电器模块的常开NO和公共端COM接入电磁阀驱动回路9V电池正极 - COM端 - NO端 - 电磁阀线圈 - 9V电池负极。务必在继电器线圈两端并联续流二极管。最后连接电源确保逻辑电源给Arduino、传感器和驱动电源给电磁阀的“地”GND连接在一起即“共地”这是电路正常工作的基础。踩坑实录我第一次组装时电磁阀死活不动作。排查了半天发现是继电器模块的“高电平触发”和“低电平触发”模式没搞清。有些继电器模块有跳线帽选择务必根据说明书设置成与Arduino输出一致通常是高电平触发。用万用表通断档测试当给控制信号时听继电器是否有“咔嗒”声并测量触点是否导通这是最直接的排查方法。5.2 软件校准最关键的“教骰子认面”这是整个项目最精细的一步。你需要告诉系统当骰子以某个姿态静止时它对应的四元数数据是什么应该触发哪几个电磁阀。校准步骤上传基础代码先上传一个能读取MPU-6050四元数并通过串口打印出来的程序。确保传感器工作正常。固定初始姿态将骰子小心地以“1点”面朝上平稳地放在外壳腔体内。记录此时串口监视器打印出的稳定的四元数值q.w, q.x, q.y, q.z。这个姿态就是你的“参考零点”。修改判断逻辑在你的主代码中将读取到的实时四元数与这个“1点”面的参考四元数进行比较。但由于四元数表示旋转直接比较数值不直观。更实用的方法是像前面所述计算当前姿态的“上”向量。在校准阶段你需要记录六个面分别朝上时的“上”向量或对应的四元数。编写判断函数在代码中预设这六个参考向量。在循环中计算当前实时四元数对应的“上”向量然后计算这个向量与六个参考向量的点积夹角余弦。点积最大的那个参考向量对应的面就是当前朝上的面。映射测试依次将骰子每个面朝上放置观察串口输出的判断结果是否正确同时观察对应的电磁阀是否被触发。如果不正确检查参考向量数据是否记录准确或者传感器是否安装牢固、有无松动。高级技巧由于传感器安装偏差、骰子内部配重不均等因素实际静止时计算出的方向可能会有轻微波动。可以在代码中加入阈值判断和去抖。例如只有当某个方向持续稳定200毫秒以上才确认为最终结果并触发一次电磁阀动作避免在骰子翻滚过程中误触发。5.3 总装与功能测试当电路、代码、外壳都准备好后进行总装将面包板、电池等用尼龙扎带或双面胶固定在底座内。将电磁阀插入上盖的安装孔并用强力胶如环氧树脂从内部加固。连接电磁阀与底座内继电器的导线留出适当长度保证上盖能开合。将内置陀螺仪的骰子放入腔体并将其数据线穿过预留的线槽连接到底座的MPU-6050接口上。合上上盖紧固螺丝或卡扣。进行最终测试摇晃外壳让骰子滚动后静止观察对应的点数电磁阀是否迅速、准确地弹出。测试各个面。6. 常见问题排查与项目优化方向即使按照步骤操作你也可能会遇到一些问题。这里列出一些常见故障和解决方法问题现象可能原因排查步骤与解决方案电磁阀完全不动作1. 电源问题2. 继电器未吸合3. 控制信号问题1. 用万用表测量9V电池电压检查电磁阀回路通断。2. 给继电器控制脚直接接高电平听是否有“咔嗒”声测触点通断。3. 用digitalWrite和delay写一个简单测试程序用LED或万用表测量Arduino控制引脚是否有输出。电磁阀随机误动作1. 继电器控制线受到干扰2. 电源波动3. 代码逻辑错误1. 缩短连接线或使用双绞线。在继电器控制端和地之间加一个104瓷片电容滤波。2. 为驱动电源9V电池并联一个大电容如470uF稳压。3. 检查姿态判断代码加入稳定延时和阈值判断避免数据抖动导致误判。姿态判断不准1. MPU-6050未校准2. 参考姿态数据记录不准3. 骰子滚动未停止就判断1. 运行MPU-6050的校准例程获取偏移量并写入代码。2. 重新执行校准步骤确保骰子绝对静止时记录数据。3. 在代码中增加检测当角速度gyro读数连续若干次接近零时才认为骰子静止开始判断姿态。骰子滚动不自然或卡住1. 内部导线缠绕2. 腔体空间过小或不平3. 配重不当1. 重新整理和固定骰子内部的陀螺仪导线尽量短且不影响重心。2. 检查并打磨3D打印腔体内部确保光滑无毛刺。3. 调整骰子内的配重蓝丁胶使其重心居中滚动更随机。这个项目本身已经完成了一个完整的闭环但它还有巨大的扩展潜力无线化将Teensy换成ESP32或Arduino HC-05蓝牙模块通过蓝牙将骰子点数发送到手机APP或电脑上显示实现真正的“远程”读取而不仅仅是物理指示。多骰子与游戏逻辑扩展系统同时支持多个智能骰子并编写简单的游戏逻辑如骰子游戏“快艇骰子”自动计算分数。可视化与记录在上盖增加LED灯环根据点数点亮不同区域。或者将每次投掷的结果和时间戳通过Wi-Fi上传到服务器形成游戏记录。结构优化设计更精巧的磁吸充电接口解决骰子供电问题。或者尝试使用微型振动电机代替电磁阀实现更安静的“触觉反馈”式报数。这个项目最让我着迷的地方在于它用一个具体的、有趣的载体把嵌入式开发中那些抽象的概念——传感器采样、数据滤波、状态机、驱动电路——都串联了起来。调试过程中看着骰子终于能准确响应不同朝向那种成就感远超单纯点亮一个LED。硬件项目的魅力就在于你的代码和逻辑最终在物理世界得到了实实在在的回响。希望你在复现和改造这个项目的过程中也能体验到这种乐趣。如果在制作中遇到任何问题不妨回头检查一下电源、地线和传感器的校准这三个往往是大多数问题的根源。