|
【FireBeetle ESP32 + SimpleFOC】打造两轮差速遥控小车,从倾角实验到无线控制
【项目背景】
最近迷上了无刷电机的FOC控制,SimpleFOC库让DIY变得异常简单。手头正好有两颗集成AS5600磁编码器的无刷电机(极对数7),配上SimpleFOCMini驱动板和FireBeetle ESP32,再加上MPU6050陀螺仪,就萌生了做一辆小车的想法。原本打算做一个自平衡车,但考虑到结构复杂度,最终决定做成两轮差速驱动加万向轮的形式,用手机网页遥控,既简单又好玩。 本文将分享整个制作过程,包括硬件选型、软件调试、倾角传感实验以及最终的网页遥控实现。希望能给同样对FOC小车感兴趣的朋友一些参考。 【硬件清单】
组件 | 型号/说明 | 数量 | | 主控板 | FireBeetle ESP32 (DFR0478) | 1 | | 无刷电机(带编码器) | 外转子无刷电机,AS5600磁编码器,极对数7,12V供电,扭矩300g·cm | 2 | | 驱动板 | SimpleFOCMini (基于DRV8313,三相PWM输入) | 2 | | 姿态传感器 | MPU6050 (I2C接口) | 1 | | 电池 | 3S锂电池 (11.1V) 或 2S (7.4V)+12V压板 | 1
| | 车架 | 亚克力板/3D打印件 + 万向轮 | 1套 | | 其他 | 杜邦线、螺丝、铜柱等 |
【硬件连接】 电机0编码器:SDA→GPIO21,SCL→GPIO22 电机1编码器:SDA→GPIO19,SCL→GPIO18 MPU6050:与电机0共用I2C总线 (SDA21/SCL22) 电机0驱动:PWM引脚:25,26,27;使能引脚9 电机1驱动:PWM引脚:5,13,10;使能引脚2 电池电压12V接入驱动板VIN,ESP32可由驱动板5V供电或单独供电
注意:SimpleFOCMini驱动板支持3相PWM输入,需将ESP32的PWM信号连接到驱动板的IN1-IN3,使能引脚接高电平有效。 关于FOC FOC(Field-Oriented Control,磁场定向控制)是一种先进的无刷电机控制技术,通过坐标变换将定子电流分解为励磁分量和转矩分量,实现类似直流电机的独立控制。相比传统的方波控制,FOC具有转矩平滑、效率高、噪音低、动态响应快等优点。SimpleFOC开源库完美封装了FOC算法,让我们可以用 Arduino轻松驱动无刷电机。 【项目阶段一:倾角控制实验】 在做小车之前,我先用MPU6050测试了通过车身倾角控制电机正反转。这个实验为后续的直立控制打下基础,虽然最终没用上,但过程很有趣。 代码思路初始化两个AS5600编码器(各占用独立I2C总线)和MPU6050。 将两个电机配置为速度控制模式(MotionControlType::velocity)。 循环读取MPU6050的Y轴倾角(取决于安装方向),当倾角大于阈值时电机正转,小于负阈值时反转,中间区域停止。 通过motor.move(target)设置目标速度,loopFOC()高频执行FOC算法。
关键代码片段
- void loop() {
- mpu6050.update();
- sensor_0.update(); sensor_1.update();
-
- roll = mpu6050.getAngleY(); // 获取倾斜角度
-
- float target = 0;
- if (roll > threshold) target = motor_speed;
- else if (roll < -threshold) target = -motor_speed;
-
- motor_0.loopFOC(); motor_0.move(target);
- motor_1.loopFOC(); motor_1.move(target);
-
- // 打印调试信息...
- }
复制代码 实验结果:左右倾斜mpu6050传感器,两轮能同步正反转,响应灵敏,但速度环PID参数需要根据电机特性调整。通过串口打印观察,目标速度与倾角呈线性关系,但由于是简单的开关控制,不够平滑。
演示视频
【项目阶段二:网页遥控两轮差速小车】 放弃自平衡方案后,我增加了万向轮,将小车改为两轮差速驱动。用手机浏览器访问ESP32的Web服务器,通过按钮和滑块控制运动。 网页交互设计 软件架构使用ESPAsyncWebServer库搭建异步Web服务器,避免阻塞主循环。 HTML页面内嵌JavaScript,通过Fetch API向服务器发送GET请求。 主循环中不断执行FOC算法,并根据全局变量left_motor_cmd和right_motor_cmd设置电机目标速度(扭矩模式)。
电机控制模式选择 原SimpleFOC例程常用扭矩模式(电压控制),因为电机参数已知(相电阻2.9Ω),可以直接通过电压控制扭矩。但在速度模式下,需要整定PID,简单起见我保留了扭矩模式,将网页传来的“速度值”作为扭矩值(实际是电压值),通过motor.move()直接设置。若需精确速度控制,可改为速度模式并整定PID。 网页控制代码亮点 HTML关键部分(已做移动端优化): - <style>
- .btn {
- user-select: none; /* 禁止选中 */
- -webkit-touch-callout: none; /* 禁止长按菜单 */
- touch-action: manipulation; /* 优化触摸 */
- }
- </style>
-
- <button class="btn" ontouchstart="sendAction('f', event)" ontouchend="sendAction('s', event)">前进</button>
复制代码
JavaScript: - function sendAction(cmd, event) {
- if (event) event.preventDefault();
- fetch(`/action?cmd=${cmd}`);
- }
复制代码
通过传递event并调用preventDefault(),完美解决了手机长按按钮时弹出菜单导致touchend不触发的问题。 主控逻辑 在loop()中: - sensor_0.update(); sensor_1.update();
- motor_0.loopFOC(); motor_1.loopFOC();
- motor_0.move(-left_motor_cmd); // 左电机取反(根据实际方向调整)
- motor_1.move(right_motor_cmd);
复制代码
Web服务器回调函数根据命令更新left_motor_cmd和right_motor_cmd: - void updateMotorCommands(char cmd) {
- switch (cmd) {
- case 's': left_motor_cmd = 0; right_motor_cmd = 0; break;
- case 'f': left_motor_cmd = base_speed; right_motor_cmd = base_speed; break;
- case 'b': left_motor_cmd = -base_speed; right_motor_cmd = -base_speed; break;
- case 'l': left_motor_cmd = -turn_speed; right_motor_cmd = turn_speed; break;
- case 'r': left_motor_cmd = turn_speed; right_motor_cmd = -turn_speed; break;
- }
- }
复制代码
【成果展示】
【问题及解决】 通过这个项目,我深入理解了FOC控制原理,并学会了用ESP32搭建Web服务器实现无线遥控。SimpleFOC库大大降低了无刷电机的使用门槛,让创客能轻松玩转高性能电机。下一步我计划加入闭环速度控制,并尝试用手机重力感应控制小车,让它更加“智能”。
【完整代码】
代码.zip
|