mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-12-23 04:41:24 +01:00
Merge branch 'devel-overcurrent' into devel
This commit is contained in:
commit
2f65d4347e
@ -1 +1 @@
|
||||
#define GITHUB_SHA "devel-202306182208Z"
|
||||
#define GITHUB_SHA "devel-202306190642Z"
|
||||
|
153
MotorDriver.cpp
153
MotorDriver.cpp
@ -159,11 +159,7 @@ MotorDriver::MotorDriver(int16_t power_pin, byte signal_pin, byte signal_pin2, i
|
||||
// senseFactorInternal, raw2mA(1000),mA2raw(1000));
|
||||
}
|
||||
|
||||
// prepare values for current detection
|
||||
sampleDelay = 0;
|
||||
lastSampleTaken = millis();
|
||||
progTripValue = mA2raw(TRIP_CURRENT_PROG);
|
||||
|
||||
}
|
||||
|
||||
bool MotorDriver::isPWMCapable() {
|
||||
@ -172,6 +168,7 @@ bool MotorDriver::isPWMCapable() {
|
||||
|
||||
|
||||
void MotorDriver::setPower(POWERMODE mode) {
|
||||
if (powerMode == mode) return;
|
||||
bool on=mode==POWERMODE::ON;
|
||||
if (on) {
|
||||
// when switching a track On, we need to check the crrentOffset with the pin OFF
|
||||
@ -372,63 +369,123 @@ void MotorDriver::getFastPin(const FSH* type,int pin, bool input, FASTPIN & res
|
||||
}
|
||||
|
||||
void MotorDriver::checkPowerOverload(bool useProgLimit, byte trackno) {
|
||||
if (millis() - lastSampleTaken < sampleDelay) return;
|
||||
lastSampleTaken = millis();
|
||||
int tripValue= useProgLimit?progTripValue:getRawCurrentTripValue();
|
||||
|
||||
// Trackname for diag messages later
|
||||
|
||||
switch (powerMode) {
|
||||
case POWERMODE::OFF:
|
||||
sampleDelay = POWER_SAMPLE_OFF_WAIT;
|
||||
if (overloadNow) {
|
||||
// reset overload condition as we have just turned off power
|
||||
// DIAG(F("OVERLOAD POFF OFF"));
|
||||
overloadNow=false;
|
||||
lastPowerChange = micros();
|
||||
}
|
||||
if (microsSinceLastPowerChange() > POWER_SAMPLE_ALL_GOOD) {
|
||||
power_sample_overload_wait = POWER_SAMPLE_OVERLOAD_WAIT;
|
||||
}
|
||||
break;
|
||||
case POWERMODE::ON:
|
||||
// Check current
|
||||
lastCurrent=getCurrentRaw();
|
||||
if (lastCurrent < 0) {
|
||||
// We have a fault pin condition to take care of
|
||||
lastCurrent = -lastCurrent;
|
||||
setPower(POWERMODE::OVERLOAD); // Turn off, decide later how fast to turn on again
|
||||
if (commonFaultPin) {
|
||||
if (lastCurrent < tripValue) {
|
||||
setPower(POWERMODE::ON); // maybe other track
|
||||
}
|
||||
// Write this after the fact as we want to turn on as fast as possible
|
||||
// because we don't know which output actually triggered the fault pin
|
||||
DIAG(F("COMMON FAULT PIN ACTIVE: POWERTOGGLE TRACK %c"), trackno + 'A');
|
||||
} else {
|
||||
DIAG(F("TRACK %c FAULT PIN ACTIVE - OVERLOAD"), trackno + 'A');
|
||||
if (lastCurrent < tripValue) {
|
||||
lastCurrent = tripValue; // exaggerate
|
||||
}
|
||||
// We have a fault pin condition to take care of
|
||||
if (!overloadNow) {
|
||||
// turn on overload condition as fault pin has gone active
|
||||
// DIAG(F("OVERLOAD FPIN ON"));
|
||||
overloadNow=true;
|
||||
lastPowerChange = micros();
|
||||
}
|
||||
lastCurrent = -lastCurrent;
|
||||
if (commonFaultPin) {
|
||||
if (lastCurrent < tripValue) {
|
||||
// probably other track, do a fast toggle.
|
||||
setPower(POWERMODE::OVERLOAD); // Turn off, decide later how fast to turn on again
|
||||
setPower(POWERMODE::ON); // maybe other track
|
||||
// Write this after the fact as we want to turn on as fast as possible
|
||||
// because we don't know which output actually triggered the fault pin
|
||||
DIAG(F("COMMON FAULT PIN ACTIVE: POWERTOGGLE TRACK %c"), trackno + 'A');
|
||||
}
|
||||
} else {
|
||||
if (lastCurrent < tripValue) {
|
||||
if (power_sample_overload_wait <= (POWER_SAMPLE_OVERLOAD_WAIT * 10) && // almost virgin
|
||||
microsSinceLastPowerChange() < POWER_SAMPLE_IGNORE_FAULT_LOW) {
|
||||
// Ignore 50ms fault pin if no current
|
||||
DIAG(F("TRACK %c FAULT PIN 50ms ignore"), trackno + 'A');
|
||||
break;
|
||||
}
|
||||
lastCurrent = tripValue; // exaggerate so condition below (*) is true
|
||||
} else {
|
||||
if (power_sample_overload_wait <= POWER_SAMPLE_OVERLOAD_WAIT && // virgin
|
||||
microsSinceLastPowerChange() < POWER_SAMPLE_IGNORE_FAULT_HIGH) {
|
||||
// Ignore 5ms fault pin if we see current
|
||||
DIAG(F("TRACK %c FAULT PIN 5ms ignore"), trackno + 'A');
|
||||
break;
|
||||
}
|
||||
}
|
||||
DIAG(F("TRACK %c FAULT PIN ACTIVE"), trackno + 'A');
|
||||
}
|
||||
}
|
||||
if (lastCurrent < tripValue) {
|
||||
sampleDelay = POWER_SAMPLE_ON_WAIT;
|
||||
if(power_good_counter<100)
|
||||
power_good_counter++;
|
||||
else
|
||||
if (power_sample_overload_wait>POWER_SAMPLE_OVERLOAD_WAIT) power_sample_overload_wait=POWER_SAMPLE_OVERLOAD_WAIT;
|
||||
// // //
|
||||
// above we looked at fault pin, below we look at current
|
||||
// // //
|
||||
if (lastCurrent < tripValue) { // see above (*)
|
||||
if (overloadNow) {
|
||||
// current is below trip value, turn off overload condition
|
||||
// DIAG(F("OVERLOAD PON OFF"));
|
||||
overloadNow=false;
|
||||
lastPowerChange = micros();
|
||||
}
|
||||
if (microsSinceLastPowerChange() > POWER_SAMPLE_ALL_GOOD) {
|
||||
power_sample_overload_wait = POWER_SAMPLE_OVERLOAD_WAIT;
|
||||
}
|
||||
} else {
|
||||
setPower(POWERMODE::OVERLOAD);
|
||||
unsigned int mA=raw2mA(lastCurrent);
|
||||
unsigned int maxmA=raw2mA(tripValue);
|
||||
power_good_counter=0;
|
||||
sampleDelay = power_sample_overload_wait;
|
||||
DIAG(F("TRACK %c POWER OVERLOAD %dmA (limit %dmA) shutdown for %dms"), trackno + 'A', mA, maxmA, sampleDelay);
|
||||
if (power_sample_overload_wait >= 10000)
|
||||
power_sample_overload_wait = 10000;
|
||||
else
|
||||
power_sample_overload_wait *= 2;
|
||||
// too much current
|
||||
if (!overloadNow) {
|
||||
// current is over trip value, turn on overload condition
|
||||
// DIAG(F("OVERLOAD PON ON"));
|
||||
overloadNow=true;
|
||||
lastPowerChange = micros();
|
||||
}
|
||||
unsigned long uSecs = microsSinceLastPowerChange();
|
||||
if (power_sample_overload_wait > POWER_SAMPLE_OVERLOAD_WAIT || // not virgin
|
||||
uSecs > POWER_SAMPLE_OFF_DELAY) {
|
||||
// Overload has existed longer than delay (typ. 10ms)
|
||||
setPower(POWERMODE::OVERLOAD);
|
||||
if (overloadNow) {
|
||||
// the setPower just turned off, so overload is now gone
|
||||
// DIAG(F("OVERLOAD PON OFF"));
|
||||
overloadNow=false;
|
||||
lastPowerChange = micros();
|
||||
}
|
||||
unsigned int mA=raw2mA(lastCurrent);
|
||||
unsigned int maxmA=raw2mA(tripValue);
|
||||
DIAG(F("TRACK %c POWER OVERLOAD %dmA (limit %dmA) shutdown after %lus for %lus"),
|
||||
trackno + 'A', mA, maxmA, uSecs, power_sample_overload_wait);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case POWERMODE::OVERLOAD:
|
||||
// Try setting it back on after the OVERLOAD_WAIT
|
||||
case POWERMODE::OVERLOAD:
|
||||
if (overloadNow) {
|
||||
// state overload mode means power is off, turn off overload condition flag as well
|
||||
// DIAG(F("OVERLOAD POVER OFF"));
|
||||
overloadNow=false;
|
||||
lastPowerChange = micros();
|
||||
}
|
||||
// Try setting it back on after the OVERLOAD_WAIT
|
||||
if (microsSinceLastPowerChange() > power_sample_overload_wait) {
|
||||
// adjust next wait time
|
||||
power_sample_overload_wait *= 2;
|
||||
if (power_sample_overload_wait > POWER_SAMPLE_RETRY_MAX)
|
||||
power_sample_overload_wait = POWER_SAMPLE_RETRY_MAX;
|
||||
// power on test
|
||||
setPower(POWERMODE::ON);
|
||||
sampleDelay = POWER_SAMPLE_ON_WAIT;
|
||||
// Debug code....
|
||||
DIAG(F("TRACK %c POWER RESTORE (check %dms)"), trackno + 'A', sampleDelay);
|
||||
break;
|
||||
default:
|
||||
sampleDelay = 999; // cant get here..meaningless statement to avoid compiler warning.
|
||||
// here we change power but not the overloadNow as that was
|
||||
// already changed to false when we entered POWERMODE::OVERLOAD
|
||||
// so we need to set the lastPowerChange anyway.
|
||||
lastPowerChange = micros();
|
||||
DIAG(F("TRACK %c POWER RESTORE (was off %lus)"), trackno + 'A', power_sample_overload_wait);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -186,6 +186,16 @@ class MotorDriver {
|
||||
inline void setTrackLetter(char c) {
|
||||
trackLetter = c;
|
||||
};
|
||||
// this returns how much time has passed since the last power change. If it
|
||||
// was really long ago (approx > 52min) advance counter approx 35 min so that
|
||||
// we are at 18 minutes again. Times for 32 bit unsigned long.
|
||||
inline unsigned long microsSinceLastPowerChange() {
|
||||
unsigned long now = micros();
|
||||
unsigned long diff = now - lastPowerChange;
|
||||
if (diff > (1UL << (7 *sizeof(unsigned long)))) // 2^(4*7)us = 268.4 seconds
|
||||
lastPowerChange = now - 30000000UL; // 30 seconds ago
|
||||
return diff;
|
||||
};
|
||||
#ifdef ANALOG_READ_INTERRUPT
|
||||
bool sampleCurrentFromHW();
|
||||
void startCurrentFromHW();
|
||||
@ -217,8 +227,8 @@ class MotorDriver {
|
||||
int rawCurrentTripValue;
|
||||
// current sampling
|
||||
POWERMODE powerMode;
|
||||
unsigned long lastSampleTaken;
|
||||
unsigned int sampleDelay;
|
||||
bool overloadNow = false;
|
||||
unsigned long lastPowerChange; // timestamp in microseconds
|
||||
int progTripValue;
|
||||
int lastCurrent;
|
||||
#ifdef ANALOG_READ_INTERRUPT
|
||||
@ -228,10 +238,19 @@ class MotorDriver {
|
||||
int maxmA;
|
||||
int tripmA;
|
||||
|
||||
// Wait times for power management. Unit: milliseconds
|
||||
static const int POWER_SAMPLE_ON_WAIT = 100;
|
||||
static const int POWER_SAMPLE_OFF_WAIT = 1000;
|
||||
static const int POWER_SAMPLE_OVERLOAD_WAIT = 20;
|
||||
// Times for overload management. Unit: microseconds.
|
||||
// Base for wait time until power is turned on again
|
||||
static const unsigned long POWER_SAMPLE_OVERLOAD_WAIT = 100UL;
|
||||
// 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
|
||||
// need to be non-NMRA-compliant because of decoders that are not either.
|
||||
|
Loading…
Reference in New Issue
Block a user