Wednesday, February 13, 2013

Firebot Day 3

This day was mostly spent on that flame sensor. The line sensor and sonar were pretty reliable.

I noticed that the bot was going after reflections of the flame on the walls of the maze, so I decided to make the flame finding code a bit less primitive.
This scanning code looks for the brightest light values and lowest light values. It also records the encoder values each time it finds a new brightest value. This way, it knows exactly where to turn to in order to face the brightest point found.


bool scanRightForFlame(){ // turn right 180 degrees.
//Initialize variables
int dimmestLight = SensorValue[flameSensor];
int brightestLight = dimmestLight;
int brightestLightAngle = 0;
resetEncoders();

         // TURN_SCAN is a constant for how much the bot turns while it scans
while(SensorValue[leftEncoder]<TURN_SCAN || SensorValue[rightEncoder]<TURN_SCAN){
//keep turning right
if(SensorValue[leftEncoder]<TURN_SCAN){
motor[leftMotor] = MED_LEFT_SPEED;
}else{motor[leftMotor] = 0;}
if(SensorValue[rightEncoder]<TURN_SCAN){
motor[rightMotor] = -MED_RIGHT_SPEED;
}else{motor[rightMotor] = 0;}
  //record values while turning
int currentLight = SensorValue[flameSensor];
if(currentLight < dimmestLight){
dimmestLight = currentLight;
}
if(currentLight > brightestLight){
brightestLight = currentLight;
brightestLightAngle = (SensorValue[leftEncoder]+SensorValue[rightEncoder])/2; //Average of two encoders
}
}
stopMotors(80);
if((brightestLight-dimmestLight) > FLAME_TOLERANCE){ 
// Significant difference between light values
// turn back to face flame
int turnBack = TURN_SCAN-brightestLightAngle+7;
resetEncoders();
while(SensorValue[leftEncoder]<turnBack || SensorValue[rightEncoder]<turnBack){
if(SensorValue[leftEncoder]<turnBack){
motor[leftMotor] = -MED_LEFT_SPEED;
}else{motor[leftMotor] = 0;}
if(SensorValue[rightEncoder]<turnBack){
motor[rightMotor] = MED_RIGHT_SPEED;
}else{motor[rightMotor] = 0;}
  }
  stopMotors(300);
return true;
}
else{ // Flame not found
  turnRight(TURN_90/3);
  return false;}
    stopMotors(500);
}

Firebot Day 2

Continuing work on this firefighting bot, Everette and I wanted some device installed that could potentially snuff the flame.


The "fan" we created was practically a rush job, but I didn't mind having a weak prototype. It gave me something to code.

// Swing fan left and right
void fanFlame(int angle, int iterations){
  for(int i=0; i<iterations; i++){
    motor[fanServo] = FAN_CENTER - angle;
    wait1Millisecond(300);

    motor[fanServo] = FAN_CENTER + angle;
    wait1Millisecond(300);

  }
}

The video shows the bot failing to find the flame. Oh well.

Friday, February 1, 2013

FireBot: It Begins

Today, we had few guidelines. Basically, it was a free day to finish up whatever we were behind on. But ultimately, we were preparing for the FireBot competition.
With four rooms separated by 14 inch walls, the idea is to extinguish a candle that has been placed randomly in one of the rooms.
The field was built just today, so we got some time to test on the real deal.


Everette and I added a platform on our bot for an extinguishing device, and hastily built a fan using a servo and whatever parts we had to emulate a fan. (we used big gears)

Apparently no video of that fan fanning. It was adorable.

The fan didn't seem very effective. We'll probably go with a thing that pats out the flame instead. More worrying is the fact that our flame sensing function wasn't working out this time. I'm just glad the line sensing seems reliable.
Everette said he wanted to know the code better, so I plan to explain it online to him. He also took the bot home with him so he could make whatever improvements he wanted. That's good. I'm glad he feels confident enough to do so.



Walls, Lines, and Fire

Today went way better than the last ones! I got there early and jump-started our transition from Everette's bot to mine. We moved the encoders, flame sensor, and line sensor over, but were given a new sensor - the ultra-sonic sensor, which is basically a sonar device. It reads the distance to whatever is ahead of it.


Everette made a cool suggestion that we mount the line sensor using the sonar sensor like so:
Fewer parts to worry about.

Next, we needed a good spot to place the flame sensor. Since the candle is going to hold the flame several inches from the floor, we needed a raised platform of some kind on the bot.
I came up with a little something for that:
Kind of ridiculous looking, but quick and easy.

Now to the program.

goForwardUntilCloseToWall();
turnRight(TURN_90);
goForwardUntilLine(); // pretty self-explanatory
scanForFlame(); // this function has the bot turn right 90 degrees, turn back 180 until flame is detected
goForwardUntilLine(); // go up to the candle
scanForFlame(); // correct direction if not facing candle

With three independent sensors, the testing process would take quite a while, though we did have some really promising results early on. I was only concerned that the bot wasn't facing directly toward the candle when it detected it.
The sonar worked pretty well, but the flame and line sensor's tolerance needed quite a bit of tweaking in the program.
By the end of class, our bot's performance was hit and miss, but the final presentation was successful.

Seemed the flame sensor needed a bigger flame than that tiny candle produces.

Lines and Fire

Our upcoming big challenge is to create a lean, mean, firefighting robot.
...Or a little guy that'll put out a candle for you.

For this challenge, we need not only to detect the flame, but to get our bearings inside a four-room building. For this, we need an flame sensor to find the flame, and a line sensor to  find the "doors" to each room.
An infrared light sensor can be used to find the flame since fire emits so much infrared light.
Little infrared? - no flame.
Lots of infrared? - flame detected.

Just an infrared LDR working with a 10K resistor like in my Hexbug.

The line sensor also uses an infrared sensor, but it also needs an infrared light emitter working with it.  The emitter constantly shoots infrared at the floor, and depending on whether or not there's black electrical tape below, the sensor will receive varying reflection from it.
Lots of infrared? - no line.
Little infrared? - line found.

I added electrical tape around the sides so they emit and receive to and from the floor only.

We were supposed to have this bot up and running, so we can see it stop at a line, then point to the flame when it sees it, but we spent quite a bit of time being confused about the construction and testing of these new sensors. On top of that, the bot that Everette built seemed unwilling to give us a strong drive-train, as we observed during the maze-run last week.
Tomorrow, we plan to start fresh, and transfer everything to my bot.



Running a Maze

This time, we got to do something with our VEX bots. The aim was to navigate a maze using no sensors besides the bot's internal clock. This means we had to calculate how much time it takes for the bot to travel a certain distance, then hard-code a set of instructions that allows it to follow the path all on its own.

Start in the lower right, and get to the X.

I was partnered with Everette, who's deaf and mute, but he was one of the people I wanted to work with, since he showed interest in the Robotics team earlier. (Plus, I always wanted to learn some sign language.) We have interpreters to facilitate communication too.
Everette seemed to think I should be be leading our efforts, which is cool, since I have some experience in this stuff, and love messing with robots and programming.

He took a picture of the maze on his iPad for us to reference while we prepare the robot and develop the program. I found that the bot needed about 400 milliseconds to travel one floor tile, and using that number as a unit (TILE_TIME), I quickly calculated some approximations of the steps that the robot had to take to complete the maze. I used functions like goForward(int milliseconds) that runs the motors for some milliseconds.

goForward(3500); // The goForward function multiplies 3500 it by TILE_TIME, then divides by 1000.
turnLeft(TURN_90); // TURN_90 is a constant that I recorded for how long it takes to turn exactly 90 degrees
goForward(3000);
turnRight(TURN_90); // etc...

It looked like this would turn out to be pretty easy, but we soon learned that the varying power given by the quickly draining battery made it much trickier. I figured something like this would happened, so I tried adjusting my constants like TILE_TIME to work for our current battery level. (e.g. increase TILE_TIME so a sluggish bot with a low-level battery could go the correct distance)
In the end, we didn't get quite enough time to perfect it, so our bot didn't quite succeed, but it did wind up pretty close to the end of the maze.

The battery was a bit lower than anticipated.

The next challenge was to use encoders to measure how far the robots have traveled. This solves the battery issue, since encoders measure how many rotations of the wheels have occurred, which gives us actual data, and accounts for any friction in the drive-train.

The big problem Everette and I ran into was purely mechanical. The encoders didn't seem to fit quite right on my bot, so we hastily switched over to Everette's. This turned out to be a bad decision, since his drive-train was problematic for ambiguous reasons. Its output was downright feeble on one side. We spent all the rest of class time trying to fix it, but never succeeded, so we went out to present without any prior testing.

The thing that I found hilarious was that even without any testing, my program's encoder counter was dead-on for the distances we wanted the bot to go. it attempted its first turn at just the right spot, but failed to complete it.




Tuesday, January 29, 2013

Hacking a Hexbug

I wasn't totally sure of all the things I wanted my toy to do by the time I finished hacking it, but I knew I wanted fine motor control. Unfortunately, this bug mechanically cannot turn left or right since its wheels are all locked together by their axles, and it only has one motor.
In any case, I should be able to reverse the motor electronically. For that, I needed the H-bridge. It's got six ports: four switch inputs, and two outputs for the motor. I've got the setup as follows:
switch1: controller
switch2: controller
switch3: ground
switch4: power*
output1: motorPower
output2: motorGround

The controller needs only to switch output voltage between switch1 and switch2 in order to change motor direction. That makes my controller program pretty simple.
*I am going to route power from the battery through a transistor directly controlled by my controller. This gives the controller control over all the current that gets to the motor.
So I made a quick test program that ran the motor back and forth.

The green board is the H-bridge I made earlier. Motor output looks strong!
The last part of the video is explained below.

Next, I wanted some input. I wanted to use the original touch sensors from the Hexbug, but when I soldered wires to them, they stopped working. It was frustrating, but I decided to scrap them. I only have about to week to finish this project, so I went straight to a sensor I've already gotten working - the LDR. (light-dependent resistor)
Seeing as insects are pretty sensitive to light, I figured light sensors would be a good fit. I planned for it to have one LDR on each side, so it would run away from wherever it detected a change in light.
My program simply sets a variable "lightLevel" for each sensor upon setup, then checks every 1/10 second whether the sensor reads differently up to some threshold I choose.

int lightLevelAhead = analogRead(frontLightSensor);
int lightLevelBehind = analogRead(backLightSensor);


boolean lightAheadChanged(){
  boolean didChange = (abs(analogRead(frontLightSensor) - lightLevelAhead) > 50);
  lightLevelAhead = analogRead(frontLightSensor);  //reset comparison variable
  return didChange;
}
boolean lightBehindChanged(){
  boolean didChange = (abs(analogRead(backLightSensor) - lightLevelBehind) > 50);
  lightLevelBehind = analogRead(backLightSensor); //reset comparison variable
  return didChange;
}

My threshold is 50 in this case. The lower the threshold, the more sensitive it is.

Using this code, I have the bug run its motors for a second when light changes - in either direction, depending on which LDR detected change.
I also decided to add a piezo sounder and LED for some audio and visual feedback.


I use my finger to cast a shadow over the LDRs.
The piezo just plays a couple notes in the direction it's running.

So far so good, but this won't work at all as a toy if it's stuck on USB power. I needed to figure out how to get the controller chip working without that red launchpad board. Thanks to YouTube, I found out that the chip runs almost exactly as you would expect, with battery power and ground on pins 1 and 20, but it also needs a 10K resistor connecting power to the reset pin.
I could mount the chip on that white breadboard, but that's a pretty big chunk of plastic for such a small bot. And with one weekend left to finish, I wanted to finalize my design. 
Fortunately, my brother happened to have a flat breadboard that I can cut to size. This breadboard requires soldering, so I needed an IC socket to mount the chip on so it can be removed again.
One trip to Radioshack later, I got started transferring my design to a more permanent form. 

That's the chip in the middle, sitting in its IC socket.

 Lookin' good!

I planned to have the H-bridge sandwich itself between the board and the bug, so I left room for the H-bridge wires to plug directly into it through six holes in the board. That also gives the H-bridge some rigidity, so I don't have to worry about it falling down. I thought it was clever.

Nightmare-fuel.

I have a friend who's actually educated in music composition, so I had him over to help me program a song I like into the controller. I'll have it play on setup.
I turn it on and...

The song's great, but there's clearly something wrong with the power, since the program is rebooting when it tries to power the motor. The board also seems to be shutting off randomly during testing.
I spent more time than I care to mention trying to make sure the batteries were making good connection with the board. I even found that my power switch was malfunctioning, so I added another and moved the connection to that one. 
I also added more voltage to the power by using a couple half-height button-cell 1.5V batteries in place of a single 1.5V. That gave it three cells, totaling about 4V (with an already used up button cell).
I was warned about overpowering the motor, but I have a transistor in place to prevent that.
Speaking of the transistor, that low-gain transistor I was using may not have been allowing enough current to the motor, so as suggested by my professor, I replaced it with a high-gain darlington transistor.

"Help! Assistance is required! I believe there is something wrong with me!"

Well, it's better than before, and I'm not getting anymore random shut-offs.
The problem, I suspect, is that the batteries have a current output limit that's just too low to power the controller AND the motor, even with 4V. When the batteries try powering the motor against the weight of the bot, it either just struggles, or reboots.
I'm sure my professor can tell me how to fix this, but I'm out of time, and that concludes my efforts to make this a functional toy.
At least it works fine when I hold it off the floor. I've got something to present!

"The fun levels will be at maximum efficiency!"