From 9d48f696d21da471cfa434dcf486e8aa051fc409 Mon Sep 17 00:00:00 2001 From: "Hans R. Tanner" Date: Tue, 4 Oct 2022 08:42:07 -0400 Subject: [PATCH 1/7] fork ceated --- DCCEXParser.cpp | 20 ++++++++++++++++++-- DCCWaveform.cpp | 8 ++++++++ DCCWaveform.h | 25 +++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index b2626001..1550e58e 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -292,6 +292,15 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) return; break; + case 'A': //switch current reporting on/off + if (params==2) { // + { + DCCWaveform::mainTrack.setRMSMode(p[0], stream); + DCCWaveform::progTrack.setRMSMode(p[1], stream); + } + return; + } + break; case 'a': // ACCESSORY or { int address; @@ -487,9 +496,16 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) case 'c': // SEND METER RESPONSES // - StringFormatter::send(stream, F("\n"), DCCWaveform::mainTrack.getCurrentmA(), + if (params==0) + { + StringFormatter::send(stream, F("\n"), round(DCCWaveform::mainTrack.getCurrentmA()), DCCWaveform::mainTrack.getMaxmA(), DCCWaveform::mainTrack.getTripmA()); - StringFormatter::send(stream, F("\n"), DCCWaveform::mainTrack.get1024Current()); //'a' message deprecated, remove once JMRI 4.22 is available +// StringFormatter::send(stream, F("\n"), DCCWaveform::mainTrack.get1024Current()); //'a' message deprecated, remove once JMRI 4.22 is available + } + else + if (p[0]== 0) + StringFormatter::send(stream, F("\n"), round(DCCWaveform::mainTrack.getCurrentRMS()), round(DCCWaveform::progTrack.getCurrentRMS()), + DCCWaveform::mainTrack.getMaxmA(), DCCWaveform::mainTrack.getTripmA()); return; case 'Q': // SENSORS diff --git a/DCCWaveform.cpp b/DCCWaveform.cpp index 2c5ab9a7..18cbf587 100644 --- a/DCCWaveform.cpp +++ b/DCCWaveform.cpp @@ -24,6 +24,7 @@ #include +#include "StringFormatter.h" #include "DCCWaveform.h" #include "DCCTimer.h" #include "DIAG.h" @@ -134,10 +135,17 @@ void DCCWaveform::checkPowerOverload(bool ackManagerActive) { switch (powerMode) { case POWERMODE::OFF: sampleDelay = POWER_SAMPLE_OFF_WAIT; + if (sendCurrentSample || (accuSize > 0)) + StringFormatter::send(outStream, F("\n"), isMainTrack ? 0 : 1, 0); break; case POWERMODE::ON: // Check current lastCurrent=motorDriver->getCurrentRaw(); + if (sendCurrentSample) + StringFormatter::send(outStream, F("\n"), isMainTrack ? 0 : 1, getCurrentmA()); + else + if (accuSize > 0) + currAccu = (currAccu * accuFact) + (sq((float)getCurrentmA())); if (lastCurrent < 0) { // We have a fault pin condition to take care of lastCurrent = -lastCurrent; diff --git a/DCCWaveform.h b/DCCWaveform.h index 3838b8ea..08cd63c4 100644 --- a/DCCWaveform.h +++ b/DCCWaveform.h @@ -72,6 +72,22 @@ class DCCWaveform { return motorDriver->raw2mA(lastCurrent); return 0; } + inline void setRMSMode(byte newMode, Print* stream) { //0: OFF 1: Broadcast mA Reading >1: Internal calc buffer size + outStream = stream; + sendCurrentSample = newMode == 1; + accuSize = newMode; + if (newMode > 1) + { + accuFact = (float)(newMode - 1) / newMode; + currAccu = 0; + } + } + inline float getCurrentRMS() { + if (accuSize == 0) + return 0; + else + return sqrt(currAccu / accuSize); + } inline int getMaxmA() { if (maxmA == 0) { //only calculate this for first request, it doesn't change maxmA = motorDriver->raw2mA(motorDriver->getRawCurrentTripValue()); //TODO: replace with actual max value or calc @@ -102,6 +118,10 @@ class DCCWaveform { inline bool canMeasureCurrent() { return motorDriver->canMeasureCurrent(); }; + inline void setReportCurrent(bool newStatus, Print *stream) { + sendCurrentSample = newStatus; + outStream = stream; + }; inline void setAckLimit(int mA) { ackLimitmA = mA; } @@ -153,6 +173,11 @@ class DCCWaveform { unsigned long power_sample_overload_wait = POWER_SAMPLE_OVERLOAD_WAIT; unsigned int power_good_counter = 0; + bool sendCurrentSample; + Print* outStream; + volatile double currAccu = 0; + byte accuSize = 0; + float accuFact = 0; // ACK management (Prog track only) volatile bool ackPending; volatile bool ackDetected; From 5c472e13cc91f8bf74bf6b3311c8a96d5ac3a55c Mon Sep 17 00:00:00 2001 From: "Hans R. Tanner" Date: Tue, 4 Oct 2022 09:26:07 -0400 Subject: [PATCH 2/7] Update DCCWaveform.h Eliminate function using older setup format --- DCCWaveform.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/DCCWaveform.h b/DCCWaveform.h index 08cd63c4..45ecc034 100644 --- a/DCCWaveform.h +++ b/DCCWaveform.h @@ -118,10 +118,10 @@ class DCCWaveform { inline bool canMeasureCurrent() { return motorDriver->canMeasureCurrent(); }; - inline void setReportCurrent(bool newStatus, Print *stream) { - sendCurrentSample = newStatus; - outStream = stream; - }; +// inline void setReportCurrent(bool newStatus, Print *stream) { +// sendCurrentSample = newStatus; +// outStream = stream; +// }; inline void setAckLimit(int mA) { ackLimitmA = mA; } From d286b3cd00bed7ebdfc95ec6d636b1577d17322f Mon Sep 17 00:00:00 2001 From: "Hans R. Tanner" Date: Tue, 4 Oct 2022 09:28:20 -0400 Subject: [PATCH 3/7] Update DCCWaveform.h --- DCCWaveform.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/DCCWaveform.h b/DCCWaveform.h index 45ecc034..ba84531c 100644 --- a/DCCWaveform.h +++ b/DCCWaveform.h @@ -118,10 +118,6 @@ class DCCWaveform { inline bool canMeasureCurrent() { return motorDriver->canMeasureCurrent(); }; -// inline void setReportCurrent(bool newStatus, Print *stream) { -// sendCurrentSample = newStatus; -// outStream = stream; -// }; inline void setAckLimit(int mA) { ackLimitmA = mA; } From a95a4dded2e6a173cf3741a1d3fca820e8798125 Mon Sep 17 00:00:00 2001 From: "Hans R. Tanner" Date: Wed, 5 Oct 2022 19:52:52 -0400 Subject: [PATCH 4/7] add broadcastCurrent --- CommandDistributor.cpp | 6 ++++++ CommandDistributor.h | 1 + DCCEXParser.cpp | 16 ++++++++-------- DCCWaveform.cpp | 16 ++++++++-------- DCCWaveform.h | 40 +++++++++++++++++++--------------------- SerialManager.cpp | 3 ++- 6 files changed, 44 insertions(+), 38 deletions(-) diff --git a/CommandDistributor.cpp b/CommandDistributor.cpp index 9bde2593..dcbce4fd 100644 --- a/CommandDistributor.cpp +++ b/CommandDistributor.cpp @@ -118,6 +118,12 @@ void CommandDistributor::broadcastLoco(byte slot) { #endif } +void CommandDistributor::broadcastCurrent(uint8_t track, uint16_t value) +{ + StringFormatter::send(broadcastBufferWriter,F("\n"), track, value); + broadcast(false); +} + void CommandDistributor::broadcastPower() { bool main=DCCWaveform::mainTrack.getPowerMode()==POWERMODE::ON; bool prog=DCCWaveform::progTrack.getPowerMode()==POWERMODE::ON; diff --git a/CommandDistributor.h b/CommandDistributor.h index a9af3bbd..868cb784 100644 --- a/CommandDistributor.h +++ b/CommandDistributor.h @@ -32,6 +32,7 @@ public : static void broadcastSensor(int16_t id, bool value); static void broadcastTurnout(int16_t id, bool isClosed); static void broadcastPower(); + static void broadcastCurrent(uint8_t track, uint16_t value); static void broadcastText(const FSH * msg); static void forget(byte clientId); private: diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 1550e58e..7e3c78fa 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -293,10 +293,10 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) break; case 'A': //switch current reporting on/off - if (params==2) { // + if ((params==2) && (p[0] <= 1) && (p[1] <= 1)) { // currently only 0,1 higher values reserved for buffer size for local calculation { - DCCWaveform::mainTrack.setRMSMode(p[0], stream); - DCCWaveform::progTrack.setRMSMode(p[1], stream); + DCCWaveform::mainTrack.setRMSMode(p[0]); + DCCWaveform::progTrack.setRMSMode(p[1]); } return; } @@ -496,16 +496,16 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) case 'c': // SEND METER RESPONSES // - if (params==0) +// if (params==0) { StringFormatter::send(stream, F("\n"), round(DCCWaveform::mainTrack.getCurrentmA()), DCCWaveform::mainTrack.getMaxmA(), DCCWaveform::mainTrack.getTripmA()); // StringFormatter::send(stream, F("\n"), DCCWaveform::mainTrack.get1024Current()); //'a' message deprecated, remove once JMRI 4.22 is available } - else - if (p[0]== 0) - StringFormatter::send(stream, F("\n"), round(DCCWaveform::mainTrack.getCurrentRMS()), round(DCCWaveform::progTrack.getCurrentRMS()), - DCCWaveform::mainTrack.getMaxmA(), DCCWaveform::mainTrack.getTripmA()); +// else +// if (p[0]== 0) +// StringFormatter::send(stream, F("\n"), round(DCCWaveform::mainTrack.getCurrentRMS()), round(DCCWaveform::progTrack.getCurrentRMS()), +// DCCWaveform::mainTrack.getMaxmA(), DCCWaveform::mainTrack.getTripmA()); return; case 'Q': // SENSORS diff --git a/DCCWaveform.cpp b/DCCWaveform.cpp index 18cbf587..7b1062f8 100644 --- a/DCCWaveform.cpp +++ b/DCCWaveform.cpp @@ -24,11 +24,11 @@ #include -#include "StringFormatter.h" #include "DCCWaveform.h" #include "DCCTimer.h" #include "DIAG.h" #include "freeMemory.h" +#include "CommandDistributor.h" DCCWaveform DCCWaveform::mainTrack(PREAMBLE_BITS_MAIN, true); DCCWaveform DCCWaveform::progTrack(PREAMBLE_BITS_PROG, false); @@ -135,17 +135,17 @@ void DCCWaveform::checkPowerOverload(bool ackManagerActive) { switch (powerMode) { case POWERMODE::OFF: sampleDelay = POWER_SAMPLE_OFF_WAIT; - if (sendCurrentSample || (accuSize > 0)) - StringFormatter::send(outStream, F("\n"), isMainTrack ? 0 : 1, 0); + if (sendCurrentSample) // || (accuSize > 0)) + CommandDistributor::broadcastCurrent(isMainTrack ? 0 : 1, 0); break; case POWERMODE::ON: // Check current lastCurrent=motorDriver->getCurrentRaw(); - if (sendCurrentSample) - StringFormatter::send(outStream, F("\n"), isMainTrack ? 0 : 1, getCurrentmA()); - else - if (accuSize > 0) - currAccu = (currAccu * accuFact) + (sq((float)getCurrentmA())); + if (sendCurrentSample) // || (accuSize > 0)) + CommandDistributor::broadcastCurrent(isMainTrack ? 0 : 1, getCurrentmA()); +// else +// if (accuSize > 0) +// currAccu = (currAccu * accuFact) + (sq((float)getCurrentmA())); if (lastCurrent < 0) { // We have a fault pin condition to take care of lastCurrent = -lastCurrent; diff --git a/DCCWaveform.h b/DCCWaveform.h index ba84531c..77dec2c1 100644 --- a/DCCWaveform.h +++ b/DCCWaveform.h @@ -25,6 +25,7 @@ #define DCCWaveform_h #include "MotorDriver.h" +#include "StringFormatter.h" // Wait times for power management. Unit: milliseconds const int POWER_SAMPLE_ON_WAIT = 100; @@ -57,7 +58,6 @@ class DCCWaveform { static void loop(bool ackManagerActive); static DCCWaveform mainTrack; static DCCWaveform progTrack; - void beginTrack(); void setPowerMode(POWERMODE); POWERMODE getPowerMode(); @@ -72,22 +72,21 @@ class DCCWaveform { return motorDriver->raw2mA(lastCurrent); return 0; } - inline void setRMSMode(byte newMode, Print* stream) { //0: OFF 1: Broadcast mA Reading >1: Internal calc buffer size - outStream = stream; - sendCurrentSample = newMode == 1; - accuSize = newMode; - if (newMode > 1) - { - accuFact = (float)(newMode - 1) / newMode; - currAccu = 0; - } - } - inline float getCurrentRMS() { - if (accuSize == 0) - return 0; - else - return sqrt(currAccu / accuSize); + inline void setRMSMode(byte newMode) { //0: OFF 1: Broadcast mA Reading >1: Internal calc buffer size + sendCurrentSample = (newMode == 0x01); +// accuSize = newMode; +// if (newMode > 1) +// { +// accuFact = (float)(newMode - 1) / newMode; +// currAccu = 0; +// } } +// inline float getCurrentRMS() { +// if (accuSize == 0) +// return 0; +// else +// return sqrt(currAccu / accuSize); +// } inline int getMaxmA() { if (maxmA == 0) { //only calculate this for first request, it doesn't change maxmA = motorDriver->raw2mA(motorDriver->getRawCurrentTripValue()); //TODO: replace with actual max value or calc @@ -169,11 +168,10 @@ class DCCWaveform { unsigned long power_sample_overload_wait = POWER_SAMPLE_OVERLOAD_WAIT; unsigned int power_good_counter = 0; - bool sendCurrentSample; - Print* outStream; - volatile double currAccu = 0; - byte accuSize = 0; - float accuFact = 0; + bool sendCurrentSample = false; +// volatile double currAccu = 0; +// byte accuSize = 0; +// float accuFact = 0; // ACK management (Prog track only) volatile bool ackPending; volatile bool ackDetected; diff --git a/SerialManager.cpp b/SerialManager.cpp index 87172276..16c95195 100644 --- a/SerialManager.cpp +++ b/SerialManager.cpp @@ -21,6 +21,8 @@ #include "SerialManager.h" #include "DCCEXParser.h" +#include "DCCWaveform.h" + SerialManager * SerialManager::first=NULL; SerialManager::SerialManager(Stream * myserial) { @@ -78,5 +80,4 @@ void SerialManager::loop2() { if (bufferLength < (COMMAND_BUFFER_SIZE-1)) buffer[bufferLength++] = ch; } } - } From 9282d6a72f6f031be16a9871a20d49f148d40c90 Mon Sep 17 00:00:00 2001 From: "Hans R. Tanner" Date: Tue, 1 Nov 2022 21:03:22 -0400 Subject: [PATCH 5/7] Update DCCWaveform.cpp --- DCCWaveform.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DCCWaveform.cpp b/DCCWaveform.cpp index 7b1062f8..8be571f0 100644 --- a/DCCWaveform.cpp +++ b/DCCWaveform.cpp @@ -296,6 +296,8 @@ void DCCWaveform::schedulePacket(const byte buffer[], byte byteCount, byte repea void DCCWaveform::setAckBaseline() { if (isMainTrack) return; int baseline=motorDriver->getCurrentRaw(); + for (int i = 0; i < 32; i++) + baseline = max(baseline, motorDriver->getCurrentRaw()); ackThreshold= baseline + motorDriver->mA2raw(ackLimitmA); if (Diag::ACK) DIAG(F("ACK baseline=%d/%dmA Threshold=%d/%dmA Duration between %uus and %uus"), baseline,motorDriver->raw2mA(baseline), From fe6fe09ac8112b7a7410bcd47a137f61ccb234c5 Mon Sep 17 00:00:00 2001 From: "Hans R. Tanner" Date: Wed, 2 Nov 2022 09:40:36 -0400 Subject: [PATCH 6/7] baseline calibration --- DCCWaveform.cpp | 30 ++++++++++++++++++++++++++++++ MotorDrivers.h | 4 ++-- StringFormatter.cpp | 3 +-- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/DCCWaveform.cpp b/DCCWaveform.cpp index 8be571f0..b2d9b5be 100644 --- a/DCCWaveform.cpp +++ b/DCCWaveform.cpp @@ -297,7 +297,11 @@ void DCCWaveform::setAckBaseline() { if (isMainTrack) return; int baseline=motorDriver->getCurrentRaw(); for (int i = 0; i < 32; i++) +<<<<<<< Updated upstream baseline = max(baseline, motorDriver->getCurrentRaw()); +======= + baseline=max(baseline, motorDriver->getCurrentRaw()); +>>>>>>> Stashed changes ackThreshold= baseline + motorDriver->mA2raw(ackLimitmA); if (Diag::ACK) DIAG(F("ACK baseline=%d/%dmA Threshold=%d/%dmA Duration between %uus and %uus"), baseline,motorDriver->raw2mA(baseline), @@ -305,6 +309,32 @@ void DCCWaveform::setAckBaseline() { minAckPulseDuration, maxAckPulseDuration); } +/* +void DCCWaveform::setAckBaseline() { + if (isMainTrack) return; + int baseline = motorDriver->getCurrentRaw(); + + int baselinemin = baseline; + int baselinemax = baseline; + int newSample = 0; + for (int i = 0; i < 32; i++) + { + newSample = motorDriver->getCurrentRaw(); + baselinemax = max(baselinemax, newSample); + baselinemin = min(baselinemin, newSample); + } + baseline = baselinemax; + ackThreshold= baseline + motorDriver->mA2raw(ackLimitmA); + + if (Diag::ACK) DIAG(F("ACK min %d max %d"), baselinemin, baselinemax); + + if (Diag::ACK) DIAG(F("ACK baseline=%d/%dmA Threshold=%d/%dmA Duration between %uus and %uus"), + baseline,motorDriver->raw2mA(baseline), + ackThreshold,motorDriver->raw2mA(ackThreshold), + minAckPulseDuration, maxAckPulseDuration); +} +*/ + void DCCWaveform::setAckPending() { if (isMainTrack) return; ackMaxCurrent=0; diff --git a/MotorDrivers.h b/MotorDrivers.h index cfb0dd84..7513855d 100644 --- a/MotorDrivers.h +++ b/MotorDrivers.h @@ -47,8 +47,8 @@ // // Arduino standard Motor Shield #define STANDARD_MOTOR_SHIELD F("STANDARD_MOTOR_SHIELD"), \ - new MotorDriver(3, 12, UNUSED_PIN, UNUSED_PIN, A0, 2.99, 2000, UNUSED_PIN), \ - new MotorDriver(11, 13, UNUSED_PIN, UNUSED_PIN, A1, 2.99, 2000, UNUSED_PIN) + new MotorDriver(3, 12, UNUSED_PIN, UNUSED_PIN, A0, 41.54, 5000, UNUSED_PIN), \ + new MotorDriver(11, 13, UNUSED_PIN, UNUSED_PIN, A1, 41.54, 5000, UNUSED_PIN) // Pololu Motor Shield #define POLOLU_MOTOR_SHIELD F("POLOLU_MOTOR_SHIELD"), \ diff --git a/StringFormatter.cpp b/StringFormatter.cpp index 73a910ff..28ee86de 100644 --- a/StringFormatter.cpp +++ b/StringFormatter.cpp @@ -29,13 +29,12 @@ #include "LCDDisplay.h" -bool Diag::ACK=false; +bool Diag::ACK=true; bool Diag::CMD=false; bool Diag::WIFI=false; bool Diag::WITHROTTLE=false; bool Diag::ETHERNET=false; bool Diag::LCN=false; - void StringFormatter::diag( const FSH* input...) { if (!diagSerial) return; From 6b725ccc6025d9e3e4ab3238f689fe9c7513bcea Mon Sep 17 00:00:00 2001 From: "Hans R. Tanner" Date: Fri, 4 Nov 2022 20:39:05 -0400 Subject: [PATCH 7/7] test --- DCCWaveform.cpp | 7 +++---- MotorDrivers.h | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/DCCWaveform.cpp b/DCCWaveform.cpp index b2d9b5be..6dd8fe83 100644 --- a/DCCWaveform.cpp +++ b/DCCWaveform.cpp @@ -295,13 +295,10 @@ void DCCWaveform::schedulePacket(const byte buffer[], byte byteCount, byte repea void DCCWaveform::setAckBaseline() { if (isMainTrack) return; + pinMode(7, OUTPUT); int baseline=motorDriver->getCurrentRaw(); for (int i = 0; i < 32; i++) -<<<<<<< Updated upstream baseline = max(baseline, motorDriver->getCurrentRaw()); -======= - baseline=max(baseline, motorDriver->getCurrentRaw()); ->>>>>>> Stashed changes ackThreshold= baseline + motorDriver->mA2raw(ackLimitmA); if (Diag::ACK) DIAG(F("ACK baseline=%d/%dmA Threshold=%d/%dmA Duration between %uus and %uus"), baseline,motorDriver->raw2mA(baseline), @@ -365,7 +362,9 @@ void DCCWaveform::checkAck() { return; } + digitalWrite(7, !digitalRead(7)); int current=motorDriver->getCurrentRaw(); + digitalWrite(7, current > ackThreshold); numAckSamples++; if (current > ackMaxCurrent) ackMaxCurrent=current; // An ACK is a pulse lasting between minAckPulseDuration and maxAckPulseDuration uSecs (refer @haba) diff --git a/MotorDrivers.h b/MotorDrivers.h index 7513855d..6a9c8ee6 100644 --- a/MotorDrivers.h +++ b/MotorDrivers.h @@ -47,8 +47,8 @@ // // Arduino standard Motor Shield #define STANDARD_MOTOR_SHIELD F("STANDARD_MOTOR_SHIELD"), \ - new MotorDriver(3, 12, UNUSED_PIN, UNUSED_PIN, A0, 41.54, 5000, UNUSED_PIN), \ - new MotorDriver(11, 13, UNUSED_PIN, UNUSED_PIN, A1, 41.54, 5000, UNUSED_PIN) + new MotorDriver(3, 12, UNUSED_PIN, UNUSED_PIN, A0, 65.54, 7000, UNUSED_PIN), \ + new MotorDriver(11, 13, UNUSED_PIN, UNUSED_PIN, A1, 65.54, 7000, UNUSED_PIN) // Pololu Motor Shield #define POLOLU_MOTOR_SHIELD F("POLOLU_MOTOR_SHIELD"), \