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