Friday, August 14, 2009

So

So why no updates for a week? Because I have been busy building the program up.. a lot of my previously dicussed goals are being worked towards and theres no new code thats ready for publication yet. It is getting closer though, I've moved the code into function calls and now I am just setting some stuff up so that it can be used as I envision it.

Right now it is a pretty simple system:

ArdPyth.Start(DataSize,FlagChars,Baud,Port)
ArdPyth.Send(Data)
ArdPyth.Read()
ArdPyth.Close(Port)
ArdPyth.Interrupt --- To be implemented.

Start is just how it sounds, you declare the size of data you expect(However many characters long). Then you add in the "FlagChars" which are the end of data signals such as "/f/" or "&P&" just anything you do not expect to see in your data transmission. Baud & Port are straight forward. This program then uses a startup routine on the other end that waits for a startup sequence then sets itself up to work with the parameters. Some of things I still have to implement on the other side is data-sanitizing, possibly data fragmentation, and some various optimizing ideas I have.

Send is pretty straightforward, just takes the data to be sent off(int, strings, whatever) and converts it to a string then fires that off, along with its orginal variable type. On the other end the program accepts it and rebuilds it as its previous type. This is currently async, which means there is no way to verify the data's arrival or correctness.

Read is basically the exact oppisote of send. Takes the data in, sanitizes it*, then converts it back to its previous data type and this is read in as a variable. This is where the problems start though, C doesn't like dynamic typing as a language.. so how can you use it?

You can't just say:

Blah = ArdPyth.Read();

What if the data its reading is a floating point variable and blah is a string? Well! One of my ideas(read: not written yet) is to add in a type command on the ArdPyth.Read command. So it would be like this:

Blah = ArdPyth.Read(integer);

This would tell the read command that the output has to be an integer, if the data inside is a string though and does not conform to integers then it would produce an error code in the integer. A quick if statement on the C side of things, and WHAM! Done. I still got to write this out and see how it works in real world.. but thats later.

ArdPyth.Close(Port) is the single most straightforward command. It wipes the buffer, then closes connection.

The interrupt command is something I keep playing with in my head, it would be only useful for the arduino to arduino communication though. It would allow me to demand the other arduino read its buffer until it finds a certain character, then do whatever it tells it do. This could be useful if I have 2 or 3 arduino's together that are doing something time sensitive like balancing, if one accelermator detects an anamoloy(Oh no! I'm falling!! Aaah!) it would interrupt the other 2 and tell them to check. If all 3 agree, it does something. Thats a poor example because even that would take too long I imagine..

Anyways, code will be up sunday night.

* It does not currently sanitize the data. I have been waaaaay too lazy to bother coding this, its a lot of work to make fast.

Saturday, August 8, 2009

Update!

Sorry everyone about no updates, been busy with life and family. No real news on the project, but monday you should see a new post. I decided to make this whole system a lot more robust.. heres the rough idea:

  • Setup routine: This can be called to enable the serial port, determine data packet sizes, header type, etc etc.
  • Send function: Just like it sounds, a simple function I can call to transmit whatever data I want to the system from the ard, and the reverse.
  • Ard to Ard protocol: I am a firm believer in using as few "computers" as possible to accomplish something, however I do believe that somethings are best seperated. IE if you have a balance robot, it can't exactly be successful if 80% of the CPU load is spent reading a laser range finder or something. As such, I'd like to get an arduino library created that uses the same system as the python, except it would utilize interrupts to demand attention, that kind of thing.
  • Test the over all system for speed. I need a benchmark to work from, so I should start doing that soon.
Hopefully I can get some of this sketched out better in the coming days. My goal is starting to shape up a bit better... I really love the idea of using the Wii nunchucks for some kind of "floating" system control. Using the accelermators as some kind of camera/turret/grabber control, and then using the thumb controls and buttons as inputs to control the function. If this is a goal I want to achieve then the serial communication between all the systems will be crucial..

Anyways! Look for an update monday night or tuesday!

Regards,

Tuesday, July 28, 2009

Build #4!

New features for build #4:

  • It actually does something useful. (WOW!)
  • Has basic error checking inplace, should help eliminate string index errors
  • Has a basic packet structure in place, 959595 indicates that data is coming in.

First of all, this program will read the data in from the Sharp IR range sensor I am using as a semi random number generator. You will notice on the output it looks like this:

Output:
C&

C is 69 or something in ASCII(too lazy to check), which is a range that this sensor could be producing. In order to verify it is accurate, I replaced the actual sensor input on the ard with "343" and ran it, the output was W. Go ahead, hit alt + 343. W is the result, which verifies the output.

Also, please note in the code below, in the function, that I am using basic error checking to avoid errors. This one was implemented because I was getting a pretty constant string index error after a few seconds because it would not have any data and thus nothing to access(I think :P). Anyways, this basically runs a length check on the string and then verifys that the index that is about to be called is actually there, if not it breaks out of the while loop and goes around again. I am no professional coder, just a hobbyist, but I feel that these kinds of steps are crucial to a solid program. I am sure there are cleaner ways to do it, and I will look for them and try to think them up, but this is working for now.

You will see that I used 959595 for the initial "header" part of the data, and then only a & as the end in the function. The 959595 was used because it should be bigger then any of my sensor readings, and I used & because it was a random variable.

Anyways! Below is the code, as always.. feel free to use it for anything you want, no credit needed at all. Just enjoy it and hopefully learn some. Oh, that reminds me, this is all done in strings really. It is just easier in python and ard to use strings all around then dealing with conversions at the moment.

import serial
import time


Sensors1 = 0
r = 0
y = 0
# Setup area, starts serial, gives some info, then sleeps for about 2 seconds.

ser = serial.Serial('/dev/ttyUSB0', 19200, timeout=0) # Pretty straightforward, opens that device up for serial.
print "Current port location:" # Informational
print ser.portstr # Prints basic port information
time.sleep(1.75)

def Sensor_Read(): # This is the function that reads the sensor in.
i = 0
j = 0
r = 0
while i == 0:
r = ser.read(2)
if(j >= len(r)): break # Makes sure I am not refrencing an index that is out of range
if(r[j] == '&'): i = 1 # Reads until I find a &
j = j+1
return r

while y == 0:

sensors1 = ser.read(6)
if(ser.inWaiting() > 0): # Don't run this until something is in the buffer
if(len(sensors1) > 0):
if sensors1 == "959595": # This is arbitrary, I just told the arduino to write that as a 'header'
print "Output:"
print Sensor_Read()
time.sleep(.1)
else:
ser.flushInput() # If the numbers aren't write, wipe the buffer and retry

ser.close()

Now is the arduino code, a few quick notes. It is a very compact code base, because the ard is by far the weaker of the two systems for processing power and memory. Also, I commented out the build notice because it is not terribly relevant right now.

int InputSer = 0;
int potPin = 7;
int AnalogIn = 0;
void setup()
{
Serial.begin(19200); //Rather straightforward, 9600 baud rate for this serial connection.
//Serial.println("Adruino Python serial system. Ard Client. Build #4");
}


void loop() {

AnalogIn = analogRead(potPin);
Serial.println("959595");
Serial.write(AnalogIn); // This will send the intiger on the same line as the &, & carries a /n(line term) on it.
Serial.write('&'); // Signals end of variable
delay(100);


}

I really wish there was a way to make that code look cleaner, but just copy it to a wordpad(or whatever) and view it there. This is currently working on the Arduino mega and CentOS5 with Python 2.6(I believe). Also you need the PySerial module installed. Google it, if you still need help just email me or comment here.

Thanks all! Enjoy!


Its working :)

Quick update, made a lot of progress today. Hopefully enough to release build 4 tonight(with code!). Basically, I have a few small bugs to iron out and it should be good. I ended up using a datapacket idea like I said earlier, introduced the first function to my code as well. Good stuff :)

Look for an update in the next 12 hours.

Sunday, July 26, 2009

Determined

Well I have determined the next step and commands needed. As I am 'new' to python a lot of googling has occurred, and lots of rummaging through documentation. Anyways, it turned out to be a super simple answer… Instead of fighting the Arduino's natural tendency to do everything in ASCII, I am going to embrace it. As far as I can tell, the ard sends everything in 8 ASCII sequences.

Example:

If I were to have the ard send over "I am a pretty duck!" on serial, and then have the python app just write out this:

print Serial.read()

It would appear on the screen as so:

I am a p

retty du

ck!

If I use the print Serial.readln() it would just come out as the single line of "I am a pretty duck!".

Anyways, using the serial.read() command on python I can have the ard send over something like "75757575" and have the python read that in as a string. Then convert that string to integer by using the int() command.

or:

BufferStr = serial.read()

BufferInt = int(BufferStr)

Assuming that BufferStr does indeed contain "75757575", BufferInt would then also contain 75757575.

Notice the lack of quote marks, indicating that is not a string but an actual integer value. This should alleviate my issues of type and data size. Using that, I should be able to get my system running pretty damn well by Wednesday night.

Oh, also I suppose an explanation is needed for my posting patterns. I work 3 or 4 day work weeks, 12 hour days though. So on work days I generally am at work, come home, fall asleep within an hour, and then head back to work after I wake up. During these swings I won't be able to do much with the actual code… mostly just research stuff on breaks at work.

Regards!

Thursday, July 23, 2009

Update

Just wanted to put a quick update on the blog about current progress and issues. I am currently trying to setup a system to deal with varying data size. Obiviously if I am going to use this data for any sort of processing it has to be parsed correctly, I need to have a section of data that is cleanly accepted and verified. Right now I have it basically just reading everything in the buffer and printing it on the screen.. that works because I can easily distingush that "44" *pause* "512" *pause* "423 means that it was 44, 512, 423. However, when I remove the built-in pauses I am getting an output similiar to this:

44512354235212361263271581246123. Which is, of course, useless. So now I am faced with a larger series of questions that need answering.

1. What data format is the Arduino sending out when I use the Serial.write(X); command.

2. What data format is the Python program assuming the data coming in is?

3. Assuming the data types are both ASCII, then doesn't that limit the size of the data to 1 byte? Or 255 in decimal form?


I spent yesterday fiddiling with it, setting the arduino to write decimal numbers, or bytes, and was not getting the expected results. I suppose I need to buckle down and just start working out a data packet system.

So, that is where I am right now. No code updates or examples.. just a bit of theory discussion.

Tuesday, July 21, 2009

Code and further work


So in order to start this off right, I wanted to establish the very most basic of communication and method to verify that communication. Essentially I setup a breadboard with 3 LED's and each LED is wired to the Arduino on a different digital pin. This will let verify that what the python is telling the Arduino, is really occuring.

As you can see on the left in the photo, the setup is simple. The "red" is the connection for the Arduino to the LED's(through resistors) and then the black coming from the LED's are the ground. That goes to a shared ground, which then is wired back to the arduino's onboard ground. Very straightforward.

Here is a video I made of the setup in action. Sorry for the bad quality on all of my media.. its coming from a G1 phone, and thus pretty horrible.



As you can see, I now have a successful setup that allows a python "script" to command my Arduino in a very basic form. At the very bottom of this post I have both the arduino code and the python script. In order to run the python script you will need Python(http://www.python.org/) and also the Python Serial module(http://pyserial.sourceforge.net/). The code is designed to run a linux box, so keep that in mind. The only change you would need to make on a windows box is in the '/dev/ttyUSB0' section. You would need to change that to COMX, where X is the arduino's communication port.

I am writing this assuming that you have basic programming knowledge, which is all I have myself. It is a quick and dirty example of how this could work. I say quick and dirty because the Python script does no actual "thinking" it just sends the arduino a letter, waits a second, sends another, waits a bit more, and sends a third letter. In the Python code you will notice at the start it has a delay put in and that is because Python will exectue so fast that the serial buffers can't sync up.

Hopefully this is pretty self-explanatory. If you have any questions just comment and I will get to them ASAP. This is just the very very first step in the setup. Next comes building some functions for both the arduino and the Python. I am currently planning on a basic "start" section where the Python and arduino can negoitate with eachother about what type of error checking. This is done for scaling purposes; as the code base gets larger I want to have it already capable of a 'strict' error system that minimizes lost data. Then I will have a second one that is 'speed orientated' and whos only goal will be to make sure that it is discarding damaged chunks of code.

Please note, I generally won't be posting twice a day, but this is the first day and I am a pot of coffee in. :) Thanks all! Heres the code:


Python:

import serial
import time

ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=0)

print "Current port location:"
print ser.portstr
time.sleep(1.75)

print ser.readline()
time.sleep(.1)

ser.write("P")
time.sleep(1.5)

ser.write("Q")
time.sleep(1.5)

ser.write("R")
time.sleep(1.5)

ser.close()


Now, onto the Arduino "sketch":

int led1 = 31;
int led2 = 33;
int led3 = 35;
int InputSer = 0; // led1-3 are just variables for which pins are connected to LED's on a breadboard.
void setup()
{
Serial.begin(9600); //Rather straightforward, 9600 baud rate for this serial connection.
Serial.println("Adruino Python serial system. Ard Client. Build #3");
pinMode(led1, OUTPUT); // These are setting the pins to be used as OUTPUT's(and thus power the LED's).
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
}


void loop() {

if (Serial.available() > 0) { //This is a test to see if anything is in the buffer. If so:

InputSer = Serial.read(); //This will read the next byte in the serial buffer.
Serial.println(InputSer); //This prints that variable, only done for debugging.
if(InputSer == 80){ // P to hit LED1 on
digitalWrite(led1, HIGH); // sets the LED on
delay(1000);
digitalWrite(led1, LOW);
}
if(InputSer == 81){ // Q to hit LED2 on
digitalWrite(led2, HIGH); // sets the LED on
delay(1000);
digitalWrite(led2, LOW);
}
if(InputSer == 82){ // R to hit LED3 on
digitalWrite(led3, HIGH); // sets the LED on
delay(1000);
digitalWrite(led3, LOW);
}
// Above you will see that I have a few different things that may need explaining. First of all, the 80, 81, and 82. This is what P, Q, and R are in "byte" form. These are just some numbers I guessed at random..
// If you are curious what numbers == what letters, just hit alt + XXXX. Alt 0080 is P. 81 is Q, 82 is R.
}
}