1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-12-24 13:21:23 +01:00

Current detector factors

This commit is contained in:
Asbelos 2020-07-02 17:54:09 +01:00
parent b0debd1fab
commit 505a8346d8
5 changed files with 33 additions and 27 deletions

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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)()) {

View File

@ -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)());