Arduino-Python : Serial.read() problem...

Good evening,
I am currently working on a project and would like some help since I have been trying to solve the following problem for 2 days… =(
I need my Python programme to send a command, then some characters to arduino. These characters must be stored in the Arduino in order to be used later. However, although the sent characters seem to be correct, Arduino only reads ‘\xff’

Here is my Python code :

#!/usr/bin/python3
# -*-coding:Latin-1 -*

                                    
from algoLambda import *
import serial 
import time


ser = serial.Serial(port= 'COM4:', baudrate = 115200, timeout=2) #initialize serial comms at 115200 baud

ser.close()
ser.open()

continuer = 'y'

if(ser.isOpen()): #test whether port is open

    while(continuer == 'y'):
        angstrom = int(input("Please select a wavelength...")) #Choose wavelength
        print("type of angstrom : " + str(type(angstrom))) #Checking the type of angstrom parameter
##        if (lambdaPE(angstrom) is None):
##            print("aucune valeur de retour lambdaPE()")
##            return None


##                  SET binMod AND binPE PARAMETER

            
        PE = lambdaPE(angstrom)#        shall be angstrom // 256
        print("PE : " + str(PE)) #Checking
   
        binMod, binPE = convBin(angstrom)       
  
        chainePE = ""
        for i in binPE:
            chainePE = chainePE+str(i) # converting PE into string
        print("binPE: "+ chainePE)

 
##                  COMMAND ARDUINO : SEND chainePE which must be stored in Arduino

        
        ser.write(b'p')
        ser.write(bytes(str(chainePE),'Latin-1'))

##                      READING ON ARDUINO'S SERIAL MONITOR

        try:
            line = "1"
            j=0
            while(j<5): # in case it would be a buffer problem
                line = ser.readline() #reading on Arduino's serial monitor
                print(line) 
                j+=1
        except(KeyboardInterrupt,SystemExit): #leaving pgr = CTRL+C
            ser.close() # closing  port
        except: # other interruptions
            print("erreur inconnue")

        if (lambdaModulo(angstrom) == None):
            exit("aucune valeur de retour lambdaModulo()")		
     
        modulo = lambdaModulo(angstrom)
        print("Modulo du codage de longueur d'onde : " + str(modulo)) # Checking whether we have angstrom%256
        
        chaineMod = ""      #initializing
        for i in binMod:        #converting list into string
            chaineMod = chaineMod + str(i)                


##              COMMAND ARDUINO : SEND chaineMod which must be stored in Arduino

        
        print("binMod: "+ chaineMod)    #Checking
        ser.write(b'm')     #sending command to Arduino
        ser.write(bytes(chaineMod,'Latin-1'))   #sending bytes to get them with Arduino


##                      READING ON ARDUINO'S SERIAL MONITOR


        try:
            line = "1"
            j=0
            while(j<5): 
                line = ser.readline() 
                print(line) 
                j+=1
        except(KeyboardInterrupt,SystemExit): 
            ser.close() 
        except: 
            print("erreur inconnue")
            
        continuer = input("Voulez-vous continuer ? y/n\n")

Here is algoLambda.py :

#!/usr/bin/python3
# -*- coding:LATIN-1 -*-

def lambdaPE(angstrom):
	"lambdaPE() calcule la partie entière de la longueur d'onde choisie"
	if(angstrom>10000 or angstrom<=0):
		print("choix de longueur d'onde hors limite")
		return None
	else:
		angstrom = angstrom//256
	
	return angstrom
	
	
def lambdaModulo(angstrom):
	"lambdaModulo() calcule la longueur d'onde choisie modulo 256"	
	if(angstrom>10000 or angstrom<=0):
		print("choix de longueur d'onde hors limite")
		return None
	else:
		angstrom = angstrom%256
	
	return angstrom
	

def convBin(angstrom):
	"convBin() converts angstroms en binaries"
	angstromPE = lambdaPE(angstrom)
	angstromMod = lambdaModulo(angstrom)
	
	binPE = []; binMod = []
	
	for i in [0,1,3,4,5,6,7]:
		binMod.append(angstromMod & 1)
		binPE.append(angstromPE & 1)
		#print(binMod); print(binPE); print()	
		angstromMod = angstromMod >> 1; 
		angstromPE = angstromPE >> 1
	
	print(binMod); print(binPE)
	
	return binMod,binPE

Now… my Arduino code… :

  int modulo[9]= {0,0,0,0,0,0,0,0,0}; //to store lambda_final%256
  int PE[9]  = {0,0,0,0,0,0,0,0,0}; // to store lambda_final//256
  
  void setup()
{
  Serial.begin(115200);
  Serial.println("\nTest communication Python/arduino : set Lambda");
}

void get_modulo()
{
//  if(Serial.available()>0){              //Serial.available() seems to = 0.. for unknown reasons
    char temp[8];                          //to store incoming bytes... and should be temp[9] by the way...  
    for(int i=0; i<8; i++){
      temp[i] = Serial.read();
      Serial.print(temp[i]);              //this returns \xff\xff\xff....
    }
//  }
  Serial.println("");
}

void get_partie_entiere()
{
//.  if(Serial.available()>0){            //Serial.available() seems to = 0.. for unknown reasons
     char temp[8];                        //to store incoming bytes... and should be temp[9] by the way...
    Serial.print("Partie Entiere:");
    for(int i=0; i<8; i++){
      temp[i] = Serial.read();
      Serial.print(temp[i]);            //this returns \xff\xff\xff....
    }
    Serial.println("debug");
  //}
  Serial.println("");
}


void loop()
{
                                //Waiting for commands on Serial port from Python program
  if (Serial.available()>0)
  {
    char inByte = Serial.read();
    switch(inByte)
    {
      case 'm': 
        get_modulo();
        break;
        
      case 'p': 
        get_partie_entiere();
        break;
    }
    Serial.flush(); //waits for the transmission of outgoing serial data to complete
  }
}

And here is what I get :

Please select a wavelength…3
type of angstrom : <class ‘int’>
PE : 0
[1, 1, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0]
binPE: 0000000
b’\n’
b’Test communication Python/arduino : set Lambda\r\n’
b’Partie Entiere:\xff\xff\xff\xff\xff\xff\xff\xffdebug\r\n’ //Here I was supposed to get binPE, that is 0000000
b’\r\n’
b’’
Modulo du codage de longueur d’onde : 3
binMod: 1100000
b’\xff\xff\xff\xff\xff\xff\xff\xff\r\n’ ** //Here I was supposed to get binMod, that is 1100000**
b’’
b’’
b’’
b’’
Voulez-vous continuer ? y/n

I also tried to communicate with Arduino through a simple code. the following example is working as expected :

Python code :

#!/usr/bin/python3
# -*-coding:Latin-1 -*

                        
# Sending chars to Arduino through Python, and print them on Arduino's Serial Monitor
# this program reads what is printed on this serial monitor et prints it in the shell

import serial 
import time


ser = serial.Serial(port= '/COM4:', baudrate = 9600, timeout=2) #définition de la liaison série

ser.close()
ser.open()

continuer = 'y'
mot="101"
while(continuer == 'y'):
    if(ser.isOpen()): #test que le port est ouvert
        ser.write(b"w")
        ser.write(bytes(str(mot),'Latin-1')) #on envoie une donnée à l'arduino

        if(continuer =='y'):
            line = ser.readline() #lecture d'une ligne sur le moniteur série
            print(line) #on écrit la ligne du moniteur série sur le terminal
        continuer = input("Voulez-vous continuer ? y/n\n")

ser.close()

Arduino Code :

char temp[3];
  void setup()
{
  Serial.begin(9600);
  Serial.println("\nTest communication Python/arduino : serial monitor");
}

void loop()
{
  if (Serial.available()>0)
  {
    char inByte = Serial.read();
    Serial.flush();
    switch(inByte)
    {
      case 'w':
        for(int i=0; i<3; i++){
          temp[i] = Serial.read();
          Serial.print(temp[i]);
        }
    }
      Serial.println("");
  }
  delay(3000);
}

result :

b’\n’
Voulez-vous continuer ? y/n
y
b’Test communication Python/arduino : serial monitor\r\n’
Voulez-vous continuer ? y/n
y
b’101\r\n’
Voulez-vous continuer ? y/n
y
b’101\r\n’
Voulez-vous continuer ? y/n
y
b’101\r\n’
Voulez-vous continuer ? y/n

Could you please help me to solve this \xff problem ?.. :~

algoLambda.py (968 Bytes)

modif_lambda_arduino.py (2.88 KB)

I have a similar functional example that may help you. I am including the arduino sketch and the client side python

TRNG_SD.ino (13.8 KB)

get1M.py (1.17 KB)

Serial.available() seems to = 0.. for unknown reasons

Common issue. It's zero because nothing has arrived yet - serial data transmission is very slow. Unfortunately, you read eight characters anyway. Negative one AKA 0xFF is what serial.read returns when you read but there's nothing there. You cannot assume that once one character arrives that the rest will also have done so.

if (Serial.available()>0)
  {
    char inByte = Serial.read();
    Serial.flush();
    switch(inByte)
    {
      case 'w':
        for(int i=0; i<3; i++){
          temp[i] = Serial.read();

Yup, see that’s there’s at least one character to read and then go and read four of them.

I wrote some demo Python and Arduino code in this Thread which may be useful.

...R

Hey!

Thank you for all your replies. My piece of code was not optimal indeed. I thought that, if the Arduino received the first byte, the others would follow thereafter. But obviously I was mistaken! I have been working on it since early this morning and, thanks to the programmes you sent to me, I managed to fix my problems! Thanks everybody!

if (Serial.available()>0)
  {
    char inByte = Serial.read();
    Serial.flush();

If there is anything to read, read it, and then wait until all outgoing data has been sent. Can you explain why THAT is necessary?

PaulS: if (Serial.available()>0)   {     char inByte = Serial.read();     Serial.flush();

If there is anything to read, read it, and then wait until all outgoing data has been sent. Can you explain why THAT is necessary?

This is something you have to point out fairly often, and I suspect the readers may not understand your somewhat cryptic explanations because, to the ordinary-man-in-the-street it must seem like the function is intended to empty the serial buffers in the same way you empty (flush) a toilet. That's certainly what I thought when I first came across it.

This function is very poorly named. A much better name would be Serial.waitUntilSendBufferEmpties() - but I won't hold my breath for that change to the IDE.

...R

This is something you have to point out fairly often

I shouldn't have to. There is a whole section full of information about what the Arduino-specific functions and methods do. Calling a function that does something that you don't expect or understand is not very bright, in my opinion.

The purpose of the Serial.flush() function changed with 1.0. It went from the almost always useless dumpUnknownAmountsOfUnreadData() to the almost always equally useless waitUntilSendBufferEmpties(). Why people are so addicted to using that function remains a mystery to me.

You know as well as I do that nobody ever RTFMs.

One of the attractions of the Arduino system (perhaps its main attraction?) is that you can do stuff without RTFM. Then if you become really interested you can start the background reading.

I hadn't realized they changed the behaviour of the function from one which did what its name implied (however useless) to one that doesn't.

...R

I hadn't realized they changed the behaviour of the function from one which did what its name implied (however useless) to one that doesn't.

I'm afraid that that is the real problem. Too many examples out on the net use Serial.flush() incorrectly, and uselessly. Getting people to delete the useless call is nearly impossible. But, that won't stop me from pointing out that it IS useless.

PaulS: But, that won't stop me from pointing out that it IS useless.

Adding a few words of explanation will soften the blow for newbies :)

...R

Adding a few words of explanation will soften the blow for newbies

Maybe. But, I really want them to do some research and pay attention to what they are doing. There is no excuse for ignorance.

PaulS: There is no excuse for ignorance.

I am inclined to change that to "there is no excuse for stupidity or laziness".

We are all ignorant when we start something new and it is nice to meet an expert who will explain where we are going wrong, or where we have misunderstood something which is obvious to the expert.

If they continue to ignore advice that's a different matter.

...R