Arduino使用inputString.indexOf解析多变量串口字符串时显示异常的问题排查与解决方案咨询
Let's break down what's causing your display issues and fix them properly so you can scale up to 10 variables without headaches.
The Root Causes
- LCD Overlapping Text: When you update a value on the LCD, you're not clearing the old characters first. If a new value is shorter than the previous one (e.g., changing from
100to60), leftover characters will stay on screen and cause weird overlaps. - Fragile Index-Based Parsing: Your current code relies on chained
indexOfcalls that are hard to scale and easy to break. Adding more variables increases the chance of miscalculating delimiter positions, which leads to parsing garbage data.
Step-by-Step Solution
1. Fix LCD Text Overlaps
Each data field has a fixed width (e.g., CPU load is 2 characters, fan speed is 5). Before printing a new value, print enough spaces to overwrite the old content in that area.
2. Replace Parsing with Segment-Based Logic
Instead of chasing delimiter positions manually, split the incoming string by the | character and process each segment individually. This is far more scalable for 10 variables.
Here's the revised Arduino code:
#include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27,20,4); String inputString = ""; boolean stringComplete = false; unsigned long previousUpdate = 0; void printInitialLCDStuff() { lcd.setCursor(0, 0); lcd.print("CPU "); lcd.setCursor(7, 0); lcd.print("%"); lcd.setCursor(11, 0); lcd.print("C"); lcd.setCursor(17, 0); lcd.print("RPM"); lcd.setCursor(0, 1); lcd.print("GPU "); lcd.setCursor(7, 1); lcd.print("%"); lcd.setCursor(11, 1); lcd.print("C"); lcd.setCursor(17, 1); lcd.print("RPM"); lcd.setCursor(0, 2); lcd.print("MEM"); lcd.setCursor(8, 2); lcd.print("MB"); lcd.setCursor(17, 2); lcd.print("PWM"); lcd.setCursor(0, 3); lcd.print("RAM "); lcd.setCursor(8, 3); lcd.print("GBU"); lcd.setCursor(17, 3); lcd.print("GBF"); } void serialEvent() { while (Serial.available()) { char inChar = (char)Serial.read(); inputString += inChar; previousUpdate = millis(); // Trigger parsing when we hit the final delimiter if (inChar == '|') { stringComplete = true; } } } // New scalable parsing function void parseAndDisplay(String input) { int start = 0; int pipePos = input.indexOf('|'); while (pipePos != -1) { String segment = input.substring(start, pipePos); // Skip empty segments (from trailing delimiter) if (segment.length() > 1) { char label = segment.charAt(0); String value = segment.substring(1); // Handle each variable with its LCD position and width switch(label) { case 'A': // CPU Load (2 chars, position 4,0) lcd.setCursor(4, 0); lcd.print(" "); // Clear area lcd.setCursor(4, 0); lcd.print(value); break; case 'B': // CPU Temp (2 chars, position 9,0) lcd.setCursor(9, 0); lcd.print(" "); lcd.setCursor(9, 0); lcd.print(value); break; case 'C': // CPU Fan (5 chars, position 13,0) lcd.setCursor(13, 0); lcd.print(" "); lcd.setCursor(13, 0); lcd.print(value); break; // Add your 7 additional variables here case 'D': // GPU Load (2 chars, position 4,1) lcd.setCursor(4, 1); lcd.print(" "); lcd.setCursor(4, 1); lcd.print(value); break; case 'E': // GPU Temp (2 chars, position 9,1) lcd.setCursor(9, 1); lcd.print(" "); lcd.setCursor(9, 1); lcd.print(value); break; // Continue adding cases F, G, H, I, J for remaining variables } } start = pipePos + 1; pipePos = input.indexOf('|', start); } } void setup() { lcd.init(); lcd.backlight(); printInitialLCDStuff(); Serial.begin(9600); inputString.reserve(200); } void loop() { serialEvent(); // Optional: Add timeout for partial serial data if (inputString.length() > 0 && millis() - previousUpdate > 100) { stringComplete = true; } if (stringComplete) { parseAndDisplay(inputString); inputString = ""; stringComplete = false; } }
Why This Works
- Scalable Parsing: Adding new variables only requires a new
casein the switch statement—no need to adjust complexindexOfchains. - Clean LCD Updates: Clearing each field before printing ensures old values don't overlap with new ones, eliminating the weird mixed text you saw.
- Robust Serial Handling: The optional timeout ensures we only parse after waiting for the full string to arrive, preventing partial data from breaking the parser.
Keep your Python string format the same (e.g., Axx|Bxx|Cxxxxx|Dxx|...|Jxx| with the trailing |), and you'll be able to support 10 variables smoothly.
内容的提问来源于stack exchange,提问作者mystikro

