Hello, I'm new here. I have a short history working with Arduino in a case by case basis with good results, but I have a question on this application.
I'm building a controller and have a Nano Every running a Parallax Feedback 360 Servo. I have a inbound 12v square wave signal (that I have running through a 10k/22k voltage divider, so actual input to the Arduino is a fixed 3.8V with a varying frequency.)
The code for that is operating well and tested out great with a regular normal servo, the problem is that, as this is for a gauge cluster, I need about a 350 degree sweep, so that's why I went with the feedback 360.
I'm powering the servo with my 12v in rail cut down to 6v with a 7806, and the servo functions great in continuous rotation with the current setup.
My current problem stems from the code for this particular servo. There seems to be a few attempts at making this work, but none that worked well for me. I actually found a library dedicated for it, but It's built on the wrong chipset.
Here's the code that is copied from an older post here (thanks @JavelinPoint!), although I can't seem to get it to work with some test movements. Ideally I'd like to see this test code turn the servo to a 30, 60, 180 and like a 270 degree angle before I go any further with it. I have my signal out hooked to pin 9, and my "feedback" connected to A0 (pin 14). At this point I'm having compiling errors, so I'm not sure.
Thanks in advance!
#include <Servo.h> //Servo library
//PID angle control for Parallax 360 Servo
Servo servo_test; //initialize a servo object for the connected servo
int pinFeedback = A0;
int target_angle = 180;
float tHigh = 0;
float tLow = 0;
int tCycle = 0;
float dc = 0;
float angle = 0; //Measured angle from feedback
float dcMin = 2.9; //From Parallax spec sheet
float dcMax = 97.1; //From Parallax spec sheet
float Kp = .7; //Proportional Gain, higher values for faster response, higher values contribute to overshoot.
float Ki = .2; //Integral Gain, higher values to converge faster to zero error, higher values produce oscillations. Higher values are more unstable near a target_angle = 0.
float iLimit = 5; //Arbitrary Anti-wind-up
float Kd = 1; //Derivative Gain, higher values dampen oscillations around target_angle. Higher values produce more holding state jitter. May need filter for error noise.
float prev_error = 0;
float prev_pError = 0;
float error = 0;
float pError = 0;
float iError = 0;
void setup()
{
servo_test.attach(9); // attach the signal pin of servo to pin9 of arduino
pinMode(A0, INPUT);
}
void loop()
{
//use line below to determine "center" of servo. When near values of 90, manually force servo by hand in both directions to see if it continues to turn.
//servo_test.write(85); //clockwise: max 0 - 90 min, counter-clockwise: min 96-180 max, may be different for your servo, 93 stopped.
while(1) //From Parallax spec sheet
{
tHigh = pulseIn(pinFeedback, HIGH);
tLow = pulseIn(pinFeedback, LOW);
tCycle = tHigh + tLow;
if ( tCycle > 1000 && tCycle < 1200)
{
break; //valid tCycle;
}
}
dc = (100 * tHigh) / tCycle; //From Parallax spec sheet, you are trying to determine the percentage of the HIGH in the pulse
angle = ((dc - dcMin) * 360) / (dcMax - dcMin + 1); //From Parallax spec sheet
//Keep measured angles within bounds
if (angle < 0)
{
angle = 0;
}
else if(angle > 359)
{
angle = 359;
}
if (target_angle < 0)
{
target_angle = 360 + target_angle; //handles negative target_angles;
}
error = target_angle - angle;
if(error > 180)
{
error = error - 360; //tells it to rotate in the other direction because it is a smaller angle that way.
}
if (error < -180)
{
error = 360 - error - 360; //tells it to rotate in the other direction because it is a smaller angle that way.
}
// PID controller stuff, Adjust values of Kp, Ki, and Kd above to tune your system
float pError = Kp * error;
float iError = Ki * (error + prev_error);
if (iError > iLimit)
{
iError = iLimit;
}
if (iError < -iLimit)
{
iError = -iLimit;
}
prev_error = error;
float dError = Kd * (pError - prev_pError);
prev_pError = pError;
error = error / 2; //max 180 error will have max 90 offset value
int val = 93 - (Kp * error) - iError - dError; // 93 is the middle of my servo's "no motion" dead-band
servo_test.write(val); //Move the servo
void loop() {
for (val = 0; val <= 30; val += 1) {
servo_test.write(val);
delay(100);
}
for (val = 30; val >= 60; val -= 1) {
servo_test.write(val);
delay(100);
}
}
}