尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

ESP32多屏联动模拟赛车仪表:动态数据映射与SIMHUB实战

ESP32多屏联动模拟赛车仪表:动态数据映射与SIMHUB实战 1. 从单屏到多屏模拟赛车仪表进阶的核心思路玩模拟赛车的人迟早会走到一个岔路口原厂游戏自带的仪表盘信息太少或者布局不合心意想自己搞一套外置仪表。最开始大家基本都是从一块Arduino加一个OLED或者小TFT屏起步的能显示个转速、车速就已经很满足了。但玩着玩着就会发现一块屏根本不够用——转速要盯着、圈速要盯着、轮胎温度也要盯着还有油量、档位、G力、刹车偏置……一块屏塞得密密麻麻开车的时候根本来不及看。这时候就自然过渡到了多屏联动的需求。所谓多屏联动不是简单地把几块屏插在一起各显示各的而是让它们作为一个整体协同工作主屏负责核心驾驶信息副屏负责战术信息第三块屏可能专门做警示灯或者遥测数据可视化。而动态数据映射则是让这些屏幕上的内容能够根据驾驶状态实时变化——比如进站时自动切换到油量策略界面出站后切回圈速对比轮胎温度过高时对应区域闪烁告警。这套东西听起来复杂但拆开来看核心无非是三件事数据从哪来、数据怎么分、数据怎么显示。SIMHUB负责从游戏里把遥测数据抓出来Arduino负责接收并驱动屏幕中间的分发和映射逻辑就是我们需要自己写的部分。我前后折腾了大概三套方案从最开始的单块Uno加I2C屏到后来用ESP32做网络分发再到现在的多屏协同架构踩过的坑基本覆盖了新手能遇到的所有典型问题。这篇文章适合已经玩过基础版Arduino赛车仪表、想进一步做多屏联动的朋友。如果你还没入门建议先搞一块Uno加一个0.96寸OLED把基础数据跑通再来看这篇。全文会围绕架构设计、硬件选型、数据映射逻辑、实操步骤、问题排查五个维度展开每个部分都会给出我实际验证过的参数和代码片段你可以直接抄作业也可以根据自己的需求调整。提示多屏方案对Arduino的性能有一定要求如果你还在用Uno R3建议至少升级到ESP32或者Uno R4不然后面会讲到的一些动态映射逻辑跑起来会卡顿。2. 硬件选型与通信架构为什么我最终选了ESP32做主控2.1 主控芯片的对比与选择逻辑先说结论多屏联动场景下ESP32是性价比最高的选择。我试过用Arduino Uno R3同时驱动两块I2C OLED和一块SPI TFT结果刷新率直接掉到个位数转速指针卡得像幻灯片。后来换成ESP32同样的屏幕配置刷新率稳定在30fps以上而且还有余力跑网络通信。具体对比一下我用过的几款主控主控型号核心频率内存多屏支持能力网络能力适合场景Arduino Uno R316MHz2KB SRAM单屏勉强双屏吃力需外接模块入门单屏Arduino Nano16MHz2KB SRAM同Uno需外接模块空间受限的单屏ESP32240MHz520KB SRAM三屏流畅内置WiFi/蓝牙多屏联动首选ESP826680MHz80KB SRAM双屏可行内置WiFi双屏网络方案Arduino Uno R448MHz32KB SRAM双屏流畅内置WiFi预算充足的Uno升级ESP32的优势不只是性能它的双核架构让网络通信和屏幕刷新可以分到不同核心上跑互不干扰。我现在的方案是核心0负责接收SIMHUB发来的UDP数据包并解析核心1专门负责驱动三块屏幕的刷新实测下来数据延迟稳定在15ms以内肉眼完全感觉不到。2.2 屏幕类型与接口分配多屏方案里屏幕的接口分配是个容易忽略但很关键的问题。I2C屏幕接线简单但带宽有限SPI屏幕刷新快但占用引脚多。我的建议是主屏转速车速用SPI接口的1.8寸TFT刷新率要求最高SPI的带宽足够支撑每秒30帧以上的局部刷新。副屏圈速油量轮胎用I2C接口的1.3寸OLED信息密度高但刷新要求相对低I2C的400kHz速率够用。第三屏警示灯遥测用I2C接口的0.96寸OLED只显示少量状态信息刷新率要求最低。I2C设备可以共用同一组SDA/SCL引脚通过不同地址区分。ESP32的默认I2C引脚是GPIO21SDA和GPIO22SCL我实际用下来发现这两个引脚接两块OLED完全没问题地址分别是0x3C和0x3D。SPI屏幕单独占用一组引脚具体接线后面实操部分会详细说。注意I2C总线上挂载多个设备时总线上拉电阻很关键。很多模块自带上拉电阻如果并联太多会导致等效电阻过小通信不稳定。我实测两块OLED并联时工作正常三块以上就需要检查上拉电阻是否合适必要时去掉部分模块的上拉电阻。2.3 SIMHUB的数据输出机制SIMHUB本身是一个游戏遥测数据转发工具它支持多种输出方式UDP、共享内存、串口等。多屏方案里我推荐用UDP输出因为ESP32内置WiFi可以直接通过网络接收数据省去了USB线缆的束缚而且UDP的延迟比串口更低。SIMHUB的UDP输出配置里你需要设置目标IP和端口。ESP32作为客户端连接WiFi后会获得一个局域网IP把这个IP填到SIMHUB的UDP输出设置里就行。端口我习惯用20777这是SIMHUB社区里比较常用的一个端口号不容易和其他服务冲突。数据格式方面SIMHUB默认输出的是它自己的数据包结构包含了几十个字段。你不需要全部解析只挑你需要的字段就行。我常用的字段包括Speed车速、RPM转速、Gear档位、Throttle油门、Brake刹车、Steering转向角、Fuel油量、TyreTemp轮胎温度等。具体字段名可以在SIMHUB的文档里查到不同游戏版本可能略有差异。3. 动态数据映射的核心逻辑让屏幕知道什么时候该显示什么3.1 什么是动态数据映射静态映射就是“转速永远显示在屏幕左上角”动态映射则是“转速在正常范围内显示在左上角超过红线区时整个屏幕边框变红闪烁”。前者只是把数据画出来后者是让数据根据状态改变显示方式。我最初做单屏的时候就是纯静态映射所有数据固定位置显示。后来发现开车的时候根本注意不到关键信息——油量快没了还在看圈速轮胎过热了还在盯转速。动态映射解决的就是这个问题让屏幕主动告诉你该看什么。实现动态映射的核心是一个状态机。你需要定义几种驾驶状态每种状态下屏幕的布局和内容不同。我目前定义了五种状态常规驾驶主屏显示转速车速档位副屏显示圈速油量第三屏显示轮胎温度。进站准备油量低于设定阈值时触发副屏自动切换到油量策略界面显示剩余圈数和建议加油量。轮胎过热任一轮胎温度超过阈值时触发第三屏对应轮胎位置闪烁红色主屏边框变橙。换挡提示转速接近红线时触发主屏顶部LED条闪烁提示升档。事故/失控G力超过阈值或车辆打滑时触发全屏闪烁警示。状态之间的切换逻辑用简单的if-else就能实现关键是阈值要可配置不同车型、不同赛道的最佳阈值不一样硬编码在代码里会很难受。3.2 数据分发的实现方式多屏联动的另一个核心问题是数据怎么从ESP32分发到三块屏幕上。最直接的方式是每块屏幕各自从主循环里读取全局变量但这样会导致刷新不同步——主屏已经更新了副屏还是旧数据。我的做法是统一数据池屏幕刷新调度。ESP32收到UDP数据后先解析到一个全局结构体里这个结构体就是“数据池”。然后三块屏幕各自有一个刷新函数每个函数从数据池里读取自己需要的字段按照自己的刷新周期更新。主屏刷新周期是33ms约30fps副屏是100ms第三屏是200ms。这样既保证了主屏的流畅性又不会让副屏和第三屏占用过多CPU时间。// 数据池结构体定义 struct TelemetryData { float speed; // 车速 km/h float rpm; // 转速 int gear; // 档位 float throttle; // 油门 0-100 float brake; // 刹车 0-100 float fuel; // 油量 0-100 float tyreTemp[4]; // 四轮温度 float gForceX; // 横向G力 float gForceY; // 纵向G力 unsigned long lastUpdate; // 最后更新时间 }; TelemetryData telemetry; // 主屏刷新函数核心1 void taskMainScreen(void *pvParameters) { while(1) { updateMainScreen(telemetry); vTaskDelay(33 / portTICK_PERIOD_MS); } } // 副屏刷新函数核心1 void taskSubScreen(void *pvParameters) { while(1) { updateSubScreen(telemetry); vTaskDelay(100 / portTICK_PERIOD_MS); } }上面这段代码展示了双核调度的基本框架。核心0跑UDP接收和解析核心1跑三个屏幕的刷新任务。实际写的时候要注意数据池的读写保护——核心0在写数据池的时候核心1可能在读不加保护会出现数据撕裂。简单做法是用一个portMUX_TYPE自旋锁或者用双缓冲机制。3.3 阈值配置与动态切换的实操细节动态映射的阈值配置我建议放在一个单独的头文件里用宏定义或者常量数组方便修改。比如// config.h 阈值配置 #define RPM_REDLINE 7200 // 红线转速 #define RPM_SHIFT_LIGHT 6800 // 换挡提示转速 #define FUEL_LOW_THRESHOLD 15.0 // 低油量阈值百分比 #define TYRE_TEMP_HIGH 110.0 // 轮胎高温阈值摄氏度 #define GFORCE_ALERT 2.5 // G力告警阈值这些阈值不是拍脑袋定的要根据你常玩的游戏和车型来调。比如F1车型的红线转速通常在12000以上而GT3车型一般在7000左右。轮胎温度阈值也因车型而异GT3的最佳工作温度在80-100度超过110度就开始明显衰减了。状态切换的逻辑我写成了一个独立函数每帧调用一次enum DrivingState { STATE_NORMAL, STATE_PIT_PREP, STATE_TYRE_HOT, STATE_SHIFT, STATE_ALERT }; DrivingState currentState STATE_NORMAL; DrivingState evaluateState(TelemetryData data) { // 优先级从高到低判断 if (abs(data.gForceX) GFORCE_ALERT || abs(data.gForceY) GFORCE_ALERT) { return STATE_ALERT; } if (data.rpm RPM_SHIFT_LIGHT data.rpm RPM_REDLINE) { return STATE_SHIFT; } for (int i 0; i 4; i) { if (data.tyreTemp[i] TYRE_TEMP_HIGH) { return STATE_TYRE_HOT; } } if (data.fuel FUEL_LOW_THRESHOLD) { return STATE_PIT_PREP; } return STATE_NORMAL; }这段逻辑里优先级顺序很重要。事故告警优先级最高因为安全相关换挡提示其次因为影响驾驶节奏轮胎过热再次进站准备最低。实际跑的时候你会发现有时候多个条件同时满足比如轮胎过热的同时油量也低了这时候按优先级只显示最高优先级的界面但可以在界面上用小图标提示其他状态。4. 完整实操流程从零搭建三屏联动系统4.1 硬件清单与接线方案先列一下我当前方案用到的全部硬件你可以根据预算和需求增减硬件型号/规格数量用途主控ESP32 DevKit V11核心处理主屏1.8寸 SPI TFT (ST7735)1转速车速档位副屏1.3寸 I2C OLED (SH1106)1圈速油量轮胎第三屏0.96寸 I2C OLED (SSD1306)1警示灯遥测电源5V 2A USB供电1整机供电连接线杜邦线若干-接线接线方案如下SPI TFT主屏VCC → 3.3VGND → GNDCS → GPIO5RESET → GPIO4DC → GPIO2MOSI → GPIO23SCK → GPIO18LED → 3.3V背光常亮I2C OLED副屏和第三屏共用总线VCC → 3.3VGND → GNDSDA → GPIO21SCL → GPIO22两块I2C屏幕的地址通过模块背面的电阻跳线区分默认一块是0x3C另一块改成0x3D。改地址的方法因模块而异有的需要焊跳线有的可以直接在背面短接。我用的两块模块刚好一块默认0x3C另一块把背面的A0电阻位短接后就变成0x3D了。提示ESP32的3.3V输出电流有限三块屏幕同时工作时背光全开可能会超过ESP32的供电能力。建议TFT背光直接接5V如果模块支持或者用外部5V电源单独给屏幕供电ESP32只负责信号线。4.2 开发环境配置与库安装开发环境我用的是Arduino IDE 2.x版本比1.8.x的代码补全和调试体验好很多。如果你还在用1.8.6建议升级特别是多文件项目的时候2.x的标签页管理方便太多。需要安装的库TFT_eSPI驱动SPI TFT性能比Adafruit_ST7735好很多支持DMA刷新。U8g2驱动I2C OLED支持多种字体和图形内存占用可控。WiFiUdpESP32内置不需要额外安装。ArduinoJson如果SIMHUB输出的是JSON格式需要这个库解析。不过我用的SIMHUB版本输出的是二进制结构直接按字节偏移解析就行不需要JSON库。TFT_eSPI的配置需要修改User_Setup.h文件选择正确的驱动芯片和引脚定义。这一步是新手最容易卡住的地方因为TFT_eSPI的配置项很多改错一个就白屏。我的配置如下// TFT_eSPI User_Setup.h 关键配置 #define ST7735_DRIVER #define TFT_WIDTH 128 #define TFT_HEIGHT 160 #define TFT_CS 5 #define TFT_DC 2 #define TFT_RST 4 #define TFT_MOSI 23 #define TFT_SCLK 18 #define LOAD_GLCD #define LOAD_FONT2 #define LOAD_FONT4 #define SPI_FREQUENCY 40000000SPI_FREQUENCY设成40MHz是我实测下来ST7735能稳定工作的最高频率再高会出现花屏。如果你的屏幕质量好可以试试80MHz但要做好散热。4.3 SIMHUB端配置与数据验证SIMHUB端的配置相对简单但有几个细节容易忽略。打开SIMHUB后进入Settings→UDP勾选Enable UDP然后设置IP地址填ESP32的局域网IP可以在ESP32的串口监视器里看到。端口20777数据频率建议设成60Hz和游戏帧率匹配。数据格式选Raw或者Custom具体看你用的SIMHUB版本。配置完之后先在ESP32上跑一个简单的UDP接收测试程序把收到的数据包打印到串口确认数据能正常收到。这一步很重要我见过太多人直接上完整代码结果屏幕不亮排查半天发现是UDP根本没通。// UDP接收测试 #include WiFi.h #include WiFiUdp.h const char* ssid 你的WiFi名称; const char* password 你的WiFi密码; WiFiUDP udp; char packetBuffer[512]; void setup() { Serial.begin(115200); WiFi.begin(ssid, password); while (WiFi.status() ! WL_CONNECTED) { delay(500); Serial.print(.); } Serial.println(\nWiFi connected); Serial.print(IP: ); Serial.println(WiFi.localIP()); udp.begin(20777); } void loop() { int packetSize udp.parsePacket(); if (packetSize) { int len udp.read(packetBuffer, 512); Serial.print(Received ); Serial.print(len); Serial.println( bytes); // 打印前16个字节的十六进制值 for (int i 0; i 16 i len; i) { Serial.printf(%02X , packetBuffer[i]); } Serial.println(); } }跑通这个测试后你会看到串口不断打印出十六进制数据。接下来就是根据SIMHUB的数据包结构找到你需要的字段的字节偏移。这个偏移量因SIMHUB版本和游戏不同会有差异最可靠的方法是查SIMHUB的官方文档或者用社区里别人整理好的偏移表。4.4 屏幕布局设计与代码实现三块屏幕的布局我改了好几版最终定下来的方案是主屏1.8寸TFT128x160顶部档位大字显示居中占1/4屏高。中部转速条横向带红线区标记。底部车速数字大字体右下角显示G力数值。副屏1.3寸OLED128x64左半圈速和delta时间。右半油量条和剩余圈数。底部四轮温度用四个小方块表示温度越高颜色越红。第三屏0.96寸OLED128x64上半换挡提示LED条从左到右逐渐点亮。下半状态文字显示当前驾驶状态NORMAL/PIT/TYRE HOT等。主屏的转速条我用TFT_eSPI的fillRect实现每帧只重绘变化的部分避免全屏刷新导致闪烁。具体做法是记录上一帧的转速值如果变化超过一定阈值才重绘转速条区域。// 主屏转速条局部刷新 void updateRPMBar(float rpm) { static float lastRPM -1; if (abs(rpm - lastRPM) 50) return; // 变化太小不刷新 lastRPM rpm; int barWidth map(rpm, 0, RPM_REDLINE, 0, 120); barWidth constrain(barWidth, 0, 120); tft.fillRect(4, 60, 120, 12, TFT_BLACK); // 清空区域 tft.fillRect(4, 60, barWidth, 12, TFT_GREEN); if (rpm RPM_SHIFT_LIGHT) { tft.fillRect(4, 60, barWidth, 12, TFT_YELLOW); } if (rpm RPM_REDLINE) { tft.fillRect(4, 60, barWidth, 12, TFT_RED); } }副屏的轮胎温度显示我用U8g2的drawBox画四个小方块颜色根据温度映射。U8g2在I2C OLED上不支持彩色所以用填充程度来表示温度高低——温度越高方块填充越满。// 副屏轮胎温度显示 void updateTyreTemp(U8G2 u8g2, float temps[4]) { int xPos[4] {0, 32, 64, 96}; for (int i 0; i 4; i) { int fillHeight map(temps[i], 60, 120, 0, 16); fillHeight constrain(fillHeight, 0, 16); u8g2.drawFrame(xPos[i], 48, 28, 16); u8g2.drawBox(xPos[i], 48 (16 - fillHeight), 28, fillHeight); } }4.5 动态映射的完整状态切换实现把前面说的状态机和屏幕刷新结合起来主循环的结构是这样的void loop() { // 核心0接收UDP数据 int packetSize udp.parsePacket(); if (packetSize) { udp.read(packetBuffer, 512); parseTelemetry(packetBuffer, telemetry); telemetry.lastUpdate millis(); } // 评估当前驾驶状态 DrivingState newState evaluateState(telemetry); if (newState ! currentState) { currentState newState; onStateChange(currentState); // 状态切换时的特殊处理 } // 根据状态更新屏幕 updateMainScreen(telemetry, currentState); updateSubScreen(telemetry, currentState); updateThirdScreen(telemetry, currentState); delay(10); // 控制循环频率 }onStateChange函数里处理状态切换时的特殊逻辑比如从NORMAL切到PIT_PREP时副屏需要立即刷新成油量策略界面而不是等下一个刷新周期。这个函数里还可以加一些过渡动画比如闪烁两次提示状态变化。5. 常见问题与排查技巧实录5.1 屏幕不亮或花屏的排查思路这是新手遇到最多的问题我按排查顺序列一下现象可能原因排查方法完全黑屏供电不足万用表测VCC电压低于3.0V就是供电问题白屏无内容驱动芯片不匹配确认TFT_eSPI的驱动宏定义和实际芯片一致花屏/雪花SPI频率过高降低SPI_FREQUENCY到20MHz测试部分区域异常引脚接触不良重新插拔杜邦线或换一根线I2C屏幕不亮地址冲突用I2C扫描程序确认地址I2C扫描程序是排查I2C问题的利器几行代码就能跑#include Wire.h void setup() { Wire.begin(21, 22); Serial.begin(115200); Serial.println(I2C Scanner); } void loop() { for (byte addr 1; addr 127; addr) { Wire.beginTransmission(addr); if (Wire.endTransmission() 0) { Serial.printf(Found: 0x%02X\n, addr); } } delay(5000); }跑一遍就能知道总线上有哪些设备、地址是多少。如果只扫到一个地址说明另一块屏幕的地址没改成功或者接线有问题。5.2 数据延迟与刷新卡顿的优化多屏方案跑起来之后最常见的问题是数据延迟。你踩油门屏幕上要过零点几秒才反应这在赛道里是致命的。我实测下来延迟主要来自三个环节第一是UDP接收环节。ESP32的WiFi默认开启了省电模式会导致UDP包接收有延迟。在setup()里加一行WiFi.setSleep(false)就能关掉省电模式延迟能从50ms降到10ms以内。第二是数据解析环节。如果你在解析函数里做了大量浮点运算或者字符串操作会拖慢整个循环。我的做法是解析函数只做字节到整数的转换浮点运算留到屏幕刷新函数里做。第三是屏幕刷新环节。TFT全屏刷新一次要几十毫秒如果每帧都全屏刷新30fps根本达不到。必须用局部刷新只重绘变化的部分。我前面给的转速条代码就是局部刷新的例子。提示ESP32的双核调度里loop()默认跑在核心1上。如果你用FreeRTOS创建了独立任务注意任务的优先级设置。屏幕刷新任务的优先级要高于UDP接收任务否则屏幕刷新会被网络数据打断。5.3 动态映射的阈值调参经验阈值调参是个体力活但有几个技巧可以少走弯路先记录再调参。在调参之前先跑一圈完整的比赛把遥测数据记录到SD卡或者通过串口打印出来。然后离线分析这些数据看看转速、油量、轮胎温度的实际分布范围再定阈值。我一开始把轮胎高温阈值设成100度结果发现正常跑两圈就超了后来记录数据才发现我常玩的那辆车最佳工作温度就在95-105度之间阈值得设到115度才合理。阈值要分车型。不同车型的转速红线、最佳胎温、油耗率都不一样。我的做法是在config.h里定义多组阈值用宏切换// 车型阈值配置 #define CAR_GT3 // #define CAR_F1 // #define CAR_RALLY #ifdef CAR_GT3 #define RPM_REDLINE 7200 #define TYRE_TEMP_HIGH 115.0 #define FUEL_LOW_THRESHOLD 12.0 #endif #ifdef CAR_F1 #define RPM_REDLINE 12500 #define TYRE_TEMP_HIGH 105.0 #define FUEL_LOW_THRESHOLD 8.0 #endif留出缓冲区间。阈值不要设得太临界比如红线7200换挡提示不要设成7100那样几乎一直在闪。我一般设成红线的90%左右7200的红线对应6500左右的换挡提示给驾驶员留出反应时间。5.4 多屏联动的同步问题三块屏幕刷新周期不同会出现一种情况主屏已经显示新档位了副屏的圈速还是上一圈的。这在正常驾驶时问题不大但在进站或者事故时信息不一致会让人困惑。我的解决方案是关键状态强制同步。在onStateChange函数里不管当前刷新周期到没到强制刷新所有屏幕一次。这样状态切换时三块屏幕是同步的日常驾驶时各自按自己的周期刷新兼顾了流畅性和一致性。void onStateChange(DrivingState newState) { // 强制刷新所有屏幕 updateMainScreen(telemetry, newState); updateSubScreen(telemetry, newState); updateThirdScreen(telemetry, newState); // 状态切换提示 if (newState STATE_ALERT) { // 全屏闪烁两次 for (int i 0; i 2; i) { tft.fillScreen(TFT_RED); delay(100); tft.fillScreen(TFT_BLACK); delay(100); } } }5.5 电源管理与稳定性三块屏幕加ESP32的功耗不小特别是TFT背光全开的时候。我实测下来ESP32加三块屏幕的峰值电流能到500mA左右。如果你用电脑的USB口供电可能会遇到电压跌落导致ESP32重启的问题。我的做法是用独立的5V 2A电源适配器供电ESP32和屏幕都从这个电源取电。如果必须用USB供电建议加一个大电容1000uF以上在电源输入端缓冲瞬时电流需求。另外ESP32的WiFi模块在发送数据时会有电流尖峰如果电源质量不好会导致屏幕闪烁或者ESP32重启。在电源引脚附近并一个100nF的陶瓷电容和10uF的钽电容能明显改善稳定性。6. 进阶扩展让仪表系统更智能6.1 基于驾驶风格的自动布局调整动态映射的下一步是自适应布局。我最近在尝试的一个方向是根据驾驶风格自动调整屏幕布局。比如检测到连续几圈刹车点都很晚、油门开度很大说明驾驶风格偏激进这时候把轮胎温度和油量信息放大显示因为激进驾驶对轮胎和油耗的影响更大。实现思路是记录最近几圈的驾驶数据计算一个“激进指数”然后根据指数调整屏幕布局参数。这个功能还在实验阶段但初步效果不错特别是在耐力赛里能帮你更早发现轮胎衰减。6.2 多车遥测对比如果你经常和朋友一起跑线上比赛可以扩展成多车遥测对比。ESP32同时接收多个SIMHUB实例的UDP数据在副屏上显示你和对手的圈速差、油量差、轮胎温度差。这个功能需要每个玩家都开SIMHUB的UDP输出并且ESP32要能区分不同来源的数据包。实现上可以用不同的端口号区分不同玩家或者在同一端口里用数据包头的ID字段区分。我试过用端口区分配置简单但需要ESP32开多个UDP监听内存占用会高一些。6.3 无线更新与配置每次改阈值都要重新烧录固件很麻烦特别是仪表已经装在支架上了。我的做法是加一个简单的Web配置页面ESP32开一个HTTP服务你可以在手机或电脑浏览器里修改阈值参数保存到EEPROM里重启后生效。这个功能用ESP32的WebServer库就能实现代码量不大但实用性很高。我现在调参基本不用重新烧录了浏览器里改完保存就行。提示Web配置页面和UDP接收可以共存但要注意Web请求处理会占用CPU时间可能导致UDP数据延迟。我的做法是把Web服务放在核心0上和UDP接收同一个核心屏幕刷新在核心1上不受影响。6.4 外壳与安装的实操建议最后说点硬件之外的。三块屏幕的安装位置很影响使用体验。我的方案是主屏放在方向盘正后方视线不用离开赛道就能看到副屏放在主屏右侧稍微偏一点角度第三屏放在主屏上方专门看警示信息。外壳我用3D打印的材料是PETG比PLA耐温好一些夏天车内温度高的时候不会变形。如果你没有3D打印机用亚克力板手工切割也行就是精度差一点。屏幕和外壳之间用黑色海绵胶条密封防止漏光影响夜间驾驶。接线方面我用的是硅胶软线比杜邦线耐弯折而且颜色区分明显排查问题方便。所有接线用热缩管包好避免短路。ESP32用尼龙柱固定在外壳底部USB接口朝下方便插拔。这套系统我从最开始的一块屏折腾到现在前后大概花了三个月中间换过两次主控、三次屏幕布局。现在这套方案已经稳定跑了半年多每周至少用十个小时没出过大问题。如果你也在做类似的东西希望这些经验能帮你少走点弯路。
返回列表