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

Merge branch 'master' into copyrightmessages

This commit is contained in:
Harald Barth 2021-05-16 08:12:09 +02:00
commit 3fa805c0e7
14 changed files with 633 additions and 166 deletions

121
DCC.cpp
View File

@ -126,7 +126,7 @@ void DCC::setFunctionInternal(int cab, byte byte1, byte byte2) {
if (byte1!=0) b[nB++] = byte1; if (byte1!=0) b[nB++] = byte1;
b[nB++] = byte2; b[nB++] = byte2;
DCCWaveform::mainTrack.schedulePacket(b, nB, 3); // send packet 3 times DCCWaveform::mainTrack.schedulePacket(b, nB, 0);
} }
uint8_t DCC::getThrottleSpeed(int cab) { uint8_t DCC::getThrottleSpeed(int cab) {
@ -142,7 +142,7 @@ bool DCC::getThrottleDirection(int cab) {
} }
// Set function to value on or off // Set function to value on or off
void DCC::setFn( int cab, byte functionNumber, bool on) { void DCC::setFn( int cab, int16_t functionNumber, bool on) {
if (cab<=0 ) return; if (cab<=0 ) return;
if (functionNumber>28) { if (functionNumber>28) {
@ -159,7 +159,7 @@ void DCC::setFn( int cab, byte functionNumber, bool on) {
else { else {
b[nB++] = 0b11000000; // Binary State Control Instruction long form b[nB++] = 0b11000000; // Binary State Control Instruction long form
b[nB++] = (functionNumber & 0x7F) | (on ? 0x80 : 0); // low order bits and state flag b[nB++] = (functionNumber & 0x7F) | (on ? 0x80 : 0); // low order bits and state flag
b[nB++] = functionNumber >>8 ; // high order bits b[nB++] = functionNumber >>7 ; // high order bits
} }
DCCWaveform::mainTrack.schedulePacket(b, nB, 4); DCCWaveform::mainTrack.schedulePacket(b, nB, 4);
return; return;
@ -183,7 +183,7 @@ void DCC::setFn( int cab, byte functionNumber, bool on) {
// Change function according to how button was pressed, // Change function according to how button was pressed,
// typically in WiThrottle. // typically in WiThrottle.
// Returns new state or -1 if nothing was changed. // Returns new state or -1 if nothing was changed.
int DCC::changeFn( int cab, byte functionNumber, bool pressed) { int DCC::changeFn( int cab, int16_t functionNumber, bool pressed) {
int funcstate = -1; int funcstate = -1;
if (cab<=0 || functionNumber>28) return funcstate; if (cab<=0 || functionNumber>28) return funcstate;
int reg = lookupSpeedTable(cab); int reg = lookupSpeedTable(cab);
@ -213,7 +213,7 @@ int DCC::changeFn( int cab, byte functionNumber, bool pressed) {
return funcstate; return funcstate;
} }
int DCC::getFn( int cab, byte functionNumber) { int DCC::getFn( int cab, int16_t functionNumber) {
if (cab<=0 || functionNumber>28) return -1; // unknown if (cab<=0 || functionNumber>28) return -1; // unknown
int reg = lookupSpeedTable(cab); int reg = lookupSpeedTable(cab);
if (reg<0) return -1; if (reg<0) return -1;
@ -224,7 +224,7 @@ int DCC::getFn( int cab, byte functionNumber) {
// Set the group flag to say we have touched the particular group. // Set the group flag to say we have touched the particular group.
// A group will be reminded only if it has been touched. // A group will be reminded only if it has been touched.
void DCC::updateGroupflags(byte & flags, int functionNumber) { void DCC::updateGroupflags(byte & flags, int16_t functionNumber) {
byte groupMask; byte groupMask;
if (functionNumber<=4) groupMask=FN_GROUP_1; if (functionNumber<=4) groupMask=FN_GROUP_1;
else if (functionNumber<=8) groupMask=FN_GROUP_2; else if (functionNumber<=8) groupMask=FN_GROUP_2;
@ -398,10 +398,6 @@ const ackOp FLASH READ_CV_PROG[] = {
const ackOp FLASH LOCO_ID_PROG[] = { const ackOp FLASH LOCO_ID_PROG[] = {
BASELINE, BASELINE,
SETCV, (ackOp)1,
SETBIT, (ackOp)7,
V0,WACK,NAKFAIL, // test CV 1 bit 7 is a zero... NAK means no loco found
SETCV, (ackOp)19, // CV 19 is consist setting SETCV, (ackOp)19, // CV 19 is consist setting
SETBYTE, (ackOp)0, SETBYTE, (ackOp)0,
VB, WACK, ITSKIP, // ignore consist if cv19 is zero (no consist) VB, WACK, ITSKIP, // ignore consist if cv19 is zero (no consist)
@ -691,9 +687,31 @@ byte DCC::ackManagerBitNum;
bool DCC::ackReceived; bool DCC::ackReceived;
bool DCC::ackManagerRejoin; bool DCC::ackManagerRejoin;
CALLBACK_STATE DCC::callbackState=READY;
ACK_CALLBACK DCC::ackManagerCallback; ACK_CALLBACK DCC::ackManagerCallback;
void DCC::ackManagerSetup(int cv, byte byteValueOrBitnum, ackOp const program[], ACK_CALLBACK callback) { void DCC::ackManagerSetup(int cv, byte byteValueOrBitnum, ackOp const program[], ACK_CALLBACK callback) {
if (!DCCWaveform::progTrack.canMeasureCurrent()) {
callback(-2);
return;
}
ackManagerRejoin=DCCWaveform::progTrackSyncMain;
if (ackManagerRejoin ) {
// Change from JOIN must zero resets packet.
setProgTrackSyncMain(false);
DCCWaveform::progTrack.sentResetsSincePacket = 0;
}
DCCWaveform::progTrack.autoPowerOff=false;
if (DCCWaveform::progTrack.getPowerMode() == POWERMODE::OFF) {
DCCWaveform::progTrack.autoPowerOff=true; // power off afterwards
if (Diag::ACK) DIAG(F("Auto Prog power on"));
DCCWaveform::progTrack.setPowerMode(POWERMODE::ON);
DCCWaveform::progTrack.sentResetsSincePacket = 0;
}
ackManagerCv = cv; ackManagerCv = cv;
ackManagerProg = program; ackManagerProg = program;
ackManagerByte = byteValueOrBitnum; ackManagerByte = byteValueOrBitnum;
@ -703,8 +721,7 @@ void DCC::ackManagerSetup(int cv, byte byteValueOrBitnum, ackOp const program[]
void DCC::ackManagerSetup(int wordval, ackOp const program[], ACK_CALLBACK callback) { void DCC::ackManagerSetup(int wordval, ackOp const program[], ACK_CALLBACK callback) {
ackManagerWord=wordval; ackManagerWord=wordval;
ackManagerProg = program; ackManagerSetup(0, 0, program, callback);
ackManagerCallback = callback;
} }
const byte RESET_MIN=8; // tuning of reset counter before sending message const byte RESET_MIN=8; // tuning of reset counter before sending message
@ -723,21 +740,9 @@ void DCC::ackManagerLoop() {
// (typically waiting for a reset counter or ACK waiting, or when all finished.) // (typically waiting for a reset counter or ACK waiting, or when all finished.)
switch (opcode) { switch (opcode) {
case BASELINE: case BASELINE:
ackManagerRejoin=DCCWaveform::progTrackSyncMain; if (checkResets(DCCWaveform::progTrack.autoPowerOff || ackManagerRejoin ? 20 : 3)) return;
if (!DCCWaveform::progTrack.canMeasureCurrent()) {
callback(-2);
return;
}
setProgTrackSyncMain(false);
if (DCCWaveform::progTrack.getPowerMode() == POWERMODE::OFF) {
if (Diag::ACK) DIAG(F("Auto Prog power on"));
DCCWaveform::progTrack.setPowerMode(POWERMODE::ON);
DCCWaveform::progTrack.sentResetsSincePacket = 0;
DCCWaveform::progTrack.autoPowerOff=true;
return;
}
if (checkResets(DCCWaveform::progTrack.autoPowerOff ? 20 : 3)) return;
DCCWaveform::progTrack.setAckBaseline(); DCCWaveform::progTrack.setAckBaseline();
callbackState=READY;
break; break;
case W0: // write 0 bit case W0: // write 0 bit
case W1: // write 1 bit case W1: // write 1 bit
@ -748,6 +753,7 @@ void DCC::ackManagerLoop() {
byte message[] = {cv1(BIT_MANIPULATE, ackManagerCv), cv2(ackManagerCv), instruction }; byte message[] = {cv1(BIT_MANIPULATE, ackManagerCv), cv2(ackManagerCv), instruction };
DCCWaveform::progTrack.schedulePacket(message, sizeof(message), PROG_REPEATS); DCCWaveform::progTrack.schedulePacket(message, sizeof(message), PROG_REPEATS);
DCCWaveform::progTrack.setAckPending(); DCCWaveform::progTrack.setAckPending();
callbackState=AFTER_WRITE;
} }
break; break;
@ -758,6 +764,7 @@ void DCC::ackManagerLoop() {
byte message[] = {cv1(WRITE_BYTE, ackManagerCv), cv2(ackManagerCv), ackManagerByte}; byte message[] = {cv1(WRITE_BYTE, ackManagerCv), cv2(ackManagerCv), ackManagerByte};
DCCWaveform::progTrack.schedulePacket(message, sizeof(message), PROG_REPEATS); DCCWaveform::progTrack.schedulePacket(message, sizeof(message), PROG_REPEATS);
DCCWaveform::progTrack.setAckPending(); DCCWaveform::progTrack.setAckPending();
callbackState=AFTER_WRITE;
} }
break; break;
@ -888,21 +895,61 @@ void DCC::ackManagerLoop() {
ackManagerProg++; ackManagerProg++;
} }
} }
void DCC::callback(int value) { void DCC::callback(int value) {
ackManagerProg=NULL; // no more steps to execute static unsigned long callbackStart;
if (DCCWaveform::progTrack.autoPowerOff) { // We are about to leave programming mode
if (Diag::ACK) DIAG(F("Auto Prog power off")); // Rule 1: If we have written to a decoder we must maintain power for 100mS
DCCWaveform::progTrack.doAutoPowerOff(); // Rule 2: If we are re-joining the main track we must power off for 30mS
switch (callbackState) {
case AFTER_WRITE: // first attempt to callback after a write operation
callbackStart=millis();
callbackState=WAITING_100;
if (Diag::ACK) DIAG(F("Stable 100mS"));
break;
case WAITING_100: // waiting for 100mS
if (millis()-callbackStart < 100) break;
// stable after power maintained for 100mS
// If we are going to power off anyway, it doesnt matter
// but if we will keep the power on, we must off it for 30mS
if (DCCWaveform::progTrack.autoPowerOff) callbackState=READY;
else { // Need to cycle power off and on
DCCWaveform::progTrack.setPowerMode(POWERMODE::OFF);
callbackStart=millis();
callbackState=WAITING_30;
if (Diag::ACK) DIAG(F("OFF 30mS"));
}
break;
case WAITING_30: // waiting for 30mS with power off
if (millis()-callbackStart < 30) break;
//power has been off for 30mS
DCCWaveform::progTrack.setPowerMode(POWERMODE::ON);
callbackState=READY;
break;
case READY: // ready after read, or write after power delay and off period.
// power off if we powered it on
if (DCCWaveform::progTrack.autoPowerOff) {
if (Diag::ACK) DIAG(F("Auto Prog power off"));
DCCWaveform::progTrack.doAutoPowerOff();
}
// Restore <1 JOIN> to state before BASELINE
if (ackManagerRejoin) {
setProgTrackSyncMain(true);
if (Diag::ACK) DIAG(F("Auto JOIN"));
}
ackManagerProg=NULL; // no more steps to execute
if (Diag::ACK) DIAG(F("Callback(%d)"),value);
(ackManagerCallback)( value);
} }
// Restore <1 JOIN> to state before BASELINE
setProgTrackSyncMain(ackManagerRejoin);
if (Diag::ACK) DIAG(F("Callback(%d)"),value);
(ackManagerCallback)( value);
} }
void DCC::displayCabList(Print * stream) { void DCC::displayCabList(Print * stream) {
int used=0; int used=0;
for (int reg = 0; reg < MAX_LOCOS; reg++) { for (int reg = 0; reg < MAX_LOCOS; reg++) {

17
DCC.h
View File

@ -54,6 +54,14 @@ enum ackOp : byte
SKIPTARGET = 0xFF // jump to target SKIPTARGET = 0xFF // jump to target
}; };
enum CALLBACK_STATE : byte {
AFTER_WRITE, // Start callback sequence after something was written to the decoder
WAITING_100, // Waiting for 100mS of stable power
WAITING_30, // waiting to 30ms of power off gap.
READY, // Ready to complete callback
};
// Allocations with memory implications..! // Allocations with memory implications..!
// Base system takes approx 900 bytes + 8 per loco. Turnouts, Sensors etc are dynamically created // Base system takes approx 900 bytes + 8 per loco. Turnouts, Sensors etc are dynamically created
#ifdef ARDUINO_AVR_UNO #ifdef ARDUINO_AVR_UNO
@ -76,10 +84,10 @@ public:
static void writeCVByteMain(int cab, int cv, byte bValue); static void writeCVByteMain(int cab, int cv, byte bValue);
static void writeCVBitMain(int cab, int cv, byte bNum, bool bValue); static void writeCVBitMain(int cab, int cv, byte bNum, bool bValue);
static void setFunction(int cab, byte fByte, byte eByte); static void setFunction(int cab, byte fByte, byte eByte);
static void setFn(int cab, byte functionNumber, bool on); static void setFn(int cab, int16_t functionNumber, bool on);
static int changeFn(int cab, byte functionNumber, bool pressed); static int changeFn(int cab, int16_t functionNumber, bool pressed);
static int getFn(int cab, byte functionNumber); static int getFn(int cab, int16_t functionNumber);
static void updateGroupflags(byte &flags, int functionNumber); static void updateGroupflags(byte &flags, int16_t functionNumber);
static void setAccessory(int aAdd, byte aNum, bool activate); static void setAccessory(int aAdd, byte aNum, bool activate);
static bool writeTextPacket(byte *b, int nBytes); static bool writeTextPacket(byte *b, int nBytes);
static void setProgTrackSyncMain(bool on); // when true, prog track becomes driveable static void setProgTrackSyncMain(bool on); // when true, prog track becomes driveable
@ -141,6 +149,7 @@ private:
static bool ackReceived; static bool ackReceived;
static bool ackManagerRejoin; static bool ackManagerRejoin;
static ACK_CALLBACK ackManagerCallback; static ACK_CALLBACK ackManagerCallback;
static CALLBACK_STATE callbackState;
static void ackManagerSetup(int cv, byte bitNumOrbyteValue, ackOp const program[], ACK_CALLBACK callback); static void ackManagerSetup(int cv, byte bitNumOrbyteValue, ackOp const program[], ACK_CALLBACK callback);
static void ackManagerSetup(int wordval, ackOp const program[], ACK_CALLBACK callback); static void ackManagerSetup(int wordval, ackOp const program[], ACK_CALLBACK callback);
static void ackManagerLoop(); static void ackManagerLoop();

View File

@ -31,6 +31,9 @@ DCCWaveform DCCWaveform::progTrack(PREAMBLE_BITS_PROG, false);
bool DCCWaveform::progTrackSyncMain=false; bool DCCWaveform::progTrackSyncMain=false;
bool DCCWaveform::progTrackBoosted=false; bool DCCWaveform::progTrackBoosted=false;
int DCCWaveform::progTripValue=0; int DCCWaveform::progTripValue=0;
volatile uint8_t DCCWaveform::numAckGaps=0;
volatile uint8_t DCCWaveform::numAckSamples=0;
uint8_t DCCWaveform::trailingEdgeCounter=0;
void DCCWaveform::begin(MotorDriver * mainDriver, MotorDriver * progDriver) { void DCCWaveform::begin(MotorDriver * mainDriver, MotorDriver * progDriver) {
mainTrack.motorDriver=mainDriver; mainTrack.motorDriver=mainDriver;
@ -290,13 +293,15 @@ void DCCWaveform::setAckPending() {
ackPulseDuration=0; ackPulseDuration=0;
ackDetected=false; ackDetected=false;
ackCheckStart=millis(); ackCheckStart=millis();
numAckSamples=0;
numAckGaps=0;
ackPending=true; // interrupt routines will now take note ackPending=true; // interrupt routines will now take note
} }
byte DCCWaveform::getAck() { byte DCCWaveform::getAck() {
if (ackPending) return (2); // still waiting if (ackPending) return (2); // still waiting
if (Diag::ACK) DIAG(F("%S after %dmS max=%d/%dmA pulse=%duS"),ackDetected?F("ACK"):F("NO-ACK"), ackCheckDuration, if (Diag::ACK) DIAG(F("%S after %dmS max=%d/%dmA pulse=%duS samples=%d gaps=%d"),ackDetected?F("ACK"):F("NO-ACK"), ackCheckDuration,
ackMaxCurrent,motorDriver->raw2mA(ackMaxCurrent), ackPulseDuration); ackMaxCurrent,motorDriver->raw2mA(ackMaxCurrent), ackPulseDuration, numAckSamples, numAckGaps);
if (ackDetected) return (1); // Yes we had an ack if (ackDetected) return (1); // Yes we had an ack
return(0); // pending set off but not detected means no ACK. return(0); // pending set off but not detected means no ACK.
} }
@ -310,10 +315,15 @@ void DCCWaveform::checkAck() {
} }
int current=motorDriver->getCurrentRaw(); int current=motorDriver->getCurrentRaw();
numAckSamples++;
if (current > ackMaxCurrent) ackMaxCurrent=current; if (current > ackMaxCurrent) ackMaxCurrent=current;
// An ACK is a pulse lasting between minAckPulseDuration and maxAckPulseDuration uSecs (refer @haba) // An ACK is a pulse lasting between minAckPulseDuration and maxAckPulseDuration uSecs (refer @haba)
if (current>ackThreshold) { if (current>ackThreshold) {
if (trailingEdgeCounter > 0) {
numAckGaps++;
trailingEdgeCounter = 0;
}
if (ackPulseStart==0) ackPulseStart=micros(); // leading edge of pulse detected if (ackPulseStart==0) ackPulseStart=micros(); // leading edge of pulse detected
return; return;
} }
@ -321,8 +331,20 @@ void DCCWaveform::checkAck() {
// not in pulse // not in pulse
if (ackPulseStart==0) return; // keep waiting for leading edge if (ackPulseStart==0) return; // keep waiting for leading edge
// if we reach to this point, we have
// detected trailing edge of pulse // detected trailing edge of pulse
ackPulseDuration=micros()-ackPulseStart; if (trailingEdgeCounter == 0) {
ackPulseDuration=micros()-ackPulseStart;
}
// but we do not trust it yet and return (which will force another
// measurement) and first the third time around with low current
// the ack detection will be finalized.
if (trailingEdgeCounter < 2) {
trailingEdgeCounter++;
return;
}
trailingEdgeCounter = 0;
if (ackPulseDuration>=minAckPulseDuration && ackPulseDuration<=maxAckPulseDuration) { if (ackPulseDuration>=minAckPulseDuration && ackPulseDuration<=maxAckPulseDuration) {
ackCheckDuration=millis()-ackCheckStart; ackCheckDuration=millis()-ackCheckStart;

View File

@ -161,8 +161,11 @@ class DCCWaveform {
unsigned int ackPulseDuration; // micros unsigned int ackPulseDuration; // micros
unsigned long ackPulseStart; // micros unsigned long ackPulseStart; // micros
unsigned int minAckPulseDuration = 2000; // micros unsigned int minAckPulseDuration = 4000; // micros
unsigned int maxAckPulseDuration = 8500; // micros unsigned int maxAckPulseDuration = 8500; // micros
volatile static uint8_t numAckGaps;
volatile static uint8_t numAckSamples;
static uint8_t trailingEdgeCounter;
}; };
#endif #endif

View File

@ -1 +1 @@
#define GITHUB_SHA "c4f45dd" #define GITHUB_SHA "90487d2"

View File

@ -12,11 +12,13 @@ Both CommandStation-EX and BaseStation-Classic support much of the NMRA Digital
* simultaneous control of multiple locomotives * simultaneous control of multiple locomotives
* 2-byte and 4-byte locomotive addressing * 2-byte and 4-byte locomotive addressing
* 128-step speed throttling * 28 or 128-step speed throttling
* Activate/de-activate all accessory function addresses 0-2048 * Activate/de-activate all accessory function addresses 0-2048
* Control of all cab functions F0-F28 * Control of all cab functions F0-F28 and F29-F68
* Main Track: Write configuration variable bytes and set/clear specific configuration variable (CV) bits (aka Programming on Main or POM) * Main Track: Write configuration variable bytes and set/clear specific configuration variable (CV) bits (aka Programming on Main or POM)
* Programming Track: Same as the main track with the addition of reading configuration variable bytes * Programming Track: Same as the main track with the addition of reading configuration variable bytes
* And manu more custom features. see [What's new in CommandStation-EX?](#whats-new-in-commandstation-ex)
# Whats in this Repository? # Whats in this Repository?
@ -38,11 +40,11 @@ in config.h.
## What's new in CommandStation-EX? ## What's new in CommandStation-EX?
* WiThrottle server built in. Connect Engine Driver or WiThrottle clients directly to your Command Station * WiThrottle server built in. Connect Engine Driver or WiThrottle clients directly to your Command Station (or through JMRI as before)
* WiFi and Ethernet shield support * WiFi and Ethernet shield support
* No more jumpers or soldering! * No more jumpers or soldering!
* Direct support for all the most popular motor control boards * Direct support for all the most popular motor control boards including single pin (Arduino) or dual pin (IBT_2) type PWM inputs without the need for an adapter circuit
* I2C Display support * I2C Display support (LCD and OLED)
* Improved short circuit detection and automatic reset from an overload * Improved short circuit detection and automatic reset from an overload
* Current reading, sensing and ACK detection settings in milliAmps instead of just pin readings * Current reading, sensing and ACK detection settings in milliAmps instead of just pin readings
* Improved adherence to the NMRA DCC specification * Improved adherence to the NMRA DCC specification
@ -50,6 +52,21 @@ in config.h.
* Railcom cutout (beta) * Railcom cutout (beta)
* Simpler, modular, faster code with an API Library for developers for easy expansion * Simpler, modular, faster code with an API Library for developers for easy expansion
* New features and functions in JMRI * New features and functions in JMRI
* Ability to join MAIN and PROG tracks into one MAIN track to run your locos
* "Drive-Away" feature - Throttles with support, like Engine Driver, can allow a loco to be programmed on a usable, electrically isolated programming track and then drive off onto the main track
* Diagnostic commands to test decoders that aren't reading or writing correctly
* Support for Uno, Nano, Mega, Nano Every and Teensy microcontrollers
* User Functions: Filter regular commands (like a turnout or output command) and pass it to your own function or accessory
* Support for LCN (layout control nodes)
* mySetup.h file that acts like an Autoexec.Bat command to send startup commands to the CS
* High Accuracty Waveform option for rock steady DCC signals
* New current response outputs current in mA, overlimit current, and maximum board capable current. Support for new current meter in JMRI
* USB Browser based EX-WebThrottle
* New, simpler, function control command
* Number of locos discovery command `<#>`
* Emergency stop command <!>
* Release cabs from memory command <-> all cabs, <- CAB> for just one loco address
* Automatic slot (register) management
* Automation (coming soon) * Automation (coming soon)
NOTE: DCC-EX is a major rewrite to the code. We started over and rebuilt it from the ground up! For what that means to you, click [HERE](notes/rewrite.md). NOTE: DCC-EX is a major rewrite to the code. We started over and rebuilt it from the ground up! For what that means to you, click [HERE](notes/rewrite.md).

View File

@ -0,0 +1,85 @@
The DCC-EX Team is pleased to release CommandStation-EX-v3.0.0 as a Production Release. This release is a major re-write of earlier versions. We've re-architected the code-base so that it can better handle new features going forward. Download the compressed files here:
**Downloads (zip and tar.gz) below. These are named without version number in the folder name to make the Arduino IDE happy.**
[CommandStation-EX.zip](https://github.com/DCC-EX/CommandStation-EX/files/5611333/CommandStation-EX.zip)
[CommandStation-EX.tar.gz](https://github.com/DCC-EX/CommandStation-EX/files/5611335/CommandStation-EX.tar.gz)
**Known Bugs:**
- **Consisting through JMRI** - currently does not work in this release. A number of testers were able to develop a work around. If interested enter a Support Ticket.
- **Wi-Fi** - works, but can be challenging to use if you want to switch between AP mode and STA station mode.
- **Pololu Motor Shield** - is supported with this release, but the user may have to play around with some timings to enable programming mode due to limitation in its current sensing circuitry
**Summary of the key new features added to CommandStation-EX V3.0.0:**
- **WiFi Support** - AP and station modes supported. Auto-detection of an ESP8266 WiFi module with AT firmware on a Mega's serial port. Connection to JMRI and WiThrottle clients.
- **Withrottle Integrations** - Act as a host for four WiThrottle clients concurrently.
- **Add LCD/OLED support** - OLED supported on Mega only
- **Improved CV programming routines** - checks for length of CV pulse, and breaks out of the wait state once it has received an ACK, now reading one CV per second.
- **Improved current sensing** - rewrote current sensing routines for safer operation. Current thresholds based on milliamps, not magic numbers
- **Individual track power control** - Ability to toggle power on either or both tracks, and to "JOIN" the tracks and make them output the same waveform for multiple power districts.
- **Single or Dual-Pin PWM output** - Allows control of H-bridges with PH/EN or dual PWM inputs
- **New, simpler function command** - ```<F>``` command allows setting functions based on their number, not based on a code as in ```<f>```
- **Function reminders** - Function reminders are sent in addition to speed reminders
- **Functions to F28** - All NMRA functions are now supported
- **Filters and user functions** - Ability to filter commands in the parser and execute custom code based on them
- **Diagnostic ```<D>``` commands** - See documentation for a full list of new diagnostic commands
- **Rewrote DCC++ Parser** - more efficient operation, accepts multi-char input and uses less RAM
- **Rewritten waveform generator** - capable of using any pin for DCC waveform out, eliminating the need for jumpers
- **Rewritten packet generator** - Simplify and make smaller, remove idea of "registers" from original code
- **Add free RAM messages** - Free RAM messages are now printed whenever there is a decerase in available RAM
- **Fix EEPROM bugs**
- **Number of locos discovery command** - ```<#>``` command
- **Support for more locomotives** - 20 locomotives on an UNO and 50 an a Mega.
- **Automatic slot managment** - slot variable in throttle/function commands are ignored and slot management is taken care of automatically. ```<!>``` command added to release locos from memory.
**Key Contributors**
**Project Lead**
- Fred Decker - Holly Springs, North Carolina, USA (FlightRisk)
**CommandStation-EX Developers**
- Chris Harlow - Bournemouth, UK (UKBloke)
- Harald Barth - Stockholm, Sweden (Haba)
- Fred Decker - Holly Springs, North Carolina, USA (FlightRisk)
- Dave Cutting - Logan, Utah, USA (Dave Cutting/ David Cutting)
- M Steve Todd - - Engine Driver and JMRI Interface
- Scott Catalanno - Pennsylvania
- Gregor Baues - Île-de-France, France (grbba)
**exInstaller Software**
- Anthony W - Dayton, Ohio, USA (Dex, Dex++)
**Website and Documentation**
- Mani Kumar - Bangalor, India (Mani / Mani Kumar)
- Fred Decker - Holly Springs, North Carolina, USA (FlightRisk)
- Dave Cutting - Logan, Utah, USA (Dave Cutting/ David Cutting)
- Roger Beschizza - Dorset, UK (Roger Beschizza)
- Keith Ledbetter - Chicago, Illinois, USA (Keith Ledbetter)
-Kevin Smith - (KCSmith)
**Beta Testing / Release Management / Support**
- Larry Dribin - Release Management
- Keith Ledbetter
- BradVan der Elst
- Andrew Pye
- Mike Bowers
- Randy McKenzie
- Roberto Bravin
- Sim Brigden
- Alan Lautenslager
- Martin Bafver
- Mário André Silva
- Anthony Kochevar
- Gajanatha Kobbekaduwe
- Sumner Patterson
- Paul - Virginia, USA
**Downloads (zip and tar.gz) below. These are named without version number in the folder name to make the Arduino IDE happy.**
[CommandStation-EX.zip](https://github.com/DCC-EX/CommandStation-EX/files/5611333/CommandStation-EX.zip)
[CommandStation-EX.tar.gz](https://github.com/DCC-EX/CommandStation-EX/files/5611335/CommandStation-EX.tar.gz)

View File

@ -0,0 +1,206 @@
The DCC-EX Team is pleased to release CommandStation-EX-v3.1.0 as a Production Release. Release v3.1.0 is a minor release that adds additional features and fixes a number of bugs. With the number of new features, this could have easily been a major release. The team is continually improving the architecture of DCC++EX to make it more flexible and optimizing the code so as to get more performance from the Arduino (and other) microprocessors. This release includes all of the Point Releases from v3.0.1 to v3.0.16.
**Downloads (zip and tar.gz) below. These are named without version number in the folder name to make the Arduino IDE happy.**
[CommandStation-EX.zip](https://github.com/DCC-EX/CommandStation-EX/releases/download/v3.1.0-Prod/CommandStation-EX.zip)
[CommandStation-EX.tar.gz](https://github.com/DCC-EX/CommandStation-EX/releases/download/v3.1.0-Prod/CommandStation-EX.tar.gz)
**Known Issues**
- **Wi-Fi** - works, but requires sending <AT> commands from a serial monitor if you want to switch between AP mode and STA station mode after initial setup
- **Pololu Motor Shield** - is supported with this release, but the user may have to adjust timings to enable programming mode due to limitation in its current sensing circuitry
#### Summary of key features and/or bug fixes by Point Release
**Summary of the key new features added to CommandStation-EX V3.0.16**
- Ignore CV1 bit 7 read if rejected by a non NMRA compliant decoder when identifying loco id
**Summary of the key new features added to CommandStation-EX V3.0.15**
- Send function commands just once instead of repeating them 4 times
**Summary of the key new features added to CommandStation-EX V3.0.14**
- Add feature to tolerate decoders that incorrectly have gaps in their ACK pulse
- Provide proper track power management when joining and unjoining tracks with <1 JOIN>
**Summary of the key new features added to CommandStation-EX V3.0.13**
- Fix for CAB Functions greater than 127
**Summary of the key new features added to CommandStation-EX V3.0.12**
- Fixed clear screen issue for nanoEvery and nanoWifi
**Summary of the key new features added to CommandStation-EX V3.0.11**
- Reorganized files for support of 128 speed steps
**Summary of the key new features added to CommandStation-EX V3.0.10**
- Added Support for the Teensy 3.2, 3.5, 3.6, 4.0 and 4.1 MCUs
- No functional change just changes to avoid complier warnings for Teensy/nanoEvery
**Summary of the key new features added to CommandStation-EX V3.0.9**
- Rearranges serial newlines for the benefit of JMRI
- Major update for efficiencies in displays (LCD, OLED)
- Add I2C Support functions
**Summary of the key new features added to CommandStation-EX V3.0.8**
- Wraps <* *> around DIAGS for the benefit of JMRI
**Summary of the key new features added to CommandStation-EX V3.0.7**
- Implemented support for older 28 apeed step decoders - Option to turn on 28 step speed decoders in addition to 128. If set, all locos will use 28 steps.
- Improved overload messages with raw values (relative to offset)
**Summary of the key new features added to CommandStation-EX V3.0.6**
- Prevent compiler warning about deprecated B constants
- Fix Bug that did not let us transmit 5 byte sized packets - 5 Byte commands like PoM (programming on main) were not being sent correctly
- Support for Huge function numbers (DCC BinaryStateControl) - Support Functions beyond F28
- <!> ESTOP all - New command to emergency stop all locos on the main track
- <- [cab]> estop and forget cab/all cabs - Stop and remove loco from the CS. Stops the repeating throttle messages
- `<D RESET>` command to reboot Arduino
- Automatic sensor offset detect
- Improved startup msgs from Motor Drivers (accuracy and auto sense factors)
- Drop post-write verify - No need to double check CV writes. Writes are now even faster.
- Allow current sense pin set to UNUSED_PIN - No need to ground an unused analog current pin. Produce startup warning and callback -2 for prog track cmds.
**Summary of the key new features added to CommandStation-EX V3.0.5**
- Fix Fn Key startup with loco ID and fix state change for F16-28
- Removed ethernet mac config and made it automatic
- Show wifi ip and port on lcd
- Auto load config.example.h with warning
- Dropped example .ino files
- Corrected .ino comments
- Add Pololu fault pin handling
- Waveform speed/simplicity improvements
- Improved pin speed in waveform
- Portability to nanoEvery and UnoWifiRev2 CPUs
- Analog read speed improvements
- Drop need for DIO2 library
- Improved current check code
- Linear command
- Removed need for ArduinoTimers files
- Removed option to choose different timer
- Added EX-RAIL hooks for automation in future version
- Fixed Turnout list
- Allow command keywords in mixed case
- Dropped unused memstream
- PWM pin accuracy if requirements met
**Summary of the key new features added to CommandStation-EX V3.0.4**
- "Drive-Away" Feature - added so that throttles like Engine Driver can allow a loco to be programmed on a usable, electrically isolated programming track and then drive off onto the main track
- WiFi Startup Fixes
**Summary of the key new features added to CommandStation-EX V3.0.3**
- Command to write loco address and clear consist
- Command will allow for consist address
- Startup commands implemented
**Summary of the key new features added to CommandStation-EX V3.0.2:**
- Create new output for current in mA for `<c>` command - New current response outputs current in mA, overlimit current, and maximum board capable current
- Simultaneously update JMRI to handle new current meter
**Summary of the key new features added to CommandStation-EX V3.0.1:**
- Add back fix for jitter
- Add Turnouts, Outputs and Sensors to `<s>` command output
**CommandStation-EX V3.0.0:**
**Release v3.0.0 was a major rewrite if earlier versions of DCC++. The code base was re-architeced and core changes were made to the Waveform generator to reduce overhead and make better use of Arduino.** **Summary of the key new features added in Release v3.0.0 include:**
- **New USB Browser Based Throttle** - WebThrottle-EX is a full front-end to controller to control the CS to run trains.
- **WiFi Support** - AP and station modes supported. Auto-detection of an ESP8266 WiFi module with AT firmware on a Mega's serial port. Connection to JMRI and WiThrottle clients.
- **Withrottle Integrations** - Act as a host for up to four WiThrottle clients concurrently.
- **Add LCD/OLED support** - OLED supported on Mega only
- **Improved CV programming routines** - checks for length of CV pulse, and breaks out of the wait state once it has received an ACK, now reading one CV per second.
- **Improved current sensing** - rewrote current sensing routines for safer operation. Current thresholds based on milliamps, not magic numbers
- **Individual track power control** - Ability to toggle power on either or both tracks, and to "JOIN" the tracks and make them output the same waveform for multiple power districts.
- **Single or Dual-Pin PWM output** - Allows control of H-bridges with PH/EN or dual PWM inputs
- **New, simpler function command** - `<F>` command allows setting functions based on their number, not based on a code as in `<f>`
- **Function reminders** - Function reminders are sent in addition to speed reminders
- **Functions to F28** - All NMRA functions are now supported
- **Filters and user functions** - Ability to filter commands in the parser and execute custom code based on them. (ex: Redirect Turnout commands via NRF24)
- **Diagnostic `<D>` commands** - See documentation for a full list of new diagnostic commands
- **Rewrote DCC++ Parser** - more efficient operation, accepts multi-char input and uses less RAM
- **Rewritten waveform generator** - capable of using any pin for DCC waveform out, eliminating the need for jumpers
- **Rewritten packet generator** - Simplify and make smaller, remove idea of "registers" from original code
- **Add free RAM messages** - Free RAM messages are now printed whenever there is a decerase in available RAM
- **Fix EEPROM bugs**
- **Number of locos discovery command** - `<#>` command
- **Support for more locomotives** - 20 locomotives on an UNO and 50 an a Mega.
- **Automatic slot management** - slot variable in throttle/function commands are ignored and slot management is taken care of automatically. `<->` and `<- CAB>` commands added to release locos from memory and stop packets to the track.
**Key Contributors**
**Project Lead**
- Fred Decker - Holly Springs, North Carolina, USA (FlightRisk)
**CommandStation-EX Developers**
- Chris Harlow - Bournemouth, UK (UKBloke)
- Harald Barth - Stockholm, Sweden (Haba)
- Neil McKechnie - Worcestershire, UK (NeilMck)
- Fred Decker - Holly Springs, North Carolina, USA (FlightRisk)
- Dave Cutting - Logan, Utah, USA (Dave Cutting/ David Cutting)
- M Steve Todd -
- Scott Catalano - Pennsylvania
- Gregor Baues - Île-de-France, France (grbba)
**Engine Driver and JMRI Interface**
- M Steve Todd
**exInstaller Software**
- Anthony W - Dayton, Ohio, USA (Dex, Dex++)
**Website and Documentation**
- Mani Kumar - Bangalor, India (Mani / Mani Kumar)
- Fred Decker - Holly Springs, North Carolina, USA (FlightRisk)
- Dave Cutting - Logan, Utah, USA (Dave Cutting/ David Cutting)
- Roger Beschizza - Dorset, UK (Roger Beschizza)
- Keith Ledbetter - Chicago, Illinois, USA (Keith Ledbetter)
- Kevin Smith - Rochester Hills, Michigan USA (KC Smith)
**WebThrotle-EX**
- Fred Decker - Holly Springs, NC (FlightRisk/FrightRisk)
- Mani Kumar - Bangalor, India (Mani /Mani Kumar)
- Matt H - Somewhere in Europe
**Beta Testing / Release Management / Support**
- Larry Dribin - Release Management
- Kevin Smith - Rochester Hills, Michigan USA (KC Smith)
- Keith Ledbetter
- BradVan der Elst
- Andrew Pye
- Mike Bowers
- Randy McKenzie
- Roberto Bravin
- Sim Brigden
- Alan Lautenslager
- Martin Bafver
- Mário André Silva
- Anthony Kochevar
- Gajanatha Kobbekaduwe
- Sumner Patterson
- Paul - Virginia, USA
**Downloads (zip and tar.gz) below. These are named without version number in the folder name to make the Arduino IDE happy.**
[CommandStation-EX.zip](https://github.com/DCC-EX/CommandStation-EX/releases/download/v3.1.0-Prod/CommandStation-EX.zip)
[CommandStation-EX.tar.gz](https://github.com/DCC-EX/CommandStation-EX/releases/download/v3.1.0-Prod/CommandStation-EX.tar.gz)

View File

@ -39,7 +39,6 @@ bool Turnout::activate(int n,bool state){
Turnout * tt=get(n); Turnout * tt=get(n);
if (tt==NULL) return false; if (tt==NULL) return false;
tt->activate(state); tt->activate(state);
EEStore::store();
turnoutlistHash++; turnoutlistHash++;
return true; return true;
} }
@ -68,7 +67,9 @@ void Turnout::activate(bool state) {
PWMServoDriver::setServo(data.tStatus & STATUS_PWMPIN, (data.inactiveAngle+(state?data.moveAngle:0))); PWMServoDriver::setServo(data.tStatus & STATUS_PWMPIN, (data.inactiveAngle+(state?data.moveAngle:0)));
else else
DCC::setAccessory(data.address,data.subAddress, state); DCC::setAccessory(data.address,data.subAddress, state);
EEStore::store(); // Save state if stored in EEPROM
if (EEStore::eeStore->data.nTurnouts > 0 && num > 0)
EEPROM.put(num, data.tStatus);
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -107,6 +108,7 @@ void Turnout::load(){
if (data.tStatus & STATUS_PWM) tt=create(data.id,data.tStatus & STATUS_PWMPIN, data.inactiveAngle,data.moveAngle); if (data.tStatus & STATUS_PWM) tt=create(data.id,data.tStatus & STATUS_PWMPIN, data.inactiveAngle,data.moveAngle);
else tt=create(data.id,data.address,data.subAddress); else tt=create(data.id,data.address,data.subAddress);
tt->data.tStatus=data.tStatus; tt->data.tStatus=data.tStatus;
tt->num=EEStore::pointer()+offsetof(TurnoutData,tStatus); // Save pointer to status byte within EEPROM
EEStore::advance(sizeof(tt->data)); EEStore::advance(sizeof(tt->data));
#ifdef EESTOREDEBUG #ifdef EESTOREDEBUG
tt->print(tt); tt->print(tt);
@ -126,6 +128,7 @@ void Turnout::store(){
#ifdef EESTOREDEBUG #ifdef EESTOREDEBUG
tt->print(tt); tt->print(tt);
#endif #endif
tt->num=EEStore::pointer()+offsetof(TurnoutData,tStatus); // Save pointer to tstatus byte within EEPROM
EEPROM.put(EEStore::pointer(),tt->data); EEPROM.put(EEStore::pointer(),tt->data);
EEStore::advance(sizeof(tt->data)); EEStore::advance(sizeof(tt->data));
tt=tt->nextTurnout; tt=tt->nextTurnout;

View File

@ -54,6 +54,8 @@ class Turnout {
#ifdef EESTOREDEBUG #ifdef EESTOREDEBUG
void print(Turnout *tt); void print(Turnout *tt);
#endif #endif
private:
int num; // EEPROM address of tStatus in TurnoutData struct, or zero if not stored.
}; // Turnout }; // Turnout
#endif #endif

View File

@ -171,16 +171,16 @@ wifiSerialState WifiInterface::setup2(const FSH* SSid, const FSH* password,
#ifdef DONT_TOUCH_WIFI_CONF #ifdef DONT_TOUCH_WIFI_CONF
DIAG(F("DONT_TOUCH_WIFI_CONF was set: Using existing config")); DIAG(F("DONT_TOUCH_WIFI_CONF was set: Using existing config"));
#else #else
StringFormatter::send(wifiStream, F("AT+CWMODE=1\r\n")); // configure as "station" = WiFi client
checkForOK(1000, true); // Not always OK, sometimes "no change"
// Older ES versions have AT+CWJAP, newer ones have AT+CWJAP_CUR and AT+CWHOSTNAME // Older ES versions have AT+CWJAP, newer ones have AT+CWJAP_CUR and AT+CWHOSTNAME
StringFormatter::send(wifiStream, F("AT+CWJAP?\r\n")); StringFormatter::send(wifiStream, F("AT+CWJAP_CUR?\r\n"));
if (checkForOK(2000, true)) { if (!(checkForOK(2000, true))) {
oldCmd=true; oldCmd=true;
while (wifiStream->available()) StringFormatter::printEscape( wifiStream->read()); /// THIS IS A DIAG IN DISGUISE while (wifiStream->available()) StringFormatter::printEscape( wifiStream->read()); /// THIS IS A DIAG IN DISGUISE
} }
StringFormatter::send(wifiStream, F("AT+CWMODE%s=1\r\n"), oldCmd ? "" : "_CUR"); // configure as "station" = WiFi client
checkForOK(1000, true); // Not always OK, sometimes "no change"
const char *yourNetwork = "Your network "; const char *yourNetwork = "Your network ";
if (strncmp_P(yourNetwork, (const char*)SSid, 13) == 0 || strncmp_P("", (const char*)SSid, 13) == 0) { if (strncmp_P(yourNetwork, (const char*)SSid, 13) == 0 || strncmp_P("", (const char*)SSid, 13) == 0) {
if (strncmp_P(yourNetwork, (const char*)password, 13) == 0) { if (strncmp_P(yourNetwork, (const char*)password, 13) == 0) {
@ -199,40 +199,40 @@ wifiSerialState WifiInterface::setup2(const FSH* SSid, const FSH* password,
} else { } else {
// SSID was configured, so we assume station (client) mode. // SSID was configured, so we assume station (client) mode.
if (oldCmd) { if (oldCmd) {
// AT command early version supports CWJAP/CWSAP // AT command early version supports CWJAP/CWSAP
StringFormatter::send(wifiStream, F("AT+CWJAP=\"%S\",\"%S\"\r\n"), SSid, password); StringFormatter::send(wifiStream, F("AT+CWJAP=\"%S\",\"%S\"\r\n"), SSid, password);
ipOK = checkForOK(WIFI_CONNECT_TIMEOUT, true); ipOK = checkForOK(WIFI_CONNECT_TIMEOUT, true);
} else { } else {
// later version supports CWJAP_CUR // later version supports CWJAP_CUR
StringFormatter::send(wifiStream, F("AT+CWHOSTNAME=\"%S\"\r\n"), hostname); // Set Host name for Wifi Client StringFormatter::send(wifiStream, F("AT+CWHOSTNAME=\"%S\"\r\n"), hostname); // Set Host name for Wifi Client
checkForOK(2000, true); // dont care if not supported checkForOK(2000, true); // dont care if not supported
StringFormatter::send(wifiStream, F("AT+CWJAP_CUR=\"%S\",\"%S\"\r\n"), SSid, password); StringFormatter::send(wifiStream, F("AT+CWJAP_CUR=\"%S\",\"%S\"\r\n"), SSid, password);
ipOK = checkForOK(WIFI_CONNECT_TIMEOUT, true); ipOK = checkForOK(WIFI_CONNECT_TIMEOUT, true);
} }
if (ipOK) { if (ipOK) {
// But we really only have the ESSID and password correct // But we really only have the ESSID and password correct
// Let's check for IP (via DHCP) // Let's check for IP (via DHCP)
ipOK = false; ipOK = false;
StringFormatter::send(wifiStream, F("AT+CIFSR\r\n")); StringFormatter::send(wifiStream, F("AT+CIFSR\r\n"));
if (checkForOK(5000, F("+CIFSR:STAIP"), true,false)) if (checkForOK(5000, F("+CIFSR:STAIP"), true,false))
if (!checkForOK(1000, F("0.0.0.0"), true,false)) if (!checkForOK(1000, F("0.0.0.0"), true,false))
ipOK = true; ipOK = true;
} }
} }
if (!ipOK) { if (!ipOK) {
// If we have not managed to get this going in station mode, go for AP mode // If we have not managed to get this going in station mode, go for AP mode
// StringFormatter::send(wifiStream, F("AT+RST\r\n")); // StringFormatter::send(wifiStream, F("AT+RST\r\n"));
// checkForOK(1000, true); // Not always OK, sometimes "no change" // checkForOK(1000, true); // Not always OK, sometimes "no change"
int i=0; int i=0;
do { do {
// configure as AccessPoint. Try really hard as this is the // configure as AccessPoint. Try really hard as this is the
// last way out to get any Wifi connectivity. // last way out to get any Wifi connectivity.
StringFormatter::send(wifiStream, F("AT+CWMODE=2\r\n")); StringFormatter::send(wifiStream, F("AT+CWMODE%s=2\r\n"), oldCmd ? "" : "_CUR");
} while (!checkForOK(1000+i*500, true) && i++<10); } while (!checkForOK(1000+i*500, true) && i++<10);
while (wifiStream->available()) StringFormatter::printEscape( wifiStream->read()); /// THIS IS A DIAG IN DISGUISE while (wifiStream->available()) StringFormatter::printEscape( wifiStream->read()); /// THIS IS A DIAG IN DISGUISE
@ -262,7 +262,7 @@ wifiSerialState WifiInterface::setup2(const FSH* SSid, const FSH* password,
oldCmd ? "" : "_CUR", macTail, macTail, channel); oldCmd ? "" : "_CUR", macTail, macTail, channel);
} else { } else {
// password configured by user // password configured by user
StringFormatter::send(wifiStream, F("AT+CWSAP%s=\"DCCEX_%s\",\"%S\",%d,4\r\n"), oldCmd ? "" : "_CUR", StringFormatter::send(wifiStream, F("AT+CWSAP%s=\"DCCEX_%s\",\"%S\",%d,4\r\n"), oldCmd ? "" : "_CUR",
macTail, password, channel); macTail, password, channel);
} }
} while (!checkForOK(WIFI_CONNECT_TIMEOUT, true) && i++<2); // do twice if necessary but ignore failure as AP mode may still be ok } while (!checkForOK(WIFI_CONNECT_TIMEOUT, true) && i++<2); // do twice if necessary but ignore failure as AP mode may still be ok

View File

@ -76,7 +76,7 @@ The configuration file for DCC-EX Command Station
// is set (recommended), that password will be used for AP mode. // is set (recommended), that password will be used for AP mode.
// The AP mode password must be at least 8 characters long. // The AP mode password must be at least 8 characters long.
// //
// Your SSID may not conain ``"'' (double quote, ASCII 0x22). // Your SSID may not contain ``"'' (double quote, ASCII 0x22).
#define WIFI_SSID "Your network name" #define WIFI_SSID "Your network name"
// //
// WIFI_PASSWORD is the network password for your home network or if // WIFI_PASSWORD is the network password for your home network or if

View File

@ -1,128 +1,190 @@
The DCC-EX Team is pleased to release CommandStation-EX-v3.0.0 as a Production Release. This release is a major re-write of earlier versions. We've re-architected the code-base so that it can better handle new features going forward. The DCC-EX Team is pleased to release CommandStation-EX-v3.1.0 as a Production Release. Release v3.1.0 is a minor release that adds additional features and fixes a number of bugs. With the number of new features, this could have easily been a major release. The team is continually improving the architecture of DCC++EX to make it more flexible and optimizing the code so as to get more performance from the Arduino (and other) microprocessors. This release includes all of the Point Releases from v3.0.1 to v3.0.16.
**Known Bugs:** **Downloads (zip and tar.gz) below. These are named without version number in the folder name to make the Arduino IDE happy.**
- **Consisting through JMRI** - currently does not work in this release. You may use the <M> command to do this manually.
- **Wi-Fi** - works, but can be challenging to use if you want to switch between AP mode and STA station mode. [CommandStation-EX.zip](https://github.com/DCC-EX/CommandStation-EX/releases/download/v3.1.0-Prod/CommandStation-EX.zip)
- **Pololu Motor Shield** - is supported with this release, but the user may have to play around with some timings to enable programming mode due to limitation in its current sensing circuitry [CommandStation-EX.tar.gz](https://github.com/DCC-EX/CommandStation-EX/releases/download/v3.1.0-Prod/CommandStation-EX.tar.gz)
**Known Issues**
- **Wi-Fi** - works, but requires sending <AT> commands from a serial monitor if you want to switch between AP mode and STA station mode after initial setup
- **Pololu Motor Shield** - is supported with this release, but the user may have to adjust timings to enable programming mode due to limitation in its current sensing circuitry
#### Summary of key features and/or bug fixes by Point Release
**Summary of the key new features added to CommandStation-EX V3.0.16**
- Ignore CV1 bit 7 read if rejected by a non NMRA compliant decoder when identifying loco id
**Summary of the key new features added to CommandStation-EX V3.0.15**
- Send function commands just once instead of repeating them 4 times
**Summary of the key new features added to CommandStation-EX V3.0.14**
- Add feature to tolerate decoders that incorrectly have gaps in their ACK pulse
- Provide proper track power management when joining and unjoining tracks with <1 JOIN>
**Summary of the key new features added to CommandStation-EX V3.0.13**
- Fix for CAB Functions greater than 127
**Summary of the key new features added to CommandStation-EX V3.0.12**
- Fixed clear screen issue for nanoEvery and nanoWifi
**Summary of the key new features added to CommandStation-EX V3.0.11**
- Reorganized files for support of 128 speed steps
**Summary of the key new features added to CommandStation-EX V3.0.10**
- Added Support for the Teensy 3.2, 3.5, 3.6, 4.0 and 4.1 MCUs
- No functional change just changes to avoid complier warnings for Teensy/nanoEvery
**Summary of the key new features added to CommandStation-EX V3.0.9**
- Rearranges serial newlines for the benefit of JMRI
- Major update for efficiencies in displays (LCD, OLED)
- Add I2C Support functions
**Summary of the key new features added to CommandStation-EX V3.0.8**
- Wraps <* *> around DIAGS for the benefit of JMRI
**Summary of the key new features added to CommandStation-EX V3.0.7** **Summary of the key new features added to CommandStation-EX V3.0.7**
- **Support for 28 Speed steps** - Option to turn on 28 step speed decoders in addition to 128. If set, all locos will use 28 steps.
- **Improved overload messages with raw values (relative to offset)** - Implemented support for older 28 apeed step decoders - Option to turn on 28 step speed decoders in addition to 128. If set, all locos will use 28 steps.
- Improved overload messages with raw values (relative to offset)
**Summary of the key new features added to CommandStation-EX V3.0.6** **Summary of the key new features added to CommandStation-EX V3.0.6**
- **Prevent compiler warning about deprecated B constants** - Prevent compiler warning about deprecated B constants
- **Fix Bug that did not let us transmit 5 byte sized packets** - 5 Byte commands like PoM (programming on main) were not being sent correctly - Fix Bug that did not let us transmit 5 byte sized packets - 5 Byte commands like PoM (programming on main) were not being sent correctly
- **Huge function numbers (DCC BinaryStateControl)** - Support Functions beyond F28 - Support for Huge function numbers (DCC BinaryStateControl) - Support Functions beyond F28
- **<!> ESTOP all** - New command to emergency stop all locos on the main track - <!> ESTOP all - New command to emergency stop all locos on the main track
- **<- [cab]> estop and forget cab/all cabs** - Stop and remove loco from the CS. Stops the repeating throttle messages - <- [cab]> estop and forget cab/all cabs - Stop and remove loco from the CS. Stops the repeating throttle messages
- **``<D RESET>`` command to reboot arduino** - `<D RESET>` command to reboot Arduino
- **Automatic sensor offset detect** - - Automatic sensor offset detect
- **Improved startup msgs from Motor Drivers (accuracy and auto sense factors)** - - Improved startup msgs from Motor Drivers (accuracy and auto sense factors)
- **Drop post-write verify** - No need to double check CV writes. Writes are now even faster. - Drop post-write verify - No need to double check CV writes. Writes are now even faster.
- **Allow current sene pin set to UNUSED_PIN** - No need to ground an unused analog current pin. Produce startup warning and callback -2 for prog track cmds. - Allow current sense pin set to UNUSED_PIN - No need to ground an unused analog current pin. Produce startup warning and callback -2 for prog track cmds.
**Summary of the key new features added to CommandStation-EX V3.0.5** **Summary of the key new features added to CommandStation-EX V3.0.5**
- **Fix Fn Key startup with loco ID and fix state change for F16-28**
- removed ethernet mac config and made it automatic - Fix Fn Key startup with loco ID and fix state change for F16-28
- show wifi ip and port on lcd - Removed ethernet mac config and made it automatic
- auto load config.example.h with warningh - Show wifi ip and port on lcd
- dropped example .ino files - Auto load config.example.h with warning
- corrected .ino comments - Dropped example .ino files
- pololu fault pin handling - Corrected .ino comments
- waveform speed/simplicity improvements - Add Pololu fault pin handling
- improved pin speed in waveform - Waveform speed/simplicity improvements
- portability to nanoEvery and UnoWifiRev2 CPUs - Improved pin speed in waveform
- analog read speed improvements - Portability to nanoEvery and UnoWifiRev2 CPUs
- drop need for DIO2 library - Analog read speed improvements
- improved current check code - Drop need for DIO2 library
- linear <a> command - Improved current check code
- removed need for ArduinoTimers files - Linear command
- removed <D DCC SLOW> - Removed need for ArduinoTimers files
- Removed option to choose different timer - Removed option to choose different timer
- Added EX-RAIL hooks for later - Added EX-RAIL hooks for automation in future version
- fixed Turnout list - Fixed Turnout list
- allow command keywords in mixed case - Allow command keywords in mixed case
- dropped unused memstream - Dropped unused memstream
- PWM pin accuracy if requirements met. - PWM pin accuracy if requirements met
**Summary of the key new features added to CommandStation-EX V3.0.4** **Summary of the key new features added to CommandStation-EX V3.0.4**
- **"Drive-Away" Feature added so that throttles like Engine Driver can allow a loco to be programmed on a usable, electrically isolated programming track and then drive off onto the main track.
- **WiFi Startup Fixes** - "Drive-Away" Feature - added so that throttles like Engine Driver can allow a loco to be programmed on a usable, electrically isolated programming track and then drive off onto the main track
- WiFi Startup Fixes
**Summary of the key new features added to CommandStation-EX V3.0.3** **Summary of the key new features added to CommandStation-EX V3.0.3**
- **<W addr> command to write loco address and clear consist**
- **<R> command will allow for consist address** - Command to write loco address and clear consist
- **Startup commands implemented** - Command will allow for consist address
- Startup commands implemented
**Summary of the key new features added to CommandStation-EX V3.0.2:** **Summary of the key new features added to CommandStation-EX V3.0.2:**
- **Create new output for current in mA for ``<c>`` command** - New current response outputs current in mA, overlimit current, and maximum board capable current
- **Simultaneously update JMRI to handle new current meter** - Create new output for current in mA for `<c>` command - New current response outputs current in mA, overlimit current, and maximum board capable current
- Simultaneously update JMRI to handle new current meter
**Summary of the key new features added to CommandStation-EX V3.0.1:** **Summary of the key new features added to CommandStation-EX V3.0.1:**
- **Add back fix for jitter**
- **Add Turnouts, Outputs and Sensors to ```<s>``` command output**
**Summary of the key new features added to CommandStation-EX V3.0.0:** - Add back fix for jitter
- Add Turnouts, Outputs and Sensors to `<s>` command output
- **New USB Browser Based Throttle** - WebThrottle-EX is a full front-end to controller to control the CS to run trains. **CommandStation-EX V3.0.0:**
- **WiFi Support** - AP and station modes supported. Auto-detection of an ESP8266 WiFi module with AT firmware on a Mega's serial port. Connection to JMRI and WiThrottle clients.
- **Withrottle Integrations** - Act as a host for up to four WiThrottle clients concurrently.
- **Add LCD/OLED support** - OLED supported on Mega only
- **Improved CV programming routines** - checks for length of CV pulse, and breaks out of the wait state once it has received an ACK, now reading one CV per second.
- **Improved current sensing** - rewrote current sensing routines for safer operation. Current thresholds based on milliamps, not magic numbers
- **Individual track power control** - Ability to toggle power on either or both tracks, and to "JOIN" the tracks and make them output the same waveform for multiple power districts.
- **Single or Dual-Pin PWM output** - Allows control of H-bridges with PH/EN or dual PWM inputs
- **New, simpler function command** - ```<F>``` command allows setting functions based on their number, not based on a code as in ```<f>```
- **Function reminders** - Function reminders are sent in addition to speed reminders
- **Functions to F28** - All NMRA functions are now supported
- **Filters and user functions** - Ability to filter commands in the parser and execute custom code based on them. (ex: Redirect Turnout commands via NRF24)
- **Diagnostic ```<D>``` commands** - See documentation for a full list of new diagnostic commands
- **Rewrote DCC++ Parser** - more efficient operation, accepts multi-char input and uses less RAM
- **Rewritten waveform generator** - capable of using any pin for DCC waveform out, eliminating the need for jumpers
- **Rewritten packet generator** - Simplify and make smaller, remove idea of "registers" from original code
- **Add free RAM messages** - Free RAM messages are now printed whenever there is a decerase in available RAM
- **Fix EEPROM bugs**
- **Number of locos discovery command** - ```<#>``` command
- **Support for more locomotives** - 20 locomotives on an UNO and 50 an a Mega.
- **Automatic slot managment** - slot variable in throttle/function commands are ignored and slot management is taken care of automatically. ```<!>``` command added to release locos from memory.
**Release v3.0.0 was a major rewrite if earlier versions of DCC++. The code base was re-architeced and core changes were made to the Waveform generator to reduce overhead and make better use of Arduino.** **Summary of the key new features added in Release v3.0.0 include:**
- **New USB Browser Based Throttle** - WebThrottle-EX is a full front-end to controller to control the CS to run trains.
- **WiFi Support** - AP and station modes supported. Auto-detection of an ESP8266 WiFi module with AT firmware on a Mega's serial port. Connection to JMRI and WiThrottle clients.
- **Withrottle Integrations** - Act as a host for up to four WiThrottle clients concurrently.
- **Add LCD/OLED support** - OLED supported on Mega only
- **Improved CV programming routines** - checks for length of CV pulse, and breaks out of the wait state once it has received an ACK, now reading one CV per second.
- **Improved current sensing** - rewrote current sensing routines for safer operation. Current thresholds based on milliamps, not magic numbers
- **Individual track power control** - Ability to toggle power on either or both tracks, and to "JOIN" the tracks and make them output the same waveform for multiple power districts.
- **Single or Dual-Pin PWM output** - Allows control of H-bridges with PH/EN or dual PWM inputs
- **New, simpler function command** - `<F>` command allows setting functions based on their number, not based on a code as in `<f>`
- **Function reminders** - Function reminders are sent in addition to speed reminders
- **Functions to F28** - All NMRA functions are now supported
- **Filters and user functions** - Ability to filter commands in the parser and execute custom code based on them. (ex: Redirect Turnout commands via NRF24)
- **Diagnostic `<D>` commands** - See documentation for a full list of new diagnostic commands
- **Rewrote DCC++ Parser** - more efficient operation, accepts multi-char input and uses less RAM
- **Rewritten waveform generator** - capable of using any pin for DCC waveform out, eliminating the need for jumpers
- **Rewritten packet generator** - Simplify and make smaller, remove idea of "registers" from original code
- **Add free RAM messages** - Free RAM messages are now printed whenever there is a decerase in available RAM
- **Fix EEPROM bugs**
- **Number of locos discovery command** - `<#>` command
- **Support for more locomotives** - 20 locomotives on an UNO and 50 an a Mega.
- **Automatic slot management** - slot variable in throttle/function commands are ignored and slot management is taken care of automatically. `<->` and `<- CAB>` commands added to release locos from memory and stop packets to the track.
**Key Contributors** **Key Contributors**
**Project Lead** **Project Lead**
- Fred Decker - Holly Springs, North Carolina, USA (FlightRisk) - Fred Decker - Holly Springs, North Carolina, USA (FlightRisk)
**CommandStation-EX Developers** **CommandStation-EX Developers**
- Chris Harlow - Bournemouth, UK (UKBloke) - Chris Harlow - Bournemouth, UK (UKBloke)
- Harald Barth - Stockholm, Sweden (Haba) - Harald Barth - Stockholm, Sweden (Haba)
- Neil McKechnie - Worcestershire, UK (NeilMck) - Neil McKechnie - Worcestershire, UK (NeilMck)
- Fred Decker - Holly Springs, North Carolina, USA (FlightRisk) - Fred Decker - Holly Springs, North Carolina, USA (FlightRisk)
- Dave Cutting - Logan, Utah, USA (Dave Cutting/ David Cutting) - Dave Cutting - Logan, Utah, USA (Dave Cutting/ David Cutting)
- M Steve Todd - - Engine Driver and JMRI Interface - M Steve Todd -
- Scott Catalanno - Pennsylvania - Scott Catalano - Pennsylvania
- Gregor Baues - Île-de-France, France (grbba) - Gregor Baues - Île-de-France, France (grbba)
**Engine Driver and JMRI Interface**
- M Steve Todd
**exInstaller Software** **exInstaller Software**
- Anthony W - Dayton, Ohio, USA (Dex, Dex++) - Anthony W - Dayton, Ohio, USA (Dex, Dex++)
**Website and Documentation** **Website and Documentation**
- Mani Kumar - Bangalor, India (Mani / Mani Kumar) - Mani Kumar - Bangalor, India (Mani / Mani Kumar)
- Fred Decker - Holly Springs, North Carolina, USA (FlightRisk) - Fred Decker - Holly Springs, North Carolina, USA (FlightRisk)
- Dave Cutting - Logan, Utah, USA (Dave Cutting/ David Cutting) - Dave Cutting - Logan, Utah, USA (Dave Cutting/ David Cutting)
- Roger Beschizza - Dorset, UK (Roger Beschizza) - Roger Beschizza - Dorset, UK (Roger Beschizza)
- Keith Ledbetter - Chicago, Illinois, USA (Keith Ledbetter) - Keith Ledbetter - Chicago, Illinois, USA (Keith Ledbetter)
- Kevin Smith - (KCSmith) - Kevin Smith - Rochester Hills, Michigan USA (KC Smith)
**WebThrotle-EX** **WebThrotle-EX**
- Fred Decker - Holly Springs, NC (FlightRisk/FrightRisk) - Fred Decker - Holly Springs, NC (FlightRisk/FrightRisk)
- Mani Kumar - Bangalor, India (Mani /Mani Kumar) - Mani Kumar - Bangalor, India (Mani /Mani Kumar)
- Matt H - Somewhere in Europe - Matt H - Somewhere in Europe
**Beta Testing / Release Management / Support** **Beta Testing / Release Management / Support**
- Larry Dribin - Release Management
- Larry Dribin - Release Management
- Kevin Smith - Rochester Hills, Michigan USA (KC Smith)
- Keith Ledbetter - Keith Ledbetter
- BradVan der Elst - BradVan der Elst
- Andrew Pye - Andrew Pye
@ -137,3 +199,8 @@ The DCC-EX Team is pleased to release CommandStation-EX-v3.0.0 as a Production R
- Gajanatha Kobbekaduwe - Gajanatha Kobbekaduwe
- Sumner Patterson - Sumner Patterson
- Paul - Virginia, USA - Paul - Virginia, USA
**Downloads (zip and tar.gz) below. These are named without version number in the folder name to make the Arduino IDE happy.**
[CommandStation-EX.zip](https://github.com/DCC-EX/CommandStation-EX/releases/download/v3.1.0-Prod/CommandStation-EX.zip)
[CommandStation-EX.tar.gz](https://github.com/DCC-EX/CommandStation-EX/releases/download/v3.1.0-Prod/CommandStation-EX.tar.gz)

View File

@ -3,7 +3,13 @@
#include "StringFormatter.h" #include "StringFormatter.h"
#define VERSION "3.0.11" #define VERSION "3.1.0"
// 3.0.16 Ignore CV1 bit 7 read rejected by decoder when identifying loco id.
// 3.0.15 only send function commands once, not 4 times
// 3.0.14 gap in ack tolerant fix, prog track power management over join fix.
// 3.0.13 Functions>127 fix
// 3.0.12 Fix HOSTNAME function for STA mode for WiFi
// 3.0.11 28 speedstep support
// 3.0.10 Teensy Support // 3.0.10 Teensy Support
// 3.0.9 rearranges serial newlines for the benefit of JMRI. // 3.0.9 rearranges serial newlines for the benefit of JMRI.
// 3.0.8 Includes <* *> wraps around DIAGs for the benefit of JMRI. // 3.0.8 Includes <* *> wraps around DIAGs for the benefit of JMRI.