diff --git a/Config.h b/Config.h index 439048b..e3e22d5 100644 --- a/Config.h +++ b/Config.h @@ -7,16 +7,19 @@ const byte MAIN_POWER_PIN = 3; const byte MAIN_SIGNAL_PIN = 12; const byte MAIN_SIGNAL_PIN_ALT = 0; // for hardware that flipflops signal pins const byte MAIN_SENSE_PIN = A0; -const byte MAIN_SENSE_FACTOR=1; // analgRead(MAIN_SENSE_PIN) * MAIN_SENSE_FACTOR = milliamps const byte MAIN_BRAKE_PIN = 9; +const int MAIN_MAX_MILLIAMPS=2000; +const float MAIN_SENSE_FACTOR=2.99; // analgRead(MAIN_SENSE_PIN) * MAIN_SENSE_FACTOR = milliamps + const byte PROG_POWER_PIN = 11; const byte PROG_SIGNAL_PIN = 13; const byte PROG_SIGNAL_PIN_ALT = 0; // for hardware that flipflops signal pins const byte PROG_SENSE_PIN = A1; const byte PROG_BRAKE_PIN = 8; -const float PROG_SENSE_FACTOR=1; // analgRead(PROG_SENSE_PIN) * PROG_SENSE_FACTOR = milliamps +const int PROG_MAX_MILLIAMPS=250; +const float PROG_SENSE_FACTOR=2.99; // analgRead(PROG_SENSE_PIN) * PROG_SENSE_FACTOR = milliamps // Allocations with memory implications..! // Base system takes approx 900 bytes + 8 per loco. Turnouts, Sensors etc are dynamically created diff --git a/DCCWaveform.cpp b/DCCWaveform.cpp index f9e45b5..50aba8d 100644 --- a/DCCWaveform.cpp +++ b/DCCWaveform.cpp @@ -3,8 +3,10 @@ #include "DCCWaveform.h" #include "DIAG.h" -DCCWaveform DCCWaveform::mainTrack(PREAMBLE_BITS_MAIN, true); -DCCWaveform DCCWaveform::progTrack(PREAMBLE_BITS_PROG, false); +DCCWaveform DCCWaveform::mainTrack(PREAMBLE_BITS_MAIN, true, MAIN_MAX_MILLIAMPS* MAIN_SENSE_FACTOR); +DCCWaveform DCCWaveform::progTrack(PREAMBLE_BITS_PROG, false, 250 * PROG_SENSE_FACTOR); + +const int ACK_MIN_PULSE_RAW=65 / PROG_SENSE_FACTOR; @@ -46,8 +48,9 @@ void DCCWaveform::interruptHandler() { const byte bitMask[] = {0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; -DCCWaveform::DCCWaveform( byte preambleBits, bool isMain) { +DCCWaveform::DCCWaveform( byte preambleBits, bool isMain, int rawCurrentTrip) { // establish appropriate pins + rawCurrentTripValue=rawCurrentTrip; isMainTrack = isMain; packetPending = false; memcpy(transmitPacket, idlePacket, sizeof(idlePacket)); @@ -87,11 +90,13 @@ void DCCWaveform::checkPowerOverload() { break; case POWERMODE::ON: // Check current - lastCurrent = Hardware::getCurrentMilliamps(isMainTrack); - if (lastCurrent < POWER_SAMPLE_MAX) sampleDelay = POWER_SAMPLE_ON_WAIT; + lastCurrent = Hardware::getCurrentRaw(isMainTrack); + if (lastCurrent <= rawCurrentTripValue) sampleDelay = POWER_SAMPLE_ON_WAIT; else { setPowerMode(POWERMODE::OVERLOAD); - DIAG(F("\n*** %S TRACK POWER OVERLOAD current=%d max=%d ***\n"), isMainTrack ? F("MAIN") : F("PROG"), lastCurrent, POWER_SAMPLE_MAX); + int mA=Hardware::getCurrentMilliamps(isMainTrack,lastCurrent); + int maxmA=Hardware::getCurrentMilliamps(isMainTrack,rawCurrentTripValue); + DIAG(F("\n*** %S TRACK POWER OVERLOAD current=%d max=%d ***\n"), isMainTrack ? F("MAIN") : F("PROG"), mA, maxmA); sampleDelay = POWER_SAMPLE_OVERLOAD_WAIT; } break; @@ -220,8 +225,8 @@ int DCCWaveform::getLastCurrent() { void DCCWaveform::setAckBaseline(bool debug) { if (isMainTrack) return; - ackThreshold=Hardware::getCurrentMilliamps(false) + ACK_MIN_PULSE; - if (debug) DIAG(F("\nACK-BASELINE mA=%d\n"),ackThreshold); + ackThreshold=Hardware::getCurrentRaw(false) + ACK_MIN_PULSE_RAW; + if (debug) DIAG(F("\nACK-BASELINE %d/%dmA"),ackThreshold,Hardware::getCurrentMilliamps(false,ackThreshold)); } void DCCWaveform::setAckPending(bool debug) { @@ -237,7 +242,8 @@ void DCCWaveform::setAckPending(bool debug) { byte DCCWaveform::getAck(bool debug) { if (ackPending) return (2); // still waiting - if (debug) DIAG(F("\nACK-%S after %dmS max=%dmA pulse=%duS"),ackDetected?F("OK"):F("FAIL"), ackCheckDuration, ackMaxCurrent, ackPulseDuration); + if (debug) DIAG(F("\nACK-%S after %dmS max=%d/%dmA pulse=%duS"),ackDetected?F("OK"):F("FAIL"), ackCheckDuration, + ackMaxCurrent,Hardware::getCurrentMilliamps(false,ackMaxCurrent), ackPulseDuration); if (ackDetected) return (1); // Yes we had an ack return(0); // pending set off but not detected means no ACK. } @@ -251,7 +257,7 @@ void DCCWaveform::checkAck() { return; } - lastCurrent=Hardware::getCurrentMilliamps(false); + lastCurrent=Hardware::getCurrentRaw(false); if (lastCurrent > ackMaxCurrent) ackMaxCurrent=lastCurrent; // An ACK is a pulse lasting between 4.5 and 8.5 mSecs (refer @haba) diff --git a/DCCWaveform.h b/DCCWaveform.h index 5c6cd15..a42960a 100644 --- a/DCCWaveform.h +++ b/DCCWaveform.h @@ -1,17 +1,12 @@ #ifndef DCCWaveform_h #define DCCWaveform_h +#include "Config.h" - -const int POWER_SAMPLE_MAX = 300; const int POWER_SAMPLE_ON_WAIT = 100; const int POWER_SAMPLE_OFF_WAIT = 1000; const int POWER_SAMPLE_OVERLOAD_WAIT = 4000; -// ACK current analogRead values (vary depending on motor shield and cpu voltage) -const int ACK_BASELINE_SAMPLES = 250 ; // current samples before sending ACKable request -const int ACK_TIMEOUT = 25 ; // millis getAck is prepared to wait for a signal -const int ACK_MIN_PULSE = 60 ; // current above baseline which a pulse is recognised const int PREAMBLE_BITS_MAIN = 20; const int PREAMBLE_BITS_PROG = 22; @@ -30,7 +25,7 @@ const byte resetPacket[] = {0x00, 0x00, 0x00}; class DCCWaveform { public: - DCCWaveform( byte preambleBits, bool isMain); + DCCWaveform( byte preambleBits, bool isMain, int maxRawCurrent); static void begin(); static void loop(); static DCCWaveform mainTrack; @@ -78,6 +73,7 @@ class DCCWaveform { POWERMODE powerMode; unsigned long lastSampleTaken; unsigned int sampleDelay; + int rawCurrentTripValue; // ACK management (Prog track only) bool ackPending; diff --git a/Hardware.cpp b/Hardware.cpp index e9eb218..f631846 100644 --- a/Hardware.cpp +++ b/Hardware.cpp @@ -39,16 +39,16 @@ void Hardware::setSignal(bool isMainTrack, bool high) { if (pin2) WritePin(pin2, high ? LOW : HIGH); } -int Hardware::getCurrentMilliamps(bool isMainTrack) { - int pin = isMainTrack ? MAIN_SENSE_PIN : PROG_SENSE_PIN; - float factor = isMainTrack ? MAIN_SENSE_FACTOR : PROG_SENSE_FACTOR; - +int Hardware::getCurrentRaw(bool isMainTrack) { // IMPORTANT: This function can be called in Interrupt() time within the 56uS timer // The default analogRead takes ~100uS which is catastrphic // so analogReadFast is used here. (-2uS) - int rawCurrent = analogReadFast(pin); - - return (int)(rawCurrent * factor); + return analogReadFast(isMainTrack ? MAIN_SENSE_PIN : PROG_SENSE_PIN); + +} + +int Hardware::getCurrentMilliamps(bool isMainTrack, int raw) { + return (int)(raw * (isMainTrack ? MAIN_SENSE_FACTOR : PROG_SENSE_FACTOR)); } void Hardware::setCallback(int duration, void (*isr)()) { diff --git a/Hardware.h b/Hardware.h index 0c69d57..dfb4845 100644 --- a/Hardware.h +++ b/Hardware.h @@ -6,7 +6,8 @@ class Hardware { static void init(); static void setPower(bool isMainTrack, bool on); static void setSignal(bool isMainTrack, bool high); - static int getCurrentMilliamps(bool isMainTrack); + static int getCurrentMilliamps(bool isMainTrack, int rawValue); + static int getCurrentRaw(bool isMainTrack); static void setBrake(bool isMainTrack, bool on); static void setCallback(int duration, void (*isr)()); // static void setSingleCallback(int duration, void (*isr)());