Sunday, February 12, 2012

Navigation... FINALLY, IT TURNS CONSISTENTLY!

During the competition, the battery had dropped off a significant amount, and that was enough to mess up my turns still.

I became eager to resolve this issue once and for all. There must be a way to compensate the motors when the battery is weaked. I then thought up a solution.

1. The power of the battery can be tested by having the robot run forward at a fixed power level for one second, and have the encoder measure the distance. When the power drops, the robot will travel a shorter distance.
2. By taking multiple measurements of varying motor power and how far the robot travels, via an encoder reading, one can gain the relationship between the motor power and the distance traveled by plotting the points in Excel. To my luck, there was a simple linear relationship. This was found to be DistanceTraveled(L+R) = 4.13*motorPower

3. To produce a perfect 90 degree turn, the values for the encoder and motor values are perfectly set for a specific battery level. So if I make sure the motor is always outputting the same strength, then my robot will turn consistently. I do a gauge of how strong the battery is using step 1. I then set the optimal values for a perfect 90 degree turn. This will be my reference point. Then using the equation for step two, I can compensate the motors to always have the same power no matter how strong the battery is.


This worked beautifully. In my test, I made 300 the reference point for the encoder calibration value. With the weakened battery, it only traveled 272 in that same second. Then with a second powerCompensated run, it shows that I was able to get it back to 301. 



This made the motors turn FAR more consistently during battery changes. There were still a few times it'd be off due to the erraticness of the motors. But I adjusted the power compensation factor so that sometimes it'd overshoot it and sometimes it'd undershoot it so that it averages itself out. I was now able to run multiple turns with much different battery values and still have it turn near perfectly, consistently.

SUCCESS!

Saturday, February 11, 2012

Navigation Continued...

So why does the robot not turn consistently the same time, everytime? I sought to find out.
Here are the reasons I came up with.

1. The voltage drop when the battery gets drained makes the motors weaker
2. Both motors should be turning equal amounts when turning in place, but it's very difficult to get the motors to do this consistently no matters what motor power values are used.

In realizing two, it occurred to me that the encoder should be all that is necessary to get both wheels to turn the same amount. I then tried to devise a code that can do this. I figured that I can take the difference of the encoder values between the left and right side, and use this to power the weaker motor. Essentially this will give the weaker motor a boost until both sides are turning equally, then the power would diminish.

I was able to achieve this with two lines of code.

  int delta;
  delta = SensorValue[leftEncoder] - SensorValue[rightEncoder];
  motor[motorR] = 55;
  motor[motorL] = 55 + delta;



Sucess! Both sides turns evenly during a turn.

Testing this gave me consistent turns! I tested a left turn 25 times and it turned a perfect 90 degrees every time.

Friday, February 10, 2012

Navigation continued.....

After yesterday's failed attempt at making a good straightening contraption, I set out to think of a new plan today. I thought the other method to do this is to make sure the robot was equidistant to the wall during the runs down the aisles. This can be done easily by mounting an ultrasonic sensor sideways. However, I needed the ultrasonic sensor to determine where to turn as well. So the decision was to use a servo to swivel the ultrasonic sensor sideways or forwards when needed.

I finished writing the code for this but the program crashed before I had a chance to save. But when testing it out, it was finnicky and would sometimes compensate the wrong direction. This was due to the sonar sometimes giving faulty readings or updating slowly. It felt like an unreliable means to make something unreliable more reliable.

Thursday, February 9, 2012

Navigation Continued....

Today, after testing out the code yesterday, I fully realized the challenge of having the robot turn consistently every time.

To tackle this, I decided two ultrasonic sensors can be used in the front to compare the two distances in front of them to make sure they're level. 

Programming this would probably involve that if one sensor value was bigger than the other, I should have one motor turn faster than the other to have it turn back into the correct direction. 

void stopstraighten()
{
  unsigned byte SonarValueL;
  SonarValueL = SensorValue[sonarL];
  unsigned byte SonarValueR;
  SonarValueR = SensorValue[sonarR];
  while(SonarValueR == SonarValueL);

  {
    motor[motorR] = 0;
    motor[motorL] = 0;
    wait1Msec(200);
  }
}

task main()
{
  while(1 == 1)
  {

    unsigned byte SonarValueL;
        unsigned byte SonarValueR;
    SonarValueL = SensorValue[sonarL];
    SonarValueR = SensorValue[sonarR];
    //straighten left

    while(abs(SensorValue[sonarR] - SensorValue[sonarL]) != 0)
    if (SensorValue[sonarR] < SensorValue[sonarL])
    {
      motor[motorR] = 40;
      motor[motorL] = -40;
          wait1Msec(30);
    motor[motorR] = 0;
    motor[motorL] = 0;
    wait1Msec(80);
    }
    //straighten right
    //SonarValueL = SensorValue[sonarL];
    //SonarValueR = SensorValue[sonarR];
    else //while(SonarValueR < SonarValueL)
    {
      motor[motorR] = -40;
      motor[motorL] = 40;
          wait1Msec(30);
    motor[motorR] = 0;
    motor[motorL] = 0;
    wait1Msec(80);
    }

  }
    motor[motorR] = 0;
    motor[motorL] = 0;
    wait10Msec(800000000);
}


However, I had difficulty with this design in the end. Since the ultrasonic sensor can only take readings in increments of an inch, there can still be great variability in alignment. 

Wednesday, February 8, 2012

Navigation

Today I started working on the navigation. I first had it navigate to the first room via the encoder and to stop in front of the flame.

Next I decided an overall strategy for navigation. It was going to use the ultrasonic sensor to determine the points to stop and turn. It was going to enter the closest room first. Using the schematic diagram, I determined the distances for each of the runs and translated it into sonar or encoder values.


Navigate to Room and EXTINGUISH

SUCCESS! With the efforts to install a fan last night and to tweak the design, the robot is now a functional fire extinguishing machine!

A 120mm computer fan was installed to HUFF AND PUFF comparable to the big bad wolf. It will blow as hard as it will suck.

A pink fan was specifically chosen to make enemies underestimate its true power.

This mean, pink, flame extinguishing machine was then instructed to navigate into ROOM 1 by using its encoders and run its flame finding program... and subsequently HUFF AND PUFF.


Tuesday, February 7, 2012

Ultrasonic and flame sensors... SYNERGIZE!

So the past two days, I got the flame sensor to detect the flame and have the robot move towards it. Then I had the ultrasonic sensor stop in front of a wall.

Today I put these two commands together so that the robot would follow the flame indefinitely until it stops two inches away from it.

void orientflame()
{
  while(SensorValue[flameR] < 500)
  {
    motor[motorR] =  40;
    motor[motorL] = -40
    wait1Msec(30);
    motor[motorR] = 0;
    motor[motorL] = 0;
    wait1Msec(20);
  }
}

void stopdistance(int distance)
{
  unsigned byte SonarValue;
  SonarValue = SensorValue[sonar];
  if((SonarValue < distance)
  {
    motor[motorR] = 0;
    motor[motorL] = 0;
    wait1Msec(200);
  }
}

task main()
{
  while(1==1)
  {
    orientflame();
      motor[motorR] = 40;
      motor[motorL] = 40;
  stopdistance(3);
  }
}

Friday, February 3, 2012

Ultrasonic Sensor

The ultrasonic sensor proved to be difficult to set up. But with a few hacks with the help of John Legoman, it came through.



The main difficulty of the sensor is that it often fluctuates between -1 and the actual distance reading. This creates problems when our code instructs the robot to stop whenever it sees a value less than 3(stop when it's 3 inches away from a wall).

John fixed this issue by converting the sensor readings with an unsigned byte variable. This warps negatives over to the max values, and thus -1 becomes 255.
unsigned byte sonarValue
sonarValue = SensorValue[sonar]

With this conversion, the code worked beautifully.

void stopdistance(int distance);
{
  unsigned byte sonarValue
  sonarValue = SensorValue[sonar]
  while(sonarValue < distance)
   {   
      motor[motorL] = 0
      motor[motorR] = 0
   }
}

task main()
while(1==1)
{
  motor[motorL] = 80
  motor[motorR] = 75
  stopdistance(3);
}

Thursday, February 2, 2012

Flame Sensor

Installing the flame sensor involved a very simple wiring. The negative end of the sensor was wired to the data input of the microcontroller. The positive end is wired to the positive end of the microcontroller. Lastly a 10kOhm resistor is used between the positive and the ground.

The sensor was then set up in robotC. A basic principle of coding a flame scanning routine was thought up. The robot would turn until it sees the flame. This can simply be coded as such:

while(SensorValue[flame] < 200)
 {
   motor[motorL]=50;
   motor[motorR]=-50;
}

The first trial of this coded proved to be difficult. The sensor would not pick up a value greater than 80 even when. A 50kOhm resistor was then tried to increase the sensitivity of the sensor. This allowed the sensor to reach ~200 in direct flame. However, this is still well below the 0-1000 range suggested in the handout. After some thought, the polarity of the sensor was flipped. This fixed our issues and our sensor worked great. The code also worked. The robot turned until it was met with the flame and it stopped.

However, there was still some issues. Sometimes the robot would miss it and would only find it the 2-3rd time around. The code was then tweaked to slow the rotation of the robot. 

while(SensorValue[flame] < 200)
 {
   motor[motorL]=50;
   motor[motorR]=-50;
  wait1000Msec(200);
   motor[motorL]=0;
   motor[motorR]=0;
   wait1000Msec(100);
}

This made the flame scanning work very well. However, the code only worked if the flame sensor was directly level with the flame. If the flame was just higher or lower by an inch, the sensor readings would vary greatly. To deal with this, the flame sensor was mounted on a set of alligator clips where the height of the sensors can be quickly adjusted.


Thursday, January 26, 2012

Project 1: Toy Hacking

Objective: This project is to hack an ordinary toy with a motor to be controlled by a microcontroller that one can program to do specific things.


My project used a remote control car in which the controller is a tilt sensor that allows the car to move forward while tilted down, or rotate 360 degrees in place while tilted up.

 I first tried soldering wires directly to the +/- terminals of the motor. From working with Professor Mason, we determined that the motor inside has an H-bridge to control the two functions of the car, move and rotate. Thus swapping between these modes is a matter of flipping the polarity. However, with the wires connected directly to the motor, the rotation would only result in spooling up the wires till it gets stuck.


I then tried to figure out how to interface directly to the controller. From working with Professor Mason, I found out that the tilt sensor works by creating a short between the two wires.

Thus I decided to disconnect the wires from the tilt sensor and allow the microcontroller to produce the short.

Given that a transistor is essentially an electronically controlled switch, I reasoned that it would be perfect for the job. I connected the two terminals that went to the tilt sensor to the collector and emitter of the transistor. Then the base was connected to output 2 of the microcontroller.

I am able to program the duration of the spin and movement in picaxe programming. The high output would short the terminals, and thus make the toy rotate. The low output would open the terminals and would open the terminals.

However, when I first tried this, I ran into a problem where the terminals were constantly shorted. From working with Prof. Mason, we determined that the output of the microcontroller isn't high enough to open the terminals on an NPN transistor. I then swapped it to a PNP transistor and everything worked as planned.
An LDR sensor was added to the circuit. My aim is to use the LDR sensor to control the turn of the toy.
Here is my coding for the LDR sensor. When light is shining on the sensor, the toy will just move forward. When the sensor is covered, the toy will turn ~90 degrees.



Thursday, January 19, 2012

Day 5 Microcontroller Board

 Fig 5.1

1. In fig 5.1, the properties of transistors is tested. The transistor is essentially a switch that's controlled by a current like a valve. The current added to the transistor can open or close the valve, depending on the type of transistor if it's an always open transistor or always closed. In this case, an always open transistor was used. Here a finger was used in order to demonstrate how the minute current passed through the finger can close the "valve" of the transistor in which the LED becomes brighter.

Fig 5.2
2. A microcontroller circuit is built. This microcontroller is useful as it is an integrated circuit that can be programmed to perform many functions, and thus making it a relatively cheap, compact, and versatile means of creating a circuit that can perform many functions. 
 
Fig 5.3
3. With the microcontroller connected to the PC via a DB9 serial cable, the microcontroller is able to be programmed to perform various tasks. Here is a basic task of coding the microcontroller to blink the LED every second.

Day 4 Logic Probe



A logic probe was created. This was done with a transistor and a light. The purpose of a logic probe is to determine the function of a circuit. The transistor is useful for this as it detects current. The greater the current entering the probe, the brighter the light as it would open up the valve to allow current to flow from the collector to the emitter.

This was also our first circuit board soldering exercise.

Day 3: Switches and Relays

 Fig 3.1
1.Here, a circuit with two switches were set up in forming an OR logic gate. The operation of either switch would toggle the LED's on or off state.
Fig 3.2
2. A relay circuit was created. A relay is made up of two switches that's controlled magnetically by an inductor coil that induces a voltage when a changing current is passed through it. This changing magnetic field is created by the introduction of a pushbutton switch into the circuit. When the button is pressed, this closes the circuit and current begins flowing. This change in current produces a magnetic field in the inductor that mechanically flips a switch in the relay, and thus toggling the LEDs. 

Thursday, January 12, 2012

Day 2: Basic circuits, circuit theory, and multimeters

Fig 2.1

Fig 2.2

1.  Basic functional circuit construction with the breadboard was conducted. This is the circuit consisting of a power source, LED, and a resistor. Here we had to analyze Ohm's law in understanding the relationship between voltage, resistance, and current. This relationship was used to determine the resistance needed to maximize the brightness of an LED given the specification of 30mA of max current for the LED.  Lastly, a potentiometer is used as a variable resistor to adjust the brightness of the LED.

2. The operation and uses of a  multimeter was explored. First it was used to test for continuity between two points on a circuit. This is done by measuring the resistance between two points. Low resistance indicates continuity, while an extremely high resistance means little to no continuity.
Second, it was used to test the voltage of an AC adapter and an AC/DC adapter. Here, the multimeters show that there is a very low tolerance on the rating of these adapters, and resistors in the circuits must be used to tune the output to the desired amount.


 

Wednesday, January 11, 2012

Day 1: Beautiful Solder Joints!


 Fig.1 - placed components on the board with special attention to its placement.
 2. Started with ugly solder joints... and I gradually beautified it as I learned the art of filling in the pads while keeping the solder flat. I painted on flux onto the contact pads to remove the oxidation to increase the contact and adhesion of the solder.
 3. Handcrafted a beautiful bracelet. Spliced some wires, brushed flux on the ends, then held the ends together in parallel and in contact as I placed the soldering iron on there. As the wire became smoldering hot, I fed it solder. I repeated this until I rejoined the 4 pieces of wire. Heatshrink was then added.
4. A new interface was created for the power supply so that it can be used for circuit boards. This was done by cutting off the original plug and soldering on a two pin connector, and then heatshrinking the end. The power supply was then tested for continuity and shorts.