[Tutor] truncated dictionary return

Wolfgang Maier wolfgang.maier at biologie.uni-freiburg.de
Mon Dec 2 09:46:06 CET 2013


richard kappler <richkappler <at> gmail.com> writes:

> 
> 
> Now I'm completely lost. While opening the serial port outside the
function sounds like a good idea, I'm thinking that might not work unless I
am mistaken. The sensorRead function once it's called would then basically
own the serial port barring other traffic, yes? That won't work as the same
serial port that receives sensor data from the arduino sends propulsion and
nav signals to the arduino which, along with controlling/reading the
sensors, also controls the motors used for propulsion, hence only opening
the port when the data is called for. The sensorRead function works, heck
it's not even mine, it was written by one of the gurus here in response to a
question I posed months ago (either Alan or Eryksun IIRC) and does exactly
what it's supposed to do, except for the timing bit.
>

No doubt, the parsing the line into a dictionary part of the function works
(and, yes, it's obvious that it was written by someone with more Python
experience than yours - no offense here :) ).
What I'm trying to tell you is that the overall control flow of your program
seems to be wrong.

> 
> Perhaps I'm looking for a simple solution where none exists but I rather
doubt it. I was thinking something along the lines of (psuedo code here)
> check incoming dict for length or number of elements
> if 8, keep
> else retry
>

This won't help, if you cannot implement the retry. You have lost a line of
data at this point and you won't be able to bring it back magically, so the
question is can you live with that?
 
> While I appreciate the above comments and any help that is offered, I
neither understand them as presented nor think they will fix the problem
with the limited understanding I do have. Again, it could be my lack of
knowledge is preventing me from seeing the light here, but it feels like
we're reinventing the wheel.
> 
> I hope that didn't come across as rude, it truly was not intended to be such.
> 
> regards, Richard
> 
>

I think you're simply not understanding the mechanism of readline(). That
method will gather bytes from the serial port until it sees a newline, then
(and only then!) return the complete line to the caller. That means your
program will be blocked when you call readline() until a complete line has
been transmitted, i.e., your sensorRead function will "own the serial port"
as you call it anyway. If this is not what you want, you'll have to use
read() instead of readline() and manage buffering yourself. Again, with
readline() your script will be halted until a full line of sensor reads data
has been transmitted, independent of where and when you opened the connection.
Now about keeping the connection alive: As you realized (I guess that is
your sync issue), you cannot control when data gets sent. This means that
you need to keep listening continuously or you may miss the beginning of a
transmission. Again, readline() will make sure that you get everything up to
the end of a line, but if you happen to open the arduino connection in the
middle of the transmission of a line, readline() has no means of restoring
the beginning of the line and your input will be incomplete (this is exactly
what's going wrong when your current code fails).
So, keep the connection alive during your script!
Switching between sending and receiving is the task of your main program
(that's the # do something with the data part in my previous message, see
below again):

def sensorRead (arduino):
    line = arduino.readline().strip()
    line = line.lstrip('{').rstrip('}').strip()
    # rest of your code

# your main program:
# open the connection
arduino = serial.Serial('/dev/ttyACM0', 9600)
sleep(1)
# keep operating
while True:
    # parse a single line of sensor reads data and store it as a dict
    reads = sensorRead(arduino)
    # do something with the data, i.e. react to it by sending commands

Best,
Wolfgang






More information about the Tutor mailing list