mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-11-25 00:56:13 +01:00
Compare commits
No commits in common. "7ce1618a9c3b57bb0693f0e6817551b550c284b4" and "efe96d1d842c40774bbd5622568109fc60bcc0d1" have entirely different histories.
7ce1618a9c
...
efe96d1d84
|
@ -487,9 +487,9 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
|
|||
#endif
|
||||
else break; // will reply <X>
|
||||
}
|
||||
TrackManager::setJoin(join);
|
||||
if (main) TrackManager::setMainPower(POWERMODE::ON);
|
||||
if (prog) TrackManager::setProgPower(POWERMODE::ON);
|
||||
TrackManager::setJoin(join);
|
||||
|
||||
CommandDistributor::broadcastPower();
|
||||
return;
|
||||
|
@ -516,12 +516,12 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
|
|||
else break; // will reply <X>
|
||||
}
|
||||
|
||||
TrackManager::setJoin(false);
|
||||
if (main) TrackManager::setMainPower(POWERMODE::OFF);
|
||||
if (prog) {
|
||||
TrackManager::progTrackBoosted=false; // Prog track boost mode will not outlive prog track off
|
||||
TrackManager::setProgPower(POWERMODE::OFF);
|
||||
}
|
||||
TrackManager::setJoin(false);
|
||||
|
||||
CommandDistributor::broadcastPower();
|
||||
return;
|
||||
|
|
|
@ -194,10 +194,8 @@ int RMTChannel::RMTfillData(const byte buffer[], byte byteCount, byte repeatCoun
|
|||
setDCCBit1(data + bitcounter-1); // overwrite previous zero bit with one bit
|
||||
setEOT(data + bitcounter++); // EOT marker
|
||||
dataLen = bitcounter;
|
||||
noInterrupts(); // keep dataReady and dataRepeat consistnet to each other
|
||||
dataReady = true;
|
||||
dataRepeat = repeatCount+1; // repeatCount of 0 means send once
|
||||
interrupts();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -214,8 +212,6 @@ void IRAM_ATTR RMTChannel::RMTinterrupt() {
|
|||
if (dataReady) { // if we have new data, fill while preamble is running
|
||||
rmt_fill_tx_items(channel, data, dataLen, preambleLen-1);
|
||||
dataReady = false;
|
||||
if (dataRepeat == 0) // all data should go out at least once
|
||||
DIAG(F("Channel %d DCC signal lost data"), channel);
|
||||
}
|
||||
if (dataRepeat > 0) // if a repeat count was specified, work on that
|
||||
dataRepeat--;
|
||||
|
|
|
@ -247,9 +247,6 @@ void DCCWaveform::schedulePacket(const byte buffer[], byte byteCount, byte repea
|
|||
pendingPacket[byteCount] = checksum;
|
||||
pendingLength = byteCount + 1;
|
||||
pendingRepeats = repeats;
|
||||
// DIAG repeated commands (accesories)
|
||||
// if (pendingRepeats > 0)
|
||||
// DIAG(F("Repeats=%d on %s track"), pendingRepeats, isMainTrack ? "MAIN" : "PROG");
|
||||
// The resets will be zero not only now but as well repeats packets into the future
|
||||
clearResets(repeats+1);
|
||||
{
|
||||
|
|
|
@ -1 +1 @@
|
|||
#define GITHUB_SHA "devel-overcurrent-202307061457Z"
|
||||
#define GITHUB_SHA "devel-202306261801Z"
|
||||
|
|
239
MotorDriver.cpp
239
MotorDriver.cpp
|
@ -173,11 +173,7 @@ bool MotorDriver::isPWMCapable() {
|
|||
|
||||
void MotorDriver::setPower(POWERMODE mode) {
|
||||
if (powerMode == mode) return;
|
||||
//DIAG(F("Track %c POWERMODE=%d"), trackLetter, (int)mode);
|
||||
lastPowerChange[(int)mode] = micros();
|
||||
if (mode == POWERMODE::OVERLOAD)
|
||||
globalOverloadStart = lastPowerChange[(int)mode];
|
||||
bool on=(mode==POWERMODE::ON || mode ==POWERMODE::ALERT);
|
||||
bool on=mode==POWERMODE::ON;
|
||||
if (on) {
|
||||
// when switching a track On, we need to check the crrentOffset with the pin OFF
|
||||
if (powerMode==POWERMODE::OFF && currentPin!=UNUSED_PIN) {
|
||||
|
@ -217,8 +213,8 @@ bool MotorDriver::canMeasureCurrent() {
|
|||
return currentPin!=UNUSED_PIN;
|
||||
}
|
||||
/*
|
||||
* Return the current reading as pin reading 0 to max resolution (1024 or 4096).
|
||||
* If the fault pin is activated return a negative current to show active fault pin.
|
||||
* Return the current reading as pin reading 0 to 1023. If the fault
|
||||
* pin is activated return a negative current to show active fault pin.
|
||||
* As there is no -0, cheat a little and return -1 in that case.
|
||||
*
|
||||
* senseOffset handles the case where a shield returns values above or below
|
||||
|
@ -376,165 +372,112 @@ void MotorDriver::getFastPin(const FSH* type,int pin, bool input, FASTPIN & res
|
|||
// DIAG(F(" port=0x%x, inoutpin=0x%x, isinput=%d, mask=0x%x"),port, result.inout,input,result.maskHIGH);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// checkPowerOverload(useProgLimit, trackno)
|
||||
// bool useProgLimit: Trackmanager knows if this track is in prog mode or in main mode
|
||||
// byte trackno: trackmanager knows it's number (could be skipped?)
|
||||
//
|
||||
// Short ciruit handling strategy:
|
||||
//
|
||||
// There are the following power states: ON ALERT OVERLOAD OFF
|
||||
// OFF state is only changed to/from manually. Power is on
|
||||
// during ON and ALERT. Power is off during OVERLOAD and OFF.
|
||||
// The overload mechanism changes between the other states like
|
||||
//
|
||||
// ON -1-> ALERT -2-> OVERLOAD -3-> ALERT -4-> ON
|
||||
// or
|
||||
// ON -1-> ALERT -4-> ON
|
||||
//
|
||||
// Times are in class MotorDriver (MotorDriver.h).
|
||||
//
|
||||
// 1. ON to ALERT:
|
||||
// Transition on fault pin condition or current overload
|
||||
//
|
||||
// 2. ALERT to OVERLOAD:
|
||||
// Transition happens if different timeouts have elapsed.
|
||||
// If only the fault pin is active, timeout is
|
||||
// POWER_SAMPLE_IGNORE_FAULT_LOW (100ms)
|
||||
// If only overcurrent is detected, timeout is
|
||||
// POWER_SAMPLE_IGNORE_CURRENT (100ms)
|
||||
// If fault pin and overcurrent are active, timeout is
|
||||
// POWER_SAMPLE_IGNORE_FAULT_HIGH (5ms)
|
||||
// Transition to OVERLOAD turns off power to the affected
|
||||
// output (unless fault pins are shared)
|
||||
// If the transition conditions are not fullfilled,
|
||||
// transition according to 4 is tested.
|
||||
//
|
||||
// 3. OVERLOAD to ALERT
|
||||
// Transiton happens when timeout has elapsed, timeout
|
||||
// is named power_sample_overload_wait. It is started
|
||||
// at POWER_SAMPLE_OVERLOAD_WAIT (40ms) at first entry
|
||||
// to OVERLOAD and then increased by a factor of 2
|
||||
// at further entries to the OVERLOAD condition. This
|
||||
// happens until POWER_SAMPLE_RETRY_MAX (10sec) is reached.
|
||||
// power_sample_overload_wait is reset by a poweroff or
|
||||
// a POWER_SAMPLE_ALL_GOOD (5sec) period during ON.
|
||||
// After timeout power is turned on again and state
|
||||
// goes back to ALERT.
|
||||
//
|
||||
// 4. ALERT to ON
|
||||
// Transition happens by watching the current and fault pin
|
||||
// samples during POWER_SAMPLE_ALERT_GOOD (20ms) time. If
|
||||
// values have been good during that time, transition is
|
||||
// made back to ON. Note that even if state is back to ON,
|
||||
// the power_sample_overload_wait time is first reset
|
||||
// later (see above).
|
||||
//
|
||||
// The time keeping is handled by timestamps lastPowerChange[]
|
||||
// which are set by each power change and by lastBadSample which
|
||||
// keeps track if conditions during ALERT have been good enough
|
||||
// to go back to ON. The time differences are calculated by
|
||||
// microsSinceLastPowerChange().
|
||||
//
|
||||
|
||||
void MotorDriver::checkPowerOverload(bool useProgLimit, byte trackno) {
|
||||
int tripValue= useProgLimit?progTripValue:getRawCurrentTripValue();
|
||||
|
||||
switch (powerMode) {
|
||||
|
||||
case POWERMODE::OFF: {
|
||||
lastPowerMode = POWERMODE::OFF;
|
||||
power_sample_overload_wait = POWER_SAMPLE_OVERLOAD_WAIT;
|
||||
break;
|
||||
}
|
||||
|
||||
case POWERMODE::ON: {
|
||||
lastPowerMode = POWERMODE::ON;
|
||||
bool cF = checkFault();
|
||||
bool cC = checkCurrent(useProgLimit);
|
||||
if(cF || cC ) {
|
||||
if (cC) {
|
||||
unsigned int mA=raw2mA(lastCurrent);
|
||||
DIAG(F("TRACK %c ALERT %s %dmA"), trackno + 'A',
|
||||
cF ? "FAULT" : "",
|
||||
mA);
|
||||
} else {
|
||||
DIAG(F("TRACK %c ALERT FAULT"), trackno + 'A');
|
||||
case POWERMODE::OFF:
|
||||
if (overloadNow) {
|
||||
// reset overload condition as we have just turned off power
|
||||
// DIAG(F("OVERLOAD POFF OFF"));
|
||||
overloadNow=false;
|
||||
setLastPowerChange();
|
||||
}
|
||||
setPower(POWERMODE::ALERT);
|
||||
break;
|
||||
}
|
||||
// all well
|
||||
if (microsSinceLastPowerChange(POWERMODE::ON) > POWER_SAMPLE_ALL_GOOD) {
|
||||
power_sample_overload_wait = POWER_SAMPLE_OVERLOAD_WAIT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case POWERMODE::ALERT: {
|
||||
// set local flags that handle how much is output to diag (do not output duplicates)
|
||||
bool notFromOverload = (lastPowerMode != POWERMODE::OVERLOAD);
|
||||
bool newPowerMode = (powerMode != lastPowerMode);
|
||||
unsigned long now = micros();
|
||||
if (newPowerMode)
|
||||
lastBadSample = now;
|
||||
lastPowerMode = POWERMODE::ALERT;
|
||||
// check how long we have been in this state
|
||||
unsigned long mslpc = microsSinceLastPowerChange(POWERMODE::ALERT);
|
||||
if(checkFault()) {
|
||||
lastBadSample = now;
|
||||
unsigned long timeout = checkCurrent(useProgLimit) ? POWER_SAMPLE_IGNORE_FAULT_HIGH : POWER_SAMPLE_IGNORE_FAULT_LOW;
|
||||
if ( mslpc < timeout) {
|
||||
if (newPowerMode)
|
||||
DIAG(F("TRACK %c FAULT PIN (%M ignore)"), trackno + 'A', timeout);
|
||||
break;
|
||||
if (microsSinceLastPowerChange() > POWER_SAMPLE_ALL_GOOD) {
|
||||
power_sample_overload_wait = POWER_SAMPLE_OVERLOAD_WAIT;
|
||||
}
|
||||
DIAG(F("TRACK %c FAULT PIN detected after %4M. Pause %4M)"), trackno + 'A', mslpc, power_sample_overload_wait);
|
||||
setPower(POWERMODE::OVERLOAD);
|
||||
break;
|
||||
}
|
||||
if (checkCurrent(useProgLimit)) {
|
||||
lastBadSample = now;
|
||||
if (mslpc < POWER_SAMPLE_IGNORE_CURRENT) {
|
||||
if (newPowerMode) {
|
||||
unsigned int mA=raw2mA(lastCurrent);
|
||||
DIAG(F("TRACK %c CURRENT (%M ignore) %dmA"), trackno + 'A', POWER_SAMPLE_IGNORE_CURRENT, mA);
|
||||
case POWERMODE::ON:
|
||||
// Check current
|
||||
lastCurrent=getCurrentRaw();
|
||||
if (lastCurrent < 0) {
|
||||
// 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;
|
||||
setLastPowerChangeOverload();
|
||||
}
|
||||
lastCurrent = -lastCurrent;
|
||||
{
|
||||
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"), trackno + 'A');
|
||||
}
|
||||
}
|
||||
// // //
|
||||
// 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;
|
||||
setLastPowerChange();
|
||||
}
|
||||
if (microsSinceLastPowerChange() > POWER_SAMPLE_ALL_GOOD) {
|
||||
power_sample_overload_wait = POWER_SAMPLE_OVERLOAD_WAIT;
|
||||
}
|
||||
} else {
|
||||
// too much current
|
||||
if (!overloadNow) {
|
||||
// current is over trip value, turn on overload condition
|
||||
// DIAG(F("OVERLOAD PON ON"));
|
||||
overloadNow=true;
|
||||
setLastPowerChange();
|
||||
}
|
||||
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;
|
||||
setLastPowerChangeOverload();
|
||||
}
|
||||
unsigned int mA=raw2mA(lastCurrent);
|
||||
unsigned int maxmA=raw2mA(tripValue);
|
||||
DIAG(F("TRACK %c POWER OVERLOAD %4dmA (max %4dmA) detected after %4M. Pause %4M"),
|
||||
trackno + 'A', mA, maxmA, uSecs, power_sample_overload_wait);
|
||||
}
|
||||
break;
|
||||
}
|
||||
unsigned int mA=raw2mA(lastCurrent);
|
||||
unsigned int maxmA=raw2mA(tripValue);
|
||||
DIAG(F("TRACK %c POWER OVERLOAD %4dmA (max %4dmA) detected after %4M. Pause %4M"),
|
||||
trackno + 'A', mA, maxmA, mslpc, power_sample_overload_wait);
|
||||
setPower(POWERMODE::OVERLOAD);
|
||||
break;
|
||||
}
|
||||
// all well
|
||||
unsigned long goodtime = micros() - lastBadSample;
|
||||
if (goodtime > POWER_SAMPLE_ALERT_GOOD) {
|
||||
if (true || notFromOverload) { // we did a RESTORE message XXX
|
||||
unsigned int mA=raw2mA(lastCurrent);
|
||||
DIAG(F("TRACK %c NORMAL (after %M/%M) %dmA"), trackno + 'A', goodtime, mslpc, mA);
|
||||
}
|
||||
setPower(POWERMODE::ON);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case POWERMODE::OVERLOAD: {
|
||||
lastPowerMode = POWERMODE::OVERLOAD;
|
||||
unsigned long mslpc = (commonFaultPin ? (micros() - globalOverloadStart) : microsSinceLastPowerChange(POWERMODE::OVERLOAD));
|
||||
case POWERMODE::OVERLOAD:
|
||||
{
|
||||
// Try setting it back on after the OVERLOAD_WAIT
|
||||
unsigned long mslpc = (commonFaultPin ? (micros() - globalOverloadStart) : microsSinceLastPowerChange());
|
||||
if (mslpc > 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);
|
||||
// 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.
|
||||
overloadNow=false;
|
||||
setLastPowerChange();
|
||||
DIAG(F("TRACK %c POWER RESTORE (after %4M)"), trackno + 'A', mslpc);
|
||||
setPower(POWERMODE::ALERT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -107,7 +107,7 @@ extern volatile portreg_t shadowPORTA;
|
|||
extern volatile portreg_t shadowPORTB;
|
||||
extern volatile portreg_t shadowPORTC;
|
||||
|
||||
enum class POWERMODE : byte { OFF, ON, OVERLOAD, ALERT };
|
||||
enum class POWERMODE : byte { OFF, ON, OVERLOAD };
|
||||
|
||||
class MotorDriver {
|
||||
public:
|
||||
|
@ -192,13 +192,24 @@ class MotorDriver {
|
|||
// 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(POWERMODE mode) {
|
||||
inline unsigned long microsSinceLastPowerChange() {
|
||||
unsigned long now = micros();
|
||||
unsigned long diff = now - lastPowerChange[(int)mode];
|
||||
unsigned long diff = now - lastPowerChange;
|
||||
if (diff > (1UL << (7 *sizeof(unsigned long)))) // 2^(4*7)us = 268.4 seconds
|
||||
lastPowerChange[(int)mode] = now - 30000000UL; // 30 seconds ago
|
||||
lastPowerChange = now - 30000000UL; // 30 seconds ago
|
||||
return diff;
|
||||
};
|
||||
inline void setLastPowerChange() {
|
||||
lastPowerChange = micros();
|
||||
};
|
||||
// as setLastPowerChange but sets the global timestamp as well which
|
||||
// is only used to sync power restore in case of common Fault pin.
|
||||
inline void setLastPowerChangeOverload() {
|
||||
if (commonFaultPin)
|
||||
globalOverloadStart = lastPowerChange = micros();
|
||||
else
|
||||
setLastPowerChange();
|
||||
};
|
||||
#ifdef ANALOG_READ_INTERRUPT
|
||||
bool sampleCurrentFromHW();
|
||||
void startCurrentFromHW();
|
||||
|
@ -207,22 +218,9 @@ class MotorDriver {
|
|||
char trackLetter = '?';
|
||||
bool isProgTrack = false; // tells us if this is a prog track
|
||||
void getFastPin(const FSH* type,int pin, bool input, FASTPIN & result);
|
||||
inline void getFastPin(const FSH* type,int pin, FASTPIN & result) {
|
||||
void getFastPin(const FSH* type,int pin, FASTPIN & result) {
|
||||
getFastPin(type, pin, 0, result);
|
||||
};
|
||||
// side effect sets lastCurrent and tripValue
|
||||
inline bool checkCurrent(bool useProgLimit) {
|
||||
tripValue= useProgLimit?progTripValue:getRawCurrentTripValue();
|
||||
lastCurrent = getCurrentRaw();
|
||||
if (lastCurrent < 0)
|
||||
lastCurrent = -lastCurrent;
|
||||
return lastCurrent >= tripValue;
|
||||
};
|
||||
// side effect sets lastCurrent
|
||||
inline bool checkFault() {
|
||||
lastCurrent = getCurrentRaw();
|
||||
return lastCurrent < 0;
|
||||
};
|
||||
}
|
||||
VPIN powerPin;
|
||||
byte signalPin, signalPin2, currentPin, faultPin, brakePin;
|
||||
FASTPIN fastSignalPin, fastSignalPin2, fastBrakePin,fastFaultPin;
|
||||
|
@ -243,14 +241,12 @@ class MotorDriver {
|
|||
int rawCurrentTripValue;
|
||||
// current sampling
|
||||
POWERMODE powerMode;
|
||||
POWERMODE lastPowerMode;
|
||||
unsigned long lastPowerChange[4]; // timestamp in microseconds
|
||||
unsigned long lastBadSample; // timestamp in microseconds
|
||||
bool overloadNow = false;
|
||||
unsigned long lastPowerChange; // timestamp in microseconds
|
||||
// used to sync restore time when common Fault pin detected
|
||||
static unsigned long globalOverloadStart; // timestamp in microseconds
|
||||
int progTripValue;
|
||||
int lastCurrent; //temp value
|
||||
int tripValue; //temp value
|
||||
int lastCurrent;
|
||||
#ifdef ANALOG_READ_INTERRUPT
|
||||
volatile unsigned long sampleCurrentTimestamp;
|
||||
volatile uint16_t sampleCurrent;
|
||||
|
@ -260,17 +256,15 @@ class MotorDriver {
|
|||
|
||||
// Times for overload management. Unit: microseconds.
|
||||
// Base for wait time until power is turned on again
|
||||
static const unsigned long POWER_SAMPLE_OVERLOAD_WAIT = 40000UL;
|
||||
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;
|
||||
// Time after which we consider a ALERT over
|
||||
static const unsigned long POWER_SAMPLE_ALERT_GOOD = 20000UL;
|
||||
// How long to ignore fault pin if current is under limit
|
||||
static const unsigned long POWER_SAMPLE_IGNORE_FAULT_LOW = 100000UL;
|
||||
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_IGNORE_CURRENT = 100000UL;
|
||||
static const unsigned long POWER_SAMPLE_OFF_DELAY = 10000UL;
|
||||
// Upper limit for retry period
|
||||
static const unsigned long POWER_SAMPLE_RETRY_MAX = 10000000UL;
|
||||
|
||||
|
|
|
@ -205,7 +205,7 @@
|
|||
#define WIFI_SERIAL_LINK_SPEED 115200
|
||||
|
||||
#if __has_include ( "myAutomation.h")
|
||||
#if defined(HAS_ENOUGH_MEMORY) || defined(DISABLE_EEPROM) || defined(DISABLE_PROG)
|
||||
#if defined(HAS_ENOUGH_MEMORY) || defined(DISABLE_EEPROM)
|
||||
#define EXRAIL_ACTIVE
|
||||
#else
|
||||
#define EXRAIL_WARNING
|
||||
|
|
23
installer.sh
23
installer.sh
|
@ -1,7 +1,7 @@
|
|||
#!/bin/bash
|
||||
|
||||
#
|
||||
# © 2022,2023 Harald Barth
|
||||
# © 2022 Harald Barth
|
||||
#
|
||||
# This file is part of CommandStation-EX
|
||||
#
|
||||
|
@ -29,33 +29,14 @@ ACLI="./bin/arduino-cli"
|
|||
|
||||
function need () {
|
||||
type -p $1 > /dev/null && return
|
||||
dpkg -l $1 2>&1 | egrep ^ii >/dev/null && return
|
||||
sudo apt-get install $1
|
||||
type -p $1 > /dev/null && return
|
||||
echo "Could not install $1, abort"
|
||||
exit 255
|
||||
}
|
||||
|
||||
|
||||
need git
|
||||
|
||||
if cat /etc/issue | egrep '^Raspbian' 2>&1 >/dev/null ; then
|
||||
# we are on a raspi where we do not support graphical
|
||||
unset DISPLAY
|
||||
fi
|
||||
|
||||
if [ x$DISPLAY != x ] ; then
|
||||
# we have DISPLAY, do the graphic thing
|
||||
need python3-tk
|
||||
need python3.8-venv
|
||||
mkdir -p ~/ex-installer/venv
|
||||
python3 -m venv ~/ex-installer/venv
|
||||
cd ~/ex-installer/venv || exit 255
|
||||
source ./bin/activate
|
||||
git clone https://github.com/DCC-EX/EX-Installer
|
||||
cd EX-Installer || exit 255
|
||||
pip3 install -r requirements.txt
|
||||
exec python3 -m ex_installer
|
||||
fi
|
||||
if test -d `basename "$DCCEXGITURL"` ; then
|
||||
: assume we are almost there
|
||||
cd `basename "$DCCEXGITURL"` || exit 255
|
||||
|
|
|
@ -3,9 +3,8 @@
|
|||
|
||||
#include "StringFormatter.h"
|
||||
|
||||
#define VERSION "4.2.63"
|
||||
// 4.2.63 - completely new overcurrent detection
|
||||
// - ESP32 protect from race in RMT code
|
||||
|
||||
#define VERSION "4.2.62"
|
||||
// 4.2.62 - Update IO_RotaryEncoder.h to ignore sending current position
|
||||
// - Update IO_EXTurntable.h to remove forced I2C clock speed
|
||||
// - Show device offline if EX-Turntable not connected
|
||||
|
|
Loading…
Reference in New Issue
Block a user