Society of Robots - Robot Forum

Software => Software => Topic started by: vidam on March 29, 2009, 07:58:34 AM

Title: python threads
Post by: vidam on March 29, 2009, 07:58:34 AM

There is this python code that has a user-interface with buttons to drive and stop DC motors over a serial port connection to send motor commands to the microprocessor from a PC. The microprocessor interprets the python bytes and commands the motor driver via a packetized serial mode. In the python gui there is also this timer thread that periodically prints debug strings to the python console.

The problem occurs that only in the start of the code the motors will turn after turning the motor drive button and stops the motors after turning the motor stop button. Also, the thread that prints the debug statements print to the screen every 3 seconds. When I press the drive button again, the motors don't turn. But the debug statements are still printed.

Is it because the serial port thread is breaking down the command protocol to the motors too much?
What is the best practice for threading a serial port for debug print statements and motors commands. There are delays between the motor commands, but that didnt' fix the problem either.
Title: Re: python threads
Post by: dunk on March 29, 2009, 04:41:54 PM
have you tried feeding the serial port on the PC running the control program into the serial port of another PC using a rollover cable?
on the second PC run some terminal software that will display control bytes in hex.
this way you can check and see what is actually coming from the serial port.

out of interest, what OS are you running?
it's years since i've used windows but there used to be an option to log serial comms.

if you are using Linux or Mac you should be able to just create a text file and specify that as the output device.
run your control program for a while then just look at the contents of the file.

Title: Re: python threads
Post by: vidam on March 30, 2009, 07:08:51 PM
Awesome idea dunk. I gave you a thumbs up for helpful. I will try running it into another PC. What is a rollover cable?

I'm running Windows Vista
Title: Re: python threads
Post by: dunk on March 31, 2009, 02:24:41 AM
Awesome idea dunk. I gave you a thumbs up for helpful. I will try running it into another PC. What is a rollover cable?
hi Vidam,
no problem.

another name for a rollover cable is a "null modem" cable.
basically the Transmit pin on one serial port goes to the Receive pin on the other and vice versa.

if you are running your motor driver without hardware flow control you will only need the following connections:
Gnd   <>   Gnd
TX      <>   RX
RX      <>   TX

if you do have hardware flow control enabled you will need to connect a few more pins.
search for "null modem cable" in that case.

once you have built/found your cable you can test it using 2 PCs running hyper terminal.
anything you type in one console should appear in the 2nd.

try digging through the various windows options to see if vista can log your serial port output too.
that will tell you the same thing.

Title: Re: python threads
Post by: devlpr on January 29, 2010, 05:47:57 PM
It's hard to say where your specific problem lies but I can offer a few notes of advice in addition to agreeing with the previous suggestions.  When you are using a serial port and multi-threading there are a few things that you need to look out for.

1. Do multiple things try to use it at the same time (From different threads).
2. In your case: Is the thread being destroyed when you hit stop?  And is it trying to open the port again in another thread or the same one?
3. Timing is critical
4. A "dirty" buffer can be your demise.  Do some checks to see what's really coming out of the port.  Often you can have some left over data from the last command sequence. This mostly happens on the Rx side.  It's bit me more than once. There is usually a flush() command to clean out the buffer to put it in a known state.
5. Is your program expecting a response from the motor controller? See #4.

What I did was write a class that handles the serial port interaction completely.  I have a few tasks that interact with the port so the class is there to manage what gets access to it and when.  Here's a use case:

(The setup)
Thread 1 reads from a sensor.
Thread 2 tells the motors when to go.
serialComPy handles the interaction (it's the gatekeeper)

In practice:
Thread 1 opens the port through serialComPy
serialComPy locks the port to other processes.

Thread 2 tries to open the port with serialComPy while Thread 1 is busy with it.
serialComPy has a lock on the port until Thread 1 is done with it.

Thread 2 waits until lock goes off.
lock goes off (by way of Thread 1 telling it to unlock)
Thread 2 uses port

etc, etc, etc...

Whoever get's the port first holds the lock and it's all handled internally in serialComPy...

You still need to look out for the other points they are all very important!  Order of events is key.

I hope this helps.

-Darin V