带有多个变量的 Arduino inputString.indexOf

如何解决带有多个变量的 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 代码中,前缀 AB 变得多余并且对接收方解析数据没有帮助。如果您将数据格式化为以 | 作为分隔符的字符串,则更易于解析,并且在 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++ 字符串和字符数组。

,

enter image description here我想通了。我没有尝试将字符串分开并将其全部分配在预选空间中,而是创建了一个字符串并编辑了字符串格式本身。现在我有一个 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 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-