如何解决带有多个变量的 Arduino inputString.indexOf
我目前正在制作 arduino 监控设备。在 Python 中收集数据,然后将字符串通过串行发送到 arduino。
在 Python 中,字符串如下所示:
cpu1 = space_pad(int(my_info['cpu_load']),2)
cpu2 = space_pad(int(my_info['cpu_temp']),2)
cpu3 = space_pad(int(my_info['cpu_fan']),5)
# Send the strings via serial to the Arduino
arduino_str = \
'A' + cpu1 + '|B' + cpu2 + '|C' + cpu3 + '|'
if serial_debug:
print(arduino_str)
else:
ser.write(arduino_str.encode())
理想情况下,我想让这个字符串尽可能大,以包含 10 个变量,我想将这些变量发送到 arduino。
arduino 代码查看字符串,它应该读取字符串的一部分并将它们整齐地放在显示器上,每个都在它自己的保留空间中。
问题是我得到的结果是乱码。当字符串仅由一个变量组成时,它显示得很好,应该在哪里,应该怎样。
向字符串中添加附加变量时,代码会中断,结果会混合或显示混乱。我的变量都很干净,只是数字,没什么特别的。
下面是我在arduino上使用的代码
#include <Wire.h>
#include <LiquidCrystal_I2C.h> // Library for LCD
LiquidCrystal_I2C lcd(0x27,20,4); // I2C address 0x27,20 column and 4 rows
String inputString = ""; // String for buffering the message
boolean stringComplete = false; // Indicates if the string is complete
unsigned long previousUpdate = 0; // Long to keep the time since last received message
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;
if (inChar == '|') {
stringComplete = true;
}
}
}
void setup() {
// Setup LCD
lcd.init(); //initialize the lcd
lcd.backlight(); //open the backlight
lcd.setCursor(0,0);
printInitialLCDStuff();
// Setup serial
Serial.begin(9600);
inputString.reserve(200);
}
void loop() {
serialEvent();
if (stringComplete) {
// CPU1
int cpu1StringStart = inputString.indexOf("A");
int cpu1StringLimit = inputString.indexOf("|");
String cpu1String = inputString.substring(cpu1StringStart + 1,cpu1StringLimit);
lcd.setCursor(4,0);
lcd.print(cpu1String);
// CPU2
int cpu2StringStart = inputString.indexOf("B",cpu1StringLimit);
int cpu2StringLimit = inputString.indexOf("|",cpu2StringStart);
String cpu2String = inputString.substring(cpu2StringStart + 1,cpu2StringLimit);
lcd.setCursor(9,0);
lcd.print(cpu2String);
// CPU3
int cpu3StringStart = inputString.indexOf("C",cpu2StringLimit);
int cpu3StringLimit = inputString.indexOf("|",cpu3StringStart);
String cpu3String = inputString.substring(cpu3StringStart + 1,cpu3StringLimit);
lcd.setCursor(13,0);
lcd.print(cpu3String);
inputString = "";
stringComplete = false;
previousUpdate = millis();
}
}
我的代码很脏,主要是改编自其他代码,因为虽然我可以阅读代码,但我写代码很糟糕。如果我犯了让任何人都畏缩的可怕错误,我深表歉意。我承认我只是涉足编码。这就是我经常在代码中做笔记的原因。
我希望我的显示器显示如下:
CPU 60% 45C 900RPM
哪里
cpu1=60
cpu2=45
cpu3=900
“CPU”、“%”、“C”和“RPM”是由 arduino 在 printInitialLCDStuff() { 而不是 Python 上编写的。
相反,我得到了这个
CPU B45% B45|B45|C
然后 RPM 在第 3 行 (0,0) 处列为 "900|"
理想情况下,我想扩展字符串排序以收集大约 10 个变量。
在我看来问题出在 arduino 代码中,因为 Python 脚本有点检查并正确输出字符串。但我可能是错的。
问题是:我是否使用了错误的代码来提取这些变量并将它们放置在显示器上的保留空间中?
我应该使用其他东西来完成工作吗?过去 3 天我一直在查看文档,但找不到有类似案例的人。我在这里发现了一些问题,但同样不是我想要的。
感谢任何帮助。在过去几天每天尝试几个小时后,我对这个代码感到非常沮丧,我愿意用 Steam 数字礼品卡奖励任何可以帮助我使用此代码的人,以表达我的感激之情。
最好的问候, 米
解决方法
可以更改您的代码以使其正常工作,但是,这就像修补它一样。我认为最好采取不同的方法。
首先,在您的 Python 代码中,前缀 A
、B
变得多余并且对接收方解析数据没有帮助。如果您将数据格式化为以 |
作为分隔符的字符串,则更易于解析,并且在 Python 中创建这样的字符串也更容易。
arduino_str = "{}|{}|{}|{}|{}|{}|{}|{}|{}|{}".format(
data0,data1,data2,data3,data4,data5,data6,data7,data8,data9)
if serial_debug:
print(arduino_str)
else:
ser.write(arduino_str.encode())
在 Arduino 方面,Serial.readStringUntil()
会读取整个字符串,直到遇到 \n
(字符串的结尾)。接收到整个字符串后,您可以使用 C++ 中的 strtok()
函数将字符串通过分隔符(在本例中为 |
)拆分为一个数组,因此拆分后的数组将如下所示:
splitted[0] = data0;
splitted[1] = data1;
....
splitted[9] = data9;
然后您可以将数组中的数据打印到 LCD。
#include <Wire.h>
#include <LiquidCrystal_I2C.h> // Library for LCD
#define NUMBER_OF_DATA 10
LiquidCrystal_I2C lcd(0x27,20,4); // I2C address 0x27,20 column and 4 rows
String incomingString = "";
void setup()
{
// Setup LCD
lcd.init();
lcd.backlight();
lcd.setCursor(0,0);
lcd.setCursor(0,0);
lcd.print("CPU % C RPM");
lcd.setCursor(0,1);
lcd.print("GPU % C RPM");
lcd.setCursor(0,2);
lcd.print("MEM MB PWM");
lcd.setCursor(0,3);
lcd.print("RAM GBU GBF");
// Setup serial
Serial.begin(9600);
}
void loop()
{
// read data from Serial until '\n' is received
while (Serial.available()) {
incomingString = Serial.readBytesUntil('\n');
}
if (incomingString) {
// convert the String object to a c_string
char *c_string = incomingString.c_str();
// make a copy of received data so that incoming data would not override the received data
char temp[strlen(c_string)+1];
strcpy(temp,c_string);
incomingString = "";
// parse the received string separated by '|' into an array
char splitted[NUMBER_OF_DATA][10] = {'\0'}; // initialise an array of 10-ch string
int i = 0;
char *p = strtok(temp,'|'); // parse first element in the string
while(p != NULL) { // loop through the string to fill the array
splitted[i++] = p;
p = strtok(NULL,'|');
}
// update LCD with the data in the array
lcd.setCursor(4,0);
lcd.print(splitted[0]);
lcd.setCursor(9,0);
lcd.print(splitted[1]);
lcd.setCursor(13,0);
lcd.print(splitted[2]);
// print the rest of data
lcd.setCursor(13,3);
lcd.print(splitted[9]);
}
}
我是根据你的代码编写的,还没有在 Arduino 上调试,所以如果它不是开箱即用的,它可能需要一些调试。我希望这能帮助你学习一些技巧和一点点 C++ 字符串和字符数组。
,我想通了。我没有尝试将字符串分开并将其全部分配在预选空间中,而是创建了一个字符串并编辑了字符串格式本身。现在我有一个 80 个字符的字符串,并按 (0,20)、(20,40)、(40,60) 和 (60,80) 自动排列。
因为这只是一个简单的资源监视器,我真的不需要任何花哨的东西,只是为了在屏幕上显示信息。
这是我做的
# Prepare CPU string line #1
cpu1 = space_pad(int(my_info['cpu_load']),3) + '% '
cpu2 = space_pad(int(my_info['cpu_temp']),2) + 'C '
cpu3 = space_pad(int(my_info['cpu_fan']),4) + 'RPM'
CPU = 'CPU ' + cpu1 + cpu2 + cpu3
# Prepare GPU string line #2
gpu1 = space_pad(int(my_info['gpu_load']),3) + '% '
gpu2 = space_pad(int(my_info['gpu_temp']),2) + 'C '
gpu3 = space_pad(int(my_info['gpu_fan']),4) + 'RPM'
GPU1 = 'GPU ' + gpu1 + gpu2 + gpu3
# Prepare GPU string line #3
gpu4 = space_pad(int(my_info['gpu_mem']),4) + 'MB '
gpu5 = space_pad(int(my_info['gpu_pwm']),3) + '% PWM'
GPU2 = 'MEM ' + gpu4 + gpu5
# Prepare RAM strng line #4
ram1 = space_pad(float(my_info['ram_used']),4) + 'GBU '
ram2 = space_pad(float(my_info['ram_free']),4) + 'GB'
RAM = 'RAM ' + ram1 + ram2
# Send the strings via serial to the Arduino
arduino_str = \
CPU + GPU1 + GPU2 + RAM + 'F'
if serial_debug:
print(arduino_str)
else:
ser.write(arduino_str.encode())
因为'|'分隔符不断显示为字符串的最后一个字符,我只是切换到我想要出现的字母,基本上是用胶带粘住它。我使用了字符“F”,它也充当字母并显示在字符串中。
至于 Arduino 代码:
#include <Wire.h>
#include <LiquidCrystal_I2C.h> // Library for LCD
LiquidCrystal_I2C lcd(0x27,20 column and 4 rows
String inputString = ""; // String for buffering the message
boolean stringComplete = false; // Indicates if the string is complete
unsigned long previousUpdate = 0; // Long to keep the time since last received message
void printInitialLCDStuff() {
}
void serialEvent() {
while (Serial.available()) {
char inChar = (char)Serial.read();
inputString += inChar;
if (inChar == 'F') {
stringComplete = true;
}
}
}
void setup() {
// Setup LCD
lcd.init(); //initialize the lcd
lcd.backlight(); //open the backlight
printInitialLCDStuff();
lcd.setCursor(0,0);
lcd.print("Arduino PC Monitor");
lcd.setCursor(0,1);
lcd.print("Waiting for data...");
lcd.setCursor(12,3);
lcd.print("Ver 1.0");
// Setup serial
Serial.begin(9600);
inputString.reserve(200);
}
void loop() {
serialEvent();
if (stringComplete) {
// 1st line
String cpuString = inputString.substring(0,20);
lcd.setCursor(0,0);
lcd.print(cpuString);
// 2nd line
String gpu1String = inputString.substring(20,40);
lcd.setCursor(0,1);
lcd.print(gpu1String);
// 3rd line
String gpu2String = inputString.substring(40,60);
lcd.setCursor(0,2);
lcd.print(gpu2String);
// 4th line
String ramString = inputString.substring(60,80);
lcd.setCursor(0,3);
lcd.print(ramString);
inputString = "";
stringComplete = false;
previousUpdate = millis();
}
}
是的,就是这么懒,几乎和用手指数数一样复杂。我喜欢它是多么简单。任何东西都可以即时编辑,只需要最少的知识。
如果我因为懒惰而被禁,我能理解。
感谢您的帮助。如果我需要做一些更复杂的事情,我已经注意到有关字符串拆分的建议。
最好的问候, 米
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。