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

stash incomplete

This commit is contained in:
Asbelos 2020-08-14 22:54:12 +01:00
parent a217031f24
commit ddc3917519
3 changed files with 140 additions and 23 deletions

View File

@ -20,19 +20,26 @@
#include "Hardware.h"
#include "DCCWaveform.h"
#include "DIAG.h"
#include <ArduinoTimers.h> // use IDE menu Tools..Manage Libraries to locate and install TimerOne
DCCWaveform DCCWaveform::mainTrack(PREAMBLE_BITS_MAIN, true, (int)(MAIN_MAX_MILLIAMPS / MAIN_SENSE_FACTOR));
DCCWaveform DCCWaveform::progTrack(PREAMBLE_BITS_PROG, false, (int)(PROG_MAX_MILLIAMPS / PROG_SENSE_FACTOR));
DCCWaveform DCCWaveform::mainTrack=NULL;
DCCWaveform DCCWaveform::progTrack=NULL;
const int ACK_MIN_PULSE_RAW=65 / PROG_SENSE_FACTOR;
bool DCCWaveform::progTrackSyncMain=false;
void DCCWaveform::begin() {
Hardware::init();
Hardware::setCallback(58, interruptHandler);
mainTrack.beginTrack();
progTrack.beginTrack();
void DCCWaveform::begin(MotorDriver mainDriver, MotorDriver progDriver) {
mainTrack=new DCCWaveform(PREAMBLE_BITS_MAIN, true, mainDriver);
progTrack=new DCCWaveform(PREAMBLE_BITS_PROG, false, progDriver);
progTrack.beginTrack(progDriver);
TimerA.initialize();
TimerA.setPeriod(58);
TimerA.attachInterrupt(interruptHandler);
TimerA.start();
}
void DCCWaveform::loop() {
@ -66,8 +73,9 @@ void DCCWaveform::interruptHandler() {
const byte bitMask[] = {0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
DCCWaveform::DCCWaveform( byte preambleBits, bool isMain, int rawCurrentTrip) {
DCCWaveform::DCCWaveform( byte preambleBits, bool isMain, MotorDriver driver) {
// establish appropriate pins
motorDriver=driver;
rawCurrentTripValue=rawCurrentTrip;
isMainTrack = isMain;
packetPending = false;
@ -80,11 +88,8 @@ DCCWaveform::DCCWaveform( byte preambleBits, bool isMain, int rawCurrentTrip) {
bits_sent = 0;
sampleDelay = 0;
lastSampleTaken = millis();
ackPending=false;
}
void DCCWaveform::beginTrack() {
setPowerMode(POWERMODE::ON);
ackPending=false;
setPowerMode(POWERMODE::ON);
}
POWERMODE DCCWaveform::getPowerMode() {
@ -94,8 +99,7 @@ POWERMODE DCCWaveform::getPowerMode() {
void DCCWaveform::setPowerMode(POWERMODE mode) {
powerMode = mode;
bool ison = (mode == POWERMODE::ON);
Hardware::setPower(isMainTrack, ison);
Hardware::setBrake(isMainTrack, !ison);
driver.setPower( ison);
if (mode == POWERMODE::ON) delay(200);
}
@ -104,7 +108,7 @@ void DCCWaveform::checkPowerOverload() {
if (millis() - lastSampleTaken < sampleDelay) return;
lastSampleTaken = millis();
int tripValue= rawCurrentTripValue;
int tripValue= driver.rawCurrentTripValue;
if (!isMainTrack && (ackPending || progTrackSyncMain)) tripValue=ACK_CURRENT_TRIP;
switch (powerMode) {
@ -113,7 +117,7 @@ void DCCWaveform::checkPowerOverload() {
break;
case POWERMODE::ON:
// Check current
lastCurrent = Hardware::getCurrentRaw(isMainTrack);
lastCurrent = driver.getCurrentRaw();
if (lastCurrent <= tripValue) {
sampleDelay = POWER_SAMPLE_ON_WAIT;
if(power_good_counter<100)
@ -122,8 +126,8 @@ void DCCWaveform::checkPowerOverload() {
if (power_sample_overload_wait>POWER_SAMPLE_OVERLOAD_WAIT) power_sample_overload_wait=POWER_SAMPLE_OVERLOAD_WAIT;
} else {
setPowerMode(POWERMODE::OVERLOAD);
unsigned int mA=Hardware::getCurrentMilliamps(isMainTrack,lastCurrent);
unsigned int maxmA=Hardware::getCurrentMilliamps(isMainTrack,tripValue);
unsigned int mA=driver.convertRawToMilliamps(lastCurrent);
unsigned int maxmA=driver.convertRawToMilliamps(tripValue);
DIAG(F("\n*** %S TRACK POWER OVERLOAD current=%d max=%d offtime=%l ***\n"), isMainTrack ? F("MAIN") : F("PROG"), mA, maxmA, power_sample_overload_wait);
power_good_counter=0;
sampleDelay = power_sample_overload_wait;
@ -183,10 +187,11 @@ void DCCWaveform::setSignal(bool high) {
if (progTrackSyncMain) {
if (!isMainTrack) return; // ignore PROG track waveform while in sync
// set both tracks to same signal
Hardware::setSyncSignal(high);
driver.setSyncSignal(high);
progTrack.driver.setSignal(high);
return;
}
Hardware::setSignal(isMainTrack,high);
driver.setSignal(high);
}
void DCCWaveform::interrupt2() {
@ -264,8 +269,8 @@ int DCCWaveform::getLastCurrent() {
void DCCWaveform::setAckBaseline(bool debug) {
if (isMainTrack) return;
ackThreshold=Hardware::getCurrentRaw(false) + ACK_MIN_PULSE_RAW;
if (debug) DIAG(F("\nACK-BASELINE %d/%dmA"),ackThreshold,Hardware::getCurrentMilliamps(false,ackThreshold));
ackThreshold=driver.getCurrentRaw() + ACK_MIN_PULSE_RAW;
if (debug) DIAG(F("\nACK-BASELINE %d/%dmA"),ackThreshold,driver.convertRawToMilliamps(ackThreshold));
}
void DCCWaveform::setAckPending(bool debug) {

77
MotorDriver.cpp Normal file
View File

@ -0,0 +1,77 @@
/*
* © 2020, Chris Harlow. All rights reserved.
*
* This file is part of Asbelos DCC API
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* It is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
*/
#include <Arduino.h>
#include "MotorDriver.h"
#include "AnalogReadFast.h"
#include "DIAG.h"
#if defined(ARDUINO_ARCH_AVR)
#include <DIO2.h> // use IDE menu Tools..Manage Libraries to locate and install DIO2
#define WritePin digitalWrite2
#define ReadPin digitalRead2
#else
#define WritePin digitalWrite
#define ReadPin digitalRead
#endif
MotorDriver::MotorDriver(byte power_pin, int signal_pin, int signal_pin2, int brake_pin, int current_pin, float sense_factor, int fault_pin) {
powerPin=power_pin;
signalPin=signal_pin;
signalPin2=signal_pin2;
brakePin=brake_pin;
currentPin=current_pin;
senseFactor=sense_factor;
faultPin=fault_pin;
I32=(int) (32000 / sensefactor);
pinMode(powerPin, OUTPUT);
pinMode(brakePin, OUTPUT);
pinMode(signalPin, OUTPUT);
if (signalPin2 != UNUSED_PIN) pinMode(signalPin2, OUTPUT);
pinMode(currentPin, INPUT);
if (faultPin != UNUSED_PIN) pinMode(faultPin, INPUT);
}
void MotorDriver::setPower(bool on) {
WritePin(powerPin, on ? HIGH : LOW);
}
void MotorDriver::setBrake( bool on) {
WritePin(brakePin, on ? HIGH : LOW);
}
void MotorDriver::setSignal( bool high) {
WritePin(signalPin, high ? HIGH : LOW);
if (signalPin2 != UNUSED_PIN) WritePin(signalPin2, high ? LOW : HIGH);
}
int MotorDriver::getCurrentRaw() {
if (faultPin != UNUSED_PIN && ReadPin(faultPin) == LOW && ReadPin(powerPin) == HIGH)
return I32:
// 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)
return analogReadFast(sensePin);
}
unsigned int MortorDriver::convertRawToMilliamps( int raw) {
return (unsigned int)(raw * senseFactor);
}

35
MotorDriver.h Normal file
View File

@ -0,0 +1,35 @@
/*
* © 2020, Chris Harlow. All rights reserved.
*
* This file is part of Asbelos DCC API
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* It is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef MotorDriver_h
#define MotorDriver_h
// Virtualised Motor shield 1-track hardware Interface
class MotorDriver {
public:
MotorDriver(byte power_pin, byte signal_pin, byte signal_pin2, byte brake_pin, byte current_pin, float senseFactor, byte faultPin);
void setPower( bool on);
void setSignal( bool high);
void setBrake( bool on);
int getCurrentRaw();
unsigned int convertToMilliamps( int rawValue);
private:
byte powerPin, signalPin, signalPin2, brakePin,currentPin,faultPin;
float senseFactor;
};
#endif