1. 项目概述与硬件选型想要打造一台能通过手机和电脑远程控制的WiFi小车鸿蒙系统搭配Hi3861开发板是个绝佳选择。这个组合既能发挥鸿蒙轻量级系统的优势又能利用Hi3861强大的WiFi连接能力。我去年用这套方案做了个智能小车实测延迟可以控制在100ms以内完全满足实时遥控的需求。核心硬件清单如下Hi3861开发板价格不到50元自带WiFi和丰富GPIO接口L9110S电机驱动模块双路H桥设计最大输出电流800mA直流减速电机建议选择6V电压规格带编码器版本更好小车底盘淘宝上30元左右的亚克力底盘套件就够用18650电池盒建议双节供电保证动力充足这里有个选购小技巧电机驱动模块一定要买带光耦隔离的版本。我最初用的廉价版在PWM调速时经常出现信号干扰后来换了带隔离的模块就再没出过问题。另外Hi3861的GPIO驱动能力有限记得选择3.3V兼容的电机驱动模块。2. 鸿蒙系统环境搭建在开始编程前需要准备好鸿蒙的开发环境。目前最新版本是OpenHarmony 3.2 LTS对Hi3861的支持已经很完善。安装过程比想象中简单下载DevEco Device Tool建议3.1以上版本安装时勾选Hi3861开发板支持包新建工程时选择WiFi IoT模板第一次编译可能会遇到工具链缺失的问题解决方法是在终端运行python build.py wifiiot -p hispark_pegasus有个坑我踩过两次鸿蒙的编译环境对路径长度敏感建议把工程直接放在D盘根目录。曾经因为路径嵌套太深导致编译失败折腾了半天才发现是这个原因。3. 电机驱动开发实战3.1 PWM初始化配置Hi3861有6路PWM输出我们只需要其中4路来控制两个电机。关键是要搞清楚GPIO和PWM通道的对应关系PWM通道GPIO引脚电机控制功能PWM0GPIO9右轮正转PWM1GPIO10右轮反转PWM3GPIO0左轮正转PWM4GPIO1左轮反转初始化代码要注意三点必须先调用GpioInit()初始化GPIO子系统设置引脚复用功能时要选对PWM模式每个PWM通道都需要单独初始化void Motor_Init(void) { // 初始化GPIO系统 GpioInit(); // 设置引脚复用功能 IoSetFunc(WIFI_IOT_IO_NAME_GPIO_0, WIFI_IOT_IO_FUNC_GPIO_0_PWM3_OUT); IoSetFunc(WIFI_IOT_IO_NAME_GPIO_1, WIFI_IOT_IO_FUNC_GPIO_1_PWM4_OUT); IoSetFunc(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_IO_FUNC_GPIO_9_PWM0_OUT); IoSetFunc(WIFI_IOT_IO_NAME_GPIO_10, WIFI_IOT_IO_FUNC_GPIO_10_PWM1_OUT); // 初始化PWM通道 PwmInit(WIFI_IOT_PWM_PORT_PWM3); PwmInit(WIFI_IOT_PWM_PORT_PWM4); PwmInit(WIFI_IOT_PWM_PORT_PWM0); PwmInit(WIFI_IOT_PWM_PORT_PWM1); }3.2 运动控制逻辑实现小车的基本运动包括前进、后退、左右转和停止。每个动作都需要精确控制两路PWM的输出组合// 前进左右轮同时正转 void Motor_Forward(void) { PwmStop(WIFI_IOT_PWM_PORT_PWM3); PwmStop(WIFI_IOT_PWM_PORT_PWM4); PwmStop(WIFI_IOT_PWM_PORT_PWM0); PwmStop(WIFI_IOT_PWM_PORT_PWM1); PwmStart(WIFI_IOT_PWM_PORT_PWM3, 500, 1000); // 左轮正转 PwmStart(WIFI_IOT_PWM_PORT_PWM0, 500, 1000); // 右轮正转 } // 左转右轮正转左轮停止 void Motor_TurnLeft(void) { PwmStop(WIFI_IOT_PWM_PORT_PWM3); PwmStop(WIFI_IOT_PWM_PORT_PWM4); PwmStop(WIFI_IOT_PWM_PORT_PWM0); PwmStop(WIFI_IOT_PWM_PORT_PWM1); PwmStart(WIFI_IOT_PWM_PORT_PWM0, 500, 1000); // 仅右轮正转 }调试时发现PWM占空比设置50%500/1000时电机转速最稳定。数值太小会导致电机抖动太大又可能超出驱动芯片的负载能力。4. WiFi通信系统设计4.1 UDP服务端实现Hi3861的WiFi模块性能足够支撑实时控制我们采用UDP协议来降低延迟。关键是要处理好这几个问题创建独立的网络任务线程设置合适的socket缓冲区大小实现简单的数据校验机制#define UDP_PORT 50001 void UdpServer_Task(void) { int sockfd socket(AF_INET, SOCK_DGRAM, 0); // 设置接收超时为100ms struct timeval tv; tv.tv_sec 0; tv.tv_usec 100000; setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, tv, sizeof(tv)); // 绑定本地端口 struct sockaddr_in serv_addr; memset(serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family AF_INET; serv_addr.sin_port htons(UDP_PORT); serv_addr.sin_addr.s_addr htonl(INADDR_ANY); bind(sockfd, (struct sockaddr *)serv_addr, sizeof(serv_addr)); // 接收处理循环 while (1) { char buf[128]; struct sockaddr_in client_addr; socklen_t len sizeof(client_addr); int ret recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)client_addr, len); if (ret 0) { ProcessControlCommand(buf); // 解析执行控制指令 } } }4.2 跨平台控制协议设计为了让手机和电脑都能控制我设计了一套简单的JSON协议{ cmd: move, action: forward, speed: 80 }协议支持五种基本指令move控制运动方向forward/backward/left/right/stopspeed设置运动速度0-100%light控制车灯开关horn鸣笛控制query状态查询在Hi3861端使用cJSON库来解析JSON数据非常方便。实测下来这套协议在100字节以内的数据包传输延迟可以控制在50ms以内。5. 客户端开发指南5.1 C#桌面客户端用Visual Studio开发控制程序时要注意.NET版本兼容性问题。推荐使用.NET Core 3.1以上版本UDP通信的核心代码如下using System.Net.Sockets; UdpClient client new UdpClient(); client.EnableBroadcast true; // 启用广播模式 // 构造控制指令 var command new { cmd move, action forward }; string json JsonConvert.SerializeObject(command); byte[] data Encoding.UTF8.GetBytes(json); // 发送到小车IP或广播地址 IPEndPoint endPoint new IPEndPoint(IPAddress.Parse(192.168.1.255), 50001); client.Send(data, data.Length, endPoint);界面设计建议加入摇杆控件我用的是开源的JoystickControl库实现了类似游戏手柄的操作体验。5.2 手机APP开发对于Android端使用Android Studio配合UDP库也很容易实现。关键点在Manifest中添加网络权限使用AsyncTask处理网络通信添加手势识别实现滑动控制iOS端稍微复杂些需要处理后台网络权限问题。建议使用SwiftUI框架代码结构会更清晰。6. 系统优化与调试6.1 延迟优化技巧通过以下几个方法可以将端到端延迟优化到100ms以内设置WiFi为802.11n模式减小UDP数据包大小控制在100字节内提高Hi3861的网络任务优先级客户端使用固定发送间隔建议50ms6.2 常见问题排查电机不转先检查PWM配置是否正确再用万用表测量驱动芯片输出控制响应慢用Wireshark抓包分析网络延迟频繁断连调整路由器信道避开拥挤的2.4G频段有个特别隐蔽的bug我调试了很久当电池电压低于6V时WiFi模块会工作不稳定。后来在电源输入端加了颗大电容就解决了。