You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Arduino使用inputString.indexOf解析多变量串口字符串时显示异常的问题排查与解决方案咨询

Fixing Arduino LCD Display Chaos When Parsing Multi-Variable Serial Strings

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

  1. 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 100 to 60), leftover characters will stay on screen and cause weird overlaps.
  2. Fragile Index-Based Parsing: Your current code relies on chained indexOf calls 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 case in the switch statement—no need to adjust complex indexOf chains.
  • 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 16:02:29