onemorecupofcoffee onemorecupofcoffee - 3 months ago 26
Python Question

Have to use sleep with pyserial when opening com port for arduino nano

I'm running pyserial (3.1.1) on Windows 10 with python 2.7

Update - get the same issue running on Xubuntu 16 as well as Windows.

I'm writing via serial to an arduino nano via usb / serial interface.

I'm writing a simple character string (eg. '2+') and reading the output in the arduino. If I keep the first time.sleep at 2 seconds after opening the com port it works. If I change it to 1 or remove it the arduino seems to receive a different character / encoding and it does not work.

Ideally I don't want any sleep so that it works quicker. Am I doing something wrong or is there a better way to do this so that I can remove the sleep or at least reduce it?

Python Code:

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 code (I'm having some minor issues with the ASCII char numbers as well - I think it is the signing of the bytes but that is the least of my problems at the moment)

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 = "";
}
}


}

Answer

I was not able to find any way around this sleep issue. The bytes were only received correctly on the arduino if at least 1.5 seconds was allowed - presumably for the serial connection to initialise.

As a workaround I had to open the serial port once on startup and then accept and write data through a socket server. This worked as expected. It seems the issue is with the opening of the serial port.

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)