I ordered one of these servos ( which works flawlesly) but the only problem for me is now how to read the angles of this servo and show them via the serial monitor.
I´m open for any ideas (also completly new coding attempts).
on a second step I want to move the servo with an command from the PC to an exact degree. Any ideas or hints how this could be done?
and at last I want to home the servo to zero degrees. This should be possible with a simple button and function if I know and can use the Information in steps 1) and 2). Am I right?
I ordered one of these servos ( which works flawlesly) but the only problem for me is now how to read the angles of this servo and show them via the serial monitor.
How can I write the map to the serial monitor?
I´m open for any ideas (also completly new coding attempts).
2) on a second step I want to move the servo with an command from the PC to an exact degree. Any ideas or hints how this could be done?
3) and at last I want to home the servo to zero degrees. This should be possible with a simple button and function if I know and can use the Information in steps 1) and 2). Am I right?
Okay to answer the first question:
The answer is in the sketch on the below url.
The 2nd question.
You are from the serial monitor.
based on the input write the new desired angle to the servo motor.
The 3rd question.
homing will be trivial.
based on an event you write 0 as the desired angle to the servo.
I could be wrong, but I think that the tutorial you are trying to use is for a feedback servo that is NOT 360 degree capable.
Your servo IS a 360 degree servo.
So to make it move to a specific position, you sill need to calibrate the feedback values. Once you have that, you can tell the servo to start moving in a particular direction, then keep reading the feedback until it gives a value that corresponds to your desired position.
The 3rd question.
homing will be trivial.
based on an event you write 0 as the desired angle to the servo.
I do not think this is accurate. A 360 continuous rotation servo does not move to s specific angle. It moves forward, backward or stops.
vinceherman:
I could be wrong, but I think that the tutorial you are trying to use is for a feedback servo that is NOT 360 degree capable.
Your servo IS a 360 degree servo.
So to make it move to a specific position, you sill need to calibrate the feedback values. Once you have that, you can tell the servo to start moving in a particular direction, then keep reading the feedback until it gives a value that corresponds to your desired position.
I do not think this is accurate. A 360 continuous rotation servo does not move to s specific angle. It moves forward, backward or stops.
adafruit claims that the tutorial is valid with the 360 degree servo.
It is not complete clear to me how the Hall effect switch is providing the angle the servo is at.
I would have to have one to play with to understand thoroughly the hall-effect position feedback.
I deal with optical disc encoders and linear encoders in cnc machines.
I am not going to write the sketches for him.
I do not have a 360 degree servo to play with so it is up to them to learn.
I still think it is trivial to write a sketch that based on where the serve currently is in rotation with respect to the home position, that the necessary "commands" can be sent to the servo to move to the 0 degree position.
Note that the example code is for a servo which provides the feedback as a simple voltage, hence the analogRead() is all that is needed.
But the servo specification clearly says that feedback is via PWM signal.
"Feedback sensor: Hall effect
Feedback signal: PWM, 3.3V, 910 Hz, 2.7–97.1% duty cycle"
Not the same thing at all. I'm not sure exactly how that works (I've never seen a servo like that) but from the description I guess your options are to input the signal through a RC/filter circuit to convert it to a voltage or, probably more useful, to use pulsein() to read the pulse length of this signal.
Either way you can't really expect the example for a different type of feedback servo to just work.
slipstick:
But the servo specification clearly says that feedback is via PWM signal.
"Feedback sensor: Hall effect
Feedback signal: PWM, 3.3V, 910 Hz, 2.7–97.1% duty cycle"
probably more useful, to use pulsein() to read the pulse length of this signal.
Thanks again Steve, that was the solution and why it did not work with the analogread.
With a simple pulsein() it works flawlessly! You get clear numbers ranging to 1051
From this point now it is easy to get it working like intended
Hi Naru (and everyone) im a having a similar problem with reading the PWM values correctly and determining angular position. I've followed the datasheet parallax has given to a T. But my problem is that for some inexplicable reason, i am missing ~40 degrees?
Naru have you had a similar issue?
It must be something to do with the hall effect sensor, as on the serial plotter, you can see an immediate change of PWM value.
The image shown here is me twiddling ever so gently around the threshold. Now the output values should be 0 to 100 (0 to 1 but magnified to 100 to show you). however its not really ever reaching 0 or 100.
im actually missing around the first and last 3% (~6% total) of my duty cycle. This should sound about right as the dutycycle minimum is 2.9% and duty cycle max is 97.1%.
//datasheet
but following their example of angular position, im missing around 40 degrees. Im fair new to this scene, im in my third year at uni and my third year project depends on getting this RIGHT.
Can any one enlightening me what im doing wrong?
i kinda need those missing 40 degrees
(can link arduino code too, but this is my first forum post ever and i dont know how to embed it properly for you guys)
I know this is an old thread, but I'm currently trying to do the same thing but am unsuccessful. I used the code in aldeba's post but it seems to cause a problem that interrupts the code when I use it. I've read the documentation from Parallax, and basically converted the C code there to Arduino, but I'm still having issues. Has anyone managed to get this to work well?
/*
Feedback 360 Angle Control [Low Level Example].c
This is a simplified example of how the low-level position control is done.
These features would normally be tucked away in a library like abdrive360
or servo360 with functions to request measured angle, set target angle,
and etc.
*/
// Library inlcudes
#include "simpletools.h" // For pulse_in, print, scan etc...
#include "servo.h" // For servo pulse control
int pinFeedback = 14; // P14 connected to feedback line
int pinControl = 12; // P12 connected to control line
volatile int angle, targetAngle; // Global shared variables
volatile int Kp = 1; // Proportional constant
void feedback360(); // Position monitoring
void control360(); // Position control
int main() // Main function
{
cog_run(feedback360, 128); // Run feedback360 in a cog
cog_run(control360, 128); // Run control360 in a cog
pause(100); // Wait 1/10 s, might not need
while(1) // Main loop
{
print("Enter angle: "); // Prompt user for angle
scan("%d", &targetAngle); // Get entered angle
print("\r"); // Next line
while(abs(targetAngle - angle) > 4) // Display until close to finish
{
print("targetAngle = %d, angle = %d\r", // Display target & measured
targetAngle, angle);
pause(50); // ...every 50 ms
}
}
}
void feedback360() // Cog keeps angle variable updated
{
int unitsFC = 360; // Units in a full circle
int dutyScale = 1000; // Scale duty cycle to 1/1000ths
int dcMin = 29; // Minimum duty cycle
int dcMax = 971; // Maximum duty cycle
int q2min = unitsFC/4; // For checking if in 1st quadrant
int q3max = q2min * 3; // For checking if in 4th quadrant
int turns = 0; // For tracking turns
// dc is duty cycle, theta is 0 to 359 angle, thetaP is theta from previous
// loop repetition, tHigh and tLow are the high and low signal times for
// duty cycle calculations.
int dc, theta, thetaP, tHigh, tLow;
// Measure feedback signal high/low times.
tLow = pulse_in(pinFeedback, 0); // Measure low time
tHigh = pulse_in(pinFeedback, 1); // Measure high time
// Calcualte initial duty cycle and angle.
dc = (dutyScale * tHigh) / (tHigh + tLow);
theta = (unitsFC - 1) - ((dc - dcMin) * unitsFC) / (dcMax - dcMin + 1);
thetaP = theta;
while(1) // Main loop for this cog
{
// Measure high and low times, making sure to only take valid cycle
// times (a high and a low on opposite sides of the 0/359 boundary
// will not be valid.
int tCycle = 0; // Clear cycle time
while(1) // Keep checking
{
tHigh = pulse_in(pinFeedback, 1); // Measure time high
tLow = pulse_in(pinFeedback, 0); // Measure time low
tCycle = tHigh + tLow;
if((tCycle > 1000) && (tCycle < 1200)) // If cycle time valid
break; // break from loop
}
dc = (dutyScale * tHigh) / tCycle; // Calculate duty cycle
// This gives a theta increasing int the
// counterclockwise direction.
theta = (unitsFC - 1) - // Calculate angle
((dc - dcMin) * unitsFC)
/ (dcMax - dcMin + 1);
if(theta < 0) // Keep theta valid
theta = 0;
else if(theta > (unitsFC - 1))
theta = unitsFC - 1;
// If transition from quadrant 4 to
// quadrant 1, increase turns count.
if((theta < q2min) && (thetaP > q3max))
turns++;
// If transition from quadrant 1 to
// quadrant 4, decrease turns count.
else if((thetaP < q2min) && (theta > q3max))
turns --;
// Construct the angle measurement from the turns count and
// current theta value.
if(turns >= 0)
angle = (turns * unitsFC) + theta;
else if(turns < 0)
angle = ((turns + 1) * unitsFC) - (unitsFC - theta);
thetaP = theta; // Theta previous for next rep
}
}
// Most rudimentary control system example,
// just proportional. This could be done
// in the same cog as the angle mesurement.
void control360() // Cog for control system
{
servo_speed(pinControl, 0); // Start servo control cog
int errorAngle, output, offset; // Control system variables
while(1) // Main loop for this cog
{
errorAngle = targetAngle - angle; // Calculate error
output = errorAngle * Kp; // Calculate proportional
if(output > 200) output = 200; // Clamp output
if(output < -200) output = -200;
if(errorAngle > 0) // Add offset
offset = 30;
else if(errorAngle < 0)
offset = -30;
else
offset = 0;
servo_speed(pinControl, output + offset); // Set output
pause(20); // Repeat after 20 ms
}
}