Closed EAGrahamJr closed 1 year ago
import com.diozero.api.ServoDevice;
import com.diozero.api.ServoTrim;
import com.diozero.devices.PCA9685;
/**
* This is weird...
*/
public class ServoAdvance {
public static void main(String[] args) throws Exception {
try (PCA9685 servoController = new PCA9685()) {
ServoDevice servo = new ServoDevice.Builder(0)
// does not work
// .setTrim(ServoTrim.TOWERPRO_SG90)
// .setTrim(newServoTrim(1500,901))
// .setTrim(newServoTrim(1450,901))
// works
// .setTrim(ServoTrim.DEFAULT)
.setTrim(new ServoTrim(1450, 900))
.setFrequency(servoController.getBoardPwmFrequency())
.setDeviceFactory(servoController)
.build();
servo.setAngle(0f);
Thread.sleep(1000);
System.out.println("Starting sweep");
for (int i = 0; i <= 180; i++) {
boolean done = false;
float current = 0f;
for (int j = 0; j < 5; j++) {
servo.setAngle(i);
Thread.sleep(5);
current = servo.getAngle();
done = servo.getAngle() == i;
if (done) break;
}
if (!done) {
System.out.printf("Failed to set angle %d - current is %.02f%n", i, current);
}
}
System.out.println("Sweep complete - rolling back");
for (int i = 180; i >= 0; i--) {
servo.setAngle(i);
Thread.sleep(5);
}
System.out.println("Rollback complete");
}
}
}
Must be rounding errors - it would be interesting to see what servo.getAngle()
returned, I assume it is one out.
Yep, one off:
Failed to set angle 35 - current is 34.00
Failed to set angle 53 - current is 52.00
Failed to set angle 78 - current is 77.00
Failed to set angle 96 - current is 95.00
Failed to set angle 134 - current is 133.00
Failed to set angle 152 - current is 151.00
Failed to set angle 177 - current is 176.00
Note that I do not get this when using straight GPIO or a different MCU, so it's likely isolated to this board?
I compared the set values from the Adafruit CircuitPython code and it does look like there is a rounding issue.
34 --> 33.54952640873334
35 --> 34.93658693209183
36 --> 35.86129394766415
The aforementioned PR didn't quite get it fixed. There's still a few misses.
Basically, when using a servo that's not using the default trim, there are certain angles the servo will not rotate to.
This is pretty weird, so I'm going to also attach the code to reproduce. The output is pretty explanatory: the code rotates the servo through all 180 degrees. If a certain angle cannot be "set" after 5 tries, the "failed" angle is output.
System: Raspberry Pi 3B+, I2C speed=400000, using the SparkFun 'hat (same chip)
This reproduces for any value of the trim where the
delta_us
is > 900 (the angles "not hit" differ based on how the delta changes).