gpt4 book ai didi

python - Arduino Sketch适用于Serial Monitor,但不适用于pyserial

转载 作者:太空宇宙 更新时间:2023-11-03 15:41:08 25 4
gpt4 key购买 nike

我正在python中测试此简单的arduino代码,但它在arduino序列中有效,而在python中不起作用。
用户定义指示灯的闪烁次数。
这适用于arduino串行监视器。但是当我在python中使用它时不起作用。有人可以帮忙吗?
谢谢

Arduino代码:

int ledPin = 13;   // select the pin for the LED
int val = 0; // variable to store the data from the serial port

void setup() {
pinMode(ledPin,OUTPUT); // declare the LED's pin as output
Serial.begin(9600);

while (!Serial) {
; // wait for serial port to connect (USB)
}
establishContact();
}

void establishContact(){
while (Serial.available() <= 0){
val = Serial.parseInt();
Serial.flush();
// Serial.println("Est");
}
}

void loop () {
if (val>0) {
for(int i=0; i<val; i++) {
digitalWrite(ledPin,HIGH);
delay(150);
digitalWrite(ledPin, LOW);
delay(150);
}
val=0;
}
}


Python代码:

import serial
import time
ser = serial.Serial('/dev/tty.usbmodem1421', baudrate=9600,timeout =None)

def blinkLED(x):
ser.write(x)
return;

最佳答案

首先,我假设您确实在代码中的某处调用了

blinkLED('10')


否则,整个讨论毫无意义。

在这方面,我将如下更改您的函数 blinkLED(x)

def blinkLED(x):
ser.write(x)
ser.flushOutput()
return




其次,我不完全相信此代码:

1: void establishContact() {
2: while (Serial.available() <= 0){
3: val = Serial.parseInt();
4: Serial.flush();
5: }
6: }


首先,我不确定您认为 Serial.flush()应该在那做什么,因为根据 documentation,它“等待传出串行数据的传输完成”,但是您不会继续发送任何信息 Serial输出。

第二,当您在第一次循环迭代中位于第 2:行时,有两种可能的情况:


A. Serial输入上有可用的内容,因此, Serial.available() > 0,您没有进入循环,也没有阅读 val
B. Serial输入(因此是 Serial.available() == 0)上没有任何内容,您进入了循环。现在有两个子情况:


B.1。如果 Serial输入上没有任何内容,则您将一直读 0并停留在该循环中
B.2。如果 Serial输入中出现某种情况,则有3种情况:


B.2.I.输入数据在执行 Serial.parseInt()之后立即到达,因此在下一个循环迭代中, Serial.available() <= 0为false,并且您退出循环而没有读取您的 val(也就是说,在情况A中结束)。
B.2.II.当执行 Serial.parseInt()时,输入数据就正确到达,并且您已成功将所有输入字节解析为 val。但是, Serial输入中没有任何内容,因此条件 Serial.available() <= 0仍然成立,您仍然陷于循环中
B.2.III。当您执行 Serial.parseInt()时,输入数据将正确到达,并且您已成功将某些输入字节解析为 val\r会忽略不属于Int值的其他一些字节(例如 \n\tSerial.parseInt(),空格,字母符号等),并保留在 Serial输入缓冲区中。因此,在下一个循环中,迭代 Serial.available() <= 0为false,然后退出循环。




当您呼叫 blinkLED('10')时,您将遇到以下情况之一:A.,B.2.I。或B.2.II ..这说明了为什么您看不到任何闪烁:要么您仍然陷于循环中,要么跳过了它却没有阅读任何内容,但仍然有 val == 0

情况B.2.III。是唯一以工作草图结束的情况。这是使用Arduino串行监视器时发生的情况,因为默认情况下,当您在键盘上按 \n时,后者会发送一个附加的 \r\n(或 enter?我不记得了。。)。

因此,我认为这解释了为什么在使用串行监视器时草图可以起作用,而在使用python代码时却不能起作用。一个快速的测试是修改 blinkLED(x),如下所示:

def blinkLED(x):
ser.write(x)
ser.write('\n')
ser.flushOutput()
return


注意:使用串行监视器可以进行一些测试,甚至 pyserial都可以使用此修复程序,但这并不意味着您的草图现在是正确的,并且始终可以使用。实际上,代码可能仍然会失败,例如如果 Serial.available > 0太早,那么您仍然不会进入循环主体并解析 val



@ArnoBozo建议更改 establishContact()如下:

1: void establishContact() {
2: while (Serial.available() > 0){
3: val = Serial.parseInt();
4: Serial.flush();
5: }
6: }


我认为这种设计也是有缺陷的,因为您再一次不能保证在您检查 Serial.available() > 0python对应物已经发送了数据(或已接收到数据)。如果不是这种情况,则不会执行循环主体,并且您永远不会解析 val。当然,您可以尝试使用 delay()进行游戏,但这会使整个草图非常脆弱。



最后观察:如果查看 Serial.parseInt()documentation,则会发现:


  
  如果没有读取到可配置的超时值的字符,或者读取了非数字,则分析停止。
  如果在发生超时(请参见Serial.setTimeout())时未读取有效数字,则返回0;否则返回0。
  


如果检查 Serial.setTimeout()documentation,则会发现 timeout“默认为1000毫秒”。再次,以重复自己和显得学究为代价,除非绝对必要,否则不应依赖通讯协议中的超时和延迟(例如,启发式地决定是时候释放与外部实体不再通信的资源了参与交流)。

因此,我的建议是擦除 Serial.parseInt()并编写自己的解析器,或者以更强大的方式使用它。您要实现的目标:

Serial.setTimeout(0);            // disables timeout
while (val == 0) { // discard any 'garbage' input
val = Serial.parseInt(); // keeps trying to read an Int
}


这种方法相当残酷(但是YOLO):Arduino直到解析成与 int不同的 0时,才会停止尝试。同样,您应该在电话号码后发送一个无效数字(例如 \n),因为否则 Serial.parseInt()不会返回,因为 timeout现在等于 0

(请注意,我没有测试此代码,如果我误解了库文档的某些部分,它也可能无法正常工作。)

关于python - Arduino Sketch适用于Serial Monitor,但不适用于pyserial,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42113932/

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