Wednesday, September 16, 2009

PAC - Python / AVR Communication Library

I love making neat little acronyms. And so begins the first post about PAC!

Today I will be discussing my thoughts on the anatomy of a proper command message.

We need to accomplish three goals every time we send and receive a message between micro controller and computer:

  1. Send the message (duh!)
  2. Ensure that the message sent was properly read
  3. After handling the message, receive any response that may be sought after (and thus repeating these these steps)
Sending the message is simple. We'll be using PySerial. PyParallel is an option, but I haven't owned a computer with one of those ports in ages. There are, of course, other python modules for communication as well, allowing communication over networks and bluetooth (pybluez?) but in the end the simplest and most common way to communicate to an MCU is over a serial connection of some kind. Plus, PySerial is very basic and easy to approach. Requirement one, checked off.

Options two and three become more complex. In a system that will rarely expand, and is being developed very quickly, one might just create a list of bytes that represent the command set you seek and be done with it. I'm guilty of this, as well as several others. Unfortunately this limits expandability and can make code slow and a nightmare to debug.

Instead, let's consider a message as a Python object itself. If we think of it in this way, we begin to find some key attributes.
  • Direction - Is it outgoing or incoming? An incoming message would be data, which requires Python to know how to parse the incoming message into the relevant data.
  • Size - Size matters. One of the best ways to determine whether or not both your PC and MCU is on the same page is for each to know exactly how many bytes are being sent for each command, and never stray from that. So assigning a length to the message before it is sent can avoid many issues, and avoids the need for an end bit.
  • Identifier - The actual command being passed in needs to have an identifier known to both PC and MCU. This won't be human readable, but a(a series of) byte(s) unique to only that command. In terms of data being sent back in response to a request for that data, this acts as additional confirmation that the data being streamed back is what we want.
  • Parameters - Data that is unique to the individual command or identifier. It is of variable length, including 0. Example: A move motor command may be sent as "moveMotor, motor # 1, full speed, motor #2, half speed". I have not yet decided if I will include the complicated possibility of allowing the MCU to determine and parse parameter strings of variable length. An example of what I am debating - should I take the easier route, and make it so that a 4 motor robot would require 4 seperate commands to set the 4 motor's speeds, or a single command with 4 parameters that the MCU parses to set all their speeds at once.
From these key attributes, we can determine what a message on the Python side should consist of. We can also tell how the overall message structure will work.

Note the difference between the number of parameters and the size. This allows the Master to send a string of commands rapidly, in one go.

No comments:

Post a Comment