1

I have create a code which opens a serial port where is an arduino connected and takes some data,so far so good,my problem is when I open my program and press the start button (which opens the serial port and wait receive the data from arduino) and I have forget for some reason to connect the arduino then obviously it doesn't do anything, when I plug it without close and open it again the program and press the start still it doesn't work.Obvious if I restart the program there is no issue but how can I solve this without restarting the program?My second issue is when my program works and receiving data and I disconnect the USB my program it doesn't close even if I press stop and try to close or if I connect it again the USB and afterwards try to close it,the only way to close it is from the Task manager.Why it happens this and how can I solve it?For the second issue I can't understand why when I close the program from the task manager and run it again still it dosn't work,works only if I unplug the USB and connect it again and rerun the program.

P.S: I know there is no obvious reasons to do such things but I'm curious and I wont to learn.

Here is the code from the start/stop button:

def onStartStopButton(self, event):
    global a2
    global q
    global i
    if not self.isLogging:
        self.isLogging = True
        self.ser = serial.Serial()
        self.ser.baudrate = 38400
        self.ser.timeout=0.25
        # Try serial ports one by one starting
        for m in range(29, 0, -1):
            self.ser.port = m
            try:
                self.ser.open()
                break
            except:
                # We end up here if this port number
                # failed to open
                pass
        if self.ser.isOpen():
            i=0
            # We successfully opened a port, so start
            self.timer.IsRunning()
            self.t=time.time() -self.tZero
            self.tZero=time.time()
            self.timer.Stop()
            self.timer.Start(100)
            self.startbtn.SetLabel("Stop")        
    else:
        i=1
        self.timer.Stop()
        self.ser.close()
        self.isLogging = False
        self.startbtn.SetLabel("Start")
        a2 = True 

def GetSample(self,event=None):
    global a2
    global a4
    global a5
    global b1
    global b2
    global b7
    global h
    global q
    global arduinoDelay     
    global last_received1
    global now
    global array

    a1=0
    a3=0

    self.t=time.time() -self.tZero      
    tiTuple=time.gmtime(self.t)    
    reste=self.t-tiTuple[3]*3600.0-tiTuple[4]*60.0-tiTuple[5]*1.0
    resteS=("%.2f" % reste )[-2::] 
    tt=time.strftime("%H:%M:%S",tiTuple)
    self.tAff.SetLabel(tt)

    while a2:#send to arduino time refresh
        for a1 in range (2):
            self.ser.write(arduinoDelay)
            time.sleep(0.5)
            h=0
            print "write to arduino delay ",arduinoDelay
        a2=False
        arduinoSensorNum = 'E'
        if '1' in sensor_select:
            arduinoSensorNum += '1'
        if '2' in sensor_select:
            arduinoSensorNum += '2'
        if '3' in sensor_select:
            arduinoSensorNum += '3'
        if '4' in sensor_select:
            arduinoSensorNum += '4'
        if '5' in sensor_select:
            arduinoSensorNum += '5'
        if '6' in sensor_select:
            arduinoSensorNum += '6'
        arduinoSensorNum += '/'
        a4=True
    if (sensor_select == ''):#if no one sensor select--> enable all
        arduinoSensorNum = 'E123456/'


    while a4:#send arduino enable num sensors
        for a3 in range (1):               
            self.ser.write(arduinoSensorNum)
            time.sleep(0.5)
            print "write to arduino sensor Num ",arduinoSensorNum
        a4=False

    if not h==1:
        q=1
        self.ser.write('S')
        print "send S "

    sample_string = self.ser.readline()
    now = datetime.datetime.now()

    if len(sample_string) == 15:#
        sample_string = sample_string[0:-1]
        sample_values = sample_string.split()

        for m in range(self.M):
            # get one value from sample
            value = int(sample_values[m])
            self.x[m][0:99] = self.x[m][1:]
            self.x[m][99] = value

        # Update plot
        self.ax.cla()
        self.ax.autoscale(False)
        self.ax.set_xlim(0, self.N - 1)
        self.ax.set_ylim(-100, 1100)
        for m in range(self.M):
            self.ax.plot(self.n, self.x[m])
        self.canvas.draw()#

    if not sample_string =='':
        h=1#stop send start to arduino
        if not b2 == True:
            file_date = open("C:/TMS Data/date.txt","a")
            file_date.write(now.strftime("%Y-%m-%d\n"))
            file_date.write(now.strftime("%H:%M:%S\n"))
            print "######################"
            b2 = True
        file_sensors = open("C:/TMS Data/sensors.txt","a")
        file_sensors.write(sample_string)
        print q
        array[q]=sample_string
        print array[q]
        q=q+1

        """if q == 7 and i==1:
            self.timer.Stop()
            self.ser.close()
            self.isLogging = False
            #self.startbtn.SetLabel("Start")
            a2 = True"""

        if q == 7:
            q=1
            b2 = False
            b7=True

    if b7 == True:
        self.textctrl0.Clear()
        self.textctrl0.AppendText(array[1])
        self.textctrl1.Clear()
        self.textctrl1.AppendText(array[2])
        self.textctrl2.Clear()
        self.textctrl2.AppendText(array[3])   
        self.textctrl3.Clear()
        self.textctrl3.AppendText(array[4])
        self.textctrl4.Clear()
        self.textctrl4.AppendText(array[5])
        self.textctrl5.Clear()
        self.textctrl5.AppendText(array[6])
        b7=False

Ok I figured it out, the problem was the part with the quotes, the use of this part was when the user pressed the stop button the code continued until take the last value from the last sensor. The above problems was solved when I add this lines in onStartButtons define!

My new problem now is that if the user press stop and the arduino was sending the value from the sensor 3 how can I make it continue and take the other 3 values from sensors 4-5-6 and then to close the serial communication?

user2971990
  • 127
  • 8
  • I don't know a lot about serial or USB, however, if the problem is persistent across program runs, then it must be related to a library or OS driver. Look into how to reset a serial port (or COM or VCOM) and try that. – dilbert Nov 20 '13 at 01:55
  • As for the unresponsive issue, the call to the serial library is halting your GUI thread (as you making that call from the GUI thread). Delegate all serial interactions to another thread and use messaging of some type (ie: wxevents ) to trigger responses in your GUI. If you set this worker thread as a daemon thread, you should be able to close your GUI without it halting. – dilbert Nov 20 '13 at 01:59

2 Answers2

1

If the calls to your serial code are making your program unresponsive, then the serial call is likely blocking the GUI's mainloop. In that case, you'll want to do all your serial work in a separate thread and use wxPython's thread-safe methods to update the display. Those methods are wx.CallAfter, wx.CallLater, and wx.PostEvent. You can read more about wxPython and threading at the following:

If you do attempt to call a wxPython method from a thread, the behavior will be undefined and you may or may not have immediate issues.

For serial issues, I would recommend reading the library's documentation and/or contacting their mailing list or dev team with questions/issues.

Mike Driscoll
  • 32,629
  • 8
  • 45
  • 88
0

It sounds to me like this is an example of an old limitation regarding UNIX serial device access (one which was inherited by Linux). There are not OS native primitives preventing contention on the devices. If multiple processes open a serial device under Linux or UNIX then, generally, the they will always be racing for any input from the device (characters will be non-deterministically received by one or another process) and output will sporadically interleaved and blocked for all processes writing to the device.

Classically UNIX and Linux programs use locking files (such as /var/log/LCK..ttyS0) to co-ordinate access to these devices. This is explained in places like: Linux Serial HOWTO: Lockfiles and has been discussed a few times on StackOverflow Stack Overflow: How can you access a serial port from two different processes (Python)

Serial Communication one to one

Community
  • 1
  • 1
Jim Dennis
  • 17,054
  • 13
  • 68
  • 116