gpt4 book ai didi

python - 无法将字符串从python发送到arduino

转载 作者:行者123 更新时间:2023-12-01 03:25:46 26 4
gpt4 key购买 nike

所以我尝试创建一个简单的程序,让我可以用计算机控制 RGB LED 的颜色。我在 python 3 上使用 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代码:

from tkinter import *
from serial import *


window = Tk()
#all definitions for the window
window.title("RGB LED control Panel")
window.geometry("300x180")
window.resizable(False,False)

Title = Label(window, text = "RGB control", width = 15)
Title.grid(row = 0, column = 0, columnspan = 3)

Explanation = Label(window, text = " This window controls the \ncolor of an RGB LED. Have \n fun!!!")
Explanation.grid(row =1 , column = 3)

RedTitle = Label(window, text = "Red", width = 5, bg = "Red")
RedTitle.grid(row = 1, column = 0)

GreenTitle = Label(window, text = "Green", width = 5, bg = "Green")
GreenTitle.grid(row = 1, column = 1)

BlueTitle = Label(window, text = "Blue", width = 5, bg = "Blue")
BlueTitle.grid(row = 1, column = 2)


RedScale = Scale(window, from_ = 0, to = 255, orient = VERTICAL)
RedScale.grid(row = 2, column = 0)

GreenScale = Scale(window, from_ = 0, to = 255, orient = VERTICAL)
GreenScale.grid(row = 2, column = 1)

BlueScale = Scale(window, from_ = 0, to = 255, orient = VERTICAL)
BlueScale.grid(row = 2, column = 2)

#now the serial com with the arduino

arduino = Serial()
arduino.baudrate = 9600
arduino.port = "COM3"
arduino.open()

while 1:
window.update_idletasks()
window.update()

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

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

arduino.write(finalString.encode("utf-8"))
print(finalString)
print("\n")

更新

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

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

以及将字符串发送到此的Python代码部分: 而1: window.update_idletasks() 窗口.update()

    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.write(finalString) 中是否缺少任何内容?

最佳答案

您正在向 Arduino 发送太多消息,因此当它调用 readString() 时,会发生什么情况?一个非常长的字符串,并且递增pos超过合法间隔0..2,这意味着您正在破坏内存堆栈 从那里任何事情都可能发生。

<小时/>

建议的修复:

  1. Serial.readString() 替换为 Serial.readStringUntil('\n')former超时时返回,而后者在匹配换行字符超时时返回。 默认超时为1秒

  2. 更改

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

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

    并删除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有关代码样式强大设计的一些反馈。

注 02:即使采用了建议的修复方案,源代码仍然容易受到错误行为的影响正确的一组情况(例如:如果 \n 匹配之前 readStringUntil() 超时会发生什么?如何处理部分输入?)

<小时/>

编辑 1: 由于您没有检查对象 RedScale 的有效性,python 代码崩溃了GreenScaleBlueScale 在使用 get() 访问它们之前,这显然在 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人满为患,有人建议这个解决方案,但我认为这是糟糕的设计,而且我怀疑仍然> buggy 。正确的解决方案是覆盖用于调整Scale实例的事件监听器,以便仅读取和使用Scale的值。当用户实际更改时发送。我会让你弄清楚细节。

关于python - 无法将字符串从python发送到arduino,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41409076/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com