Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reset an open serial port

Tags:

I am reading data from a serial port, sent by an arduino.

I have two files, which I use separately to write some code and try differents things. In one of them, I read the data and I draw it using a matplotlib figure. After I finish using it, it remains connected to my computer and sending data. So, what i need to do is to "reset" the port. This is, close the opened port and open it again, and stop it from sending data so I can use the arduino to try some modifications in the code of this file.

So to accomplish this, i mean, to reset the port, i created another file and wrote this code:

import serial

print "Opening port"

try:
  serial_port = serial.Serial("com4", 9600)
  print "Port is open"

except serial.SerialException:
  serial.Serial("com4", 9600).close()
  print "Port is closed"
  serial_port = serial.Serial("com4",9600)
  print "Port is open again"

print "Ready to use"

But this code does not seems to work.The port is still connected and sending data. So, it means that I can not close the port with my code,and then reopen it again.

What am i doing wrong? How can I stop the arduino from sending data? Or how can I reset thw arduino, maybe?

Hope you can help me.

----- EDIT -----

I accomplish to identify the real problem that i am having, and it is not what i thought. The problem was not that the port was open despite that i use the closefunction that Pyserial have. The real thing is that the port is closing as I want, but the device (the arduino) is still sending data. So, i changed the code to reproduce the situation.

This is the code:

print "Abriendo puerto"

ser = serial

try:
  ser = serial.Serial("com4", 9600, timeout = 1)
  serial_port = "Open"
  print "The port %s is available" %ser

except serial.serialutil.SerialException:
  print "The port is at use"

  ser.close()
  ser.open()

while ser.read():
  print "Sending data"

ser.setBreak(True)
time.sleep(0.2)

ser.sendBreak(duration = 0.02)
time.sleep(0.2)

ser.close()
time.sleep(0.2)
print "The port is closed"

exit()

With this code, what i do is:

1) I open the serial port

2) If the device is sending data, I print "Sending data"

3) After 1 sec, I try to close the port and stop the device from sending data

I tried these last two thing with the close function to close the port, and reading the docs I tried with setBreak and sendBreak as you can see in the code above (i left them on purpose). But the device is still sending the data, which means that the code does not work.

So, is there a way to tell the arduino "stop sending data", or can i reset the device?

like image 230
Pablo Flores Avatar asked Apr 26 '16 15:04

Pablo Flores


People also ask

How do I fix a serial port problem?

Go to Device Manager > Ports (COM & LPT) > mbed Serial Port, then right-click and select "properties". Choose "Port Settings" Tab, and click "Advanced" Under "COM Port Number", try selecting a different COM port. Unplug and replug the mbed to reload the driver - if the problem persists, try another COM port.

How do I force close a port?

There is no way to force another process to close the port so you can take it. But Windows isn't opening up the port by itself - some other application running in the background is probably doing it. Download Process Explorer and use the "Find Handle or DLL" on the Find menu to find the process with the com port open.


1 Answers

I do a very similar thing, two ways with success.

The first way is to let the Arduino send data continuously. The problem here is when your python code wakes up and starts to read from the serial port, the Arduino might be anywhere in its procedures. The simple solution is to modify the Arduino code to send some kind of "restarting" line. All your python code needs to do in this case is wait for "restart", then read real data until it again sees "restart". I had noisy lines so my code read (and parsed) through multiple cycles to make sure it got good data.

resetCount = 0;
while resetCount < 3:
    line = s.readline().rstrip("\r\n")
    if string.find(line, "restart") != -1 :
        resetCount += 1
    elif resetCount > 0 :
        fields = string.split(line, " ")
        dict[fields[0]] = fields

The second way is to implement a command-response protocol with the Arduino, wherein the Arduino sends data only when requested. In this case your python code sends a command to the Arduino ("RT" in the example below) and then reads data from the Arduino until it sees a "completed" line or it times out.

        dict = {}
        regex = re.compile('28-[0-9A-Fa-f]{12}') # 28-000005eaa80e

        s = serial.Serial('/dev/ttyS0', 9600, timeout=5)
        s.write("RT\n");

        while True:
            line = s.readline().rstrip("\r\n")
            print line
            if string.find(line, "completed") != -1:
                break;

            fields = string.split(line)
            if (regex.match(fields[0]) != None and len(fields) == 4) :
                dict[fields[0]] = fields
        s.close()
like image 63
Eric Nelson Avatar answered Sep 28 '22 03:09

Eric Nelson