1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-11-25 00:56:13 +01:00

Compare commits

...

3 Commits

Author SHA1 Message Date
Harald Barth
cade89ba16 check ADCee::init() return value 2023-06-18 09:48:15 +02:00
Harald Barth
277825c530 versiontag 2023-06-18 09:01:32 +02:00
Harald Barth
95fe7aafe0 overload detection code cleanup 2023-06-18 08:59:37 +02:00
3 changed files with 58 additions and 35 deletions

View File

@ -1 +1 @@
#define GITHUB_SHA "devel-202306142056Z" #define GITHUB_SHA "devel-202306180700Z"

View File

@ -108,8 +108,13 @@ MotorDriver::MotorDriver(int16_t power_pin, byte signal_pin, byte signal_pin2, i
} }
currentPin=current_pin; currentPin=current_pin;
if (currentPin!=UNUSED_PIN) if (currentPin!=UNUSED_PIN) {
ADCee::init(currentPin); int ret = ADCee::init(currentPin);
if (ret < -1010) { // XXX give value a name later
DIAG(F("ADCee::init error %d, disable current pin %d"), ret, currentPin);
currentPin = UNUSED_PIN;
}
}
senseOffset=0; // value can not be obtained until waveform is activated senseOffset=0; // value can not be obtained until waveform is activated
if (fault_pin != UNUSED_PIN) { if (fault_pin != UNUSED_PIN) {
@ -369,12 +374,13 @@ void MotorDriver::checkPowerOverload(bool useProgLimit, byte trackno) {
switch (powerMode) { switch (powerMode) {
case POWERMODE::OFF: case POWERMODE::OFF:
if (overloadNow) { if (overloadNow) {
// reset overload condition as we have just turned off power
// DIAG(F("OVERLOAD POFF OFF"));
overloadNow=false; overloadNow=false;
lastPowerChange = micros(); lastPowerChange = micros();
DIAG(F("OVERLOAD POFF OFF"));
} }
if (microsSinceLastPowerChange() > 5000000UL) { if (microsSinceLastPowerChange() > POWER_SAMPLE_ALL_GOOD) {
power_sample_overload_wait = 100UL; power_sample_overload_wait = POWER_SAMPLE_OVERLOAD_WAIT;
} }
break; break;
case POWERMODE::ON: case POWERMODE::ON:
@ -383,9 +389,10 @@ void MotorDriver::checkPowerOverload(bool useProgLimit, byte trackno) {
if (lastCurrent < 0) { if (lastCurrent < 0) {
// We have a fault pin condition to take care of // We have a fault pin condition to take care of
if (!overloadNow) { if (!overloadNow) {
// turn on overload condition as fault pin has gone active
// DIAG(F("OVERLOAD FPIN ON"));
overloadNow=true; overloadNow=true;
lastPowerChange = micros(); lastPowerChange = micros();
DIAG(F("OVERLOAD FPIN ON"));
} }
lastCurrent = -lastCurrent; lastCurrent = -lastCurrent;
if (commonFaultPin) { if (commonFaultPin) {
@ -398,73 +405,80 @@ void MotorDriver::checkPowerOverload(bool useProgLimit, byte trackno) {
DIAG(F("COMMON FAULT PIN ACTIVE: POWERTOGGLE TRACK %c"), trackno + 'A'); DIAG(F("COMMON FAULT PIN ACTIVE: POWERTOGGLE TRACK %c"), trackno + 'A');
} }
} else { } else {
unsigned long us;
if (lastCurrent < tripValue) { if (lastCurrent < tripValue) {
if (power_sample_overload_wait <= 1000UL && // almost virgin if (power_sample_overload_wait <= (POWER_SAMPLE_OVERLOAD_WAIT * 10) && // almost virgin
(us = microsSinceLastPowerChange()) < 50000UL) { // Ignore 50ms fault pin if no current microsSinceLastPowerChange() < POWER_SAMPLE_IGNORE_FAULT_LOW) {
DIAG(F("TRACK %c FAULT PIN ACTIVE - 50ms ignore %lus"), trackno + 'A', us); // Ignore 50ms fault pin if no current
DIAG(F("TRACK %c FAULT PIN 50ms ignore"), trackno + 'A');
break; break;
} }
lastCurrent = tripValue; // exaggerate lastCurrent = tripValue; // exaggerate so condition below (*) is true
} else { } else {
if (power_sample_overload_wait <= 100UL && // virgin if (power_sample_overload_wait <= POWER_SAMPLE_OVERLOAD_WAIT && // virgin
microsSinceLastPowerChange() < 5000UL) { // Ignore 5ms fault pin if we see current microsSinceLastPowerChange() < POWER_SAMPLE_IGNORE_FAULT_HIGH) {
DIAG(F("TRACK %c FAULT PIN ACTIVE - 5ms ignore"), trackno + 'A'); // Ignore 5ms fault pin if we see current
DIAG(F("TRACK %c FAULT PIN 5ms ignore"), trackno + 'A');
break; break;
} }
} }
DIAG(F("TRACK %c FAULT PIN ACTIVE - for real"), trackno + 'A'); DIAG(F("TRACK %c FAULT PIN ACTIVE"), trackno + 'A');
} }
} }
// // // // // //
if (lastCurrent < tripValue) { // above we looked at fault pin, below we look at current
// // //
if (lastCurrent < tripValue) { // see above (*)
if (overloadNow) { if (overloadNow) {
// current is below trip value, turn off overload condition
// DIAG(F("OVERLOAD PON OFF"));
overloadNow=false; overloadNow=false;
lastPowerChange = micros(); lastPowerChange = micros();
DIAG(F("OVERLOAD PON OFF"));
} }
if (microsSinceLastPowerChange() > 5000000UL) { if (microsSinceLastPowerChange() > POWER_SAMPLE_ALL_GOOD) {
power_sample_overload_wait = 100UL; power_sample_overload_wait = POWER_SAMPLE_OVERLOAD_WAIT;
} }
} else { } else {
// too much current // too much current
if (!overloadNow) { if (!overloadNow) {
// current is over trip value, turn on overload condition
// DIAG(F("OVERLOAD PON ON"));
overloadNow=true; overloadNow=true;
lastPowerChange = micros(); lastPowerChange = micros();
DIAG(F("OVERLOAD PON ON"));
} }
unsigned long us = microsSinceLastPowerChange(); unsigned long uSecs = microsSinceLastPowerChange();
if (power_sample_overload_wait > 100UL || // not virgin if (power_sample_overload_wait > POWER_SAMPLE_OVERLOAD_WAIT || // not virgin
us > 10000UL) { // Longer than 10ms uSecs > POWER_SAMPLE_OFF_DELAY) {
// Overload has existed longer than delay (typ. 10ms)
setPower(POWERMODE::OVERLOAD); setPower(POWERMODE::OVERLOAD);
// the setPower just turned off, so overload is now gone
if (overloadNow) { if (overloadNow) {
// the setPower just turned off, so overload is now gone
// DIAG(F("OVERLOAD PON OFF"));
overloadNow=false; overloadNow=false;
lastPowerChange = micros(); lastPowerChange = micros();
DIAG(F("OVERLOAD PON OFF"));
} }
unsigned int mA=raw2mA(lastCurrent); unsigned int mA=raw2mA(lastCurrent);
unsigned int maxmA=raw2mA(tripValue); unsigned int maxmA=raw2mA(tripValue);
DIAG(F("TRACK %c POWER OVERLOAD %dmA (limit %dmA) shutdown after %lus for %lus"), DIAG(F("TRACK %c POWER OVERLOAD %dmA (limit %dmA) shutdown after %lus for %lus"),
trackno + 'A', mA, maxmA, us, power_sample_overload_wait); trackno + 'A', mA, maxmA, uSecs, power_sample_overload_wait);
} }
} }
break; break;
case POWERMODE::OVERLOAD: case POWERMODE::OVERLOAD:
if (overloadNow) { if (overloadNow) {
// state overload mode means power is off, turn off overload condition flag as well
// DIAG(F("OVERLOAD POVER OFF"));
overloadNow=false; overloadNow=false;
lastPowerChange = micros(); lastPowerChange = micros();
DIAG(F("OVERLOAD POVER OFF"));
} }
// Try setting it back on after the OVERLOAD_WAIT // Try setting it back on after the OVERLOAD_WAIT
if (microsSinceLastPowerChange() > power_sample_overload_wait) { if (microsSinceLastPowerChange() > power_sample_overload_wait) {
// adjust next wait time // adjust next wait time
power_sample_overload_wait *= 2; power_sample_overload_wait *= 2;
if (power_sample_overload_wait > 10000000UL) if (power_sample_overload_wait > POWER_SAMPLE_RETRY_MAX)
power_sample_overload_wait = 10000000UL; power_sample_overload_wait = POWER_SAMPLE_RETRY_MAX;
// power on test // power on test
setPower(POWERMODE::ON); setPower(POWERMODE::ON);
DIAG(F("TRACK %c POWER RESTORE (check %lus)"), trackno + 'A', power_sample_overload_wait); DIAG(F("TRACK %c POWER RESTORE (was off %lus)"), trackno + 'A', power_sample_overload_wait);
} }
break; break;
default: default:

View File

@ -237,10 +237,19 @@ class MotorDriver {
int maxmA; int maxmA;
int tripmA; int tripmA;
// Wait times for power management. Unit: milliseconds // Times for overload management. Unit: microseconds.
static const int POWER_SAMPLE_ON_WAIT = 1; // Base for wait time until power is turned on again
static const int POWER_SAMPLE_OFF_WAIT = 100; static const unsigned long POWER_SAMPLE_OVERLOAD_WAIT = 100UL;
static const int POWER_SAMPLE_OVERLOAD_WAIT = 500UL; // Time after we consider all faults old and forgotten
static const unsigned long POWER_SAMPLE_ALL_GOOD = 5000000UL;
// How long to ignore fault pin if current is under limit
static const unsigned long POWER_SAMPLE_IGNORE_FAULT_LOW = 50000UL;
// How long to ignore fault pin if current is higher than limit
static const unsigned long POWER_SAMPLE_IGNORE_FAULT_HIGH = 5000UL;
// How long to wait between overcurrent and turning off
static const unsigned long POWER_SAMPLE_OFF_DELAY = 10000UL;
// Upper limit for retry period
static const unsigned long POWER_SAMPLE_RETRY_MAX = 10000000UL;
// Trip current for programming track, 250mA. Change only if you really // Trip current for programming track, 250mA. Change only if you really
// need to be non-NMRA-compliant because of decoders that are not either. // need to be non-NMRA-compliant because of decoders that are not either.