Why python pyserial put ø at the beginning of the string sent ?

Started by Richelsdorfite, April 09, 2014, 03:23:45 AM

Richelsdorfite

Hi,

I have a bug  :o Searching long time but no answer !

My Rpi send commands to my Moteino gateway via serial and pyserial librairie.
My Moteino gateaway wait for these commands and proceed.

So, I can send and received in the both way but.

When I send a string from Rpi to Moteino, pyserial put a "none" or "slash zero" ø at the beginning of the string.
For example :

Python code
#!/usr/bin/python
# -*- coding: utf-8 -*- 
port = serial.Serial(port='/dev/ttyAMA0',baudrate=115200,parity=serial.PARITY_NONE,stopbits=serial.STOPBITS_ONE,bytesize=serial.EIGHTBITS,timeout=0)

port.flushOutput()
#Ecriture de la pré-commande "LMPCDE"
cde = "LMPCDE\r\n"
cde.encode('ascii','strict')
print cde
port.write(cde )
time.sleep(.1)
data = port.readline()
print data


or

#!/usr/bin/python
# -*- coding: utf-8 -*- 

port = serial.Serial(port='/dev/ttyAMA0',baudrate=115200,parity=serial.PARITY_NONE,stopbits=serial.STOPBITS_ONE,bytesize=serial.EIGHTBITS,timeout=0)

port.flushOutput()
#Ecriture de la pré-commande "LMPCDE"
cde = "LMPCDE\r\n"
print cde
port.write(cde)
time.sleep(.1)
data = port.readline()
print data


Moteino code wait for command string read it and send it to RPI.

So:
print cde
print LMPCDE
and
print data
print øLMPCDE

I use Python 2.7.3.

Why python pyserial put ø at the beginning of the string sent ?  :o

I can modify the moteino code to erase the first char but even if it's the easy way I don't think it's the good way as I don't understand why !

Richelsdorfite

I find an other bug !

I run the python script via command line (Putty).

If I open an other Putty instance and run minicom
minicom -b 115200 -o -D /dev/ttyAMA0
and run in the first console python script, there is no ø added to LMPCDE command. Of course as the serial input is redirected to minicom, I need to pass other string command via minicom.

Richelsdorfite

Here is my entire python code :

#!/usr/bin/python
# -*- coding: utf-8 -*- 
#Importation des librairies
import MySQLdb
import serial
import time
#import string

#Mes Fonctions
def convertstring(mystring):
	if len(mystring) == 3:
		mystring = "0" + mystring
	elif len(mystring) == 2:
		mystring = "00" + mystring
	elif len(mystring) == 1:
		mystring = "000" + mystring
	return mystring
	
#Connexion à la base de donnees
db = MySQLdb.connect(host="localhost", user="root", passwd="xxxxxxx", db="logsensorsvalues") #Password containing special char (utf8)
# you must create a Cursor object. It will let
# you execute all the queries you need
cursor = db.cursor() 
# Use all the SQL you like
cursor.execute("SELECT Far_Red,Red,Red_Orange,Green,Blue,UV_410,UV_395 FROM ledlampvalues Order by ID desc limit 1")
# Values received
rows = cursor.fetchall()
#Fermeture de la base de donnees
cursor.close()
db.close()
#lecture de rows
commandstring=""
for row in rows:
	FarRed = convertstring(str(row[0]*10))	#x10 pour conserver l'architecture du protocole
	Red = convertstring(str(row[1]*10))
	RedOrange = convertstring(str(row[2]*10))
	Green = convertstring(str(row[3]*10))
	Blue = convertstring(str(row[4]*10))
	UV1 = convertstring(str(row[5]*10))
	UV2 = convertstring(str(row[6]*10))
#Formatage de la chaine de caracteres
commandstring = "C" + "F" + FarRed + "R" + Red + "O" + RedOrange + "G" + Green + "B" + Blue + "U" + UV1 + "V" + UV2 + "E" #+ "\r\n"

#Serial Port http://pyserial.sourceforge.net/pyserial_api.html#serial.FileLike.readline
#Possible values for the parameter timeout:
#timeout = None: wait forever
#timeout = 0: non-blocking mode (return immediately on read)
#timeout = x: set timeout to x seconds (float allowed)
serialport = serial.Serial()

serialport.port = "/dev/ttyAMA0"
serialport.baudrate = 115200
serialport.bytesize = serial.EIGHTBITS #number of bits per bytes
serialport.parity = serial.PARITY_NONE #set parity check: no parity
serialport.stopbits = serial.STOPBITS_ONE #number of stop bits
serialport.timeout = 0            #non-blocking mode (return immediately on read)
serialport.xonxoff = False     #disable software flow control
serialport.rtscts = False     #disable hardware (RTS/CTS) flow control
serialport.dsrdtr = False       #disable hardware (DSR/DTR) flow control
serialport.writeTimeout = 0     #timeout for write

try:
	serialport.open()
except Exception , e:
	print "error open serial port: " + str(e)
	exit()

if serialport.isOpen():
	print "Port Open"
	try:
		#Pay attention to the flush order : Output before Input
		serialport.flushOutput() #flush output buffer, aborting current output and discard all that is in buffer
		serialport.flushInput() #flush input buffer, discarding all its contents
		#Ecriture de la pré-commande "LMPCDE"   /// cde.encode('ascii','strict')
		print serialport.write('LMPCDE')
		time.sleep(.1)
		
                #DEGUG Zone
		#data = serialport.readline()
		#print data
		#while serialport.inWaiting() > 0:
		while 1:
			print serialport.read()
		#End Zone


		while serialport.inWaiting() > 0:
			data = serialport.readline()
			if data.startswith("Expecting"):
				print data
				#Waiting for an acknowledgement from Node
				while serialport.inWaiting() > 0:
					data = serialport.readline()
					if data.startswith("ok"):
						print "Sending Command"
						serialport.write(commandstring)
				
		time.sleep(.1)

		#Waiting for an acknowledgement from Node
		while serialport.inWaiting() > 0:
			data = serialport.readline()
			if data.startswith("ok"):
				print data

		serialport.close()			
	except Exception , e1:
		print "error open serial port: " + str(e1)
		exit()
else:
    print "cannot open serial port "

mrburns42

I suspect that the problem is on the Motenio end and not the python end.   A null or /0 is the string terminator.  I think the terminator from a previous string is being left in the buffer on the Motenio.  Then on the next serial port transmission, it is sitting there waiting for you. 

1.  Connect the Motenio to a terminal program like TerraTerm.   Then manually type in the commands to the Motenio.   Does it work OK?  If it works fine from a terminal program.  Then it would be a python transmission problem.  If it fails from the terminal program, then the problem is on the Motenio end.
2.  Power cycle the Motenio and send two commands from python.   Does the first command work OK and the second command have the leading null?   If so, then this is proof that this extra character is being left in the buffer. 
3.  I have not studied your python code.   Are you opening and closing the serial port connection?  Or keeping the connection active for as long as the python code is running?   If you open and close the serial port repeatedly, this can cause some communication glitches.  Try keeping the port connected all the time. 

Felix

Quote from: mrburns42 on April 17, 2014, 07:52:52 AM
I suspect that the problem is on the Motenio end and not the python end.   A null or /0 is the string terminator.  I think the terminator from a previous string is being left in the buffer on the Motenio.  Then on the next serial port transmission, it is sitting there waiting for you.

The arduino chip doesn't keep anything "waiting" in its serial buffer. It spits out everything, regardless if anything is connected to the hardware pins or not ;)