mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-11-23 08:06:13 +01:00
new overload detection
This commit is contained in:
parent
8a69403dda
commit
f5d4dcb97c
|
@ -1 +1 @@
|
||||||
#define GITHUB_SHA "devel-202306031954Z"
|
#define GITHUB_SHA "devel-202306132257Z"
|
||||||
|
|
|
@ -154,11 +154,7 @@ MotorDriver::MotorDriver(int16_t power_pin, byte signal_pin, byte signal_pin2, i
|
||||||
// senseFactorInternal, raw2mA(1000),mA2raw(1000));
|
// senseFactorInternal, raw2mA(1000),mA2raw(1000));
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare values for current detection
|
|
||||||
sampleDelay = 0;
|
|
||||||
lastSampleTaken = millis();
|
|
||||||
progTripValue = mA2raw(TRIP_CURRENT_PROG);
|
progTripValue = mA2raw(TRIP_CURRENT_PROG);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MotorDriver::isPWMCapable() {
|
bool MotorDriver::isPWMCapable() {
|
||||||
|
@ -167,6 +163,7 @@ bool MotorDriver::isPWMCapable() {
|
||||||
|
|
||||||
|
|
||||||
void MotorDriver::setPower(POWERMODE mode) {
|
void MotorDriver::setPower(POWERMODE mode) {
|
||||||
|
if (powerMode == mode) return;
|
||||||
bool on=mode==POWERMODE::ON;
|
bool on=mode==POWERMODE::ON;
|
||||||
if (on) {
|
if (on) {
|
||||||
// when switching a track On, we need to check the crrentOffset with the pin OFF
|
// when switching a track On, we need to check the crrentOffset with the pin OFF
|
||||||
|
@ -367,14 +364,21 @@ void MotorDriver::getFastPin(const FSH* type,int pin, bool input, FASTPIN & res
|
||||||
}
|
}
|
||||||
|
|
||||||
void MotorDriver::checkPowerOverload(bool useProgLimit, byte trackno) {
|
void MotorDriver::checkPowerOverload(bool useProgLimit, byte trackno) {
|
||||||
if (millis() - lastSampleTaken < sampleDelay) return;
|
//if (millis() - lastSampleTaken < sampleDelay) return;
|
||||||
lastSampleTaken = millis();
|
//lastSampleTaken = millis();
|
||||||
int tripValue= useProgLimit?progTripValue:getRawCurrentTripValue();
|
int tripValue= useProgLimit?progTripValue:getRawCurrentTripValue();
|
||||||
|
|
||||||
// Trackname for diag messages later
|
// check if there was a change from last time
|
||||||
|
if (powerMode != oldPowerMode) {
|
||||||
|
lastPowerChange = micros();
|
||||||
|
oldPowerMode = powerMode;
|
||||||
|
}
|
||||||
|
|
||||||
switch (powerMode) {
|
switch (powerMode) {
|
||||||
case POWERMODE::OFF:
|
case POWERMODE::OFF:
|
||||||
sampleDelay = POWER_SAMPLE_OFF_WAIT;
|
if (microsSinceLastPowerChange() > 5000000UL) {
|
||||||
|
power_sample_overload_wait = 100UL;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case POWERMODE::ON:
|
case POWERMODE::ON:
|
||||||
// Check current
|
// Check current
|
||||||
|
@ -382,48 +386,64 @@ 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
|
||||||
lastCurrent = -lastCurrent;
|
lastCurrent = -lastCurrent;
|
||||||
setPower(POWERMODE::OVERLOAD); // Turn off, decide later how fast to turn on again
|
|
||||||
if (commonFaultPin) {
|
if (commonFaultPin) {
|
||||||
if (lastCurrent < tripValue) {
|
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
|
setPower(POWERMODE::ON); // maybe other track
|
||||||
}
|
|
||||||
// Write this after the fact as we want to turn on as fast as possible
|
// 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
|
// because we don't know which output actually triggered the fault pin
|
||||||
DIAG(F("COMMON FAULT PIN ACTIVE: POWERTOGGLE TRACK %c"), trackno + 'A');
|
DIAG(F("COMMON FAULT PIN ACTIVE: POWERTOGGLE TRACK %c"), trackno + 'A');
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
DIAG(F("TRACK %c FAULT PIN ACTIVE - OVERLOAD"), trackno + 'A');
|
unsigned long us;
|
||||||
if (lastCurrent < tripValue) {
|
if (lastCurrent < tripValue) {
|
||||||
|
if (power_sample_overload_wait <= 1000UL && // almost virgin
|
||||||
|
(us = microsSinceLastPowerChange()) < 50000UL) { // Ignore 50ms fault pin if no current
|
||||||
|
DIAG(F("TRACK %c FAULT PIN ACTIVE - 50ms ignore %lus"), trackno + 'A', us);
|
||||||
|
break;
|
||||||
|
}
|
||||||
lastCurrent = tripValue; // exaggerate
|
lastCurrent = tripValue; // exaggerate
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
} else {
|
} else {
|
||||||
|
if (power_sample_overload_wait <= 100UL && // virgin
|
||||||
|
microsSinceLastPowerChange() < 5000UL) { // Ignore 5ms fault pin if we see current
|
||||||
|
DIAG(F("TRACK %c FAULT PIN ACTIVE - 5ms ignore"), trackno + 'A');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DIAG(F("TRACK %c FAULT PIN ACTIVE - for real"), trackno + 'A');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// // //
|
||||||
|
if (lastCurrent < tripValue) {
|
||||||
|
if (microsSinceLastPowerChange() > 5000000UL) {
|
||||||
|
power_sample_overload_wait = 100UL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// too much current
|
||||||
|
if (power_sample_overload_wait > 100UL || // not virgin
|
||||||
|
microsSinceLastPowerChange() > 10000UL) { // Longer than 10ms
|
||||||
setPower(POWERMODE::OVERLOAD);
|
setPower(POWERMODE::OVERLOAD);
|
||||||
unsigned int mA=raw2mA(lastCurrent);
|
unsigned int mA=raw2mA(lastCurrent);
|
||||||
unsigned int maxmA=raw2mA(tripValue);
|
unsigned int maxmA=raw2mA(tripValue);
|
||||||
power_good_counter=0;
|
DIAG(F("TRACK %c POWER OVERLOAD %dmA (limit %dmA) shutdown for %lus"),
|
||||||
sampleDelay = power_sample_overload_wait;
|
trackno + 'A', mA, maxmA, 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;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case POWERMODE::OVERLOAD:
|
case POWERMODE::OVERLOAD:
|
||||||
// Try setting it back on after the OVERLOAD_WAIT
|
// 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 > 10000000UL)
|
||||||
|
power_sample_overload_wait = 10000000UL;
|
||||||
|
// power on test
|
||||||
setPower(POWERMODE::ON);
|
setPower(POWERMODE::ON);
|
||||||
sampleDelay = POWER_SAMPLE_ON_WAIT;
|
DIAG(F("TRACK %c POWER RESTORE (check %lus)"), trackno + 'A', power_sample_overload_wait);
|
||||||
// Debug code....
|
}
|
||||||
DIAG(F("TRACK %c POWER RESTORE (check %dms)"), trackno + 'A', sampleDelay);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sampleDelay = 999; // cant get here..meaningless statement to avoid compiler warning.
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,6 +186,15 @@ class MotorDriver {
|
||||||
inline void setTrackLetter(char c) {
|
inline void setTrackLetter(char c) {
|
||||||
trackLetter = 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 diff = micros() - lastPowerChange;
|
||||||
|
if (diff > (1UL << (6 *sizeof(unsigned long))))
|
||||||
|
lastPowerChange += 1UL << (4 * sizeof(unsigned long));
|
||||||
|
return diff;
|
||||||
|
};
|
||||||
#ifdef ANALOG_READ_INTERRUPT
|
#ifdef ANALOG_READ_INTERRUPT
|
||||||
bool sampleCurrentFromHW();
|
bool sampleCurrentFromHW();
|
||||||
void startCurrentFromHW();
|
void startCurrentFromHW();
|
||||||
|
@ -217,8 +226,8 @@ class MotorDriver {
|
||||||
int rawCurrentTripValue;
|
int rawCurrentTripValue;
|
||||||
// current sampling
|
// current sampling
|
||||||
POWERMODE powerMode;
|
POWERMODE powerMode;
|
||||||
unsigned long lastSampleTaken;
|
POWERMODE oldPowerMode;
|
||||||
unsigned int sampleDelay;
|
unsigned long lastPowerChange; // timestamp in microseconds
|
||||||
int progTripValue;
|
int progTripValue;
|
||||||
int lastCurrent;
|
int lastCurrent;
|
||||||
#ifdef ANALOG_READ_INTERRUPT
|
#ifdef ANALOG_READ_INTERRUPT
|
||||||
|
@ -229,9 +238,9 @@ class MotorDriver {
|
||||||
int tripmA;
|
int tripmA;
|
||||||
|
|
||||||
// Wait times for power management. Unit: milliseconds
|
// Wait times for power management. Unit: milliseconds
|
||||||
static const int POWER_SAMPLE_ON_WAIT = 100;
|
static const int POWER_SAMPLE_ON_WAIT = 1;
|
||||||
static const int POWER_SAMPLE_OFF_WAIT = 1000;
|
static const int POWER_SAMPLE_OFF_WAIT = 100;
|
||||||
static const int POWER_SAMPLE_OVERLOAD_WAIT = 20;
|
static const int POWER_SAMPLE_OVERLOAD_WAIT = 500UL;
|
||||||
|
|
||||||
// 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.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user