diff --git a/IODevice.h b/IODevice.h index 673a9d2..65f5d35 100644 --- a/IODevice.h +++ b/IODevice.h @@ -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]; diff --git a/IO_PCA9685.cpp b/IO_PCA9685.cpp index aaa56ea..ddc45d8 100644 --- a/IO_PCA9685.cpp +++ b/IO_PCA9685.cpp @@ -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) } diff --git a/Turnouts.cpp b/Turnouts.cpp index 9170fa8..41b6b39 100644 --- a/Turnouts.cpp +++ b/Turnouts.cpp @@ -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);