ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

蓝牙加速度计小车:从传感器原理到整机调试的完整实践指南

蓝牙加速度计小车:从传感器原理到整机调试的完整实践指南 1. 项目概览一部手机加一块板子就能把小车开出花来先把这个项目说清楚蓝牙加速度计小车就是用手机的加速度计当方向盘通过蓝牙把手机的倾斜姿态实时发给小车手机往左倾小车左转往前倾小车前进松手回正小车就停。听起来像玩具但真正做完你会发现这里面串起了传感器原理、串口通信、PWM调速、电机驱动、干扰排查一整条链路是典型的麻雀虽小五脏俱全的硬件入门项目。我当年做这个项目的时候最大的感触是它不像那些照着教程焊一焊就能跑的东西它的坑全在你看不见的地方——手机加速度计的噪声、蓝牙模块的配对协议、电机驱动的共地问题、数据帧的粘包解析。任何一个环节没想明白小车就会表现出薛定谔的失控有时候能跑有时候发疯有时候死活连不上。所以这篇文章不只是给你一份能跑的代码更想把我踩过的坑、试过的方案、最后沉淀下来的判断标准一起讲清楚。不管你是学生做课程设计、创客空间搞工作坊还是纯粹想给娃做个能玩的遥控车这篇都适用。你不需要很深的嵌入式基础但需要一点耐心以及出了问题愿意拆开看的习惯。2. 整体方案选型为什么是蓝牙加加速度计而不是别的组合2.1 控制链路的核心矛盾遥控车这件事本质上解决的是一个人怎么把意图传给机器的问题。传统方案是物理遥控器按键或者摇杆信号经过射频模块发给车体。这个方案非常成熟但有个问题你得额外买一个遥控器而且遥控器本身也是一个要供电、要维护、要防丢的实体。用手机替代遥控器最大的优势不是省钱而是算力跟着手机走。手机上有加速度计、陀螺仪、触摸屏、WiFi、蓝牙这些传感器和通信模块如果全部堆到小车上成本会飙到离谱。但把它们留在手机端小车只需要一个蓝牙模块接收数据相当于把大脑和身体拆开了各干各的活。这个思路在真实的工业产品里也非常常见——手机控制无人机、手表控制智能家居、平板控制机械臂底层逻辑都是本地传感器 无线链路 远端执行器。你做这个小项目学的不是怎么焊一个玩具而是理解一条完整的人机交互链路该怎么设计。2.2 为什么不用WiFi、红外或者2.4G手柄很多人第一个疑问是WiFi不是更快更稳吗为什么不搞个ESP8266手机和车连同一个路由器或者手机开热点WiFi方案的问题在于连接建立这个环节。手机连WiFi需要扫描、认证、分配IP这一套流程在户外或者没有路由器的地方根本跑不起来。就算用手机热点每次开机都要等系统自动连接体验非常割裂。而蓝牙的配对是一次性的配对成功之后每次开机自动连速度在1-2秒内完成对小车的使用场景来说更接近打开即用。红外方案更不用提了直线传播、距离短、必须对准小车稍微转个角度信号就断了除非你一直追着车跑——那还不如遛狗。2.4G手柄比如nRF24L01其实是个不错的选择距离远、抗干扰强但它需要额外买一个手柄模块而且手柄的硬件成本比手机高多了。最关键的nRF24L01的调试对新手不友好需要自己写SPI通信协议而蓝牙模块HC-05/HC-06已经把协议栈封装好了你只需要学会用串口收发数据就行。2.3 为什么控制端选手机加速度计而不是虚拟摇杆这是一开始最值得纠结的地方。手机上做个虚拟摇杆两行代码就能搞定触摸事件映射到方向实现起来极其简单。那为什么还要用加速度计用虚拟摇杆你的注意力必须集中在屏幕上眼睛一直盯着手机小车稍微跑远点你就看不清它的姿态了。而用加速度计手机变成了一个物理方向盘你握着手机眼睛看着小车身体倾斜的方向就是小车的方向这是一种非常直觉化的操作体验几乎不需要学习成本。另外从技术学习的角度加速度计的数据处理比摇杆有意思得多。摇杆给你的是现成的坐标值而加速度计给你的是一堆带噪声的原始数据你需要自己去滤波、去计算倾斜角、去处理抖动、去设计死区。这些技能在以后的IMU惯性测量单元项目里全都是通用的你做的四轴飞控、平衡小车、循迹机器人底层都是这套东西。所以这个项目的核心价值在于它逼着你去理解原始传感器数据 → 信号处理 → 控制指令的完整链路而不是停留在事件回调 → 发指令的应用层。3. 硬件清单与搭建每一分钱都要花在刀刃上3.1 核心控制板选型Arduino Uno是新手最优解控制板的选择直接决定了你的开发效率和踩坑概率。市面上的主流选择无非三块Arduino Uno、STM32最小系统板、ESP32开发板。Arduino Uno的优势是生态太成熟了。你搜HC-05 Arduino能搜出几千篇教程每个引脚怎么接、每个库怎么调用都有前人踩过坑的答案。对新手来说遇到问题能搜到解决方案比硬件性能强十倍。它的缺点也明显——8位单片机主频16MHz处理加速度计数据这种级别的任务绰绰有余但如果你想后续加摄像头、跑视觉算法那它就不够用了。STM32的性能强很多但开发环境配置对新手的劝退能力也是顶级的。Keil的安装、驱动配置、下载器设置每一关都能卡掉一半人。如果这是你的第一个单片机项目我不建议一上来就挑战STM32。ESP32是个折中选择自带蓝牙和WiFi省掉外接蓝牙模块的钱。但ESP32的蓝牙走的是BLE或者经典蓝牙的SPP协议手机端的连接配置比HC-05稍微绕一点。而且ESP32的供电需求比Uno高如果你的电源方案没做好容易出现蓝牙频繁断连的问题。我的建议是第一次做就老老实实用Arduino Uno加外接HC-05模块。等你把整个链路跑通了再考虑移植到ESP32或者STM32上那时候你心里对控制逻辑和通信协议已经有底了换平台只是换个SDK的事。3.2 电机驱动、底盘与供电的搭配思路电机驱动这块项目里最常见的方案是L298N但说实话L298N的压降太大了两个通道全开的时候输入6V输出可能只有4.5V电机转速会明显不够。如果预算允许我更推荐TB6612FNG它的压降只有0.1-0.2V而且体积小一圈直接插面包板上就能用。价格也就贵几块钱但对小车动力的改善是实打实的。底盘选型有两种路线。一种是买成品的亚克力小车底盘配两个TT马达和两个万向轮大概二十多块钱。另一种是3D打印或者激光切割自己做一个外观更自由但需要你有设备。新手直接买成品底盘就好别在底盘上浪费时间你的精力应该放在控制逻辑上。供电是整个项目最容易翻车的地方我单独说一下。Arduino Uno的Vin引脚可以接受7-12V输入板载稳压器会把它降到5V给单片机供电。但电机不能从Arduino的5V引脚取电因为电机启动瞬间的电流可以达到1A甚至更高Arduino板载稳压器根本扛不住。正确的接法是电池组正极先接电机驱动板的电机电源输入再从驱动板的逻辑电源输出有的板子叫VCC或5V out给Arduino供电。这样电机的大电流和单片机的小电流是分开的互不干扰。电池选择上4节5号镍氢充电电池标称4.8V或者2节18650锂电池标称7.4V都可以。18650的动力更猛但要注意L298N和TB6612的输入电压范围TB6612最高能到13.5V7.4V完全没问题。我实测下来2节18650是最舒服的搭配续航一个小时以上动力充沛而且不用频繁换电池。3.3 蓝牙模块接线与避坑HC-05与HC-06别选错蓝牙模块是这个项目的通信枢纽也是最容易出问题的硬件。市面上最常见的两款是HC-05和HC-06外观几乎一模一样但有一个关键区别HC-05支持主从一体模式可以通过AT指令配置成主机或者从机HC-06是纯从机只能被手机连接。我们这个项目里手机是主机小车是从机所以HC-06理论上够用而且HC-06比HC-05便宜几块钱。但我的建议是直接买HC-05原因有两点第一HC-05的AT指令配置更灵活你可以在调试阶段把它配成主机连上另一个蓝牙模块做无线串口调试这对排查问题非常有帮助第二HC-05的固件相对成熟兼容性更好某些杂牌HC-06在Android手机上会莫名其妙连接失败HC-05出问题的概率低很多。接线这块有一个致命细节HC-05的RXD引脚接Arduino的TX引脚TXD接RX引脚这是交叉接法。很多人第一次接的时候照着同名相连的习惯接结果收不到任何数据。另外HC-05的逻辑电平是3.3V而Arduino的TX输出是5V直接接上去有烧毁蓝牙模块的风险。稳妥的做法是在Arduino的TX和HC-05的RXD之间串一个1K电阻分压或者用逻辑电平转换模块。很多教程不说这个但我在实操中真的烧过一个模块很心疼。还有个容易被忽略的点HC-05的STATE引脚状态引脚可以接一个LED到地配对成功后LED会从快闪变成慢闪大概2秒闪一次这是判断连接状态最直观的方式。不用额外写代码纯硬件指示调试的时候省很多事。4. 手机端加速度计原理与控制映射从原始数据到控制指令4.1 加速度计到底在测什么手机里的加速度计Accelerometer测的不是速度也不是倾斜角而是加速度。具体来说它测量的是施加在传感器上的比力specific force单位是g重力加速度。当手机平放在桌面上的时候Z轴会显示约9.8m/s²即1gX和Y轴接近0。当你把手机倾斜重力会在各个轴上产生分量比如手机竖起来Y轴变成1gZ轴变成0。所以要得到手机的倾斜角度核心算法就是利用重力的分量做反三角函数计算。最常用的公式是pitch atan2(-accX, sqrt(accY*accY accZ*accZ)) * 180 / PI roll atan2(accY, accZ) * 180 / PI其中pitch是俯仰角前后倾斜roll是横滚角左右倾斜。用atan2而不是atan是因为atan2能自动处理象限问题输出范围是-180°到180°避免了角度的跳变。这里有个概念需要强调加速度计在静止状态下测量重力矢量是非常准的但在运动状态下它测量的加速度是重力 小车运动的线加速度的合矢量。也就是说如果你拿着手机快速甩动加速度计读到的数据会包含甩动的加速度这时候算出来的倾斜角就不可信了。不过在遥控小车的场景里这个误差恰好可以接受甚至算一种特性。因为用户控制小车的时候手持手机的晃动幅度通常不大运动加速度远小于重力分量滤波之后基本不影响控制。更重要的是加上陀螺仪融合比如用互补滤波或者卡尔曼滤波会显著增加代码复杂度对新手不友好。如果你做的是平衡车或者自稳云台那种对姿态精度要求极高的项目再考虑上陀螺仪融合控制小车这个场景纯加速度计完全够用。4.2 从倾斜角到电机转速的映射逻辑拿到倾斜角之后接下来要解决的问题是角度怎么变成两个电机的转速最直观的映射方式是这样的前后倾角pitch控制车速左右倾角roll控制转向。但如果你直接用左电机速度-转向右电机速度转向这种最简单的公式会有一个体验问题手机在某个角度附近稍微抖一下车速就会剧烈变化小车表现得非常神经质。我实际调了几版之后总结出一套比较好用的映射逻辑设置死区倾斜角绝对值小于10°的时候输出为0也就是小车不动。这个死区是用来吸收手机平放时的微小噪声的。没有死区的话小车停在原地会一直轻微抖动像得了帕金森。设置平滑过渡角度从10°到45°之间线性映射到PWM 0-255。超过45°就锁定最大速度。这里的45°是上限阈值超过之后速度不再增加防止用户把手机竖得太直导致输出饱和后的突变。转向做成差速左右两个电机的PWM值分别是左电机 baseSpeed - turnValue右电机 baseSpeed turnValue这里的turnValue可以做成转向越大差速越明显的非线性关系。我用的是turnValue roll * 3线性就行如果觉得转向太灵敏或者太迟钝调这个系数就行。这里有一个细节值得注意当手机在死区附近徘徊的时候如果转向值来回穿越0点电机会频繁小幅正反转产生咔咔声时间长了可能伤电机驱动板。解决方案是给转向也加一个小死区比如roll小于5°时不输出转向。这个细节在代码里只占三行但对整车稳定性的提升非常明显。4.3 数据平滑别让传感器噪声毁掉你的驾驶体验加速度计的原始数据噪声其实不小。你可以用手机装一个传感器调试软件比如Sensor Kinetics实时查看会发现即使手机完全静止三个轴的读数也在小范围跳动。这些跳动如果直接映射到电机上就会变成持续的抖动小车开起来一顿一顿的。我试过两种滤波方案最终选定了滑动平均滤波Moving Average Filter。逻辑很简单维护一个长度为10的数组每来一个新数据就把它放进数组末尾去掉最旧的数据然后取平均值作为当前输出值。为什么选滑动平均而不是卡尔曼滤波因为这个场景下卡尔曼滤波属于杀鸡用牛刀——它的计算量更大需要调协方差矩阵而且对新手来说调参的过程很像玄学。滑动平均虽然会引入一点滞后大约几毫秒但控制小车这个场景根本感知不到这些滞后而它在代码层面的实现只有五六行维护成本极低。滤波的窗口长度数组长度取值也值得说。窗口太短比如5滤波效果不明显窗口太长比如30手机快速倾斜时指令响应会显得拖泥带水。我实测下来10-15是一个比较舒适的区间既能滤掉高频噪声又能保持指令的实时性。5. 通信协议与代码实现串口数据怎么发、怎么收、怎么解析5.1 数据帧格式设计为什么不能用裸数字手机和Arduino之间的通信本质上是通过蓝牙模块透传的串口数据波特率默认9600。初学的时候最容易犯的错误是手机端直接把角度值发过去比如发一个35Arduino端Serial.read()一个字节一个字节地读结果数据一多就全乱了。问题的根源在于串口是流式的没有天然的帧边界。你发35和135是两个字节还是三个字节Arduino怎么知道一条指令在哪里结束如果不定义协议接收端只能靠猜猜就一定会出错。所以必须设计一个简单的帧格式。我用的方案是S 方向标志 速度值 E举例说明S L 200 E表示左转200速度S F 150 E表示前进150S R 255 E表示右转255。其中S是起始符E是结束符中间是数据字段。Arduino接收端每收到一个字节就进入一个简单的状态机没收到S之前忽略所有数据收到S之后开始缓存数据直到收到E然后把缓存里的字段解析出来。这个协议虽然简单但它解决了三个关键问题一是数据边界清晰不会粘包二是错误数据比如蓝牙传输过程中的乱码会在解析阶段被丢弃三是以后想扩展功能比如加灯光控制、加鸣笛指令只要在S和E之间加字段就行不需要改动协议框架。同样的帧格式也适用于一个很常见的调试场景用serial bluetooth terminal手机端的串口蓝牙终端APP手动发指令。你在手机上装一个这样的APP连接HC-05之后直接输入S L 200 E并发送小车立刻就会左转。这个方法是验证蓝牙链路电机驱动是否正常的最快途径不需要写任何手机代码。5.2 Arduino端代码核心逻辑Arduino端的主程序逻辑就三件事读串口、解析指令、设置PWM。核心代码如下#define ENA 5 // 电机A使能脚PWM #define IN1 6 #define IN2 7 #define ENB 10 // 电机B使能脚PWM #define IN3 8 #define IN4 9 int speedLeft 0; int speedRight 0; void setup() { pinMode(ENA, OUTPUT); pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT); pinMode(ENB, OUTPUT); pinMode(IN3, OUTPUT); pinMode(IN4, OUTPUT); Serial.begin(9600); } void loop() { if (Serial.available() 0) { String command readCommand(); // 读取完整帧 if (command.length() 0) { parseCommand(command); // 解析并执行 } } } String readCommand() { static String buffer ; while (Serial.available() 0) { char c Serial.read(); if (c S) { buffer ; // 收到起始符清空缓存 } else if (c E) { String cmd buffer; // 收到结束符返回完整指令 buffer ; return cmd; } else { buffer c; // 中间数据追加到缓存 } } return ; } void parseCommand(String cmd) { // 期望格式: L 150 或 R 150 或 F 150 或 B 150 char dir cmd.charAt(0); int speed cmd.substring(2).toInt(); if (dir F) { // 前进 digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW); digitalWrite(IN3, HIGH); digitalWrite(IN4, LOW); analogWrite(ENA, speed); analogWrite(ENB, speed); } else if (dir B) { // 后退 digitalWrite(IN1, LOW); digitalWrite(IN2, HIGH); digitalWrite(IN3, LOW); digitalWrite(IN4, HIGH); analogWrite(ENA, speed); analogWrite(ENB, speed); } else if (dir L) { // 左转左轮减速右轮加速 digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW); digitalWrite(IN3, HIGH); digitalWrite(IN4, LOW); analogWrite(ENA, speed / 2); analogWrite(ENB, speed); } else if (dir R) { // 右转右轮减速左轮加速 digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW); digitalWrite(IN3, HIGH); digitalWrite(IN4, LOW); analogWrite(ENA, speed); analogWrite(ENB, speed / 2); } }这里有两个我踩过的坑必须提醒你。第一个是String类型的使用。Arduino的String类在内存紧张的时候会出现莫名奇妙的问题——内存碎片化、随机重置、甚至死机。我遇到过一次代码跑着跑着小车突然不动了重新上电又好了查了半天最后发现是String拼接操作导致堆内存溢出。后来我把所有String操作都改成了char数组问题彻底消失。上面代码里我保留了String是为了可读性但你在实际项目中如果发现异常重启优先怀疑内存问题把String换成char[]。第二个是PWM引脚的频率问题。Arduino Uno的PWM频率大约是490Hz听起来挺高但是电机是有惯性的PWM频率太低会导致电机嗡嗡响并且转速不均。如果实测发现电机噪声大可以换用analogWriteFrequency()仅限Arduino Due/Zero或者直接换更高频率的PWM信号。不过Uno上没法改只能接受现状或者换用支持高频率PWM的板子。5.3 手机端App方案从零写App到现成工具手机端的实现有几个层次我按难度从低到高排列第一层通用蓝牙串口APP。就是前面提到的serial bluetooth terminal这类工具它做的事情是连接蓝牙设备、提供一个文本框输入指令、把串口收到的内容显示在屏幕上。用它测试Arduino端的指令解析效率非常高。这个方案适合验证硬件链路的完整性但不能做加速度计控制。第二层MIT App Inventor。这是MIT开发的图形化编程工具拖拽积木块就能做App。它对新手极其友好内置了加速度计传感器组件和蓝牙客户端组件。你完全可以在不写一行Java代码的情况下做出一个能读取手机倾斜角、通过蓝牙发指令的App。我当年做课设的时候就是用App Inventor两天搞定了手机端。第三层Android原生开发Java/Kotlin。如果你以后想往移动开发方向发展可以自己写一个原生App。核心就是SensorManager里的TYPE_ACCELEROMETER监听器加上BluetoothSocket的RFCOMM通信。代码量大概几百行不算多但对新手来说Android的系统权限、蓝牙适配器、线程管理都是要额外学习的东西。我的建议是第一次做用App Inventor把全部精力放在控制逻辑上。等整车跑起来之后如果你觉得App Inventor生成的界面太丑、或者想加一些更复杂的交互再考虑转原生。App Inventor的核心逻辑是这样的使用Clock组件定时比如每100毫秒读取加速度计传感器的X、Y、Z值根据前面讲的算法计算pitch和roll用条件判断将角度转为指令pitch 10°发前进pitch -10°发后退roll决定转向值通过蓝牙客户端的SendText方法把指令字符串发出去这里有一个App Inventor特有的坑蓝牙连接必须在Screen.Initialize事件中异步进行不能在按钮点击事件里直接连接否则会阻塞UI线程导致App无响应。另外蓝牙权限需要在AndroidManifest里声明虽然App Inventor默认帮你处理了大部分但如果你导出APK签名后安装到高版本Android特别是API 31以上需要手动检查蓝牙相关的运行时权限。6. 常见问题与排查技巧实录这些坑我替你踩过了6.1 蓝牙配对成功但App连接不上别急着怀疑模块坏了这是新手问得最多的问题。症状是手机蓝牙设置里能搜到HC-05也能配对但打开蓝牙串口APP连接时提示连接失败或者Unable to connect。排查思路按顺序来第一确认配对码。HC-05的默认配对码是1234有的是0000。这是老生常谈但真的有人卡在这一步。第二确认模块是不是处于可被发现状态。HC-05上电后LED如果一直在快闪说明它还没被配对过或者正在等待配对。如果你之前已经配对过LED应该是慢闪。问题就出在这里部分Android手机在蓝牙配对后会记住这个配对关系但SPP串口配置文件连接和普通配对不是一回事。你需要先在手机蓝牙设置里取消配对然后重新配对再用APP连接。第三这是最隐蔽的一个问题部分Android手机的蓝牙栈对SPP的支持不稳定。特别是某些国产手机的高版本Android系统会默认用BLE低功耗蓝牙连接设备导致SPP连接失败。如果你在APP里看到类似bluetooth le spam的日志说明系统在尝试用BLE方式连接HC-05而HC-05不支持BLE。解决办法是在手机蓝牙设置里找到该设备检查连接方式是否被系统改成了LE如果是手动切换回经典蓝牙模式。还有一个更彻底的解决办法换一部手机测试如果换手机就正常说明是手机蓝牙栈兼容性的问题不是你的代码出了问题。6.2 电脑端识别不了HC-05Generic Bluetooth Radio驱动问题这个坑主要出现在你把HC-05插到电脑USB转串口模块上调试的时候。Windows系统插入USB转串口设备如CH340、CP2102如果没自动安装驱动设备管理器里会出现一个带黄色感叹号的未知设备。有些情况下HC-05通过USB转串口连上电脑后系统会把它识别成一个叫Generic Bluetooth Radio的蓝牙适配器并要求你安装驱动。这里要区分两种情况一种是USB转串口本身的驱动CH340或者CP2102缺失这种直接在设备管理器里右键更新驱动手动指定到驱动文件夹就行另一种是系统误把HC-05识别成蓝牙适配器这种情况其实是正常的——因为HC-05本身就带蓝牙射频系统检测到它后尝试按蓝牙适配器去加载驱动。这时候你不需要让Windows加载蓝牙驱动只需要确认USB转串口的COM口已经正确枚举比如显示COM3然后用串口终端工具比如SSCOM或者XCOM打开这个COM口波特率设9600直接发送AT如果返回OK说明模块是好的通信链路正常。如果COM口一直没有出现检查是不是USB转串口模块坏了换一个再试。我遇到过最奇葩的情况是USB转串口的TX和RX没有交叉——模块的TX要接USB转串口的RX模块的RX要接USB转串口的TX接反了也收不到数据。6.3 小车只有一边转或者根本不动这个问题的根源几乎都在电机驱动板的接线和供电上。先说只有一边转。这通常是驱动板某一通道的使能脚没接对。我用的TB6612的A通道使能脚PWMA如果不接PWM信号或者接到了普通数字脚没有PWM能力这个通道就会完全不输出表现就是只有一个轮子在转。检查方法很简单把两个使能脚都直接接到5V满速然后手动给IN1/IN2、IN3/IN4高低电平看两个电机是否都能转。这一步叫硬件自检能帮你把问题范围缩小到驱动板接线还是代码PWM输出。再说根本不动。这大概率是共地问题。蓝牙模块、Arduino、电机驱动板、电池之间必须共地——也就是说所有GND要连在一起。如果蓝牙模块单独供电而不和Arduino共地那它们之间的串口信号就没有参考电位数据传不过去而Arduino收不到指令自然不动作。这个问题在教程里经常被一笔带过但实际中十有八九的完全不动都是这个原因。还有一种是供电电压不足的问题。我用4节5号干电池非充电给L298N供电的时候电机空转还行一放到地上带负载电压瞬间掉到3V以下Arduino直接复位小车表现就是抖一下然后死机。换成2节18650之后这个问题就消失了。如果你发现小车在空载轮子悬空时一切正常一落地就抽风优先怀疑供电不是代码。6.4 手机倾斜方向反了、灵敏度不对方向反了是最容易修的在App Inventor里把X轴的符号取反就行在原生代码里就是-accX。但有些人会忽略一个坑——手机横屏和竖屏时X轴和Y轴的定义会变。如果你锁定了屏幕方向比如强制竖屏那么传感器坐标系也会固定在竖屏坐标下这时候倾斜方向才是稳定的。很多设备默认支持横竖屏自动旋转一旦屏幕旋转X和Y轴交换控制方向就全乱了。所以正确做法是在App代码里强制锁定屏幕方向为竖屏。灵敏度问题则和映射系数相关。如果你觉得小车转向太猛把转向系数前面提到的turnValue roll * 3从3改成1.5或者2。如果你觉得加速太突兀可以把线性映射改成曲线映射比如speed (int)(255 * pow(angle / 45.0, 1.5));pow指数大于1会让输出曲线在低角度区更平缓高角度区更激进。这样低速区更细腻高速区反应更快。这个公式不需要理解太深你只需要知道调指数就能改变操控手感大于1变肉小于1变贼。6.5 一个容易被忽视的连接稳定性问题蓝牙SPP连接在空旷环境下稳定传输距离大概10米但实际用起来特别是室内两三米就断连的情况很常见。原因有两个一是手机蓝牙天线位置和HC-05天线的相对角度金属外壳、人手遮挡都会衰减信号二是2.4GHz频段的干扰源太多——WiFi、无线鼠标、微波炉都挤在这个频段。这里顺带提一下那个热词bluetooth gps output。很多人第一次看到这个术语会以为蓝牙能输出GPS信号其实它指的是通过蓝牙串口透传NMEA格式的GPS定位数据——比如外接GPS模块通过蓝牙把定位信息发给手机。这也印证了蓝牙串口模块的一个通用用法它本质上是一条无线串口传什么数据都行。你甚至可以把HM-10BLE模块加一个小车板载GPS模块这样小车的坐标就能实时回传到手机端做一个简单的室外循迹功能。这个扩展留给有兴趣的人去玩但要注意这需要用BLE模块而不是HC-05因为HC-05的功耗在长期运行场景下偏高。7. 扩展升级方向同一套链路还能玩出什么花样做完基础版的加速度计小车之后你会发现整个系统的扩展潜力很大因为你已经打通了传感器采集 无线通信 电机控制这条通路剩下的只是往这条通路上加新传感器、新执行器、新控制逻辑。最容易的升级是加舵机云台和摄像头做一个简单的视觉跟随小车。手机通过蓝牙发送云台控制指令Arduino控制两个舵机转动摄像头方向摄像头画面通过WiFi图传模块回传到手机。这个项目的难点不在舵机控制而在如何把摄像头画面和云台控制指令同步——通常的方案是WiFi图传走一路蓝牙指令走另一路两条通路互不干扰。这也能解释为什么蓝牙和WiFi需要同时存在WiFi抢带宽蓝牙抢实时性各司其职。另一个方向是加超声波避障。HC-SR04超声波模块十几块钱测距精度大约在2cm到4m之间。你在小车前方装一个Arduino每100毫秒测一次距离如果小于30cm就原地转向。把手机手动控制和自动避障结合起来的方式是手机指令优先当测距值小于阈值时Arduino临时屏蔽手机的前进指令只允许后退和转向指令。这个逻辑不算复杂但涉及多优先级指令仲裁的概念是嵌入式系统设计里一个很有意思的话题。如果你对低功耗感兴趣可以试试把主控换成HM-10的BLE模块。BLEBluetooth Low Energy的功耗远低于HC-05的经典蓝牙SPP一颗CR2032纽扣电池能让BLE模块跑几个月。用BLE做数据回传比如把小车上的温湿度传感器数据发到手机上是非常经典的低功耗物联网应用。但要注意BLE和经典蓝牙在手机端的API完全不同需要重新适配。这些升级方向有一个共同的规律它们都在复用你已经建好的控制链路只是把末端的执行器、传感器或者通信模块换一下。这正是这个项目的魅力所在——它不是一条死胡同而是一个入口。最后再分享一点实操体会这个项目我从硬件焊接开始到手机App调试完成前后花了大概两个周末。最花时间的不是写代码而是排查那些看似随机的问题——蓝牙连不上、电机不动、方向反了、信号断连。这些问题的共同点是它们都发生在多个子系统的交界处。接线交叉错误是硬件和硬件的交界数据解析失败是协议和代码的交界方向反了是传感器坐标系和用户认知的交界。做硬件项目大部分时间不是在写功能而是在处理交界处的摩擦。但正是这种摩擦逼着你把每一个环节都理解得足够透彻。如果你在做的过程中卡住了别急着怀疑自己的代码。先从硬件自检开始用手机上的serial bluetooth terminal发一条固定指令看电机是否动作用万用表量一下各点电压是否正常用手摸一下驱动芯片是否过热。把这些基础项排除掉再回到代码层面查逻辑。按这个顺序走90%的问题都能在半小时内定位。希望你也能在这个项目里找到那种第一次跑通时大脑里瞬间放烟花的感觉。
返回列表