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).