Tuesday, September 29, 2009

On PAC in application

There has been a slight change in the manner of how PAC will work. While coding it I realized a weird thing - when the slave (MCU) can't talk until the Master (PC) requests something, there is little to no difference between sending a message and receiving one.


This seems to mean that the idea of writing PAC to have two different functions is a waste of time. As I began to code the Message object's get() and send() functions, I realized that too much of the code overlapped - nearly all of it.

To make it simpler on those wishing to figure out and expand PAC, now the key users function is transmit(), with the user edited function being process().

In the parameters for make(), a user puts in their sent message. What is sent is dependent on the user's design. For instance - if we are to control a motor (a common theme with robotics oriented me) then we can have a motor object created - this motor object has an id number if there is more than one in the application. The motor object also has a given voltage, desired position, or speed. If the motor command was an object extended from the Message object, say, motorCommand, and our motor object was motor1, then two lines would be needed to prepare our message:

motor1.speed = 100 #(assuming -100 to 100 percent)
motorCommand.transmit(motor1)

transmit() would first run make(), a function designed to make a string of our data understandable by our MCU. Once the string is prepared, transmit() begins, well, transmitting the data, with syncing the MCU and PC via a simple arithmetic handshake, and then continuing from there.

Of course, this is an example. It would make more sense giving the motorCommand object to motor1, so that motor1.setSpeed() would be a single, understandable call to control the motor. But the idea within setSpeed() would be exactly the same as my example.

Message.transmit() will return nothing if the Message attribute of isIncoming is set to False. If this is set to true, transmit() will eventually call process() and, in turn, return the result.

Message.result() is where users that want to adapt PAC to their own applications will do the majority of their work. By default, process() in a basic Message returns solely what is spat out by the MCU, with no parsing of the information. Raw serial data. Hardly ideal for most applications.

A user can easily implement their own object, using inheritance from the Message Class, to create their own tailored message object. By using inheritance in python, the result can be a short, easy to understand object that easily communicates with the MCU. There is only one function that the user really needs to edit and create for their object to work with PAC - process(). They need to program the inherited object what to expect from the MCU and how to understand the data flowing in.

If a command requests a sensor input from the ADC specificially, we may send the MCU a list of variable length, ranging from one through eight - the number of ADC ports on many of the 8 bit AVR chips. Then, in the order that we sent it the requested ADC's, the MCU eventually responds with the values of these ADCs.

process() is called towards the end of a call to transmit(). Since the user designed it, process() knows how to handle the incoming flow of data from the MCU, and returns a neatly organized set of data. It could be a list of lists, or an object representation of the data. What is returned is up to the user and how they want to handle their data.


On the AVR side of things...

You may have noticed that I have focussed almost entirely upon the python side. This is due in part to my indecision whether or not to use a pre-made AVR library, or just create as-simple-as-possible templates that any user can use, library or not. It is also due in part to my lack of time to try out and research the only two libraries that seem to fit the bill (AVRlib, the most likely extinct one that is hard to find, and Webplotlib, one I have never used).

No comments:

Post a Comment