412 Zeilen
14 KiB
C
412 Zeilen
14 KiB
C
//--------------------------------------------------------------------------------------------
|
|
//POWER set configuration:
|
|
void globalPower (byte state) {
|
|
if (Railpower != state) {
|
|
|
|
if (Railpower == csServiceMode && state == csShortCircuit) {
|
|
#if defined(LAN) || defined(WIFI) || defined(ESP_WIFI)
|
|
z21.setCVNackSC(); //response SHORT while Service Mode!
|
|
#endif
|
|
#if defined(XPRESSNET)
|
|
XpressNet.setCVNackSC();
|
|
#endif
|
|
}
|
|
|
|
#if defined(Z21DISPLAY)
|
|
DisplayCounter = 0xFF;
|
|
if ((Railpower == csShortCircuit) || (state == csShortCircuit)) {
|
|
Railpower = state;
|
|
DisplayUpdateRailPower(true);
|
|
}
|
|
else {
|
|
Railpower = state;
|
|
DisplayUpdateRailPower(false);
|
|
}
|
|
#else
|
|
Railpower = state;
|
|
#endif
|
|
|
|
#if defined(DEBUG)
|
|
Debug.print(F("Power State: "));
|
|
Debug.println(state);
|
|
#endif
|
|
switch (state) {
|
|
case csNormal:
|
|
#if defined(DCC)
|
|
dcc.setpower(ON);
|
|
#if defined(ProgRelaisPin)
|
|
#if defined(PROG_OUT_INVERT)
|
|
digitalWrite(ProgRelaisPin, HIGH); //ProgTrack
|
|
#else
|
|
digitalWrite(ProgRelaisPin, LOW); //ProgTrack
|
|
#endif
|
|
#endif
|
|
#if defined(INA219)
|
|
ina219.setPGain(PG_320); //Default setting range (320mV full range, ~16 A max. current, ~4mA resolution with 20 mOhm shunt)
|
|
#endif
|
|
#endif
|
|
#if defined(BOOSTER_EXT)
|
|
if (digitalRead(ShortExtPin) == LOW)
|
|
digitalWrite(GoExtPin, BOOSTER_EXT_ON);
|
|
#endif
|
|
|
|
#if (defined(BOOSTER_INT) && !defined(BOOSTER_INT_NDCC))
|
|
digitalWrite(GoIntPin, BOOSTER_INT_ON);
|
|
#endif
|
|
|
|
break;
|
|
case csTrackVoltageOff:
|
|
#if defined(DCC)
|
|
dcc.setpower(OFF);
|
|
#if defined(ProgRelaisPin)
|
|
#if defined(PROG_OUT_INVERT)
|
|
digitalWrite(ProgRelaisPin, HIGH); //ProgTrack
|
|
#else
|
|
digitalWrite(ProgRelaisPin, LOW); //ProgTrack
|
|
#endif
|
|
#endif
|
|
#endif
|
|
#if defined(BOOSTER_EXT)
|
|
digitalWrite(GoExtPin, BOOSTER_EXT_OFF);
|
|
#endif
|
|
|
|
#if (defined(BOOSTER_INT) && !defined(BOOSTER_INT_NDCC))
|
|
digitalWrite(GoIntPin, BOOSTER_INT_OFF);
|
|
#endif
|
|
|
|
break;
|
|
case csServiceMode:
|
|
#if defined(DCC)
|
|
dcc.setpower(SERVICE); //already on!
|
|
#if defined(ProgRelaisPin)
|
|
#if defined(PROG_OUT_INVERT)
|
|
digitalWrite(ProgRelaisPin, LOW); //ProgTrack
|
|
#else
|
|
digitalWrite(ProgRelaisPin, HIGH); //ProgTrack
|
|
#endif
|
|
#endif
|
|
#if defined(INA219)
|
|
ina219.setPGain(PG_80); //setting range (160mV full range
|
|
#endif
|
|
#endif
|
|
#if defined(BOOSTER_EXT)
|
|
#if defined(BOOSTER_INT)
|
|
digitalWrite(GoExtPin, BOOSTER_EXT_OFF);
|
|
#else
|
|
if (digitalRead(ShortExtPin) == LOW)
|
|
digitalWrite(GoExtPin, BOOSTER_EXT_ON);
|
|
#endif
|
|
#endif
|
|
|
|
#if (defined(BOOSTER_INT) && !defined(BOOSTER_INT_NDCC))
|
|
digitalWrite(GoIntPin, BOOSTER_INT_ON);
|
|
#endif
|
|
|
|
break;
|
|
case csShortCircuit:
|
|
#if defined(DCC)
|
|
dcc.setpower(SHORT); //shut down via GO/STOP just for the Roco Booster
|
|
#if defined(ProgRelaisPin)
|
|
#if defined(PROG_OUT_INVERT)
|
|
digitalWrite(ProgRelaisPin, HIGH); //ProgTrack
|
|
#else
|
|
digitalWrite(ProgRelaisPin, LOW); //ProgTrack
|
|
#endif
|
|
#endif
|
|
#endif
|
|
#if defined(BOOSTER_EXT)
|
|
digitalWrite(GoExtPin, BOOSTER_EXT_OFF);
|
|
#endif
|
|
|
|
#if (defined(BOOSTER_INT) && !defined(BOOSTER_INT_NDCC))
|
|
digitalWrite(GoIntPin, BOOSTER_INT_OFF);
|
|
#endif
|
|
|
|
break;
|
|
case csEmergencyStop:
|
|
#if defined(DCC)
|
|
dcc.eStop();
|
|
#endif
|
|
break;
|
|
}
|
|
if (Railpower == csShortCircuit)
|
|
digitalWrite(ShortLed, HIGH); //Short LED show State "short"
|
|
if (Railpower == csNormal)
|
|
digitalWrite(ShortLed, LOW); //Short LED show State "normal"
|
|
#if defined(LAN) || defined(WIFI) || defined(ESP_WIFI)
|
|
z21.setPower(Railpower);
|
|
#endif
|
|
#if defined(XPRESSNET)
|
|
XpressNet.setPower(Railpower); //send to XpressNet
|
|
#endif
|
|
#if defined(LOCONET)
|
|
LNsetpower(); //send to LocoNet
|
|
#endif
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------
|
|
//from DCCPacketScheduler -> notify power state when change into Programming Mode
|
|
void notifyRailpower(uint8_t state) {
|
|
if (Railpower != state) {
|
|
#if defined(Z21DEBUG)
|
|
Debug.print(F("dcc "));
|
|
#endif
|
|
|
|
globalPower(state);
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------
|
|
//--------------------------------------------------------------------------------------------
|
|
#if defined(DCC)
|
|
|
|
//--------------------------------------------------------------------------------------------
|
|
uint16_t getRailmA() {
|
|
#if defined (INA219) // current via INA219
|
|
uint16_t mA = ina219.getCurrent_mA();
|
|
if (mA > 65000) //ignore this value!
|
|
return VAmpINT;
|
|
return mA;
|
|
#elif defined(ESP32_MCU)
|
|
return (analogRead(VAmpIntPin)) / senseResist * 1000 * (3.3/4096); //adjusted to Uref more accurate
|
|
#elif defined(ESP8266_MCU) //Wemos D1 mini has a voltage divider!
|
|
uint16_t mA = analogRead(VAmpIntPin);
|
|
if (mA > 3) //remove to low values!
|
|
return mA / senseResist * 1000 * (3.3/1024); //adjusted to Uref more accurate
|
|
return 0;
|
|
#elif defined(AREF_1V1)
|
|
return analogRead(VAmpIntPin) / senseResist * 1000 * (Uref/1024); //adjusted to Uref more accurate
|
|
#else
|
|
return analogRead(VAmpIntPin) * 10; //old!
|
|
#endif
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------
|
|
uint16_t getRailVolt() {
|
|
#if defined (INA219)
|
|
return (float) ((ina219.getBusVoltage_V() + (ina219.getShuntVoltage_mV()/1000)) * 1000); //rail voltage, correctded (shunt voltage)
|
|
#elif defined(ESP32_MCU)
|
|
return ((float) analogRead(VoltIntPin) * 1000 * (100/4.7) * (3.3/496)); //adjusted to Uref more accurate
|
|
#elif defined(MEGA_MCU)
|
|
//#if defined(AREF_1V1)
|
|
//return ((float) analogRead(VoltIntPin) * 1000 * (100/4.7) * (Uref/1024)); //adjusted to Uref more accurate
|
|
//#else
|
|
//return ((float)(analogRead(VoltIntPin)-121) / 0.008); //old!
|
|
// #endif
|
|
return ((float)15.00);
|
|
#else //other MCU:
|
|
return ((float)15.00);
|
|
#endif
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------
|
|
void ShortDetection() {
|
|
//Short Circuit?
|
|
//Check BOOSTER extern
|
|
#if defined(BOOSTER_EXT)
|
|
if ((digitalRead(ShortExtPin) == HIGH) && (digitalRead(GoExtPin) == BOOSTER_EXT_ON) && (Railpower != csShortCircuit)) {
|
|
ShortTime++;
|
|
if(ShortTime == DetectShortCircuit) {
|
|
globalPower(csShortCircuit);
|
|
#if defined(DEBUG)
|
|
Debug.println(F("TRACK_SHORT_CIRCUIT EXT"));
|
|
#endif
|
|
}
|
|
}
|
|
else ShortTime = 0;
|
|
#endif
|
|
//Check BOOSTER2 (z.B. TLE5206)
|
|
#if defined(BOOSTER_INT)
|
|
//---------------Short2 for CDE external Booster----------------------------------
|
|
#if defined(BOOSTER_EXT_CDE)
|
|
if ((digitalRead(ShortIntPin) == LOW) && (Railpower != csShortCircuit)) {
|
|
globalPower(csShortCircuit);
|
|
#if defined(DEBUG)
|
|
Debug.println(F("TRACK_SHORT_CIRCUIT CDE"));
|
|
#endif
|
|
}
|
|
//---------------Short2 TLE detection----------------------------------
|
|
#elif defined(BOOSTER_INT_TLE5206)
|
|
#if defined(BOOSTER_INT_NDCC)
|
|
if ((digitalRead(ShortIntPin) == LOW) && (Railpower != csShortCircuit)) {
|
|
#else
|
|
//---------------Old: without RailCom support----------------------------------
|
|
if ((digitalRead(ShortIntPin) == LOW) && (digitalRead(GoIntPin) == BOOSTER_INT_ON) && (Railpower != csShortCircuit)) {
|
|
#endif
|
|
globalPower(csShortCircuit);
|
|
#if defined(DEBUG)
|
|
Debug.println(F("TRACK_SHORT_CIRCUIT_INT"));
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#if defined(BOOSTER_INT_CURRENT_SHORT_DETECT)
|
|
//Check if RailCom is on the rail?
|
|
if (dcc.getRailComStatus() == false) {
|
|
/*
|
|
#if defined (INA219) // current via INA219
|
|
float mA = ina219.getCurrent_mA() - 5; //reduce 5mA current power of H-Bridge
|
|
if (mA >= 0)
|
|
VAmpINT = mA;
|
|
if (ina219.getOverflow()) {
|
|
#if defined(DEBUG)
|
|
Debug.println(F("INA Overflow!"));
|
|
#endif
|
|
}
|
|
*/
|
|
VAmpINT = getRailmA();
|
|
|
|
|
|
if ((VAmpINT >= DETECT_SHORT_INT_VALUE) && (Railpower != csShortCircuit)) {
|
|
|
|
#if defined(DEBUG)
|
|
Debug.print(digitalRead(DCCPin));
|
|
Debug.print(digitalRead(GoIntPin));
|
|
Debug.print("-");
|
|
Debug.print(millis() - ShortTimeINT);
|
|
Debug.print(" mA: ");
|
|
Debug.print(VAmpINT);
|
|
#endif
|
|
|
|
ShortTimeINTcounter = 6; //ignore low values!
|
|
|
|
if (((millis() - ShortTimeINT) > DETECT_SHORT_INT_WAIT) || (VAmpINT >= DETECT_SHORT_INT_VALUE + (DETECT_SHORT_INT_VALUE / 2) ) ) {
|
|
globalPower(csShortCircuit);
|
|
#if defined(DEBUG)
|
|
Debug.print(VAmpINT);
|
|
Debug.print("-t");
|
|
Debug.print(millis() - ShortTimeINT);
|
|
Debug.println(F(" TRACK_SHORT_INT"));
|
|
#endif
|
|
}
|
|
}
|
|
else {
|
|
if (ShortTimeINTcounter > 0) {
|
|
ShortTimeINTcounter--;
|
|
/*
|
|
#if defined(DEBUG)
|
|
Debug.print(dcc.getRailComStatus());
|
|
Debug.print(digitalRead(DCCPin));
|
|
Debug.print(digitalRead(GoIntPin));
|
|
Debug.print("-");
|
|
Debug.print(VAmpINT);
|
|
Debug.print(" mA ");
|
|
Debug.println(ShortTimeINTcounter);
|
|
#endif
|
|
*/
|
|
}
|
|
else ShortTimeINT = millis();
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
//--------------------------------------------------------------------------------------------
|
|
void updateLedButton() {
|
|
//read out last LED status:
|
|
bool lastLedState = false; //OFF
|
|
#if defined(POWER_LED_INVERT)
|
|
if (digitalRead(DCCLed) == LOW)
|
|
#else
|
|
if (digitalRead(DCCLed) == HIGH)
|
|
#endif
|
|
lastLedState = true; //ON
|
|
|
|
//Button to control Railpower state
|
|
pinMode(Z21ButtonPin, INPUT_PULLUP);
|
|
if ((digitalRead(Z21ButtonPin) == LOW) && (Z21ButtonLastState == false)) { //Button DOWN
|
|
#if !(defined(ADD_ACK_COMP) && defined(ESP8266_MCU))
|
|
Z21ButtonLastState = true;
|
|
LEDcount = millis();
|
|
#endif
|
|
}
|
|
else {
|
|
if ((digitalRead(Z21ButtonPin) == HIGH) && (Z21ButtonLastState == true)) { //Button UP
|
|
Z21ButtonLastState = false;
|
|
#if defined(DEBUG)
|
|
Debug.print(F("Button "));
|
|
#endif
|
|
if (Railpower == csNormal) {
|
|
if(millis() - LEDcount > 750) { //push long?
|
|
if (FIXSTORAGE.read(52) == 0x00) //Power-Button (short): 0=Gleisspannung aus, 1=Nothalt
|
|
globalPower(csEmergencyStop);
|
|
else globalPower(csTrackVoltageOff);
|
|
}
|
|
else {
|
|
if (FIXSTORAGE.read(52) == 0x00) //Power-Button (short): 0=Gleisspannung aus, 1=Nothalt
|
|
globalPower(csTrackVoltageOff);
|
|
else globalPower(csEmergencyStop);
|
|
}
|
|
}
|
|
else globalPower(csNormal);
|
|
LEDcount = millis();
|
|
}
|
|
}
|
|
//reset to the last State:
|
|
if (lastLedState) {
|
|
pinMode(DCCLed, OUTPUT);
|
|
#if defined(POWER_LED_INVERT)
|
|
digitalWrite(DCCLed, LOW);
|
|
#else
|
|
digitalWrite(DCCLed, HIGH);
|
|
#endif
|
|
}
|
|
|
|
//Update LED
|
|
if (Railpower == csNormal) {
|
|
pinMode(DCCLed, OUTPUT);
|
|
#if defined(POWER_LED_INVERT)
|
|
digitalWrite(DCCLed, LOW);
|
|
#else
|
|
digitalWrite(DCCLed, HIGH);
|
|
#endif
|
|
#if defined(Z21DISPLAY)
|
|
if(millis() % DISPLAY_POWER_LOGO == 0 )
|
|
DisplayUpdateRailPower(false); //Update OLED Display
|
|
#endif
|
|
}
|
|
else { //Flash:
|
|
unsigned long currentMillis = millis();
|
|
if (currentMillis > LEDcount) {
|
|
pinMode(DCCLed, OUTPUT);
|
|
if (Railpower == csTrackVoltageOff) {
|
|
if (lastLedState)
|
|
LEDcount = currentMillis + 1100; //long OFF
|
|
else LEDcount = currentMillis + 300; //short ON
|
|
}
|
|
else if (Railpower == csEmergencyStop) {
|
|
if (lastLedState)
|
|
LEDcount = currentMillis + 80; //short OFF
|
|
else LEDcount = currentMillis + 700; //long ON
|
|
}
|
|
else if (Railpower == csShortCircuit) {
|
|
LEDcount = currentMillis + 200; //short flash
|
|
#if defined(Z21DISPLAY)
|
|
DisplayUpdateRailPower(false); //Update OLED Display
|
|
#endif
|
|
}
|
|
else { //csServiceMode:
|
|
LEDcount = currentMillis + 100; //fast short flash
|
|
#if defined(Z21DISPLAY)
|
|
if(currentMillis % 5 == 0 ) {
|
|
DisplayUpdateRailPower(false); //Update OLED Display
|
|
}
|
|
#endif
|
|
}
|
|
if (lastLedState)
|
|
pinMode(DCCLed, INPUT); //OFF
|
|
else {
|
|
#if defined(POWER_LED_INVERT)
|
|
digitalWrite(DCCLed, LOW); //ON
|
|
#else
|
|
digitalWrite(DCCLed, HIGH); //OFF
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
}
|