无法将字符串从python发送到arduin

2024-09-30 16:36:51 发布

您现在位置:Python中文网/ 问答频道 /正文

所以我试着创建一个简单的程序,让我可以用我的电脑控制RGB LED的颜色。为了控制颜色,我在python3上用tkinter创建了一个小窗口,但问题是当我试图更改颜色时,它根本没有响应。我不知道发生了什么事。我试着把这个字符串放到arduino代码中,结果成功了,但当我通过串行通信发送时,它根本没有响应。在

Arduino代码

//pin layout
int   red = 12;
int green = 11;
int  blue = 10;

//string that will receive
String    data;
String subData;

//Color values
int value[3];

void setup() {
  Serial.begin(9600);
  pinMode(red,OUTPUT);
  pinMode(green,OUTPUT);
  pinMode(blue,OUTPUT);  
  }

void loop() {
  while(Serial.available() == 0);
    data = Serial.readString();

    int initialVal =0;
    int val;

    int pos = 0;

    do{
    val = data.indexOf(',',initialVal);
    subData = data.substring(initialVal,val);
    value[pos] = subData.toInt();
    pos = pos + 1;
    initialVal = val + 1;
    }while(val != -1);
    Serial.println(data);
    analogWrite(red,value[0]);
    analogWrite(green,value[1]);
    analogWrite(blue,value[2]);  


  }

下面是python代码:

^{pr2}$

更新

为此,更改arduino代码(在接收字符串的部分):

  while(Serial.available() == 0);
  data = Serial.readStringUntil('\n');
  Serial.setTimeout(0.01);

以及python代码中发送字符串的部分: 而1: window.update_idletasks() 窗口.更新()

    RED = str(RedScale.get())
    GREEN = str(GreenScale.get())
    BLUE = str(BlueScale.get())

    finalString = RED + "," + GREEN + "," + BLUE + "\n"
    if lastMsg != finalString:
        finalString= finalString.encode("utf-8")
        arduino.write(finalString)
        lastMsg = finalString

    print(finalString)

LED改变了它的颜色,但有时它会变成其他颜色,python程序就会崩溃!!!!有什么遗漏吗Serial.readStringUntil(“\n”)或arduino写(终结者)?在


Tags: 字符串代码posdatavalue颜色serialval
1条回答
网友
1楼 · 发布于 2024-09-30 16:36:51

您只是在一个接一个地向Arduino发送太多的消息,所以当它调用readString()时,会花费很长的字符串,并增加pos超过合法间隔{},{这意味着你可以从那里发生任何腐败。在


建议修复:

  1. Serial.readString()替换为Serial.readStringUntil('\n'),则{a1}在其超时时返回,而后者在匹配换行符超时时返回。默认的超时是1秒

  2. 改变

    finalString = RED + "," + GREEN + "," + BLUE
    

    ^{pr2}$

    并删除print("\n")

  3. 更改python代码,使其仅在消息内容发生更改时才向Arduino发送消息。最后一封邮件:

    last_msg = ""
    while 1:
        window.update_idletasks()
        window.update()
    
        RED = str(RedScale.get())
        GREEN = str(GreenScale.get())
        BLUE = str(BlueScale.get())
    
        finalString = RED + "," + GREEN + "," + BLUE + "\n"
    
        if finalString != last_msg:
            arduino.write(finalString.encode("utf-8"))
            last_msg = finalString
    
            print(finalString)
    

注意01:即使您修复了它,也可以考虑将您的Arduino代码发布到code review,以获得关于代码样式化strong设计的一些反馈。在

注意02:即使使用了建议的修复,源代码仍然容易受到错误行为的攻击,如果匹配了readStringUntil()之前的超时,会发生什么?如何处理部分输入?)


编辑1:python代码崩溃的原因是,在使用get()访问对象之前,您没有检查对象RedScaleGreenScale和{}的有效性,而且在关闭tk窗口之后,显然会失败。在

一个天真的解决方案如下:

import sys
import time

global exitFlag
exitFlag = False

...

def endProgram():
    global exitFlag
    exitFlag = True
    window.destroy()

window.protocol("WM_DELETE_WINDOW", endProgram)

...

last_msg = ""
finalString = ""
while 1:
    if not exitFlag:
        window.update_idletasks()

    if not exitFlag:
        window.update()

    if not exitFlag:
        RED = str(RedScale.get())
        GREEN = str(GreenScale.get())
        BLUE = str(BlueScale.get())

        finalString = RED + "," + GREEN + "," + BLUE + "\n"

    if finalString != last_msg:
        arduino.write(finalString.encode("utf-8"))
        last_msg = finalString

        print(finalString)

     if exitFlag:
         sys.exit()

请注意,尽管stackoverflow过于拥挤,有人建议采用这种解决方案,但我认为这是一个糟糕的设计,我怀疑仍然是小车。一个合适的解决方案是重写事件侦听器,以调整Scale实例,这样只有当用户实际更改了Scale的值时才会读取和发送。我会让你解决细节的。在

相关问题 更多 >