Let's Make Robots!

Reading light direction off a servo. Arduino C++

Hi there smiley I am fiddling with my second light follower robot on my 2WD chassis
the first one was the classic "3 photo resistors" model.
Now iI have fitted a servo onto the chassis, and have mounted a single photo resistor onto the servo.



https://fbcdn-sphotos-e-a.akamaihd.net/hphotos-ak-ash3/178416_637341408647_239375050_o.jpg

The servo scans from 40 degrees, to 130 degrees (90 is the centre, both of these values are the extents possible without fouling the photo resistor on the bodywork)

I want the photo resistor to take a reading for each increment of servo movement, compare it to the previous reading, and once the light level starts to drop down again (as in once the photo resistor has scanned past the light, and starts to scan away from the light source), it notes the position of the servo, and logs it as a "direction" to the light source.

currently 130 is left, 90 is straight forward, and 40 is right. I would build "windows" into the factors, as in "if the light is between 80 and 100, straight forward, else steer, depending on value)

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Hey, So i looked into arrays following your advice here. You are correct, it seems to be much more useful, and less clumsy

I actually built an array code from a bit of research (its all new to me, and im only doing it to learn, not to get an end product) and ended up with a code very much like yours.

through checkin with the serial output, I have successfully populated the array, and put the "if" function in, but when i put "Direction = Horizontal servo position" as far as i can tell, it populates the result with the "light level" if the light level is high, or if it is low, it populates with the extremes of the servo (either 0 or 130)

as far as i can tell

Any clues as to where i have gone wrong?

Cheers!

 

/* Cyclops V2. rather than move to three discrete servo positions, scan, and populate PR readings on the move

 try and use "array" to define strongest light HoriDir

 */

 

 

#include <AFMotor.h>

#include <VarSpeedServo.h> 

 

AF_DCMotor motorL(3, MOTOR12_1KHZ);  

AF_DCMotor motorR(2, MOTOR12_1KHZ);

VarSpeedServo Hori;

VarSpeedServo Vert;

 

const int PR = A1; // connect PR to A1

const int RLED = 13; // indicator LED: 13 and 2 are the only properly unused digital pins on the motorshield.

const int LLED = 2; // indicator LED

 

int HoriPos = 0;      // straight forward, 

int VertPos = 90;      // 30 degrees up from horizontal

 

int HoriArray[130];

int CWHoriDir = 0;

int CCWHoriDir = 0;

 

void setup() {

 

  Serial.begin(9600);  // Serial at 9600 bps

 

  Hori.attach(9);  // Hori Servo on Pin 9 (Servo2 on the Motorshield)

  Vert.attach(10); // Vert Servo on Pin 10 (Ser1 on the Motorshield)

 

  motorL.setSpeed(150);      // set the speed of motors: 0 is stop, 255 is full speed:

  motorR.setSpeed(150);

 

  pinMode (RLED,OUTPUT);

  pinMode (LLED,OUTPUT);

 

}

 

 

void CWSweep (){

 

 

  for(HoriPos = 0; HoriPos <= 130; HoriPos += 1)

  {    

    HoriArray[HoriPos] = analogRead(PR);

    Hori.write(HoriPos);

    delay (10) ;       

  }

 

  if ((HoriArray[HoriPos] < HoriArray[HoriPos-1]) && (HoriArray[HoriPos-1] < HoriArray[HoriPos-2])){

    CWHoriDir = HoriPos;

  }

}

 

void CCWSweep (){

 

  for(HoriPos = 130; HoriPos >= 0; HoriPos-=1)   

  {  

    HoriArray[HoriPos] = analogRead(PR);

 

    Hori.write(HoriPos);

    delay (10) ;  

  }

  if ((HoriArray[HoriPos] < HoriArray[HoriPos+1]) && (HoriArray[HoriPos+1] < HoriArray[HoriPos+2])){

    CCWHoriDir = HoriPos;

  }

 

}

 

void loop() {

 

  CWSweep();

  Serial.println(CWHoriDir);

  CCWSweep();

  Serial.println(CCWHoriDir);

}

P.S. I like your focused second sweep idea, but want to get this basic version working first, and make sure i understand it.
Cheers
Ol

i have only had time to have a quick peek at your code, but one thing i noticed was this...

void CWSweep (){

 

 

  for(HoriPos = 0; HoriPos <= 130; HoriPos += 1)

  {    

    HoriArray[HoriPos] = analogRead(PR);

    Hori.write(HoriPos);

    delay (10) ;       

  }

 

  if ((HoriArray[HoriPos] < HoriArray[HoriPos-1]) && (HoriArray[HoriPos-1] < HoriArray[HoriPos-2])){

    CWHoriDir = HoriPos;

  }

}

 

you should put the if inside the for loop instead. and you only need to check if it is less once. like this...

 

 

void CWSweep (){

 

 

  for(HoriPos = 40; HoriPos <= 130; HoriPos += 1) //wasnt it from 40?

  {    

    HoriArray[HoriPos-40] = analogRead(PR);

    Hori.write(HoriPos);

   
    if ((HoriArray[HoriPos-40] < HoriArray[HoriPos-41]) && (HoriPos>0))// if it is at horipos 0 it doesnt need to compare values.

    CWHoriDir = HoriPos;

  }

    delay (10) ;       

  }

}

 

and the you need to change the CCW one aswell.

instead of where = 0; ,and later, where = 90; you could just replace where with HoriPos - 90, or, inside the for loop set where = HoriPos - 90. Either way you save yourself a little bit. Keeping the where and just using HoriPos - 90 to set where is probably the best option.

As always you are correct Bird. Well almost anyway...

you would want to set where=horipos-40 to make the array range from 90-0 and 0-90 respectively

i hope you get the idea olly. Post you code here when you have worked on it a bit more. ill be happy to help out as much as i can :)