[UPDATE] Solar tracking with Photosensors
Nomadic0
Posts: 21
Good evening!
In the execution of this program, the servos execute well when I block light from 1 section (2 photo-sensors) (4 sensors in total). However, when I block one of those same sensors as well as one adjacent to it, BOTH servos move, and then continue to move together no matter which sections I block afterward.
It's executing well (according to the terminal), but it's like the servos are storing energy(?) for the next execution of the while loop.
I am using RCTIME to measure the 'darkness' in these 4 sensors.
Any help would be appreciated. Apologies for the novice code.
Nomad
In the execution of this program, the servos execute well when I block light from 1 section (2 photo-sensors) (4 sensors in total). However, when I block one of those same sensors as well as one adjacent to it, BOTH servos move, and then continue to move together no matter which sections I block afterward.
It's executing well (according to the terminal), but it's like the servos are storing energy(?) for the next execution of the while loop.
I am using RCTIME to measure the 'darkness' in these 4 sensors.
Any help would be appreciated. Apologies for the novice code.
Nomad
#include "simpletools.h" // Include simple tools #include "servo.h" int main() // main function { int rf,lf,rb,lb,tilt,spin,frontsum,backsum,leftsum,rightsum=0; while(1) // Endless loop { high(4); // Set P4 high pause(1); // Wait for circuit to charge rf = rc_time(4, 1); // Measure decay time on P4 print("rf = %d\n", rf); // Display decay time //pause(100); high(5); // Set P5 high pause(1); // Wait for circuit to charge lf = rc_time(5, 1); // Measure decay time on P5 print("lf = %d\n", lf); // Display decay time //pause(100); high(8); // Set P8 high pause(1); // Wait for circuit to charge rb = rc_time(8, 1); // Measure decay time on P8 print("rb = %d\n", rb); // Display decay time //pause(100); high(9); // Set P9 high pause(1); // Wait for circuit to charge lb = rc_time(9, 1); // Measure decay time on P9 print("lb = %d\n", lb); // Display decay time //pause(100); frontsum=lf+rf; printf("FRONTSUM %d\n", frontsum); backsum=rb+lb; printf("BACKSUM %d\n", backsum); leftsum=lf+lb; printf("LEFTSUM %d\n", leftsum); rightsum=rf+rb; printf("RIGHTSUM %d\n", rightsum); spin=leftsum-rightsum; printf("SPIN %d\n", spin); tilt=frontsum-backsum; printf("TILT %d\n", tilt); //I then compare each labeled section to determine where the servos should move the panels (X and Y axis) if(tilt<-30000) { servo_angle(25, 900); // P25 servo to 90 degrees pause(20); servo_stop(); printf("Clockwise tilt\n"); } else if (tilt>30000) { servo_angle(25, 1800); // P25 servo to 180 degrees pause(20); servo_stop(); printf("CounterClockwise tilt\n"); } if(spin<-30000) { servo_angle(26, 900); // P26 servo to 90 degrees pause(20); servo_stop(); printf("Clockwise\n"); } else if (spin>30000) { servo_angle(26, 1800); // P26 servo to 180 degrees pause(20); servo_stop(); printf("CounterClockwise\n"); } pause(5000); //Long pause to examine the results }
Comments
Make the right two read as positive for the LeftRight servo and the left two negative, then sum for LR motion.
Make the top two read as positive for the UpDown axis and the bottom two negative, then sum for UD motion.
There was a user who did something like this with visible lasers recently if anyone can link the post, please.
That did need clarification! I am using 4 (1 on each corner)
Thank you
We have to assume that P4, P5, P8, & P9 are the photo-sensors but which is which?
Assumptions I'm making:
P4 Front Left
P5 Rear Left
P8 Front Right
P9 Rear Right
This allows variable name transformations of:
s becomes fl
t becomes rl
u becomes fr
v becomes rr
a becomes leftsum
b becomes rightsum
c becomes frontsum
d becomes rearsum
x becomes leftright
y becomes frontrear
It also helps to identify what range of values are expected, and in your test case what values you are measuring.
That alone may help you understand what is happening.
I've updated this, and the results are clearer; that the program runs correctly, but the servos are still misbehaving
Can you post some pictures so others can help examine the configuration?
I noticed that you are doing a servo_stop which kills the servos. so you want them to go lifeless.
If the sensors are on the board that the servo is moving isn't going to change the readings and cause the servos to continue to move?
I would shut the servos off and then record reading as you move the sensor board around to get a list of values returned by the sensors. The rc_time function has a time limit that may be expiring.
Anyway here is the updated code:
I really appreciate your input to help me out! I have the servos just off to the side for now (for testing the sensors with shadows).
Setup aside, I am not completely sure I understand the cog function.
The rl,fl,rb,lb in the new code are returned as 0 when I tried to execute it. (I took away the int = 0 also, same thing showed.)
By placing the input function in a cog it runs all the time no mater what other functions your doing so you can always have fresh values from the sensors. In order to get values from that cog you need to tell the compiler that the variables in that cog are changing outside the normal process by using the "volatile" key word. They also have to be declared outside the main function where I have them so that all of the code has access to those variables.
Also if you want to read your sensors at an exact time frame such as every 20 milliseconds you can adjust the cog functions to have that timing even though the reset of the program is stopped waiting for input.
I don't have your sensors or what R/C time function your using so I'm not able to test the code.
Mike
It might just be my thinking, as the compiler might optimize and only create the variable space once, but I avoid creating vars other than simple indexes in for-loops, within while/until loops.
Maybe, this would help:
dgately
Shouldn't what I'm trying to do still be possible with my code? I'm just not seeing why it doesn't clear the values.
I would code it using the cog function if I understood how to troubleshoot it.
So what you are saying is that the values don't change each time it goes through the loop.
I also don't understand your servo code. The servos move from 0 degrees to 180 degrees in tenths.
So you need to come up with an angle that you want the board at and then tell the servos that is the angle to be at.
If the sun is directly overhead then all four sensors will be on and the servos should go to 90 degrees.
You can not use the servo_stop function as this shuts down the servo control code and all the servos will stop working.
The servo function starts a cog in the background that feeds a signal to the servos that tell them where to be. This process is started automatically once it sees the first servo_angle call. Once you do a servo_stop this background function is stopped and all the servos go dead.
You need to tell each servo what angle to be at and let them go there. They will stay there until you tell them a new angle.
Mike
Mike, i appreciate it! Right now my servos are moving a rod. One is connected which tilts it. The other servo is under that setup, spinning it.
As of yet, (coming from PBASIC), I'm not sure how to just give small pulses to the servos. I was using the servo_angle only because that's the only command I've seen to control them.
That poriton is based off of a Parallax example.
When the sun is overhead, I'd like the servos to track it (using the sensors on a board) and then stay put unless the sun moves.
Nomad
Once everything is in a known position, to make small adjustments just keep track of the current position (as an integer in tenths of a degree) and add or subtract a few tenths (or whatever resolution you want), send that to the servo, measure the light and either add or subtract a few more, again measure the light, etc until you reach a max.
Do this in small increments. If you send large angle changes you have to add delays to allow the servo to reach the commanded position before sending a new command, or the servo motion will not make any sense as it starts executing the next position change before the first is done. (Surprisingly large delays are needed compared with those expected).
Tom
C is a little different than PBASIC is so it will take a little to get use to the functions.
If your using the Parallax standard servos your going to need to track the servo angles as a way to determine where you are.
At sun rise you might be at 0 and 90 degrees. At noon you might be at 90 and 90 and at sun set 180 and 90. This is assuming that the sun is directly over head. Since the servos move based on the angle fed to them you only need to tell them what angle they should be at and they will take care of the rest.
If on the other hand you are using motors, then things get a little more interesting in that you need to pulse them so they move in the correct direction and then stop them when they reach the correct angle. Your code will need to figure out how much to pulse them and then stop.
Mike
This is all becoming clearer. I was using the 90 / 180 degrees as a way to go one direction, then reverse.
Also, I am using the standard Parallax servos and photosensors (from the Boe-Bot)
I'll need to define exactly what angle I want (?) by adding/subtracting from a variable, correct?
If the Left sensor is off then you might add 10 degrees to move it in that direction until it is on fully and stop.
As the sun moves the sensor will indicate what direction it moved in and you would add or subtract a few degrees and check your results.
You could also use a real time clock and just calculate the angle based on what time it is.
Mike
Would I still want to use this?
servo_angle(PIN , VAR);
pause (??);
servo_stop():
not sure how else the motors will stop also
I understand our approach to add/sub from the angle variable. Just not sure how it'd look
The servos move from 0 to 180 degrees in tenths of an increment. Don't know how you have the servo attached to your board but movements of 1 degree is not noticeable. You will have to play with it and see how the board reacts to small movements.
So if the board is flat and the servo is at say 90 degrees to move it a small amount you would add or subtract a few degrees from your current angle. So you might try 95 or 85 to start and see how it reacts.
Here is some sample code that will allow you to enter an angle and have the servo move to that angle.
Mike
When I run this code, the servos continually move from the beginning of execution. (Even if i change 900 to 0) Although, if I enter the angle '180', one on the servos changes direction.
I am using the schematic on the left in the attached pic. (Not sure if this is intended for use with the Propeller and 9V battery).
Thanks
Nomad
Depending where the servo was before this it might require a longer pause.
After add again if the servo doesn't stop make the pause longer. If it stops and waits too long before moving make the pause shorter.
An alternative is to try this (after the includes, defines & global declarations):
The servos I was think off are these: Parallax Standard Servo 900-00005. These servo move to a given angle and stop.
The Boe-Bot servos are continues servos and don't stop, but continue to move based on signal applied. This is going to make your project much harder to code. Also the Boe-Bot uses PBASIC. So how are you coding in C ?
To work with the continues servos you will need to use the servo_speed function.
servo_speed(ServoX, 0); //Stay still
servo_speed(ServoX, -100); //Full speed clockwise
servo_speed(ServoX, 100); //Full speed clockwise
since you can only turn the servo on or off you won't know what position your at. You can only move the servo in a direction and hope it moves and then check the results. You will also have to pulse the motor to get them to move just a little and hope it was enough to get the desired movement.
For example:
servo_speed(ServoX, 50);
pause(30);
servo_speed(ServoX, 0);
This short pulse will move the servo counter clockwise for 30 milliseconds and then stop.
If the board is to heavy it will not move very much if at all.
Mike
I think this is what was definitely holding me back here.
I have used the servo_speed function and it works like I had originally planned (aside from some buzzing(?) sounds when they stop).
Also, I am using the Prop Education Kit board with the BoeBot servos. (Allowing for C)
I really appreciate the helping hand.
Nomad
This servo is 4 - 6 volt only servo and the center maybe off a little requiring the POT on the servo to be turned a little to find the center frequency and stop.
Don't know how your going to control the servos as the only feed back you have is the light sensors so you will not know if the board is tipped to far.
Mike