打开arduino nano的com端口时必须使用pyserial睡眠

时间:2016-08-15 07:00:04

标签: python arduino pyserial

我在Windows 10上使用python 2.7运行pyserial(3.1.1)

更新 - 在Xubuntu 16和Windows上运行相同的问题。

我通过USB /串行接口通过串口写入arduino nano。

我正在编写一个简单的字符串(例如'2+')并读取arduino中的输出。如果我在打开com端口后第一次保持睡眠时间为2秒,则可以正常工作。如果我将其更改为1或删除它,arduino似乎会收到不同的字符/编码,但它不起作用。

理想情况下,我不想睡觉,以便更快地运作。我做错了什么或有更好的方法做到这一点,以便我可以消除睡眠或至少减少它?

Python代码:

import sys, getopt
import time
import serial
ser = serial.Serial(
    port='COM3',
    baudrate=9600,
    parity=serial.PARITY_ODD,
    stopbits=serial.STOPBITS_TWO,
    bytesize=serial.SEVENBITS
)
time.sleep(1)  #change this to 2 and it works
ser.write('2+')
out = ''
time.sleep(1)
while ser.inWaiting() > 0:
    out += ser.read(1)
if out != '':
    print ">>" + out
else:
    print ">> nothing!"
time.sleep(1)   
ser.close()

Arduino代码(我对ASCII字符编号也有一些小问题 - 我认为这是字节的签名,但这是我目前最少的问题)

String inString = ""; 
int pinNumber = 0;

void setup() {
    // initialize serial communication at 9600 bits per second:
Serial.begin(9600);
}

void loop() {
    // expected input:    1+   //to change the digital pin to on
    // expected input:    2-   //to change the digital pin to off  
    while (Serial.available() > 0) {
        //char inChar = char(int(Serial.read()));
        char inChar = Serial.read();
        Serial.println(inChar);
        if (isDigit(inChar)) {
            inString += inChar;
            Serial.println(inString);
        }
        else {
            pinNumber = inString.toInt();
            Serial.println(pinNumber);
            pinMode(pinNumber, OUTPUT);
        if (inChar == -85) {
            Serial.println("set high");
            digitalWrite(pinNumber, HIGH);  
        } else if (inChar == -83) {
            Serial.println("set low");
            digitalWrite(pinNumber, LOW);  
        } else {
            Serial.println("NO MATCH!!!");
        }
        inString = "";
    }
}

}

3 个答案:

答案 0 :(得分:1)

您假设如果有数据,则它将是完整数据。如果在发送部分处理串口的方式有缓冲,则只能得到部分数据。

您可以尝试在python代码中添加ser.flush(),但您还应该检查收到的数据是否完整。您可以通过确保数据以已知字符终止并检查它来完成此操作。

请记住,你也应该有某种超时,这样你就不会陷入某种阅读循环。

另一个问题是,您正在阅读char类型,但根据the documentationSerial.read()实际上会返回intchar数据类型的大小为1个字节,而int的大小为2个字节,这可能就是为什么你会得到奇怪的东西(那里' sa)参考here)。

它还说read将仅返回数据的第一个字节。所以,如果你想要第二个字节,你需要阅读两次。

答案 1 :(得分:1)

打开串行连接时,Arduino是否可能会自动重置?

在Arduino Nano中,RESET引脚通过C4连接到FTDI USB到串行转换器的DTR。请参阅Arduino Nano Schematic

也许如果你删除C4或禁用DTR,你的问题就会消失。

您可以通过在设置功能中放置一个短的LED脉冲来检查这一点,看看它是否在从Python程序打开串口后发生。

答案 2 :(得分:0)

我无法找到解决这个睡眠问题的方法。如果允许至少1.5秒,则仅在arduino上正确接收字节 - 可能是串行连接初始化。

作为一种解决方法,我必须在启动时打开串口一次,然后通过套接字服务器接受和写入数据。这按预期工作。似乎问题在于打开串口。

import os, os.path
import time
import serial
import socket
import re

def sendData(msg):
    if not ser.is_open:
        ser.open()
    ser.write(msg)
    ser.flush()
    out = ''
    time.sleep(0.5)
    while ser.inWaiting() > 0:
        out += ser.read(1)
    if out != '':
        print ">>" + out
    else:
        print ">> nothing!"
    time.sleep(0.5) 

port='/dev/ttyUSB1',

serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind(('localhost', 9000))
serversocket.listen(1) # become a server socket, maximum 5 connections

ser = serial.Serial(
    port=port,
    baudrate=9600,
    parity=serial.PARITY_ODD,
    stopbits=serial.STOPBITS_TWO,
    bytesize=serial.SEVENBITS
)

while True:
    connection, address = serversocket.accept()
    buf = connection.recv(64)
    if len(buf) > 0:
        print buf
        sendData(buf)