Saturday, January 31, 2009

Video Recognition Code

#include (Servo.h)

int ir_pin = 7; //Sensor pin 1 wired through a 220 ohm resistor
int led_pin = 11; //"Ready to Receive" flag, not needed but nice
int debug = 1; //Serial connection must be started to debug
int start_bit = 3800; //Start bit threshold (Microseconds)
int bin_1 = 1900; //Binary 1 threshold (Microseconds)
int bin_0 = 900; //Binary 0 threshold (Microseconds)
int data[13];
int rm1=3;
int rm2=2;

int lm1=5;
int lm2=4;

int start=0;
int motor_initial = 0;

int servo_angle=80;
int key;

char incomingByte;
int velocity=0;


//#define servo_initial = 80;
Servo servo1;


void setup() {
pinMode(led_pin, OUTPUT);
pinMode(6, INPUT);
pinMode(7, INPUT);
pinMode(8, INPUT);//This shows when we're ready to receive
pinMode(9, INPUT);
pinMode(rm2, OUTPUT);
pinMode(lm2, OUTPUT);

digitalWrite(rm2, LOW);
digitalWrite(lm2, LOW);
digitalWrite(led_pin, LOW); //not ready yet
Serial.begin(57600);
delay(100);
Serial.print("start");
servo1.attach(10);

analogWrite(rm1,start);
analogWrite(lm1,start);
servo1.write(80);

}




int getIRKey()
{

digitalWrite(led_pin, HIGH); //Ok, i'm ready to recieve
//while(pulseIn(ir_pin, HIGH) < start_bit) { //Wait for a start bit

data[0] = pulseIn(ir_pin, HIGH); //Start measuring bits, I only want low pulses
data[1] = pulseIn(ir_pin, HIGH);
data[2] = pulseIn(ir_pin, HIGH);
data[3] = pulseIn(ir_pin, HIGH);
data[4] = pulseIn(ir_pin, HIGH);
data[5] = pulseIn(ir_pin, HIGH);
data[6] = pulseIn(ir_pin, HIGH);
data[7] = pulseIn(ir_pin, HIGH);
data[8] = pulseIn(ir_pin, HIGH);
data[9] = pulseIn(ir_pin, HIGH);
data[10] = pulseIn(ir_pin, HIGH);
data[11] = pulseIn(ir_pin, HIGH);
data[12] = pulseIn(ir_pin, HIGH);
digitalWrite(led_pin, LOW);


if(debug == 1) {
Serial.println("-----");
}
for(int i=1;i<=12;i++) { //Parse them
if (debug == 1) {
//Serial.println(data[i]);
}
if(data[i] > bin_1) { //is it a 1?
data[i] = 1;
//Serial.print("1");
}
else {
if(data[i] > bin_0) { //is it a 0?
data[i] = 0;
//Serial.print("0");
}
else {
data[i] = 2;
//Serial.print("Error"); //Flag the data as invalid; I don't know what it is!
}
}
}

for(int i=1;i<=12;i++)
{ //Pre-check data for errors
if(data[i] > 1)
{
return -1; //Return -1 on invalid data
}
}

int result = 0;
int seed = 1;
for(int i=12;i>=9;i--)
{ //Convert bits to integer
if(data[i] == 1)
{

result += seed;
}
seed = seed * 2;

}
return result; //Return key number

}

void decode_IR()
{
switch(key)
{
case 2:
servo_angle = servo_angle + 4;
servo1.write(servo_angle);
break;

case 8:
servo_angle = servo_angle - 4;
servo1.write(servo_angle);
break;

case 4:
if(start<255)
{
start = start + 4;
analogWrite(rm1, start);
analogWrite(lm1, 0);
}
// delay(100);
//digitalWrite(lm2, HIGH);
break;

case 6:
if(start<255)
{
start = start + 4;
analogWrite(lm1, start);
analogWrite(rm1, 0);
}


//delay(100);
//digitalWrite(rm2, HIGH);

break;

case 5:
servo_angle=80;
start=0;
analogWrite(rm1, 0);
analogWrite(lm1, 0);
digitalWrite(rm2, LOW);
digitalWrite(lm2, LOW);
servo1.write(80);
break;

case 12:
if(start>-255)
{
start = start-4;
throttle();
}
break;

case 13:

if(start<255)
{
start = start+4;
throttle();
}
break;

}


}

void throttle()
{
if(start>0 && start<255)
{
digitalWrite(lm2, LOW);
digitalWrite(rm2, LOW);
analogWrite(rm1, start);
analogWrite(lm1, start);
}
else if (start<0>-255)
{
digitalWrite(lm2, HIGH);
digitalWrite(rm2, HIGH);
analogWrite(rm1, 255+start);
analogWrite(lm1, 255+start);
}
}


void loop()
{


for(ir_pin=6;ir_pin<10; ir_pin++)
{
serial_input();

if(pulseIn(ir_pin, LOW, 5000) > start_bit)
{
key = getIRKey(); //Fetch the key
if (key != -1)
{
//Serial.print(" Key Recieved: ");
//Serial.println(key);
}
// if(data[0]=1, data[1]=1, data[2]=1, data[3]=1, data[4]=0, data[5]=0, data[6]=1, data[7]=1)
//{
decode_IR();
//}

}
}


}

void serial_input()
{
//Serial.print("h");
if (Serial.available() > 0)
{
// read the incoming byte:
incomingByte = Serial.read();

// say what you got:
//Serial.print("I received: ");
//Serial.println(incomingByte);
serial_decode();
}

}

void serial_decode()
{
switch(incomingByte)
{
case '0' ... '9':
{
velocity = velocity*10;
velocity += int(incomingByte)-48;
//Serial.print(velocity);
break;
}

case 'w' :
{
//Serial.print(velocity);
analogWrite(rm1, velocity);
analogWrite(lm1, velocity);
digitalWrite(rm2, LOW);
digitalWrite(lm2, LOW);
delay(1000);
velocity = 0;
break;

}

case 's':
{
analogWrite(rm1, 0);
analogWrite(lm1, 0);
digitalWrite(rm2, LOW);
digitalWrite(lm2, LOW);
velocity = 0;
break;
}

case 'a':
{
analogWrite(rm1, velocity);
digitalWrite(rm2, LOW);
digitalWrite(lm2, HIGH);
analogWrite(lm1, 255-velocity);
velocity = 0;
break;
}

case 'd':
{
analogWrite(lm1, velocity);
digitalWrite(lm2, LOW);
digitalWrite(rm2, HIGH);
analogWrite(rm1, 255-velocity);
velocity = 0;
break;
}

case 'x':
{

analogWrite(lm1, 255 - velocity);
digitalWrite(lm2, HIGH);
digitalWrite(rm2, HIGH);
analogWrite(rm1, 255 - velocity);
velocity =0;
break;
}
}

}

Hooked up to RoboRealm, we first use the RGB filter to up the predominant colors of the thing we are looking at, and then we filter out anything that's not a specific color (ours was red). Then, we dilated the object and made it filter out any pixel that didn't meet a certain size requirement, to filter out any reddish objects in the background. Then we calculated the center of gravity of the object, and let the Java Script run the rest. Here is the Java.

cog_x = GetVariable("COG_X")

motor_output = "50w"

if(cog_x < 140) then
motor_output = "50d"

end if

if(cog_x >180) then
motor_output = "50a"

end if

SetVariable("MOTOR_OUTPUT"), motor_output

And there you go!

Friday, January 30, 2009

Week Four

As I mentioned in the previous blog, success with the motor! Today we actually used RoboRealm to take the images from the camera, do some analysis and filtering, and then identify the center of mass of the object. Then, using the serial port, we were able to have the motors of the blimp steer in the direction of the red object we had the software analyze. No video of it yet, but you can see Prof. Mason's site to see what the general idea is. Right now, we are tethered to the ground, but next week, I'll try to program a USB UIRT with Robo Realm and see if that can send commands to the board

Thursday, January 29, 2009

Camera!

Camera is connected and running off battery power!! No video to upload, that'll be soon to come!

Wednesday, January 28, 2009

Motor Update

Just replaced the dead motor with one of the new motors we received. The new motor starts up a lot faster than the older one does, but when I hold my hand up to each, the new motor seems to push air less than the old motor.

Friday, January 23, 2009

IR Update

Continuing on with the IR program we've been playing with, here's the code that we used
#include (Servo.h) *these are actually <>, for some reason, blogspot is deleting it when i upload

int ir_pin = 7; //Sensor pin 1 wired through a 220 ohm resistor
int led_pin = 11; //"Ready to Receive" flag, not needed but nice
int debug = 1; //Serial connection must be started to debug
int start_bit = 3800; //Start bit threshold (Microseconds)
int bin_1 = 1900; //Binary 1 threshold (Microseconds)
int bin_0 = 900; //Binary 0 threshold (Microseconds)

int rm1=3;
int rm2=2;

int lm1=5;
int lm2=4;

int start=0;
int motor_initial = 0;

int servo_angle=80;
int key;
//#define servo_initial = 80;
Servo servo1;


void setup() {
pinMode(led_pin, OUTPUT);
pinMode(6, INPUT);
pinMode(7, INPUT);
pinMode(8, INPUT);//This shows when we're ready to receive
pinMode(9, INPUT);
pinMode(rm2, OUTPUT);
pinMode(lm2, OUTPUT);

digitalWrite(rm2, LOW);
digitalWrite(lm2, LOW);
digitalWrite(led_pin, LOW); //not ready yet
Serial.begin(19200);
servo1.attach(10);

analogWrite(rm1,start);
analogWrite(lm1,start);
servo1.write(80);

}




int getIRKey()
{
int data[13];
digitalWrite(led_pin, HIGH); //Ok, i'm ready to recieve
while(pulseIn(ir_pin, HIGH) < start_bit) { //Wait for a start bit
}
data[0] = pulseIn(ir_pin, HIGH); //Start measuring bits, I only want low pulses
data[1] = pulseIn(ir_pin, HIGH);
data[2] = pulseIn(ir_pin, HIGH);
data[3] = pulseIn(ir_pin, HIGH);
data[4] = pulseIn(ir_pin, HIGH);
data[5] = pulseIn(ir_pin, HIGH);
data[6] = pulseIn(ir_pin, HIGH);
data[7] = pulseIn(ir_pin, HIGH);
data[8] = pulseIn(ir_pin, HIGH);
data[9] = pulseIn(ir_pin, HIGH);
data[10] = pulseIn(ir_pin, HIGH);
data[11] = pulseIn(ir_pin, HIGH);
data[12] = pulseIn(ir_pin, HIGH);
digitalWrite(led_pin, LOW);


if(debug == 1) {
Serial.println("-----");
}
for(int i=1;i<=12;i++) { //Parse them
if (debug == 1) {
//Serial.println(data[i]);
}
if(data[i] > bin_1) { //is it a 1?
data[i] = 1;
Serial.print("1");
}
else {
if(data[i] > bin_0) { //is it a 0?
data[i] = 0;
Serial.print("0");
}
else {
data[i] = 2;
Serial.print("Error"); //Flag the data as invalid; I don't know what it is!
}
}
}

for(int i=1;i<=12;i++)
{ //Pre-check data for errors
if(data[i] > 1)
{
return -1; //Return -1 on invalid data
}
}

int result = 0;
int seed = 1;
for(int i=12;i>=9;i--)
{ //Convert bits to integer
if(data[i] == 1)
{
result += seed;
}
seed = seed * 2;
}

return result; //Return key number
}

void decode_IR()
{
switch(key)
{
case 2:
servo_angle = servo_angle + 1;
servo1.write(servo_angle);
break;

case 8:
servo_angle = servo_angle -1;
servo1.write(servo_angle);
break;

case 4:
start = 0;
start = start +1;
analogWrite(rm1, start);
analogWrite(lm1, 0);

// delay(100);
//digitalWrite(lm2, HIGH);
break;

case 6:
if(start<255)
{
start = start+1;
}

analogWrite(lm1, start);
analogWrite(rm1, 0);
//delay(100);
//digitalWrite(rm2, HIGH);

break;

case 5:
servo_angle=80;
start=0;
analogWrite(rm1, 0);
analogWrite(lm1, 0);
digitalWrite(rm2, LOW);
digitalWrite(lm2, LOW);
servo1.write(80);
break;

case 12:
if(start>-255)
{
start--;
throttle();
}
break;

case 13:

if(start<255)
{
start++;
throttle();
}
break;

}


}

void throttle()
{
if(start>0 && start<255)
{
digitalWrite(lm2, LOW);
digitalWrite(rm2, LOW);
analogWrite(rm1, start);
analogWrite(lm1, start);
}
else if (start<0>-255)
{
digitalWrite(lm2, HIGH);
digitalWrite(rm2, HIGH);
analogWrite(rm1, 255+start);
analogWrite(lm1, 255+start);
}
}


void loop()
{
for(ir_pin=6;ir_pin<10; ir_pin++)
{
key = getIRKey(); //Fetch the key
if (key != -1)
{
Serial.print(" Key Recieved: ");
Serial.println(key);
}
decode_IR();
}
}

The biggest difference between this video and the last video is the smoothing out of the motors and servos once after we hit the kill/all stop switch. So, things to do for next week

1. Fix Motor

2. Program motor and test if it can recognize multiple beacons (the code is in place to tell us which button is pressed, so we'll just need to see if we can have it follow multiple beacons.

3. I want to try to program the remotes to give off different addresses and headers, and then program the board to only recognize a certain set of code

4. Once we get the circuit pins in (hint hint) we can install the camera and get working on programming that. More tutorials for me from RoboRealm and Prof Mason's site.

5. Optimize code for smoother transitions for acceleration.

Right Motor Dead

Looks like the right motor went kaput. We'll need to find a new motor =\

Thursday, January 22, 2009

IR Update




Using some new code we found on the internet, we were able to convert what the IR receivers took and and output in the serial monitor as a series of 1's and 0's. When we used our universal remote, we pressed button 1 and the following appeared


The header for our remote was 1110, address was 0011, command was 0001, and the complement was 0001 1100 1110




We did the same for button 2 and this is what we got




The only thing that changed in the numbers were the last four(0000 for zero and 1111 for nine).


When we tested the Channel Up command, it gave us this:


The header changed just slightly for this.
Anyways, the point of all this? Well, since the payload for the balloon wasn't sufficient enough to lift both the motor and the RC transmitter, I've been able to program it to follow the commands of a Remote control! Now we have room for the camera! (Prof Mason, don't forget the circuit pins!)
Video of IR control in action. (A copy of the code will be up tomorrow).

Tuesday, January 20, 2009

Payload

I measured the motor and the RC transmitter combined, and that came out to 108.1 grams. With the blimp envelope, that comes out to roughly 123 grams.


The length of the blimp is 52". For a diameter, I got approximately 26". The rough volume of the blimp is 10.35 cu. ft. Using pVg, I got a total upward lift of .81 N. The mass allowed for this lift is 83 grams, which is just enough to lift the motor by itself (motor is 79 g).

The 36" balloon would give us an upward lift of 1.55 N, so the new payload would be 159 grams. I did some reading and the 52" x 36"/37" is for higher altitudes. The air is less dense up there, so the mylar balloon will actually hold 2 cubic feet more. This size balloon can hold a maximum of 20 cubic feet of helium. This balloon would be much better at lifting heavier payloads, but we would need a lot more helium. Also, for the amount of lift it gives (about 30 more grams) I don't know if it would be worth it.

The batteries just ran out on the blimp; I'll need our ghetto charger to get it recharged =P

By the way, I still don't quite understand servo controls.

Monday, January 19, 2009

New things to do...

We need more payload.
Do some calculations.
What is the current payload of the envelope when it is full?
What is the volume of the envelope?  Make appropriate approximations.  The website says "5 cubic feet" does this match what you measure?
What is the diameter of the envelope? 
If the envelope is filled with 90% pure helium and helium has a density of .18 kg/m3.  Air has a density of 1.2 kg/m3.  Given the volume of the envelope, what should the theoretical payload be? 
The mass of the envelope is about 15 grams.  Is our measured payload even close?

I can get a 52" x 36" envelope here in about a week or so.  I only want to if it will solve our problems. 

On other topics:
Write some code to read the ultrasonic sensor and then have the blimp hover exactly 1 meter above the ground.  You know how to read the US and control the motors and you have already tied them together.  Now you need to tie them together in a meaningful way so that feedback from the us is controlling the blimps altitude.  
The most common scheme for doing this is called PID (proportional integral derivative) control. This sounds fancy, but it is pretty simple.  For our purposes I don't think we will need the integral portion of it, since the balloon will oscillate a LOT.  

Read this overview of control systems 

Proportional control just means that your output is propotional to the difference between the desired altitute and the current altitude. IE if we are really far from where we want to be, we should spin the motors fast to get there.  If we are close, we should spin the motors slowly so that we don't overshoot. 
In practice we define and error as 
error = desired value - current value.

The proportional part just means that the output to the motors is proportional to the error!

Output = k1 * error    Where k1 is some constant which is tuned manually.  (When you take a control theory class you will learn lots more about this but for now, just try different numbers until it works.)

Read this section of my friend alex's web page: Proportional Control

The derivative part of proportional derivative control is as follows.  We wnat to be traveling parallel to the floor.  If the rate of change of the error is large then we are moving toward or away from it and should provide counter thrust to prevent overshoot.   
Calculate the rate of change of the error by storing error in a variable and then taking the difference.   If we were really worried about things, we would look at the elapsed time for each loop and divide, but that is close enough to constant that it shouldn't matter. 

Now read this part on Derivative Control.

We will use the derivative to modify the output as follows:
Output = k1 * error - k2 * DError

The DError term is opposing the error term.  

For putting this together see: Proportional Derivative Control

I need to talk to Alex about moving that stuff to a friendlier site.  

Ok, let me know how your progress goes.  I will try to get in and drop of the IR remote so we can play with that. 

Friday, January 16, 2009

Digital Camera Online!

Just got the digi cam to sync with my laptop. Currently reading tutorials on programming and object recognition. I did some reading on the RC code as well. We need to leave the control stick in neutral when the board boots up or else it will memorize a different position as neutral. I think we've been playing with the sticks whenever we boot it up. I'll give it a try Tuesday.

Day Two~

The first thing we attempted to do today was mount a wireless digital camera to the blimp to see if the blimp could lift both camera and the motor board. Result: crashing nose first into the ground. The motor board itself is roughly 80 grams, but the digital camera is roughly another 80 grams. Even after attempting to push all the air out with a straw and refilling with helium, there was not enough lift to carry camera and board. We also took apart the camera and attached only the camera with it's board, but it still was too much weight. Our next step is to get rid of the Li-Ion battery on the camera and connect the camera to the LiPo battery on the motor.

Next came the RC. We test the settings for almost an hour until we figured out what would work best. While DIY said to plug the servo plug into throttle, we plugged it into elevation instead. We then plugged RC1 and RC2 into throttle and rudder. With our RC controller, the left stick controlled the throttle forward and reverse, while up and down on the right stick controlled the angle of the servo for the up and down, while left and right turned the fans on the right and left side respectively. There were some issues though. The throttle control was a little off: reverse was much stronger then forward. Basically, neutral was still going in reverse, and all the way forward was barely going forward. We'll probably have to go into the RC control to modify that, which I'll poke into this weekend. Also, rudder control was a little ungainly. I think that another one of the plugs will allow better turning; ideally, to turn left, right motor spins forward while left motor spins backwards. This will allow for much tighter turner. That'll be for Tuesday.

Ultrasound came next. While in the previous video (see about three posts prior) I was able to make the fan spin high or low depending on the length of the signal that came back, it would only spin low for small distances and high for large distances. So, I did the following:

//ultrasound mark 2

int usi = 16;
int uso = 15;
int rm1 = 2;
int rm2 = 3;
int lm2 = 5;
int lm1 = 4;

void setup()
{
Serial.begin(19200);
pinMode(usi, INPUT);
pinMode(uso, OUTPUT);
pinMode(rm1, OUTPUT);
pinMode(rm2, OUTPUT);
pinMode(lm2, OUTPUT);
pinMode(lm1, OUTPUT);
}

void loop()
{
int length = 0;
digitalWrite(uso, HIGH);
delay(40);
length=pulseIn(usi, HIGH, 200000);
digitalWrite(uso, LOW);
length=(length/147); //pulse width is 147us/inch so length is in inches
Serial.println(length);
if(length>=40 && length<=45)
{
analogWrite(rm2, 0);
analogWrite(lm2, 0);
}
if(length>45)
{
analogWrite(rm2, length);
analogWrite(lm2, length);
}
if(length<40)
{
analogWrite(rm2, 45-length);
analogWrite(lm2, 45-length);
}
}

This made it so that a distance of 40-45 inches from the ground was the idea hovering distance. Anything below that, the fan would spin at 40-d, where d is the distance from the ground, so the farther from the ground it got the slower it would spin and visa versa. Another thing that we confirmed was that the board ran using the digital pins TX and RX. This means we have to use two separate lines of code to send out a pulse and read the pulse (the 147 means 147 us/inch). The ultrasound also supports another pin, which is analog. This way, we would be able to have it do analogread to measure the distance of the waves; however, we're not sure if the board has a pin programmed for the analog on the ultrasonic.


Next we worked on the IR receiver and this was a bugger of an problem to figure out. I started with a code like this.

int IR_front = 8;
int IR_back = 7;
int IR_right = 6;
int IR_left = 9;
int ledn = 12;
int lede = 17;
int leds = 11;
int ledw = 13;

int vf = 0;
int vb = 0;
int vl = 0;
int vr = 0;

void setup()
{
Serial.begin(57600);
pinMode(ledn, OUTPUT);
pinMode(lede, OUTPUT);
pinMode(leds, OUTPUT);
pinMode(ledw, OUTPUT);
pinMode(IR_front, INPUT);
pinMode(IR_back, INPUT);
pinMode(IR_left, INPUT);
pinMode(IR_right, INPUT);

digitalWrite(ledn, LOW);
digitalWrite(leds, LOW);
digitalWrite(lede, LOW);
digitalWrite(ledw, LOW);
}
void led_off()
{
digitalWrite(ledn, LOW);
digitalWrite(leds, LOW);
digitalWrite(lede, LOW);
digitalWrite(ledw, LOW);
}

void loop()
{
vf = digitalRead(IR_front);
vb = digitalRead(IR_back);
vl = digitalRead(IR_left);
vr = digitalRead(IR_right);
Serial.print(vf);
Serial.print(',');
Serial.print(vb);
Serial.print(',');
Serial.print(vl);
Serial.print(',');
Serial.println(vf);


digitalWrite(ledn, HIGH);
digitalWrite(leds, HIGH);
diitalWrite(ledw, HIGH);
digitalWrite(lede, HIGH);

delay(10);
led_off();
}

When we ran the code, all the lights on the board turned on! It was weird. We then tried pushing a bunch of infrared remotes and nothing worked. Same with the IR beacon that came with the setup. The serial prints were just giving us 1's with an occasional 0. Then we turned off the beacon and the lights remained on. We turned them back on and that's when Prof Mason noticed the flickering. We turned off the beacon and the flickering stopped. Hmmmmm....perhaps it's backwards...instead of trigger High, like we thought, maybe the beacon made the IR trigger a low spot and that's what makes it detect it. To test it, we hooked up a spectrometer and turned off all infrared in the area....and we got two bars! The IR receivers were programmed on high! So we modified the code

int IR_front = 8;
int IR_back = 7;
int IR_right = 6;
int IR_left = 9;
int ledn = 12;
int lede = 17;
int leds = 11;
int ledw = 13;

int vf = 0;
int vb = 0;
int vl = 0;
int vr = 0;

void setup()
{
Serial.begin(57600);
pinMode(ledn, OUTPUT);
pinMode(lede, OUTPUT);
pinMode(leds, OUTPUT);
pinMode(ledw, OUTPUT);
pinMode(IR_front, INPUT);
pinMode(IR_back, INPUT);
pinMode(IR_left, INPUT);
pinMode(IR_right, INPUT);

digitalWrite(ledn, LOW);
digitalWrite(leds, LOW);
digitalWrite(lede, LOW);
digitalWrite(ledw, LOW);
}
void led_off()
{
digitalWrite(ledn, LOW);
digitalWrite(leds, LOW);
digitalWrite(lede, LOW);
digitalWrite(ledw, LOW);
}

void loop()
{
vf = digitalRead(IR_front);
vb = digitalRead(IR_back);
vl = digitalRead(IR_left);
vr = digitalRead(IR_right);
Serial.print(vf);
Serial.print(',');
Serial.print(vb);
Serial.print(',');
Serial.print(vl);
Serial.print(',');
Serial.println(vf);


if(vf==LOW)
{
digitalWrite(ledn, HIGH);
}
if(vb==LOW)
{
digitalWrite(leds, HIGH);
}

if(vl==LOW)
{
digitalWrite(ledw, HIGH);
}
if(vr==LOW)
{
digitalWrite(lede, HIGH);
}
delay(10);
led_off();
}

And Bam! Success! Another thing we did was put the beacon farther away, and that caused only one LED to light up. With the beacon too close, there was too much reflection and it caused all the LED's to light up.

So, things to work on.
1. Modify RC code for the throttle.
2. Get a small plug and wires for the battery
3. Get Robo Realm and the wireless camera to sync with my laptop.

That's everything I can remember. Anything to add Professor?

IR Beacon

Great progress today.  I will look forward to your writeup.  I looked at the beacon on my scope.  Sorry about the poor quality of the pictures.  I think that the beacon is just sending "001001001" etc.  Here is what I see on the screen.  There is a carrier signal with a period of about 18 us.  This corresponds to a frequency of about 56 Khz(Which makes sense since this is a 56khz beacon.)  On top of that I see two short pulses followed by one long. 

There appears to be a lot of noise in this image due to aliasing with the carrier.   Below is a zoom in on the pulses.  The smaller pulse has a pulse width of about 1.4ms and the longer pulse has a width of 2.4ms.  Looking at the vishay datasheet: 
I have usually use the sony protocol which uses a different set of pulse widths. (1.2 ms for 0 and 1.8 ms for 1.)  Take a look at this page for an explanation:

PS:

Here is a nice overview of how IR remotes work:
http://www.sbprojects.com/knowledge/ir/ir.htm

Ok, I think I found what the pololu beacon is using. It appears that the pololu beacon is using what looks like the RCA protocol! Here is a link to the description:
http://www.sbprojects.com/knowledge/ir/rca.htm

I have a couple of universal remotes that will produce this protocol, so with any luck it should be pretty straightforward to drive the blimp with the IR remote! (A worthy project I think) This would require no additional hardware or weight on the balloon.


Thursday, January 15, 2009

Update

I tested the board with the 2 amp cord and motor works fine now. I was also able to plug in the transmitter to the board using some cables and got the thruster control to work; however, the battery died before I could adjust the aileron controls.

1.
2. right motor back
3. right motor forward
4. left motor back
5. left motor forward
6. IR right
7. IR back
8. IR front
9. IR left
10. Servos
11 LED S
12. LED N
13. LED W
14
15. Ultrasonic out
16. Ultrasonic in
17. LED E

This is a list of pins and the things that they control. The numbers on the IR receiver are 19 711 v34156.

Alright, now for some fun stuff.

I was able to program the LED's to blink:


and here is a video of the ultrasound and motor combination. Note: the code for the ultrasound is a redone version of the original code, i just played with the names and things like that. I was not able to get it to do analog read....yet


Still working on the IR system at the moment...

Wednesday, January 14, 2009

Multiple Beacons

When you have finished everything in the previous post, take a look at this.
http://diydrones.com/profiles/blogs/705844:BlogPost:39610

It looks like they haven't solved this problem either. If you can read the part numbers off the IR receivers, I can do a bit of research. I am afraid that they used 56 Khz units on the board.

Motor stalling and more

My first thought is that the power supply we are using can't source enough current for both motors. (I take it you are not running off the battery?)

What you are describing sounds like the voltage to the micro is getting to low, which causes it to reset.

Get a power supply that is already soldered to a pair of 0.1 inch pins from Ben. Try to find one that will source at least 1 Amp. The little guy I had left there will only provide 0.5 Amps.

I just soldered up a 2 Amp 5.5 Volt supply. This should work.

I received a set of standard RC gear today. The only thing we need to look at is making a plug to power the RC receiver. I need to know if the board has an output to power the RC receiver and if so, what kind of pins does it have so I can make an adapter.

I also dug out a mini camera. It needs about 8 volts to run, so it should work off of the RC battery as long as it is fresh.

Things to work on:
Skim this:
http://www.maxbotix.com/MaxSonar-EZ1__FAQ.html

Add to your motor code a bit of code that will read the Sonar Sensor. Set the speed of one of the motors equal to the value of the sonar sensor. (So when the sensor is reading far away the motor will be on high. As the object gets closer the motor will go slower. Now reverse it so that that motor runs high when an object is close and slow when an object is far.

  • There are 4 NSEW directional LEDs on the board. Figure out what channels they are on. Write a program that turns them on and off sequentially.

  • How are the IR sensors being read? What channel are they on?
Read this:
http://www.arduino.cc/en/Reference/DigitalRead
Skim this:
http://www.vishay.com/docs/81733/tsop382.pdf

  • You should be able to read a series of 1s and 0s from each of the IR sensors using the IR beacon as a source. Write a bit of code that reads each IR sensor and then sets the corresponding LED on if it is receiving infrared light.

  • If you have time, try to figure out some code to decode a signal from one of the IR sensors. The signal is a set of pulses that repeats about every 20ms and starts with the channel being held low for about 4ms or so. I don't know if the IR beacon is transmitting just straight on off or something more interesting. You can use any standard TV or VCR remote for testing. I will bring in a sony standard remote on Friday.
An intro is at:
http://profmason.com/?p=627
Here is a bit about the beacons:
http://www.robotshop.us/pololu-ir-beacon-development-kit-1.html

There is a detailed description at:
http://ww1.microchip.com/downloads/en/AppNotes/00657.pdf

Monday, January 12, 2009

Videos: 1st Day and Motor Control



Motor Update and Videos

So I managed to get both motors to work! Turns out with the digital write, the setup did matter, and we had to specify the left and right motors. However, with the analog setup, we did not have to specify; for the Arduino Pro/Blimpduino board, port 3 and 5 are pre-programmed as analog. Anyways, here's the code for an analog program I had the motor do. It amps up the motor over 10 seconds from 0 to full, holds for half a second, then cranks it back down to zero and holds again.

int rightmotor1 = 2;
int rightmotor2 = 3;
int leftmotor1 = 5;
int leftmotor2 = 4;

void setup()
{
pinMode(rightmotor1, OUTPUT);
pinMode(leftmotor2, OUTPUT);
digitalWrite(rightmotor1, LOW);
digitalWrite(leftmotor2, LOW);
}


void loop()
{
int i;
int j;
for(i=0; i<=255; i++)
{
analogWrite(rightmotor2, i);
analogWrite(leftmotor1, i);
delay(45);
}
analogWrite(rightmotor2, 255);
analogWrite(leftmotor1, 255);
delay(500);
for(j=255; j>=0; j--)
{
analogWrite(rightmotor2, j);
analogWrite(leftmotor1, j);
delay(45);
}
analogWrite(rightmotor2, 0);
analogWrite(leftmotor1, 0);

delay(2000);
}

I noticed some funny things. After three or four runs going from zero to full to back, the fans would stop following the program. I could audibly here it click and restart from the beginning. I turned the chip off, waited a minute, then restarted. It ran the program once, got almost through the second run and then clicked off and reset itself. I'm thinking possible over heating? Not too sure. I don't think we'll be able to run it at full blast all the time. Also, I noticed thats the motor starts, it stalls and does not move even though I can hear the motor whining. I am thinking that there is initial static friction that causes it not to open, or the current is too weak to trip the motor.

Videos will be uploaded momentarily

Sunday, January 11, 2009

Great Work so far

Great job so far.

I don't think that forgetting to set the pin to an output is causing the problem (I think the atmega turns the pin into an output when it is written to for the first time.)  However, this is the first thing to check!  

I think it turns out the rate of helium leakage is not that bad.  It plumped up just fine as it warmed up and was still at neutral bouyancy on Saturday.  

I will bring in some Vex RC gear for next friday.  

Here is an overview of how the motors are being driven.   



Pin 2

Pin 3

 

LOW

LOW

Shutdown

LOW

HIGH

On Full Forward

HIGH

LOW

On Full Backward

HIGH

HIGH

Assume off?


Now if we want to control the speed of the motor, we need to turn the level on an off very quickly.  This is called pulse width modulation.  Basically, a DC signal would be ON all the time.  A 50/50 signal would be on half the time and off half the time.  By varying the % time that the pulse is on we can vary the speed of the motor. (basically giving the motor little pulses of power.)

To moderate the speed of the motor we will use the following:

Pin 2

Pin 3

 

LOW

LOW

Shutdown

LOW

Analog Level

Forward at % ~to level

HIGH

Analog Level

Forward at % ~to 100% - level


Read the following page on doing analog write on the arduino:

For completeness you should probably also look at these pages:

Change the code so that it uses the analogWrite to drive the motor.
Write a bit of code to ramp the motor from 0 up to 100% over 10 seconds and then ramp it down over 10 seconds.  Look at:

Read through the motor code in the blimpduino source after you do all this and make sure you understand what they are doing.

I am torn about the RC code.  I read through it and they are using two seperate inputs.  They are doing all the right decoding for our transmitter gear, but they are setup for standard RC gear.  Ok, I just bought some RC gear.  It should be here by friday.  

Let me know when you get the motors working and I will set you to work on the servo.

Friday, January 9, 2009

Day One!

As Professor Mason would say "Hot diggity! Physics works!" Not that we didn't have any faith in physics, but it's nice when we get things to work. Like our blimp! First, how the day played out, then some pictures, and then what we need to figure out. There will eventually be video, however, I need to do some video editing before I can upload it.

Setting up the blimp took about an hour on its own. Helium had to be put in; unfortunately I put a little too much helium in and the blimp took off even with the board attached (which was about 80 grams) We added about another 15 grams to the back of the blimp and 10 to the front of the blimp, which balanced it out nicely.






We were able to attach the thrusters and chips to the middle of the blimp using a combination of styrofoam and Velcro. The styrofoam was used to put some space between the blimp and the rotor for the vector thruster
s





So, after plugging everything in, did it work? Well, we didn't have an RC receiver handy, so we booted it up in autonomous mode. Short answer is yes! it works great! Long answer: it works, but it got itself stuck in a corner and couldn't get out.

Allow me to explain. Upon booting it up, it did exactly as programmed. With the IR beacon off, it hovered about 4 feet off the ground, give or take. There was some slight drifting, but with the air conditioning on it was expected. We then placed the blimp about 8 feet away near the ceiling and activated the IR beacon about waist high on a table. The blimp servos went into self check and then proceeded forward...to the left, away from the receiver. When it was perpendicular to the receiver, it turned right, and head towards the beacon, but also towards the ceiling. It passed over the beacon and tried to turn itself around, and then got stuck in a corner.

After we did the test of the pre-installed BlimpDuino software, we tried to put in our own code. We hooked it up to my laptop and started the IDE and got a bunch of garbage on the serial monitor. We had hooked it up backwards...go figure. We first attempted to make the right motor spin and then turn off. Our code looked something like this

int rightmotor1 = 2;
int rightmotor2 = 3;
int leftmotor1 = 4;
int leftmotor2 = 5;

void setup() // run once, when the sketch starts
{
pinMode(rightmotor1, OUTPUT); // sets the digital pin as output
pinMode(rightmotor2, OUTPUT); // sets the digital pin as output
pinMode(rightmotor1, OUTPUT); // sets the digital pin as output
pinMode(rightmotor2, OUTPUT); // sets the digital pin as output
digitalWrite(rightmotor1, LOW); // Turns right motor off
digitalWrite(rightmotor2, LOW); // Turns right motor off
digitalWrite(leftmotor1, LOW); // turns left motor off
digitalWrite(leftmotor2, LOW); // turns left motor off
}

void loop() // run over and over again
{
digitalWrite(rightmotor1, HIGH); // sets the right motor on high speed
delay(1000); // waits for a second
digitalWrite(righttmotor1, LOW); // sets the right motor off
delay(100);//delays for 1/10 of a second
digitalWrite(righttmotor2,HIGH);//turns the right motor on but in the opposite direction
delay(1000); // waits for a second
digitalWrite(rightmotor1, LOW); // sets the right motor off
digitalWrite(rightmotor2, LOW); // sets the right motor off
digitalWrite(leftmotor1, LOW); // sets the left motor off
digitalWrite(leftmotor2, LOW); // sets the left motor off
delay(1000);
}

The code worked perfectly fine. At this point, to conserve the battery, we hooked it up to a 5v power regulator that was plugged in to the socket. The fans spun, but not very strongly. Then, we modified the code a little bit to alternate between the two.

int rightmotor1 = 2;
int rightmotor2 = 3;
int leftmotor1 = 4;
int leftmotor2 = 5;

void setup() // run once, when the sketch starts
{
pinMode(rightmotor1, OUTPUT); // sets the digital pin as output
pinMode(rightmotor2, OUTPUT); // sets the digital pin as output
pinMode(rightmotor1, OUTPUT); // sets the digital pin as output
pinMode(rightmotor2, OUTPUT); // sets the digital pin as output
digitalWrite(rightmotor1, LOW); // Turns right motor off
digitalWrite(rightmotor2, LOW); // Turns right motor off
digitalWrite(leftmotor1, LOW); // turns left motor off
digitalWrite(leftmotor2, LOW); // turns left motor off
}

void loop() // run over and over again
{
digitalWrite(rightmotor1, HIGH); // sets the right motor on high speed
delay(1000); // waits for a second
digitalWrite(rightmotor1, LOW); // sets the right motor off
delay(100);//delays for 1/10 of a second
digitalWrite(leftmotor1,HIGH);//turns the left motor on
delay(1000); // waits for a second
digitalWrite(rightmotor1, LOW); // sets the right motor off
digitalWrite(rightmotor2, LOW); // sets the right motor off
digitalWrite(leftmotor1, LOW); // sets the left motor off
digitalWrite(leftmotor2, LOW); // sets the left motor off
delay(1000);
}

Right motor turns on, and then silence. And more silence. then right motor turns on, and then silence. The left motor wasn't working for some reason. We noticed that the fans were spinning a little slow, so we thought maybe there wasn't enough current to power the board. So we switched out the 5v for a 12v and tried it again. Same results. We uploaded the original code to test it and it worked just fine. Vector servos fired off, then each of the fans tested themselves. So at this point, we've been pondering it until about 1730 and we called it a day.

So, things to think about until our next meeting.
- What is causing the right motor to spin correctly, but not the left?
- RC receiver: how to build and build
- I noticed that the blimp likes to bump into the ceiling a lot during autonomous mode. I know that the US sensor can detect how far from the ground it is, but is the blimp programmed to know how much top clearance it has?
- Other forms of navigation (I'm personally thinking visual recognition, but we'll see how far along in coding we get)

Notes
- The helium seems to leak at a rate much faster than a week. In about four hours the blimp went from stretch taut to a little squishy.
- Prof Mason, if you didn't get my email, I think I did not upload the autonomous software back in before I left for the day. Right now I think it will make right turns only. =\

**Edit: I just noticed as I was inspecting our code, we never specified pinmode(leftmotor1,output) in the void setup section. It reads as right and right for each. I wonder if that has something to do with it.....**

Thursday, January 8, 2009

More research

1. Arduino Pro plugged in (image from Arduino)


2. Please note that the boards operates at 3.3V (unlike most other Arduino boards, which use 5V); be careful when connecting external components. (Quoted from Arduino yet again). From details about the board, I don't see anything that says we can use a 5v (link)

3. Looking at some sample code I think it runs using PWM. This was just a test run of the blimp. I'll check the actual code once I load everything onto my laptop tonight.


Oh, and searching around the internet I found another 52" blimp that says it only takes 5 cubic feet of helium to make it go. I'll check with Air Gas and Praxair tomorrow, as well as Party City.

Question Update

1. Look up the interface to program the arduino on board(In the blimp duino docs). 
- We can use the Arduino Pro IDE to upload new code. The code is available for free at Arduino. 
OK Install this on your laptop.  What I meant was the physical pinout.  The USB-TTL cable has a 6 pin header on it.  I assume this just plugs into the board.  Find a picture of how it plugs in and post it. 

2. Does the Arduino need need a ttl interface or is the inverter already board? 
This can be an FTDI TTL-232R-3V3 USB - TTL Level Serial Converter Cable, the SparkFun FTDI Basic Breakout Board, or any other USB to 3.3V TTL serial convertor.   I have a FTDI TTL - 232R 5V USB cable.  See if you can find out if the arduino on the board is 5V tolerant (I suspect that it is, but I would hate to burn it out!) 

4. What does the program loaded on the Arduino by default do? 
- The board comes preassembled and preprogrammed with two modes: 
a. RC Mode 
- The chip will auto detect an RC signal. After it’s been recognized, the RC controls will adjust the vectoring thrusters and spin speed for thrust, pitch, and lift. 
OK, we will have to look at this.  Typically RC controllers output a pulse between 1ms and 2ms long.  A value of 1.5 ms corresponds to dead stick (0).  1 would be maximum negative and 2 would be maximum positive.  The RC gear that I have(vex) combines all the channels into one.  Look at this reference: 
also look up PPM encoding vs. PCM encoding.  See if you can find out which one the blimpduino uses. 

6. What is the RC protocol that is used? 
- Not too sure what this means. I read though the blog posts on DIY and found that it runs on dual channel, one for thrust one for steering. We turn on the RC controller first, then activate the blimp. The blimp is preprogrammed to auto detect the RC.  Again see the above PPM vs. PCM question.

8. How to mount all of this stuff on the blimp? (Look at the instructions) 
I will bring a bunch of velco. 

Back to the Helium Question:
(626) 338-4712
(909) 629-5031

Find out if they will fill our empty Argon/Hydrogen (99/1)  Gas tank with helium.  Failing that see if they will fill our empty nitrogen gas tank with Helium.  I belive these are 9 cubic meter tanks.  Find out prices and other options.

Blimp pre research

These are the responses to the questions posted by Prof Mason. I'll be installing the IDE software on my laptop tonight so I can bring it tomorrow...hopefully it does not over heat like it normally does. I noticed that there is a USB to TTL cable, so hopefully we have one of those. Other wise we'll need a computer that has a serial port.

1. Look up the interface to program the arduino on board(In the blimp duino docs).
- We can use the Arduino Pro IDE to upload new code. The code is available for free at Arduino.

2. Does the Arduino need need a ttl interface or is the inverter already board?
- The board comes without built-in USB circuitry, so an off-board USB-to-TTL serial convertor must be used to upload new code. This can be an FTDI TTL-232R-3V3 USB - TTL Level Serial Converter Cable, the SparkFun FTDI Basic Breakout Board, or any other USB to 3.3V TTL serial convertor.

3. How to mount the ultrasonic sensor on the board?
- It plugs in. Here is a picture of the orientation of the US sensor.

4. What does the program loaded on the Arduino by default do?
- The board comes preassembled and preprogrammed with two modes:
a. RC Mode
- The chip will auto detect an RC signal. After it’s been recognized, the RC controls will adjust the vectoring thrusters and spin speed for thrust, pitch, and lift.
b. Autonomous mode
- Putting it in this mode will have the blimp find it’s bearings and hover over the ground. Once the IR beacon has been activated and detected, it will try to move towards the beacon, adjusting lift to match the beacons height. If the signal is lost, it will go into standby and hover.

5. Find a link to the source for the program and post it here.
- Source code link ( you have to download and unzip it)

6. What is the RC protocol that is used?
- Not too sure what this means. I read though the blog posts on DIY and found that it runs on dual channel, one for thrust one for steering. We turn on the RC controller first, then activate the blimp. The blimp is preprogrammed to auto detect the RC.

7. Is it supported by the board?
- The RC mode works in tandem with autonomous. We can control the blimp via RC, and once we let go, the Arduino processor will kick in and operate.

8. How to mount all of this stuff on the blimp? (Look at the instructions)
- Tape. Lots of tape. For testing, we can just use regular tape/packaging tape to hold it up. To make it more permanent, we can Velcro the base of the board to the bottom of the blimp. When we fill the blimp with helium, we need to fill it about ¾, then attach the boards and continue to fill or add weights until it can support itself in midair. The blimp leaks over the course of a week, so we’ll need lots helium to refill ever week.


One more day!

Wednesday, January 7, 2009

Yay it's here!

We got it today! Yay! Professor Mason had posted some questions earlier regarding the programming and assembly, I'll get to those tomorrow. Until then, bask in the glory!




The blimp itself! It's a monster 52" blimp. We better start hunting for that helium....






Here's the Ultrasonic Sensor from the top. Model is Maxbotic EZ1.







A profile shot of the Ultrasound. The black rectangular part at the bottom connects directly to the main board.




Here it is!! The brains behind the blimp. At the top are the Vectoring Differential thrusters. Lego blogs and rotar in blue. Main board at the bottom in green. The batter is a 7.4 V LiPo battery. Did some reading...stores 2100 J of energy and has a 99.8% discharge efficieny. Frying is not a good thing =\





Closer shot of the front











Close of up one of the thrusters.

The parts are here!

The blimpduino parts arrived today.

There is a assembled board with the servo driven vectored differential thurst module. There is a balloon envelope with foam fins. A pololu IRB02A IR beacon. A max sonar EZ1.

To do:
  • Look up the interface to program the arduino on board(In the blimp duino docs)
  • Does the arduino need need a ttl interface or is the inverter already board?
  • How to mount the ultrasonic sensor on the board?
  • What does the program loaded on the arduino by default do?
  • Find a link to the source for the program and post it here.
  • What is the RC protocol that is used?
  • Is it supported by the board?
  • How to mount all of this stuff on the blimp? (Look at the instructions)
The RC gear we are using encodes all of the channels on a single line (easy for microprocessors)