mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-12-24 21:21:24 +01:00
Current detector factors
This commit is contained in:
parent
b0debd1fab
commit
505a8346d8
7
Config.h
7
Config.h
@ -7,16 +7,19 @@ const byte MAIN_POWER_PIN = 3;
|
|||||||
const byte MAIN_SIGNAL_PIN = 12;
|
const byte MAIN_SIGNAL_PIN = 12;
|
||||||
const byte MAIN_SIGNAL_PIN_ALT = 0; // for hardware that flipflops signal pins
|
const byte MAIN_SIGNAL_PIN_ALT = 0; // for hardware that flipflops signal pins
|
||||||
const byte MAIN_SENSE_PIN = A0;
|
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 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_POWER_PIN = 11;
|
||||||
const byte PROG_SIGNAL_PIN = 13;
|
const byte PROG_SIGNAL_PIN = 13;
|
||||||
const byte PROG_SIGNAL_PIN_ALT = 0; // for hardware that flipflops signal pins
|
const byte PROG_SIGNAL_PIN_ALT = 0; // for hardware that flipflops signal pins
|
||||||
const byte PROG_SENSE_PIN = A1;
|
const byte PROG_SENSE_PIN = A1;
|
||||||
const byte PROG_BRAKE_PIN = 8;
|
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..!
|
// 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
|
||||||
|
@ -3,8 +3,10 @@
|
|||||||
#include "DCCWaveform.h"
|
#include "DCCWaveform.h"
|
||||||
#include "DIAG.h"
|
#include "DIAG.h"
|
||||||
|
|
||||||
DCCWaveform DCCWaveform::mainTrack(PREAMBLE_BITS_MAIN, true);
|
DCCWaveform DCCWaveform::mainTrack(PREAMBLE_BITS_MAIN, true, MAIN_MAX_MILLIAMPS* MAIN_SENSE_FACTOR);
|
||||||
DCCWaveform DCCWaveform::progTrack(PREAMBLE_BITS_PROG, false);
|
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};
|
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
|
// establish appropriate pins
|
||||||
|
rawCurrentTripValue=rawCurrentTrip;
|
||||||
isMainTrack = isMain;
|
isMainTrack = isMain;
|
||||||
packetPending = false;
|
packetPending = false;
|
||||||
memcpy(transmitPacket, idlePacket, sizeof(idlePacket));
|
memcpy(transmitPacket, idlePacket, sizeof(idlePacket));
|
||||||
@ -87,11 +90,13 @@ void DCCWaveform::checkPowerOverload() {
|
|||||||
break;
|
break;
|
||||||
case POWERMODE::ON:
|
case POWERMODE::ON:
|
||||||
// Check current
|
// Check current
|
||||||
lastCurrent = Hardware::getCurrentMilliamps(isMainTrack);
|
lastCurrent = Hardware::getCurrentRaw(isMainTrack);
|
||||||
if (lastCurrent < POWER_SAMPLE_MAX) sampleDelay = POWER_SAMPLE_ON_WAIT;
|
if (lastCurrent <= rawCurrentTripValue) sampleDelay = POWER_SAMPLE_ON_WAIT;
|
||||||
else {
|
else {
|
||||||
setPowerMode(POWERMODE::OVERLOAD);
|
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;
|
sampleDelay = POWER_SAMPLE_OVERLOAD_WAIT;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -220,8 +225,8 @@ int DCCWaveform::getLastCurrent() {
|
|||||||
|
|
||||||
void DCCWaveform::setAckBaseline(bool debug) {
|
void DCCWaveform::setAckBaseline(bool debug) {
|
||||||
if (isMainTrack) return;
|
if (isMainTrack) return;
|
||||||
ackThreshold=Hardware::getCurrentMilliamps(false) + ACK_MIN_PULSE;
|
ackThreshold=Hardware::getCurrentRaw(false) + ACK_MIN_PULSE_RAW;
|
||||||
if (debug) DIAG(F("\nACK-BASELINE mA=%d\n"),ackThreshold);
|
if (debug) DIAG(F("\nACK-BASELINE %d/%dmA"),ackThreshold,Hardware::getCurrentMilliamps(false,ackThreshold));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DCCWaveform::setAckPending(bool debug) {
|
void DCCWaveform::setAckPending(bool debug) {
|
||||||
@ -237,7 +242,8 @@ void DCCWaveform::setAckPending(bool debug) {
|
|||||||
|
|
||||||
byte DCCWaveform::getAck(bool debug) {
|
byte DCCWaveform::getAck(bool debug) {
|
||||||
if (ackPending) return (2); // still waiting
|
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
|
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.
|
||||||
}
|
}
|
||||||
@ -251,7 +257,7 @@ void DCCWaveform::checkAck() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
lastCurrent=Hardware::getCurrentMilliamps(false);
|
lastCurrent=Hardware::getCurrentRaw(false);
|
||||||
if (lastCurrent > ackMaxCurrent) ackMaxCurrent=lastCurrent;
|
if (lastCurrent > ackMaxCurrent) ackMaxCurrent=lastCurrent;
|
||||||
// An ACK is a pulse lasting between 4.5 and 8.5 mSecs (refer @haba)
|
// An ACK is a pulse lasting between 4.5 and 8.5 mSecs (refer @haba)
|
||||||
|
|
||||||
|
@ -1,17 +1,12 @@
|
|||||||
#ifndef DCCWaveform_h
|
#ifndef DCCWaveform_h
|
||||||
#define 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_ON_WAIT = 100;
|
||||||
const int POWER_SAMPLE_OFF_WAIT = 1000;
|
const int POWER_SAMPLE_OFF_WAIT = 1000;
|
||||||
const int POWER_SAMPLE_OVERLOAD_WAIT = 4000;
|
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_MAIN = 20;
|
||||||
const int PREAMBLE_BITS_PROG = 22;
|
const int PREAMBLE_BITS_PROG = 22;
|
||||||
@ -30,7 +25,7 @@ const byte resetPacket[] = {0x00, 0x00, 0x00};
|
|||||||
|
|
||||||
class DCCWaveform {
|
class DCCWaveform {
|
||||||
public:
|
public:
|
||||||
DCCWaveform( byte preambleBits, bool isMain);
|
DCCWaveform( byte preambleBits, bool isMain, int maxRawCurrent);
|
||||||
static void begin();
|
static void begin();
|
||||||
static void loop();
|
static void loop();
|
||||||
static DCCWaveform mainTrack;
|
static DCCWaveform mainTrack;
|
||||||
@ -78,6 +73,7 @@ class DCCWaveform {
|
|||||||
POWERMODE powerMode;
|
POWERMODE powerMode;
|
||||||
unsigned long lastSampleTaken;
|
unsigned long lastSampleTaken;
|
||||||
unsigned int sampleDelay;
|
unsigned int sampleDelay;
|
||||||
|
int rawCurrentTripValue;
|
||||||
|
|
||||||
// ACK management (Prog track only)
|
// ACK management (Prog track only)
|
||||||
bool ackPending;
|
bool ackPending;
|
||||||
|
12
Hardware.cpp
12
Hardware.cpp
@ -39,16 +39,16 @@ void Hardware::setSignal(bool isMainTrack, bool high) {
|
|||||||
if (pin2) WritePin(pin2, high ? LOW : HIGH);
|
if (pin2) WritePin(pin2, high ? LOW : HIGH);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Hardware::getCurrentMilliamps(bool isMainTrack) {
|
int Hardware::getCurrentRaw(bool isMainTrack) {
|
||||||
int pin = isMainTrack ? MAIN_SENSE_PIN : PROG_SENSE_PIN;
|
|
||||||
float factor = isMainTrack ? MAIN_SENSE_FACTOR : PROG_SENSE_FACTOR;
|
|
||||||
|
|
||||||
// IMPORTANT: This function can be called in Interrupt() time within the 56uS timer
|
// IMPORTANT: This function can be called in Interrupt() time within the 56uS timer
|
||||||
// The default analogRead takes ~100uS which is catastrphic
|
// The default analogRead takes ~100uS which is catastrphic
|
||||||
// so analogReadFast is used here. (-2uS)
|
// so analogReadFast is used here. (-2uS)
|
||||||
int rawCurrent = analogReadFast(pin);
|
return analogReadFast(isMainTrack ? MAIN_SENSE_PIN : PROG_SENSE_PIN);
|
||||||
|
|
||||||
return (int)(rawCurrent * factor);
|
}
|
||||||
|
|
||||||
|
int Hardware::getCurrentMilliamps(bool isMainTrack, int raw) {
|
||||||
|
return (int)(raw * (isMainTrack ? MAIN_SENSE_FACTOR : PROG_SENSE_FACTOR));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hardware::setCallback(int duration, void (*isr)()) {
|
void Hardware::setCallback(int duration, void (*isr)()) {
|
||||||
|
@ -6,7 +6,8 @@ class Hardware {
|
|||||||
static void init();
|
static void init();
|
||||||
static void setPower(bool isMainTrack, bool on);
|
static void setPower(bool isMainTrack, bool on);
|
||||||
static void setSignal(bool isMainTrack, bool high);
|
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 setBrake(bool isMainTrack, bool on);
|
||||||
static void setCallback(int duration, void (*isr)());
|
static void setCallback(int duration, void (*isr)());
|
||||||
// static void setSingleCallback(int duration, void (*isr)());
|
// static void setSingleCallback(int duration, void (*isr)());
|
||||||
|
Loading…
Reference in New Issue
Block a user