Making Things Interactive

March 10, 2008

Lightchaser v5

Filed under: 7: Mid-Term Project,Gaku Sato — ponkotsu @ 3:32 pm

Description:
  This is a motorized light-chasing trike with the left and right motors having independent motor controls for the ability to turn/rotate in place.  It takes inputs from three light sensors on its left, right, and back sides.
  The front left/right sensors are the main inputs used to control the motors.  There are two main control algorithms:

1. ABSOLUTE
   This takes sensor inputs and compares them individually to a constant threshold to get the desired motor output.  For instance, if the left sensor detects low levels of light, the right motor should run at a low speed, and vice versa.  So if the right sensor detects high levels, it would run the left motor at high speed, allowing the trike to steer towards the light.  If they are both low, the trike would drive straight forward but slowly, so as to not wildly run after slight differences in ambient light, etc.  Also, there are MIN/MAX thresholds set so that the trike will stop running when the sensors read above MAX (sensors/trike is close enough to light source) or when they read below MIN (light source too far away or nonexistant).

2. RELATIVE
   This takes sensor inputs and compares them to each other.  For instance if the front inputs vary greatly, this means that the trike is not facing the light source.  For example, if the left input reads 700 and the right input reads 500, both of which are above the specified MIN threshold, the initial ABSOLUTE algorithm would tell the right motor to run HIGH and the left motor to run LOW.  However, since the difference is 200 (quite large), this means that the light source is hitting the sensors from the left side of the trike, so in fact, the left motor should not run at all and allow the trike to pivot without moving forwards (i.e. away from the light).  Also, while the sensor inputs have been calibrated by a coefficient to read on matching light scales, they will still have variations, especially with noise.  Relative input parsing can account for some of this and eliminate twitch motions by allowing the motors to run at the same speed if the inputs are only slightly different.

  The algorithm was the most challenging part.  Below is the motion logic from L/R sensor inputs to L/R motor outputs.  The MIN/MAX input conditions are the absolute thresholds mentioned above, and the L/H conditions are LOW<—>HIGH analog controls.

Input  Output
L      R      L      R
min min   0      0
min L       L      0
min H      H      0
min max  H     0
L     min   0      L
L     L       L      L
L     H       H     L
L     max  H      0
H    min    0     H
H     L       L      H
H     H      H      H
H     max  L      0
max min  0       H
max L      0       H
max H      0      L
max max 0      0

  The rear sensor is used to turn the trike around if it is facing the wrong way.  If the input here is significantly higher (difference threshold specified) than the front inputs, it rotates the trike towards around by almost 180degrees in the direction of the higher front input.  So if the left is slightly higher than the right when the light hits the back of the trike, this probably means that the light source is slightly more to the right, so when it turns around, it doesn’t do a full 180; it rotates slightly less to face more towards what is probably the location of the light source.

Pictures:
  Here is my current setup.  I’m working on making it fully operational, but it’s difficult to fit all the parts onto the chassis for remote operation.  So far the I/O works perfectly under various ambient conditions and light sources.  Once I get all the parts onto the chassis, it should just be a matter of tweaking the constant coefficients and thresholds in the code.
  [I’m having trouble with the camera so I will have this up soon!]

Code:

int LightL = 2;   // input analog pin – photoresistor [left]
int LightR = 3;   // input analog pin – photoresistor [right]
int LightB = 4;   // input analog pin – photoresistor [back]
int MotorL1 = 6;  // output digital pin – motor [left] – direction 1
int MotorL2 = 5;  // output digital pin – motor [left] – direction 2
int MotorL = 9;  // output analog pin – motor [left] – speed
int MotorR1 = 8;  // output digital pin – motor [right] – direction 1
int MotorR2 = 7;  // output digital pin – motor [right] – direction 2
int MotorR = 10;  // output analog pin – motor [right] – speed

int Lin;  // input – photoresistor [left]
int Rin;  // input – photoresistor [right] * coefficient
int Bin;  // input – photoresistor [back] * coefficient

long Lout;  // output – motor [left]
long Rout;  // output – motor [right]

int LightMin = 450;    // light input MIN for motion
int LightMax = 800;    // light input MAX for motion

int SpeedLow = 70;    // motor output LOW (MIN for motion)
int SpeedHigh = 255;  // motor output HIGH

int RotateDiff = 100;  // light input different threshold to rotate
int RotateTime = 1500; // motor ON time (ms) to rotate <180deg int msecond = 0; void setup() {   Serial.begin(9600);   pinMode(LightL, INPUT);   pinMode(LightR, INPUT);   pinMode(LightB, INPUT);   pinMode(MotorL, OUTPUT);   pinMode(MotorL1, OUTPUT);   pinMode(MotorL2, OUTPUT);   pinMode(MotorR, OUTPUT);   pinMode(MotorR1, OUTPUT);   pinMode(MotorR2, OUTPUT);   analogWrite(MotorL, 0);   digitalWrite(MotorL1, HIGH);  // forward: HIGH   digitalWrite(MotorL2, LOW);   // forward: LOW   analogWrite(MotorR, 0);   digitalWrite(MotorR1, HIGH);  // forward: HIGH   digitalWrite(MotorR2, LOW);   // forward: LOW   Lin = analogRead(LightL);   Rin = analogRead(LightR) *1.1;   if(max(Lin,Rin)>LightMin)
  {LightMin = max(Lin, Rin);}  // calibrate light input MIN
}

void loop()
{
  Lin = analogRead(LightL);
  Rin = analogRead(LightR) *1.1;
  Bin = analogRead(LightB) *1.0;
  Lout = 0;
  Rout = 0;

  if(Bin>Lin+RotateDiff && Bin>Rin+RotateDiff)
  {  // rotate when light sensed from behind > front + constant
    if(Lin>Rin)
    {  // rotate left
      digitalWrite(MotorL1, LOW);
      digitalWrite(MotorL2, HIGH);
    }
    else
    {  // rotate right
      digitalWrite(MotorR1, LOW);
      digitalWrite(MotorR2, HIGH);
    }
    int ms = millis();
    while(millis() < ms+RotateTime)     {       analogWrite(MotorR, SpeedLow);       analogWrite(MotorL, SpeedLow);     }     digitalWrite(MotorL1, HIGH);     digitalWrite(MotorL2, LOW);     digitalWrite(MotorR1, HIGH);     digitalWrite(MotorR2, LOW);     analogWrite(MotorL, 0);     analogWrite(MotorR, 0);   }   if(LinLightMax) {Lout=255;}
    else if(Rin>LightMin)
    {  // Lout = (SpeedHigh-SpeedLow)*(Lin-LightMin)/(LightMax – LightMin)+SpeedLow
      Lout = SpeedHigh-SpeedLow;
      Lout *= Lin-LightMin;
      Lout /= LightMax – LightMin;
      Lout += SpeedLow;
    }
  }
  if(Lin>LightMax)
  {
    Lout=0;
    if(Rin>LightMin && RinLightMax) {Rout=255;}
    else if(Lin>LightMin)
    {
      Rout = SpeedHigh-SpeedLow;
      Rout *= Rin-LightMin;
      Rout /= LightMax – LightMin;
      Rout += SpeedLow;
    }
  }
  if(Rin>LightMax)
  {
    Rout=0;
    if(Lin>LightMin && LinLightMin && LinLightMin && RinRin+200) {Lout=0;}
  if(Rin>Lin+200) {Rout=0;}
  if(abs(Lin-Rin)<50) {Rout=Lout;}   analogWrite(MotorL, Lout);   analogWrite(MotorR, Rout);   msecond = millis()/1000;   if(millis()-msecond*1000 == 0)  // display every second   {     Serial.print("L:i");     Serial.print(Lin);     Serial.print("-o");     Serial.print(Lout);     Serial.print("   R:i");     Serial.print(Rin);     Serial.print("-o");     Serial.print(Rout);     Serial.print("   B:");     Serial.println(Bin);    } }[/sourcecode] Parts List:
3x photoresistors (preferably all same model)
3x 1Kohm resistors (for photoresistor circuit)
1x 22uF capacitor (for H-bridges)
1x 9V battery pack (for Arduino)
1x 6V battery pack (for motors)
2x quad half H-bridges (for motor control)
1x Tamiya Twin-Motor Gearbox (or 2x DC motors & gearboxes + 1x chassis)
1x breadboard (currently on 2 separate in pic, but need to condense)
?x 22awg hookup wires

References:
  http://itp.nyu.edu/physcomp/Labs/DCMotorControl

Advertisements

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: