LDR/Servo Project Help

Hey there everyone. So, me and a couple classmates have a project for one of our classes. All of us are absolutely terrible/clueless with code as we have gotten close to no training or experience in it. We are also don't know much about how installing the proper electrical hardware (for example, choosing the proper resistors). So here's the project:

We've got to build a light detecting "satellite." It needs to have a 0-180 degree range. The servo has a 5" diameter, 1/2" thick, plywood disc mounted to the top. There will be two light bulbs in the room at equal height of the "satellite." When one is turned on the satellite needs to rotate to the light and point a laser on it (there will be a target). When that light bulb shuts off, another light bulb will be lit on the other side of the room and the satellite has to rotate and point the laser at the new target. While it's doing all this, we have to output an error signal on a screen (can Matlab do that)?

So far we've got the Arduino Starter Kit, the RadioShack Standard Servo (http://www.radioshack.com/radioshack-standard-servo/2730766.html#q=servo&start=6), an external 4AA battery pack to power the servo, and 2 LDR packs from Radioshack.

Our main problems so far is that we don't know what the capabilities of the Arduino is. Since we're so knew to Arduinos, we're unsure of what commands will properly execute our system. So far, we've been able to do the Sweep example as well as another example we found another example online that utilizes the Arduino (http://www.instructables.com/id/Control-Servo-with-Light/).

So what we know we need is a set of LDR's equally spaced around the servo's disc. Depending on the light from the room we're going to get a change in resistance between the LDR and have it rotate until we get an equal delta from the the outlying LDR's and a large delta for the center LDR (assuming we have an odd number of LDR's and the center one is fixed at 90 degrees).

As you can see, I'm pretty scatter brained. I'm not asking anyone to code a project for us. I was just wondering if we could get any input, advice, or have someone point us in the right direction. We've got a month to do this, but as you guys can imagine, we've got other classes and work to deal with too.

Thank you for all your help and I look forward to hear your responses

You seem to have a reasonably good grasp of the requirements and you seem to have been trying some relevant example code.

You need to plan the project in small pieces. Ensure each piece works separately before trying to integrate things.

This Thread should give you some ideas about planning and implementing a program

Try to put some code together and then come back to the Forum (just continue in this Thread) if you are having trouble. Even if your code does not work it will provide a starting point for advice.

While you are developing your project you could just use an LED in place of the laser pointer. It would not be directional, but you could see that it was working.

...R

I don't think you need LDR all around the disk. Just three should work. Spaced fairly closely together. If the one to the right has the brightest response, move clockwise. if the one to the left has the brightest response move anti-clockwise. If the one in the center has the brightest response you are on target so fire.

Thanks guys. So our professor wasn’t pleased on Wed since we didn’t have a function code even though we told him we don’t know how to code well. After that we were able to get this code to work. The code only utilizes 2 LDR’s; however, we’re having trouble trying to incorporate more. We’ve got 4 total wired to our disc. Our professor wants at least 6. The code works fine with two. We tried modifying it for 4 and it didn’t work.

#include <Servo.h> 
 
Servo myservo; 
int pos = 90;   // initial position
int sens1 = A0; // LRD 1 pin
int sens2 = A1; // LDR 2 pin

int tolerance = 20; // change this value to decrease sensitivity between LDRs for nuetral position 
 
void setup() 
{ 
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object 
  pinMode(sens1, INPUT);
  pinMode(sens2, INPUT);
  myservo.write(pos);
  delay(2000); // a 2 seconds delay while we position the solar panel
}  
 
void loop() 
{ 
  int val1 = analogRead(sens1); // read the value of sensor 1
  int val2 = analogRead(sens2); // read the value of sensor 2
 
  if((abs(val1 - val2) <= tolerance) || (abs(val2 - val1) <= tolerance)) {
    //do nothing if the difference between values is within the tolerance limit
  } else {    
    if(val1 > val2)
    {
      pos = --pos;
    }
    if(val1 < val2) 
    {
      pos = ++pos;
    }
  }
 
  if(pos > 180) { pos = 180; } // reset to 180 if it goes higher
  if(pos < 0) { pos = 0; } // reset to 0 if it goes lower
  
  myservo.write(pos); // write the position to servo
  delay(50);
}

I’m getting slightly confused about the remit. The “DISK” that you mention, does this rotate with the laser?

KenF:
I'm getting slightly confused about the remit. The "DISK" that you mention, does this rotate with the laser?

The disc is mounted to the servo so it spins as the servo spins. The laser, should, sit on the end of the disc at the midpoint (or 90 degrees).

MuuMuu101:
The disc is mounted to the servo so it spins as the servo spins. The laser, should, sit on the end of the disc at the midpoint (or 90 degrees).

Am I right in assuming that you're going to have your sensors mounted at equal distances? And your laser will be pointing at some point between the middle pair of sensors?

KenF:
Am I right in assuming that you're going to have your sensors mounted at equal distances? And your laser will be pointing at some point between the middle pair of sensors?

You are correct to assume that. For now we just approximated it. I'm trying to get a photo posted soon of what we've got.

A picture can be found on the link provided. The arrow is where the laser pointer would go.

MuuMuu101:
So our professor wasn’t pleased on Wed

Presumably that was Wed, 5 November - the day you first sought advice here.
I wonder when he gave you the assignment?

‘E’ for lack of effort, methinks

…R

Robin2:
Presumably that was Wed, 5 November - the day you first sought advice here.
I wonder when he gave you the assignment?

'E' for lack of effort, methinks

...R

He gave the assignment a couple weeks ago, but as I said earlier, the first couple weeks consisted of purchasing all of the material, figuring out how the Arduino works, and trying to understand code. It took us over a week to get the Sweep Example to run right (until we figured out we needed an external battery pack). You can think what you want. You also have to remember all of us have at least 2 other classes and part time jobs.

If you don't mind, I'd like to stick to the subject instead of flexing my fingers in a joust over the internet. I'm only looking for help for a better understanding. I'm not asking anyone to run any code for us.

So I was working on the code over the weekend and was able to get a light tracker. It actually wasn’t all too difficult and adding more LDR’s shouldn’t be an issue. So now we need to linearize our system. As of now, if a light is shining at 45 degrees, the system steps or moves at a constant velocity. We need to generate an error signal that will tell our system to move to our target (light bulb) quickly, but slow down as the system approaches our target. Do you have any suggestions on what type of controller to use? We were told a lot of previous people who took the class used Megunolink.

Here’s our code so far:

#include <Servo.h> 
 
Servo myservo; 
int pos = 90;   // initial position
int sens1 = A0; // LRD 1 pin
int sens2 = A1; // LDR 2 pin
int sens3 = A2; // LDR 3 pin
int sens4 = A3; // LDR 4 pin

int tolerance = 25; // adjusts sensitivity at nuetral position 
 
void setup() 
{ 
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object 
  pinMode(sens1, INPUT);
  pinMode(sens2, INPUT);
  pinMode(sens3, INPUT);
  pinMode(sens4, INPUT);
  myservo.write(pos);
  delay(3000); // a 3 seconds delay 
}  
 
void loop() 
{ 
  int val1 = analogRead(sens1); // read the value of sensor 1
  int val2 = analogRead(sens2); // read the value of sensor 2
  int val3 = analogRead(sens3); // read the value of sensor 3
  int val4 = analogRead(sens4); // read the value of sensor 4
 
  if((abs(val2 - val3) <= tolerance) || (abs(val3 - val2) <= tolerance)) {
    //do nothing if the difference between values is within  tolerance 
  } else {    
    
    //++ is CCW
    //-- is CW
    //Larger Resitance = Less Light for position
    
    if(val1 > val2)
    {
      pos = --pos;
    }

    if(val2 > val1) 
    {
      pos = ++pos;
    }
    
    if(val2 > val3)
    {
      pos = --pos;
    }
    
    if(val3 > val2)
    {
      pos = ++pos;
    }
   
    if(val4 > val3)
    {
      pos = ++pos;
    }
    
    if(val3 > val4)
    {
      pos = --pos;
    }
    
  }
 
  if(pos > 180) { pos = 180; } // turn to 180 if it goes higher
  if(pos < 0) { pos = 0; } // turn to 0 if it goes lower
  
  myservo.write(pos); // write the position to servo
  delay(50);
}

Thanks guys. So our professor wasn't pleased on Wed since we didn't have a function code even though we told him we don't know how to code well.

Tell your professor to get off his ass and start teaching you how to do the things he has assigned you to do. You are paying good money for instruction aren't you? Go to the department head and tell them you are not getting much for your money.

MuuMuu101:
We need to generate an error signal that will tell our system to move to our target (light bulb) quickly, but slow down as the system approaches our target.

How does you system know what direction to move? Presumably because one sensor is brighter than another? Presumably that difference reduces as the disk aligns with its target?

...R

PS I suspected time-wasting earlier. I don't see much evidence of intellectual hard work either

So, let me give you guys an update of what’s happened since the last time I posted. Yes, our original code wasn’t very intellectual or hard and we realize that now and have gained more knowledge. So, we scrapped everything and started over. First off, we now have 6 LDR’s equally spaced 270 degrees around (each 45 degrees apart) the disc (which we got recut). Then we used the serial.print function to display the values of each LDR as we swept the servo from 0 to 180 degrees. We took the average of each LDR reading at each location and plotted them in Excel (LDR reading vs. position). However, for one LDR reading, there are instances where we can obtain multiple positions so I split up the line into multiple functions (i.e. For 102 < x < 174: y = 3x -2 or something).

So, now what we’re trying to do is write a code that locates the LDR with the max value (it should be the sensor closest to the light). From there we may get multiple values so if we do we’re going to check the LDR next to it on both sides and compare the values. So, if LDR 4 is the highest we’ll check it’s position (let’s just say it’s 17 and 135). Then we’ll check LDR 3’s value and it may output a position of 34, 52, and 117. Then we look at LDR 5 and it outputs a servo position of 21 and 110. Well, since LDR 4 reads 17 and LDR 5 reads 21, we know it should be in that zone and therefore can use maybe ratios to find a final position. However, we’re having trouble in writing a code that is capable of doing this.

Now, that we theoretically have a position we can generate an error signal (through Megunolink or Matlab). Essentially what my professor wants is a ramping servo. The larger the error, the faster the servo should pulse to get it to it’s target the quickest. As it approaches it’s target, it should slow down. So, now we’re tying code out. Unfortunately, I don’t have it on me as I haven’t been writing the code personally.

So, as I've been trying to discuss and brainstorm with my groupmates, it seems that every group's problem with this project is trying to output a position. From what I've been told, no one has been successful in finding a finite or even an approximate position/angle. Therefore, everyone is having difficulty even generating an error signal.

Have you considered putting your LEDs at the bottom of short tunnels (black cardboard tubes) so that only those aimed nearest the light see anything.

I put together about 10 or 15 lines of code and 2 LDRs to identify where the sun is. Took about 15 minutes. If the Right one is brighter, move a little to the Right and test again. I suspect you are over-thinking the problem.

You could use 2 LDRs (and maybe a 3rd at the back in case the light is behind you - the sun would not be) for rough positioning and another at the bottom of a long tunnel for the final accurate direction.

...R

Will only one light be on at a time? If so you might search the forum for solar panel aiming discussions. Your project has several separate parts which you can work on separately. If a key component is vairable servo movement speed, them work on that part as a stand alone.

Robin2:
Have you considered putting your LEDs at the bottom of short tunnels (black cardboard tubes) so that only those aimed nearest the light see anything.

I put together about 10 or 15 lines of code and 2 LDRs to identify where the sun is. Took about 15 minutes. If the Right one is brighter, move a little to the Right and test again. I suspect you are over-thinking the problem.

You could use 2 LDRs (and maybe a 3rd at the back in case the light is behind you - the sun would not be) for rough positioning and another at the bottom of a long tunnel for the final accurate direction.

…R

So with my old code where I had a bunch of if statements saying if light is over there, go to that direction, I tried putting small straws over the LDR’s and they had trouble picking up the light.

We’re not allowed to use that 10-15 lines of code. That’s what our old code was like. What makes it challenging is that he doesn’t want the servo to move till Arduino figures out what angle the light source is at. Once Arduino knows the angle the light source is, it will reference a linear error curve with a PID and tell the servo, “you need to move in this direction, this quickly.” Right now, we have a code that identifies the highest value LDR. Theoretically, the LDR next to it should display the second highest value. From there, we have a specified “zone.” Our biggest issue is that no one knows how to get the exact angle between the zone.

zoomkat:
Will only one light be on at a time? If so you might search the forum for solar panel aiming discussions. Your project has several separate parts which you can work on separately. If a key component is vairable servo movement speed, them work on that part as a stand alone.

We've googled and looked all over youtube and that's how we got our original code which is not what he wants. The test should be conducted in a decently dark room and only one light bulb will be own at a time.