1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-12-23 21:01:25 +01:00

Make defaults for PWM (servo) positions 0 (PWM off) if not configured.

When writing to a PWM device (servo or LED for example), it is possible to request the target position in the call, or to ask for a SET or RESET position.  In the latter case, the positions corresponding to SET and RESET must be known, i.e. preconfigured.  Defaults were assigned for this, but because the correct values will depend on the hardware device being driven, the defaults have been removed.
In addition, the <T> command, when defining a servo turnout, now configures the PWM positions (not required by <T> commands, but desirable for consistency with other commands).
This commit is contained in:
Neil McKechnie 2021-08-29 12:04:13 +01:00
parent 09eae0ea91
commit 1bb7b5cc77
3 changed files with 20 additions and 23 deletions

View File

@ -120,9 +120,9 @@ public:
}
// User-friendly function for configuring a servo pin.
inline static bool configureServo(VPIN vpin, uint16_t activePosition, uint16_t inactivePosition, uint8_t profile, uint8_t initialState=0) {
int params[] = {(int)activePosition, (int)inactivePosition, profile, initialState};
return IODevice::configure(vpin, CONFIGURE_SERVO, 4, params);
inline static bool configureServo(VPIN vpin, uint16_t activePosition, uint16_t inactivePosition, uint8_t profile, uint16_t duration, uint8_t initialState=0) {
int params[] = {(int)activePosition, (int)inactivePosition, profile, (int)duration, initialState};
return IODevice::configure(vpin, CONFIGURE_SERVO, 5, params);
}
// write invokes the IODevice instance's _write method.
@ -285,13 +285,11 @@ private:
uint16_t stepNumber; // Index of current step (starting from 0)
uint16_t numSteps; // Number of steps in animation, or 0 if none in progress.
uint8_t currentProfile; // profile being used for current animation.
uint16_t duration; // time (tenths of a second) for animation to complete.
}; // 14 bytes per element, i.e. per pin in use
struct ServoData *_servoData [16];
static const uint16_t _defaultActivePosition = 410;
static const uint16_t _defaultInactivePosition = 205;
static const uint8_t _catchupSteps = 5; // number of steps to wait before switching servo off
static const byte FLASH _bounceProfile[30];

View File

@ -45,10 +45,10 @@ void PCA9685::create(VPIN firstVpin, int nPins, uint8_t I2CAddress) {
// Configure a port on the PCA9685.
bool PCA9685::_configure(VPIN vpin, ConfigTypeEnum configType, int paramCount, int params[]) {
if (configType != CONFIGURE_SERVO) return false;
if (paramCount != 4) return false;
if (paramCount != 5) return false;
#ifdef DIAG_IO
DIAG(F("PCA9685 Configure VPIN:%d Apos:%d Ipos:%d Profile:%d state:%d"),
vpin, params[0], params[1], params[2], params[3]);
DIAG(F("PCA9685 Configure VPIN:%d Apos:%d Ipos:%d Profile:%d Duration:%d state:%d"),
vpin, params[0], params[1], params[2], params[3], params[4]);
#endif
int8_t pin = vpin - _firstVpin;
@ -62,12 +62,13 @@ bool PCA9685::_configure(VPIN vpin, ConfigTypeEnum configType, int paramCount, i
s->activePosition = params[0];
s->inactivePosition = params[1];
s->profile = params[2];
int state = params[3];
s->duration = params[3];
int state = params[4];
if (state != -1) {
// Position servo to initial state
_writeAnalogue(vpin, state ? s->activePosition : s->inactivePosition, 0, 0);
}
return true;
}
@ -119,13 +120,10 @@ void PCA9685::_write(VPIN vpin, int value) {
if (value) value = 1;
struct ServoData *s = _servoData[pin];
if (s == NULL) {
// Pin not configured, just write default positions to servo controller
writeDevice(pin, value ? _defaultActivePosition : _defaultInactivePosition);
} else {
// Use configured parameters for advanced transitions
_writeAnalogue(vpin, value ? s->activePosition : s->inactivePosition, s->profile, 0);
}
if (s != NULL) {
// Use configured parameters
_writeAnalogue(vpin, value ? s->activePosition : s->inactivePosition, s->profile, s->duration);
} // else { /* ignorethe request */ }
}
// Device-specific writeAnalogue function, invoked from IODevice::writeAnalogue().
@ -152,8 +150,8 @@ void PCA9685::_writeAnalogue(VPIN vpin, int value, uint8_t profile, uint16_t dur
// Servo pin not configured, so configure now using defaults
s = _servoData[pin] = (struct ServoData *) calloc(sizeof(struct ServoData), 1);
if (s == NULL) return; // Check for memory allocation failure
s->activePosition = _defaultActivePosition;
s->inactivePosition = _defaultInactivePosition;
s->activePosition = 0;
s->inactivePosition = 0;
s->currentPosition = value;
s->profile = Instant; // Use instant profile (but not this time)
}

View File

@ -249,9 +249,10 @@
// Don't touch the _closed parameter, retain the original value.
// We don't really need to do the following, since a call to IODevice::_writeAnalogue
// will provide all the data that is required!
// int params[] = {(int)thrownPosition, (int)closedPosition, profile, closed};
// IODevice::configure(vpin, IODevice::CONFIGURE_SERVO, 4, params);
// will provide all the data that is required! However, if someone has configured
// a Turnout, we should ensure that the SET() RESET() and other commands that use write()
// behave consistently with the turnout commands.
IODevice::configureServo(vpin, thrownPosition, closedPosition, profile, 0, closed);
// Set position directly to specified position - we don't know where it is moving from.
IODevice::writeAnalogue(vpin, closed ? closedPosition : thrownPosition, PCA9685::Instant);