因此,我试图创建一个简单的程序,使我可以用计算机控制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代码部分: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 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
memory stack
建议的修复程序:
更换Serial.readString()
用Serial.readStringUntil('\n')
的前返回时超时,而后者返回时,它匹配新行字符或它超时。的默认超时是1秒。
改变
finalString = RED + "," + GREEN + "," + BLUE
至
finalString = RED + "," + GREEN + "," + BLUE + "\n"
并删除 print("\n")
更改您的python代码,以便仅在消息内容更改为wrt时才向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代码发布到代码审查中,以获取有关代码样式和强大设计的一些反馈。
注02:即使所提出的修正,该源代码仍然脆弱到错误的行为给予正确的一组的情况下(例如:如果发生了什么readStringUntil()
超时前\n
?匹配你怎么跟部分输入处理)
编辑1:该Python代码崩溃是由于事实,你不检查对象的有效性RedScale
,GreenScale
并BlueScale
与访问之前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()
需要注意的是,虽然计算器是人满为患了人建议这个解决方案,我认为这是糟糕的设计,我怀疑还是马车。正确的解决方案是重写Scale实例的事件侦听器,以便仅当用户实际更改Scale的值时才读取和发送Scale的值。我会让你弄清楚细节。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句