Friday, February 17, 2012

"Team Insufficient Mana"

"--because the magic didn't happen."


Although our robot was stumped by the first room, our attempt was not a total loss. Through this course we learned:

- How to interface non-proprietary devices to a highly proprietary platform


- How to construct and program a robot to navigate a maze autonomously


- How to construct and program a robot capable of finding and extinguishing a flame


- How to build an array in RobotC


- Various methods for error-checking and heuristic analysis of environmental variables
     (light intensity for finding a flame, available power, navigation)




In addition, the exercise proved great practice for my fabrication and construction skills.



For the final competition I hard-coded values for the shaft encoders, retrieved by manually pushing the robot through the maze and extracting the values from debugger. However, do to irregularities on the surface of tiles and floating values from the left encoder, the robot was unable to navigate the maze with any large amount of success. The robot did reach the first room on its second attempt and promptly froze--it was later discovered that gremlins in the machine had misplaced a segment of abandoned code in the middle of the "inRoom" function (which detailed the actions of the robot for pinpointing the flame inside a room of the maze once IR Sensor thresholds were met). As a result, the robot found the flame in the room and became stuck in a "while" loop.


In the future, an effort will be made to identify any limiting factors early on, as we assumed that the PIC microcontroller in the VEX brain had sufficient memory for acquiring the strategy we were counting on for victory.



Wednesday, February 8, 2012

Testing

...is what we should be doing...


In order to work around the memory limitations of the VEX brain and fully utilize a grid array navigation system, we devised a method of interfacing a Bluetooth receiver to the robot so that it can download instructions via wireless communication with a laptop.

Success was in the form of a VEX bot directly controlled over Bluetooth, but it remains to be seen whether we can pull off the autonomous portion in time for competition.

Monday, February 6, 2012

Engineering an Extinguisher

Now...THIS...has probably been my favorite part of the project, tied only with Rick Rolling the class earlier in the course with my Annoy-a-tron Toy.

Sometimes, my best ideas owe their inspiration to a dream. Such was the case this time.

In order to achieve the maximum time bonus (based on flame extinguishing methods) in the firefighting robot competition, the rules state that a robot must use a non-contact, non-wind method to put out the candle flame.

Ideas were thrown around, many of which involved a high-pressure canister, water deflection, a water squirt gun...but none of these were sufficient, and a few of them exceeded our budget restriction of $20 (retail).

--A high-pressure canister (CO2 cartridge) would require a robust control valve, which was expensive and too complex to interface to the VEX brain reliably.


--A cheap plastic squirt gun creates a narrow stream of water, which translates to a very small margin of error in a platform and environment with a high level of unpredictability, and it was also difficult to construct a mechanical method of triggering the squirt gun quickly so that it built up enough pressure to project water at the flame.




Thus, it begins...






My search criteria was simple: a small container, capable of withstanding relatively high internal pressures while being easily triggered (mechanically). I began cleaning out my closet the weekend before when I noticed I had a can of silly string from about 5 or 6 years ago.

I punctured the sidewall of the can, purged its contents, cut it in two with the assistance of an air-powered circular die grinder and inspected its operational equipment. Inside was a straw leading up to a high-pressure valve, easily operated by exerting a finger's effort of pressure on the spray nozzle at the top exterior of the device. It was just what I had been looking for; it even had the Dollar Tree price tag still adhered to the plastic cap.

I requisitioned a Schrader valve from a discarded bicycle tire, set it into the sidewall of the can through a small circular hole from the die grinder and sealed the whole construction with JB Weld.

The result was a small device, capable of withstanding relatively high pressures while being easily triggered by pressing on the spray nozzle. Critical to its continued success is that it is also reusable: by removing the pintle assembly inside the Schrader valve, the can is capable of being preloaded with plain water before the valve is replaced and the canister is pressurized with air compressed by a bicycle tire pump (through the same valve!).

The device worked exactly as designed, but a greater cross-section was needed to remove the off-chance that the robot did not properly align itself with the flame. The original nozzle was a non-atomized design to spray silly string, and so the opening was relatively large to accommodate the flow of the suspension. By searching through the cleaning products and other aerosol devices around my house, I was able to locate a nozzle which 1) created the desired wide cross-section and atomization of the contents and 2) fit over the neck of the can's control valve--a suitable nozzle was lifted from a can of stainless steel cleaner.

I have since stress-tested the modified device and found that it is capable of pressures in excess of 70psi, which is far more than is needed for the desired operation. I almost lost my sight and hearing in the process when the can had a catastrophic failure and exploded at the seam of the Schrader valve and the JB Weld--Super Glue is suspected to have weakened the area from the runoff of a previously attempted repair.

I have also since purchased two more cans of silly string and an air horn (for its nozzle) from Dollar Tree, and these have undergone the same treatment as the first, providing me with a total of three working extinguishers of different sizes and capacities (the original can had a piece of dried silly string lodged in its valve and could not be repaired).


The second can, after failure
Note the cracking near the base of the Schrader valve



Second can, repaired and JB Weld cured by a heat lamp



All three cans, sitting on my desk at home
*The air horn nozzle in red
**The smallest can has the ideal nozzle

Friday, February 3, 2012

Sensing Location with a "Pinger"/SONAR Sensor

....we were doing fine at getting readings from the VEX SONAR sensor until the robot brain crashed and the robot crashed into a wall--we had aluminum extensions fixed to the front of the robot as bumper protection, but as the result of a freak accident they managed to slide between the partitions of the wall and failed to work. After spending about 15 minutes or so troubleshooting our software and hardware for faults, we determined that the VEX CPU had simply crashed for unexplainable reasons, as it wasn't responding to any changes in the software and RobotC debugger began posting static values for all pids.

When the brain was finally rebooted, the SONAR sensor appeared to have suffered a critical failure, thought possibly due to physical damage as a result of the robot running into the wall at full speed. However, we soon realized that the CPU was posting a static value of "16" (inches interpreted) even without the SONAR sensor plugged in.

So...it remains to be determined exactly what has happened and whether the situation is permanent or can be rectified.

Thursday, February 2, 2012

Infrared Photo Transistors and Locating a Flame

We interfaced IR phototransistors with the VEX brain and experimented with different resistor values in a positive-coefficient type voltage control circuit.


The rest of the night was spent adjusting the software and physical positioning of the sensors to optimize the ability of the robot to hone in on the location of a candle flame.

Wednesday, February 1, 2012

VEX Bot Maze Running and Using Wheel Encoders


A picture of our square-bot that would attempt to navigate its way through the tile maze

**Note the wheel encoders



A video of another group's run (immediately after ours).

I'll post a video of our run later, because my phone decided not to save the video I took.




RobotC Maze Code

#pragma config(Sensor, in2,    rightEncoder,   sensorRotation)
#pragma config(Sensor, in3,    leftEncoder,    sensorRotation)
#pragma config(Motor,  port2,           LEFT,         tmotorNormal, openLoop)
#pragma config(Motor,  port3,           RIGHT,         tmotorNormal, openLoop, reversed)
//*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//

#define square  124
#define fleft   65
#define fright  63
#define rleft   -63
#define rright  -61

void turnLeft( int turnTicks ){
  SensorValue[rightEncoder] = 0;
  SensorValue[leftEncoder] = 0;
  motor[LEFT] = rleft;      //left
  motor[RIGHT] = fright;
  while (SensorValue[rightEncoder] < turnTicks);
  motor[LEFT] = 0;
  motor[RIGHT] = 0;
  int RightTurns = SensorValue[rightEncoder];
  int LeftTurns = SensorValue[leftEncoder];
}

void turnRight( int turnTicks ){
  SensorValue[rightEncoder] = 0;
  SensorValue[leftEncoder] = 0;
  motor[LEFT] = fleft;      //right
  motor[RIGHT] = rright;
  while (SensorValue[rightEncoder] < turnTicks);
  motor[LEFT] = 0;
  motor[RIGHT] = 0;
  int RightTurns = SensorValue[rightEncoder];
  int LeftTurns = SensorValue[leftEncoder];
}

void goForward( int goticks ){
  SensorValue[rightEncoder] = 0;
  SensorValue[leftEncoder] = 0;
  motor[LEFT] = fleft;      //foward
  motor[RIGHT] = fright;
  while (SensorValue[rightEncoder] < goticks);
  motor[LEFT] = 0;
  motor[RIGHT] = 0;
  int RightTurns = SensorValue[rightEncoder];
  int LeftTurns = SensorValue[leftEncoder];

}

task main( )
{
  goForward( square*4.5 );
  wait1Msec(200);
  turnLeft( 99 );
  wait10Msec(20);
  goForward(square*2);
  wait10Msec(20);
  turnLeft(99);
  wait10Msec(20);
  goForward(square*4);
  wait10Msec(20);
  turnRight(99);
  wait10Msec(20);
  goForward(square*2);
  wait10Msec(20);
  turnRight(99);
  wait10Msec(20);
  goForward(square*6);
  wait10Msec(20);
  turnRight(99);
  goForward(square*4);
  turnRight(99);
  turnLeft(45);
  turnRight(140);
  turnLeft(500);
}