Arduino-Python USB serial communication

Hi, I've a problem interfacing arduino with a python program that I've written. I'd like to read a string of 231 char at least ten time per second. When I try to read the strings I see that the entire message is broken in more strings (not the buffer size) randomly in time. Baudrate is 115200. Can anyone help me in solving this problem? Thank you in advance,

Can you post your code, both Arduino and Python? That makes it easier for us to give some advice.

ok,

void setup() {
 int i;
 
 Serial.begin(115200);
 pinMode(outPin1,OUTPUT); 
 pinMode(outPin2,OUTPUT); 
 pinMode(outPin3,OUTPUT); 

 flag=0; 
 j=0; 
 
 for (i=0; i<pidPinNum; i++) {
   Input[i] = myPID[i].getInput();
   myPID[i].SetMode(AUTOMATIC);
   myPID[i].setNTCcoefficents(-4.16734e-4,6.4803e-4,-2.0405e-6);
 }
}

void loop() {
 
  unsigned long start = millis();
  double f_value;
  int i_value,i_string,i,k;
  char signal_type;  
    
  if (start-previous > interval) {
      //Serial.println("Alive");    
      
          
      Serial.print("#A00#");
      Serial.print(analogRead(tempPin0));
      Serial.print("#A01#");
      Serial.print(analogRead(tempPin1));
      Serial.print("#A02#");
      Serial.print(analogRead(tempPin2));
      
      /*
      Serial.print("#s00#"); Serial.print(Setpoint,6);
      Serial.print("#p00#"); Serial.print(consKp,6);
      Serial.print("#i00#"); Serial.print(consKi,6);
      Serial.print("#d00#"); Serial.print(consKd,6);
      */
      for (k=0; k<pidPinNum; k++) {
        
        for (i=0; i<100; i++) { string[i]='\0';} Serial.print("#s0"); Serial.print(myPID[k].pinOutput); Serial.print("#"); dtostre(Setpoint[k]  ,string,4,' '); Serial.print(string);
        for (i=0; i<100; i++) { string[i]='\0';} Serial.print("#p0"); Serial.print(myPID[k].pinOutput); Serial.print("#"); dtostre(myPID[k].abKp,string,4,' '); Serial.print(string);
        for (i=0; i<100; i++) { string[i]='\0';} Serial.print("#i0"); Serial.print(myPID[k].pinOutput); Serial.print("#"); dtostre(myPID[k].abKi,string,4,' '); Serial.print(string);
        for (i=0; i<100; i++) { string[i]='\0';} Serial.print("#d0"); Serial.print(myPID[k].pinOutput); Serial.print("#"); dtostre(myPID[k].abKd,string,4,' '); Serial.print(string);      

        Serial.print("#m");Serial.print(myPID[k].pinOutput); Serial.print("#00"); Serial.print(myPID[k].GetMode());
      
        Serial.print("#o0");Serial.print(myPID[k].pinOutput); Serial.print("#");
        Serial.print(Output[k]);
        Serial.print("#I0");Serial.print(myPID[k].pinOutput); Serial.print("#");
        Serial.print(myPID[k].getInput());
    }

and the python side

class gui_arduino:
    def __init__(self,parent):
        self.win_os = False
        self.ser_var = ""

        try:
            self.ser = serial.Serial('/dev/tty.usbmodem1d11', 115200)
            #self.t = threading.Thread(target=self.serial_reader)
            #self.t.start()
        except:
            try:
                self.ser = serial.Serial('/dev/tty.usbmodem1a21', 115200)
            except:
                try:
                    self.ser = serial.Serial(port='COM4', baudrate=115200, dsrdtr=True)
                    #self.ser.databits=4
                    print self.ser
                except:
                    self.win_os = True

  def read_values(self):

        self.ser_var=self.ser.read(self.ser.inWaiting())
        if len(self.ser_var)>0:
            print self.ser_var

        ser_dict = {}
        ser_list = self.ser_var.split("#")
        #print ser_list
        try:
            ser_list.remove('')
        except ValueError:
            print "***********************Value Error"

        if len(ser_list) > 0:
            for i in range(0,len(ser_list)-1,2):
                ser_dict[ser_list[i]]=ser_list[i+1] 
            #print ser_dict

            for key,item in ser_dict.items():
                if 'A' in key :
                    try:       
                        T=self.voltage2temperature(item)
                        #print key
                        #print key.split("A")[1]
                        #print T
                        self.AI_values["AI_%d"%(int(key.split("A")[1]))].set(T)
                    except KeyError:
                        pass
                    except ValueError:
                        pass
                      
                        
                elif 'D' in key:
                    try:
                        self.DI_values["DI_%d"%(int(key.split("D")[1]))].set(item)
                    except ValueError:
                        pass
                    except KeyError:
                            pass
                elif 'm' in key:
                    #print "%02d"%int(key.split("m")[1])
                    try:
                        button = self.AUTO_buttons["%02d"%int(key.split("m")[1])]
                        if button.getState() != int(item) :
                            button.setState(int(item))
                            
                    except KeyError:
                        pass
                elif 'I' in key:
                    self.PID_signals[key].set(item)
                    self.voltage2temperature(1023.)
                    
                elif 'o' in key:
                    self.PID_signals[key].set(item)
                else:
                    try:
                        if self.PID_entry[key][1] == True:
                        #print "here1: "+key+" "+item
                            self.PID_entry[key][0].set(item)
                    except:
                        pass

        
        self.root.after(sampling_time,self.read_values)

Obviously it’s only a part of the code. Let me know if you want to know more.
Thanks,

Please post the whole code ................. as I cannot see the datatypes of vars and initialized value you use..... I cannot test the code here .....

OK,

What is the output of the Arduino sketch when you capture it with the serial monitor?

Does it shows the output you expect? if so we can consider the arduino code to be correct, if not what did you expect ?

Also, with your python code you should be more explicit in which exceptions you care to catch. The way the code is written any number of bad exceptions will be silently caught and ignored. Therefore, only catch the exceptions you know should cause that sequence of events and allow the other exceptions to alert you when you have exceptional behavior.

Very good, I try to explain the problem with a more simple and detailed example:

Arduino side:

long interval = 100;
long previous = 0;

void setup() {
  Serial.begin(115200);
}

void loop() {
  unsigned long start = millis();
  
  if (start-previous > interval) {
    Serial.print("1234567890#0#1234567890#1#1234567890#2#1234567890#3#1234567890#4#1234567890#5#1234567890#6#1234567890#7#1234567890#8#1234567890#9#1234567890#10#1234567890#11#1234567890#12#1234567890#13#1234567890#14#1234567890");
    previous = start;
  }

}

Pyhton side:

import time
import serial

if __name__ == '__main__':

    start = time.time()
    pass
   
    ser = serial.Serial(port='COM4', baudrate=115200, dsrdtr=True)
    while 1:
        ser_var=ser.read(ser.inWaiting())
        print time.asctime()+" "+ser_var
        time.sleep(0.1)
        if time.time()-start > 10:
            break
        
    ser.close()
    print "serial port close"

the output

Fri May 18 17:18:03 2012 
Fri May 18 17:18:03 2012 1234567890#0#1234567890#1#1234567890#2#1234567890#3#1234567890#4#1234567890#5#1234567890#6#1234567890#7#1234567890#8#1234567890#9#1234567890#10#1234567890#11#1234567890#12#1234567890#13#1234567890#14#1234567890
Fri May 18 17:18:03 2012 1234567890#0#1234567890#1#1234567890#2#1234567890#3#1234567890#4#1234567890#5#1234567890#6#1234567890#7#1234567890#8#1234567890#9#1234567890#10#1234567890#11#1234567890#12#1234567890#13#1234567890#14#1234567890
Fri May 18 17:18:03 2012 1234567890#0#1234567890#1#1234567890#2#1234567890#3#1234567890#4#1234567890#5#1234567890#6#1234567890#7#1234567890#8#1234567890#9#1234567890#10#1234567890#11#1234567890#12#1234567890#13#1234567890#14#1234567890
Fri May 18 17:18:03 2012 1234567890#0#1234567890#1#1234567890#2#1234567890#3#1234567890#4#1234567890#5#1234567890#6#1234567890#7#1234567890#8#1234567890#9#1234567890#10#1234567890#11#1234567890#12#1234567890#13#1234567890#14#1234567890
Fri May 18 17:18:04 2012 1234567890#0#1234567890#1#1234567890#2#1234567890#3#1234567890#4#1234567890#5#1234567890#6#1234567890#7#1234567890#8#1234567890#9#1234567890#10#1234567890#11#1234567890#12#1234567890#13#1234567890#14#12345678901234567890#0#1234567890#1#1234567890
Fri May 18 17:18:04 2012 #2#1234567890#3#1234567890#4#1234567890#5#1234567890#6#1234567890#7#1234567890#8#1234567890#9#1234567890#10#1234567890#11#1234567890#12#1234567890#13#1234567890#14#12345678901234567890#0#1234567890#1#1234567890#2#1234567890#3#1234567890#4#1234567890#5#1234567890#6#1234567890#7#1234567890#8#1234567890#9#1234567890#10#1234567890#11#1234567890#12#1234567890#13#1234567890#14#1234567890

I cannot explain the last two communication strings (Fri May 18 17:18:04 2012). Can anyone help me?

For starters, you have clock skew. You're making the assumption that both have exactly the same timing.

For testing, change your python:

import time
import serial

if __name__ == '__main__':

    start = time.time()
   
    ser = serial.Serial(port='COM4', baudrate=115200, dsrdtr=True)
    while 1:
        ser_var=ser.read(210)
        print time.asctime()+" "+ser_var
        
    ser.close()
    print "serial port close"

Also, are you sure you need dsrdtr enabled? You might just use, "serial.Serial(port='COM4', baudrate=115200)".