☰
ESP32桌面宠物机器人Nova改造:从Freenove小车到智能交互
2026/10/7 7:44:52 网站建设 项目流程

1. 项目缘起与整体设计思路

1.1 为什么选择 Freenove ESP32 小车套件作为改造平台

手头这台 Freenove ESP32 四驱小车套件,是我两年前买来学 Arduino 的入门玩具。它自带一块 ESP32-WROVER-E 模组、四路直流减速电机、一块 8x16 的 LED 点阵屏、一个超声波测距模块、一个红外接收头,还有一堆杜邦线和亚克力结构件。原厂配套的例程跑完一遍之后,它就被我扔在角落里吃灰了。直到最近整理桌面,看着它落满灰尘的样子,突然冒出一个念头:能不能把它改造成一个有“性格”的桌面宠物机器人,而不是一个只会按固定路线跑圈的遥控车?

这个想法落地之后,我给它取名叫Nova。Nova 的核心定位很明确:一个放在办公桌上、能对环境和人的互动做出即时反馈的小型机器人。它不需要多强的算力,也不需要多复杂的机械结构,但必须满足三个条件——反应要快、表情要丰富、交互要自然。ESP32 双核 240MHz 的主频、内置 Wi-Fi 和蓝牙、丰富的 GPIO 和外设接口,正好能撑起这个定位。而且 Freenove 这套底盘的机械结构已经调好了,省去了大量装配和调试的时间,我可以把精力集中在“让它活起来”这件事上。

选 ESP32 而不是 Arduino Uno 或者树莓派,理由很直接。Arduino Uno 没有无线能力,做出来的东西只能插着线跑,失去了桌面宠物的灵动感;树莓派虽然性能强,但功耗高、启动慢,而且用 Python 写底层电机控制会有明显的延迟抖动。ESP32 刚好卡在中间:有无线、有双核、有硬件定时器和 LEDC 外设、功耗还低,用 Arduino 框架或者 ESP-IDF 都能开发,生态成熟,踩坑成本低。Freenove 的套件里还附带了一块扩展板,把电机驱动、LED 点阵、超声波接口都集成好了,接线基本是即插即用,这对快速原型验证非常友好。

1.2 Nova 的核心功能定义与交互逻辑

Nova 的功能设计围绕“桌面宠物”这个场景展开,我把它拆成了四个层次。第一层是基础运动,四驱底盘支持前进、后退、转向和原地旋转,运动逻辑用 ESP32 的 LEDC 外设生成 PWM 波控制电机转速,通过调整两路 PWM 的占空比实现差速转向。第二层是表情系统,8x16 的 LED 点阵屏用来显示眼睛、嘴巴和简单动画,比如眨眼、眯眼、张嘴、生气时眼睛变红等。第三层是环境感知,超声波模块负责检测前方障碍物,红外接收头用来接收遥控器指令,后续还计划加一个温湿度传感器做环境数据采集。第四层是无线交互,ESP32 内置 Wi-Fi 和蓝牙,我打算做一个简单的 Web 页面和蓝牙串口控制通道,用手机就能直接操控 Nova 的动作和表情。

交互逻辑上,Nova 的状态机设计得比较克制。它默认处于“待机”状态,眼睛缓慢眨眼,偶尔左右张望;当超声波检测到有人靠近时,切换到“警觉”状态,眼睛睁大、身体微微后退;如果收到遥控指令,进入“执行”状态,按照指令运动或表演动作;执行完毕后自动回到待机。这个状态机用 FreeRTOS 的两个任务来实现:一个任务负责传感器数据采集和状态判断,另一个任务负责电机控制和 LED 点阵刷新。两个任务通过队列通信,避免阻塞。ESP32 双核的优势在这里体现得很明显——一个核跑传感器和逻辑,另一个核跑显示和电机,互不干扰,刷新率和响应速度都能稳住。

1.3 开发环境选型:PlatformIO 还是 Arduino IDE

开发环境这块我纠结了一阵。Arduino IDE 上手快,Freenove 官方例程也是基于 Arduino IDE 写的,直接打开就能编译烧录。但 Arduino IDE 的代码补全和库管理实在太弱了,项目稍微大一点就难以维护。我最终选了PlatformIO + VS Code这套组合。PlatformIO 的库依赖管理是声明式的,在platformio.ini里写清楚依赖库和版本号,换台电脑也能一键还原环境。而且 PlatformIO 支持多环境配置,我可以同时维护 ESP32 的 Arduino 框架版本和 ESP-IDF 版本,方便对比测试。

安装过程不复杂,但有几个坑得提前说。VS Code 装好之后,在扩展市场搜 PlatformIO IDE 安装,首次启动会自动下载 PlatformIO Core 和工具链。国内网络环境下这一步可能会很慢甚至超时,我的做法是提前配置好镜像源,或者手动下载离线包。PlatformIO 的离线包在官网有提供,下载后解压到~/.platformio目录下即可。另外,ESP32 的编译速度在 Windows 上确实偏慢,第一次编译一个中等规模的项目可能要两三分钟。我的经验是把项目放在 SSD 上、关闭杀毒软件的实时扫描、在platformio.ini里开启编译缓存,这三招下来编译时间能砍掉一半左右。

2. 核心硬件解析与接线要点

2.1 ESP32 主控板与扩展板的引脚分配

Freenove 套件里的 ESP32 主控板是标准的 38 引脚布局,但扩展板把大部分引脚都占用了,留给用户自定义的引脚其实不多。我在规划 Nova 的硬件接线时,先把扩展板的原理图翻出来看了一遍,确认了每个功能模块占用的 GPIO。电机驱动用的是 TB6612FNG,四路电机占用了 GPIO 12、13、14、15、16、17、18、19 这八个引脚,其中四个是方向控制,四个是 PWM 调速。LED 点阵屏用的是 MAX7219 驱动芯片,占用 GPIO 5、18、23 三个引脚做 SPI 通信。超声波模块占用 GPIO 34 和 35,这两个是输入专用引脚,不能做输出。红外接收头占用 GPIO 39。

剩下的可用引脚里,我挑了两个做扩展:GPIO 25 和 GPIO 26 留给温湿度传感器 DHT22,GPIO 27 留给一个蜂鸣器做声音反馈。这里有个细节要注意,ESP32 的 GPIO 34 到 39 是输入专用,没有内部上拉电阻,接按钮或者传感器的时候必须外接上拉电阻,否则读数会飘。我一开始没注意,超声波模块的 Echo 引脚接在 GPIO 35 上,读数一直不稳定,后来在模块端加了一个 10K 的上拉电阻才解决。

提示:ESP32 的 GPIO 6 到 GPIO 11 连接的是内部 SPI Flash,绝对不要用来接外部设备,否则会导致程序无法启动。GPIO 0 是启动模式选择引脚,上电时如果被拉低会进入下载模式,做产品的时候要避免外部电路在启动瞬间把它拉低。

2.2 电机驱动与电源管理的实操细节

TB6612FNG 这颗电机驱动芯片比传统的 L298N 好用很多,导通电阻小、发热低、支持 PWM 频率高。Freenove 扩展板上已经焊好了这颗芯片,电机接口也是标准的 PH2.0 端子,直接插上就行。但电源部分需要特别注意。套件里配的是四节 AA 电池盒,输出电压在 4.8V 到 6V 之间,而 ESP32 的工作电压是 3.3V,电机驱动逻辑电平也是 3.3V。扩展板上有一颗 AMS1117-3.3 稳压芯片,把电池电压降到 3.3V 给 ESP32 供电。问题在于,当四个电机同时启动的瞬间,电流会突然拉大,导致 3.3V 电压跌落,ESP32 会复位。我实测过,四节满电的镍氢电池在电机堵转时,电压能从 5.2V 瞬间掉到 3.8V 以下,AMS1117 的压差不够,输出就稳不住。

解决办法有两个。方案一是换电池,用两节 18650 锂电池串联,电压 7.4V,经过 AMS1117 降到 3.3V 时压差充足,电压跌落的影响小很多。方案二是加电容,在扩展板的电源输入端并联一个 470uF 到 1000uF 的电解电容,再并一个 0.1uF 的陶瓷电容滤高频。我两个方案都上了,现在四驱同时启动也不会复位。另外,电机电源和逻辑电源最好分开走线,避免电机电流在地线上产生压降干扰 ESP32 的模拟采样。扩展板本身没有做电源隔离,我在电池盒和扩展板之间加了一个拨动开关,方便断电重启。

2.3 LED 点阵屏的驱动原理与刷新策略

8x16 的 LED 点阵屏是 Nova 表情系统的核心。这块屏用的是 MAX7219 驱动芯片,每颗芯片驱动 8x8 的 LED 矩阵,两块级联组成 8x16。MAX7219 通过 SPI 接口接收数据,刷新率最高可以到 800Hz,人眼完全看不到闪烁。但 Arduino 的LedControl库默认刷新率比较低,而且每次刷新都要占用 CPU 时间。我的做法是用 ESP32 的硬件 SPI 加上 DMA 传输,把刷新任务放在一个独立的 FreeRTOS 任务里,优先级设低一点,每 10ms 刷新一次。这样主循环完全不受影响,表情动画也能保持流畅。

表情数据我定义成了一个二维数组,每个表情是一帧 8x16 的位图,用uint8_t数组存储。比如“眨眼”动画就是三帧:眼睛全开、半闭、全闭,循环播放。为了节省内存,我把所有表情帧放在 PROGMEM 里,需要的时候再读出来。这里有个坑,MAX7219 的数据格式是每列 8 位,对应 8 行 LED,而我的位图是按行定义的,所以写入之前要做一次转置。我写了一个简单的转置函数,在初始化的时候把位图预处理成 MAX7219 需要的格式,运行时直接查表,省去了实时计算的开销。

3. 软件架构与核心代码实现

3.1 FreeRTOS 双核任务划分与通信机制

Nova 的软件架构基于 FreeRTOS,我把功能拆成了三个任务。任务一是传感器采集,运行在 Core 0 上,每 50ms 读一次超声波距离和红外接收状态,把数据打包成结构体,通过队列发送给逻辑任务。任务二是行为逻辑,也运行在 Core 0 上,从队列里取传感器数据,根据当前状态机决定下一步动作,把电机指令和表情指令分别发送到两个队列。任务三是执行输出,运行在 Core 1 上,从队列里取指令,驱动电机和刷新 LED 点阵。三个任务通过 FreeRTOS 的队列通信,队列长度都设成 5,满了就丢弃最旧的数据,保证实时性。

任务优先级的分配有讲究。传感器采集任务优先级设成 3,行为逻辑设成 2,执行输出设成 4。执行输出的优先级最高,因为电机控制和 LED 刷新对时序要求最严格,延迟超过 20ms 人眼就能看出卡顿。传感器采集优先级中等,超声波模块本身有测量周期,读太快也没意义。行为逻辑优先级最低,因为它只做决策,不直接控制硬件,偶尔延迟一下不影响体验。栈大小方面,传感器任务给了 2048 字节,逻辑任务 4096 字节,输出任务 3072 字节。ESP32 的 RAM 有 520KB,这点开销完全不是问题。

// 队列定义 QueueHandle_t sensorQueue = xQueueCreate(5, sizeof(SensorData)); QueueHandle_t motorQueue = xQueueCreate(5, sizeof(MotorCmd)); QueueHandle_t faceQueue = xQueueCreate(5, sizeof(FaceCmd)); // 任务创建 xTaskCreatePinnedToCore(sensorTask, "Sensor", 2048, NULL, 3, NULL, 0); xTaskCreatePinnedToCore(logicTask, "Logic", 4096, NULL, 2, NULL, 0); xTaskCreatePinnedToCore(outputTask, "Output", 3072, NULL, 4, NULL, 1);

3.2 超声波测距的滤波与避障逻辑

超声波模块 HC-SR04 的原始读数抖动很大,直接拿来用会导致 Nova 频繁误判。我用了两个手段做滤波。第一是硬件层面,在 Echo 引脚上加了一个 RC 低通滤波,电阻 1K,电容 0.1uF,把高频噪声滤掉。第二是软件层面,连续读五次,去掉最大值和最小值,剩下的取平均。这样处理之后,读数稳定性明显提升,在 30cm 范围内的波动能控制在 1cm 以内。

避障逻辑我设计得比较保守。当距离小于 15cm 时,Nova 进入“警觉”状态,眼睛睁大,身体后退 10cm;当距离小于 8cm 时,进入“躲避”状态,快速后退并转向,直到距离大于 20cm 才恢复。这里有个细节,超声波模块的测量角度只有 15 度左右,如果障碍物在侧面,它是测不到的。所以我在底盘左右两侧各加了一个红外避障传感器,作为补充。红外传感器的输出是数字信号,直接接 GPIO 就行,代码里用外部中断处理,响应速度比轮询快很多。

float readUltrasonic() { digitalWrite(TRIG_PIN, LOW); delayMicroseconds(2); digitalWrite(TRIG_PIN, HIGH); delayMicroseconds(10); digitalWrite(TRIG_PIN, LOW); long duration = pulseIn(ECHO_PIN, HIGH, 30000); float distance = duration * 0.034 / 2; return distance; } float filteredDistance() { float readings[5]; for (int i = 0; i < 5; i++) { readings[i] = readUltrasonic(); delay(10); } // 排序后去掉最大最小值 // ... 省略排序代码 return (readings[1] + readings[2] + readings[3]) / 3.0; }

3.3 LED 点阵表情动画的实现与优化

表情动画的实现分三步:定义帧数据、预处理转置、定时刷新。帧数据我用了一个 Python 脚本从图片生成,把 8x16 的黑白图片转成uint8_t数组,每个字节代表一列。生成之后直接粘贴到代码里,放在 PROGMEM 中。预处理转置在setup()里做一次,把行优先的位图转成列优先的格式,存到一个全局数组里。刷新任务每 10ms 调用一次refreshDisplay(),从当前动画帧里取数据,通过 SPI 写到 MAX7219。

动画切换我用了一个简单的状态变量currentAnim,每个动画有一个帧数组和帧率。比如“眨眼”动画有三帧,帧率 100ms;“生气”动画有两帧,帧率 200ms,循环播放。切换动画的时候直接改currentAnim和对应的帧指针,刷新任务下一轮就会用新数据。这里要注意动画切换的原子性,如果刷新任务正在读帧数据,主逻辑突然改了指针,可能会读到半新半旧的数据。我的做法是用一个互斥锁保护动画状态,切换的时候先拿锁,改完再释放。ESP32 的 FreeRTOS 支持递归互斥锁,用起来很方便。

提示:MAX7219 的 SPI 时钟频率最高支持 10MHz,但实际用的时候建议降到 1MHz 到 4MHz,走线长或者干扰大的时候更稳定。我在platformio.ini里把 SPI 频率设成了 2MHz,刷新 8x16 的点阵完全够用,也没有出现花屏。

4. 无线交互与扩展功能

4.1 ESP32 内嵌 Web 页面的实现方式

Nova 的 Web 控制页面跑在 ESP32 上,用的是ESPAsyncWebServer库。这个库比标准的WebServer库好用很多,支持异步处理,不会阻塞主循环。页面本身是一个简单的 HTML 文件,包含几个按钮:前进、后退、左转、右转、停止,还有一个表情选择下拉框。按钮点击的时候,浏览器发送一个 GET 请求到 ESP32,比如/move?dir=forward,ESP32 解析参数后把指令发到电机队列。

HTML 文件我放在 LittleFS 文件系统里,而不是直接嵌在代码里。这样做的好处是修改页面不用重新编译固件,直接通过串口或者 OTA 上传新的 HTML 文件就行。PlatformIO 对 LittleFS 的支持很好,在platformio.ini里加一行board_build.filesystem = littlefs,然后把 HTML 文件放在data目录下,编译的时候会自动打包成镜像。上传的时候用pio run --target uploadfs命令,几秒钟就搞定。

// Web 服务器路由 server.on("/move", HTTP_GET, [](AsyncWebServerRequest *request){ String dir = request->getParam("dir")->value(); MotorCmd cmd; if (dir == "forward") cmd = {200, 200}; else if (dir == "backward") cmd = {-200, -200}; else if (dir == "left") cmd = {-150, 150}; else if (dir == "right") cmd = {150, -150}; else cmd = {0, 0}; xQueueSend(motorQueue, &cmd, 0); request->send(200, "text/plain", "OK"); });

4.2 蓝牙串口控制与手机 App 配网

除了 Wi-Fi,Nova 还支持蓝牙串口控制。ESP32 的经典蓝牙和 BLE 都支持,我用的是经典蓝牙的 SPP 协议,手机端装一个通用的蓝牙串口 App 就能连。代码里用BluetoothSerial库,初始化之后SerialBT.available()就能读到手机发来的指令。指令格式和 Web 页面保持一致,比如发送MOVE:F表示前进,FACE:2表示切换到第二个表情。蓝牙的好处是不需要配网,开机就能连,适合在没有 Wi-Fi 的环境下快速控制。

配网这块我用了WiFiManager库,第一次上电的时候 Nova 会开一个热点,手机连上之后弹出配置页面,输入 Wi-Fi 密码后自动保存并重启。后续上电会自动连接保存的 Wi-Fi,连不上就重新开热点。这个库的好处是不需要在代码里硬编码 Wi-Fi 密码,分享给别人的时候也不用担心密码泄露。不过WiFiManager的默认超时是 180 秒,我改成了 60 秒,避免长时间卡在配网模式。

4.3 温湿度传感器与边缘 AI 的初步尝试

温湿度传感器我选的是 DHT22,精度比 DHT11 高不少,温度误差正负 0.5 度,湿度误差正负 2%。接线很简单,VCC 接 3.3V,GND 接地,数据脚接 GPIO 25,中间加一个 10K 的上拉电阻。代码里用DHTesp库读取数据,每 2 秒读一次,读到的温湿度显示在 Web 页面上,同时根据温度调整 Nova 的表情——温度高于 30 度时显示“热”的表情,低于 10 度时显示“冷”的表情。这个功能虽然简单,但让 Nova 有了对环境的基本感知,不再只是一个遥控玩具。

边缘 AI 这块我还在摸索阶段。ESP32 的算力有限,跑不了复杂的神经网络,但跑一些简单的分类模型还是可以的。我试过用 TensorFlow Lite for Microcontrollers 部署一个三层的全连接网络,输入是超声波距离、红外状态、温湿度,输出是“前进”“后退”“转向”三个动作。模型训练在电脑上完成,量化成 int8 之后只有几 KB,推理时间在 10ms 以内。不过实际效果一般,因为训练数据太少,模型容易过拟合。后续打算加一个 MPU6050 陀螺仪,采集更多维度的数据,再重新训练一版。

5. 常见问题与排查实录

5.1 编译与烧录阶段的典型问题

问题一:PlatformIO 编译 ESP32 项目时报错fatal error: esp32-hal.h: No such file or directory。这个通常是平台包没装全,在 PlatformIO 的 PIO Home 里点 Platforms,搜 espressif32,重新安装一遍。如果还是不行,删掉~/.platformio目录下的packages文件夹,重新编译,让 PlatformIO 自动下载依赖。

问题二:烧录时提示Failed to connect to ESP32: Timed out waiting for packet header。检查 USB 线是不是只供电不传数据,换一根线试试。如果线没问题,按住开发板上的 BOOT 键,再点烧录,等出现Connecting...的时候松开。Freenove 的板子有自动下载电路,正常情况下不需要手动按,但如果串口被其他程序占用了,自动下载会失败。关掉串口监视器和其他占用串口的软件再试。

问题三:Windows 上编译速度特别慢,每次都要好几分钟。在platformio.ini里加build_cache_dir = .pio/build_cache,开启编译缓存。另外把项目目录加到 Windows Defender 的排除列表里,实时扫描对编译速度影响很大。如果还是慢,考虑换 Linux 或者 macOS 开发,同样的项目在 Ubuntu 上编译只要 30 秒左右。

5.2 运行阶段的硬件与软件故障排查

问题四:电机启动时 ESP32 复位。前面电源部分已经分析过,根本原因是电压跌落。先加电容,470uF 起步,不行就换 18650 电池。另外检查电机线有没有短路,四驱底盘的电机线在亚克力板边缘容易磨破皮,我用热缩管把裸露的接头都包了一遍。

问题五:LED 点阵显示花屏或者闪烁。先检查 SPI 线有没有接好,MAX7219 的 DIN、CLK、CS 三根线要远离电机线,避免干扰。如果线没问题,把 SPI 频率降到 1MHz 试试。还有一种可能是刷新任务和主循环抢 SPI 总线,确保只有刷新任务在操作 MAX7219,其他任务不要直接调 SPI。

问题六:超声波读数一直不变或者跳变。检查 Echo 引脚有没有上拉电阻,GPIO 34 到 39 是输入专用,没有内部上拉。另外超声波模块对电源噪声很敏感,在 VCC 和 GND 之间并一个 0.1uF 的陶瓷电容,效果立竿见影。如果还是不行,换一个超声波模块,HC-SR04 的品控参差不齐,我买到过一批次品,读数完全不能用。

问题七:Web 页面打不开或者响应很慢。先确认 ESP32 和手机在同一个 Wi-Fi 网络下,然后检查ESPAsyncWebServer的端口是不是 80。如果路由器开了 AP 隔离,设备之间不能互访,需要在路由器设置里关掉。另外WiFiManager配网之后,ESP32 的 IP 地址可能会变,在串口监视器里打印一下 IP,用新 IP 访问。

5.3 常见问题速查表

现象可能原因排查方法解决方案
编译报错找不到头文件平台包缺失检查~/.platformio/packages重装 espressif32 平台
烧录超时串口被占用或线材问题换线、关串口监视器手动按 BOOT 键烧录
电机启动复位电源电压跌落万用表测 3.3V 电压加电容或换 18650 电池
LED 点阵花屏SPI 干扰或频率过高降低 SPI 频率远离电机线,加屏蔽
超声波读数异常缺上拉电阻或电源噪声检查 GPIO 34-39 上拉加 10K 上拉和 0.1uF 电容
Web 页面无法访问网络隔离或 IP 变化串口打印 IP关 AP 隔离,用新 IP
蓝牙连不上配对信息冲突删除手机端配对记录重新配对,重启 ESP32

提示:ESP32 的 GPIO 12 是启动模式引脚之一,如果外部电路在上电时把它拉高,ESP32 会进入错误的启动模式。Freenove 扩展板上 GPIO 12 接了电机驱动,上电瞬间电机驱动的输入阻抗可能会影响电平,导致偶尔启动失败。我的做法是在 GPIO 12 和 GND 之间加一个 10K 的下拉电阻,确保上电时电平稳定。

6. 个人实操心得与后续扩展方向

6.1 从零到一搭建 Nova 的几点体会

这个项目从起意到基本能用,前后花了大概三周时间,大部分时间不是在写代码,而是在调硬件和排查各种莫名其妙的故障。最大的体会是电源设计比代码重要得多。我一开始把精力都放在软件架构上,结果电机一启动就复位,查了两天才发现是电源问题。后来换了 18650 电池、加了电容,所有莫名其妙的复位和花屏问题都消失了。如果你也要做类似的项目,先把电源方案定下来,再动代码,能省掉很多返工。

第二个体会是不要追求一步到位。我最初想把所有功能都塞进去,结果代码越写越乱,调试难度指数级上升。后来我改成增量开发:先让电机能转,再加 LED 点阵,再加超声波,最后加无线控制。每加一个功能就测试一遍,确保之前的没问题再继续。这样虽然看起来慢,但实际效率高很多,出了问题也能快速定位是哪个环节引入的。

第三个体会是善用现成的库,但要知道库的边界。Arduino 生态的库很多,但质量参差不齐。ESPAsyncWebServer和WiFiManager这两个库帮我省了大量时间,但LedControl库的性能不行,我最后还是自己写了 SPI 刷新逻辑。选库的时候先看 GitHub 的 star 数和最近更新时间,太老的库慎用,ESP32 的 Arduino 核心更新很快,老库可能不兼容。

6.2 Nova 后续可以怎么玩

Nova 目前的功能还比较基础,后续我打算从三个方向扩展。第一是加一个摄像头模块,ESP32-CAM 或者外接 OV2640,做简单的图像识别,比如识别手势或者颜色,让 Nova 能对人的动作做出反应。第二是加一个麦克风模块,用 INMP441 做声音采集,检测拍手或者特定频率的声音,实现声控唤醒。第三是加一个舵机云台,让超声波模块能旋转扫描,实现更广的探测范围,同时云台的动作也能作为表情的一部分,让 Nova 的“肢体语言”更丰富。

软件层面,我打算把行为逻辑从硬编码的状态机改成基于规则引擎的决策系统,用 JSON 配置文件定义状态和转移条件,这样调整行为不用重新编译固件,改配置文件就行。另外还想试试 ESP-IDF 的原生开发,对比一下和 Arduino 框架在性能和资源占用上的差异。ESP32 的蓝牙 Mesh 功能也很有意思,如果做多个 Nova,可以让它们之间互相通信,实现群体行为,比如一起前进、一起转向,像一群小动物一样。

最后分享一个我在调试过程中发现的小技巧。ESP32 的串口日志默认输出到 UART0,但如果你用 USB 转串口模块接在 GPIO 16 和 17 上,可以把日志重定向到 UART2,这样 UART0 就空出来做其他用途。在platformio.ini里加-D CORE_DEBUG_LEVEL=3可以控制日志级别,调试的时候开 verbose,发布的时候关掉,能省不少串口带宽。这个技巧在同时用串口和蓝牙的时候特别有用,避免日志和蓝牙数据抢串口。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询