Files

86 lines
2.9 KiB
C++
Raw Permalink Normal View History

2025-12-14 15:02:55 +01:00
#include "AdafruitServoMotor.hpp"
#include "StateMachine.hpp"
2025-12-14 18:57:28 +01:00
#include "defs.hpp"
2025-12-14 15:02:55 +01:00
// Motor hardware angle must be at least changed by that much before
// the motion is commited to the motor (prevent motor rattle)
2025-12-14 18:57:28 +01:00
constexpr float MIN_DELTA_FOR_MOTION_COMMIT = 0.01f;
2025-12-14 15:02:55 +01:00
AdafruitServoMotor::AdafruitServoMotor(
AdafruitPWMBoard& driver,
const uint8_t motorIndex,
const float gearboxRatio,
const float scaleCalibration,
const float zeroOffset,
const float minSafeAngle,
const float maxSafeAngle,
const float specRangeDeg,
2025-12-14 18:57:28 +01:00
const float initialPosition,
2025-12-14 15:02:55 +01:00
const uint16_t minPulseLength,
2025-12-14 18:57:28 +01:00
const uint16_t maxPulseLength
2025-12-14 15:02:55 +01:00
) noexcept:
driver(driver),
motorIndex(motorIndex),
RangedMotor(
gearboxRatio,
scaleCalibration,
zeroOffset,
minSafeAngle,
maxSafeAngle
),
currentHardwarePosition (virtualAngleToHardwareAngle(initialPosition)),
lastCommittedHardwarePosition(virtualAngleToHardwareAngle(initialPosition)),
specRangeDeg(specRangeDeg),
minPulseLength(minPulseLength),
maxPulseLength(maxPulseLength)
{
if (motorIndex >= 16) {
StateMachine::getInstance().raiseError("Servo motor index out of range for adafruit pwm board!");
}
if (!driver.isGood()) {
StateMachine::getInstance().raiseError("Servo motor received offline driver board!");
}
if (!driver.occupyMotorSlot(motorIndex)) {
StateMachine::getInstance().raiseError("Servo motor index already occupied for adafruit pwm board!");
}
}
bool AdafruitServoMotor::moveTo(const float target) noexcept
{
if (!driver.isGood()) {
StateMachine::getInstance().raiseError("Servo motor driver board gone offline!");
}
2025-12-14 18:57:28 +01:00
const float hardwareTarget = virtualAngleToHardwareAngle(target);
currentHardwarePosition = constrain(hardwareTarget, safeHardwareMinAngle, safeHardwareMaxAngle);
// Only move the motor if it would turn it at least n degrees
if (abs(lastCommittedHardwarePosition - currentHardwarePosition) >= MIN_DELTA_FOR_MOTION_COMMIT) {
commitMoveImmediately();
}
2025-12-14 15:02:55 +01:00
2025-12-14 18:57:28 +01:00
// True if they are the same, e.g. no clamping was applied
return (abs(currentHardwarePosition - hardwareTarget) < COMP_EPSILON);
2025-12-14 15:02:55 +01:00
}
void AdafruitServoMotor::commitMoveImmediately() noexcept
{
2025-12-14 18:57:28 +01:00
if (!driver.isGood()) {
StateMachine::getInstance().raiseError("Servo motor driver board gone offline!");
}
2025-12-14 15:02:55 +01:00
driver.get().setPWM(motorIndex, 0, hardwareAngleToPulse(currentHardwarePosition));
lastCommittedHardwarePosition = currentHardwarePosition;
return false;
}
uint16_t AdafruitServoMotor::hardwareAngleToPulse(const float hardwareAngle) const noexcept
{
2025-12-14 18:57:28 +01:00
const float t = hardwareAngle / specRangeDeg;
const uint16_t pulse = minPulseLength + t * (maxPulseLength - minPulseLength);
return pulse;
2025-12-14 15:02:55 +01:00
}