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