diff --git a/lib/nmea2ktwai/Nmea2kTwai.cpp b/lib/nmea2ktwai/Nmea2kTwai.cpp index 084f428..5053f7e 100644 --- a/lib/nmea2ktwai/Nmea2kTwai.cpp +++ b/lib/nmea2ktwai/Nmea2kTwai.cpp @@ -5,9 +5,12 @@ #define LOGID(id) ((id >> 8) & 0x1ffff) -Nmea2kTwai::Nmea2kTwai(gpio_num_t _TxPin, gpio_num_t _RxPin): - tNMEA2000(),RxPin(_RxPin),TxPin(_TxPin) +static const int TIMEOUT_OFFLINE=256; //# of timeouts to consider offline + +Nmea2kTwai::Nmea2kTwai(gpio_num_t _TxPin, gpio_num_t _RxPin, unsigned long recP): + tNMEA2000(),RxPin(_RxPin),TxPin(_TxPin),recoveryPeriod(recP) { + lastRecoveryCheck=millis(); } bool Nmea2kTwai::CANSendFrame(unsigned long id, unsigned char len, const unsigned char *buf, bool wait_sent) @@ -21,7 +24,7 @@ bool Nmea2kTwai::CANSendFrame(unsigned long id, unsigned char len, const unsigne esp_err_t rt=twai_transmit(&message,0); if (rt != ESP_OK){ if (rt == ESP_ERR_TIMEOUT){ - txTimeouts++; + if (txTimeouts < TIMEOUT_OFFLINE) txTimeouts++; } logDebug(LOG_MSG,"twai transmit for %ld failed: %x",LOGID(id),(int)rt); return false; @@ -111,11 +114,31 @@ Nmea2kTwai::Status Nmea2kTwai::getStatus(){ rt.rx_missed=state.rx_missed_count; rt.rx_overrun=state.rx_overrun_count; rt.tx_timeouts=txTimeouts; - if (rt.tx_timeouts > 256 && rt.state == ST_RUNNING){ + if (rt.tx_timeouts >= TIMEOUT_OFFLINE && rt.state == ST_RUNNING){ rt.state=ST_OFFLINE; } return rt; } +bool Nmea2kTwai::checkRecovery(){ + if (recoveryPeriod == 0) return false; //no check + unsigned long now=millis(); + if ((lastRecoveryCheck+recoveryPeriod) > now) return false; + lastRecoveryCheck=now; + Status canState=getStatus(); + bool strt=false; + if (canState.state != Nmea2kTwai::ST_RUNNING){ + if (canState.state == Nmea2kTwai::ST_BUS_OFF){ + strt=true; + bool rt=startRecovery(); + logDebug(LOG_INFO,"start can recovery - result %d",(int)rt); + } + if (canState.state == Nmea2kTwai::ST_STOPPED){ + bool rt=CANOpen(); + logDebug(LOG_INFO,"restart can driver - result %d",(int)rt); + } + } + return strt; +} bool Nmea2kTwai::startRecovery(){ esp_err_t rt=twai_driver_uninstall(); diff --git a/lib/nmea2ktwai/Nmea2kTwai.h b/lib/nmea2ktwai/Nmea2kTwai.h index 8f614ac..4a89c2c 100644 --- a/lib/nmea2ktwai/Nmea2kTwai.h +++ b/lib/nmea2ktwai/Nmea2kTwai.h @@ -5,7 +5,7 @@ class Nmea2kTwai : public tNMEA2000{ public: - Nmea2kTwai(gpio_num_t _TxPin, gpio_num_t _RxPin); + Nmea2kTwai(gpio_num_t _TxPin, gpio_num_t _RxPin, unsigned long recP=0); typedef enum{ ST_STOPPED, ST_RUNNING, @@ -25,7 +25,7 @@ class Nmea2kTwai : public tNMEA2000{ STATE state=ST_ERROR; } Status; Status getStatus(); - bool startRecovery(); + bool checkRecovery(); static const char * stateStr(const STATE &st); virtual bool CANOpen(); virtual ~Nmea2kTwai(){}; @@ -47,9 +47,12 @@ class Nmea2kTwai : public tNMEA2000{ private: void initDriver(); + bool startRecovery(); gpio_num_t TxPin; gpio_num_t RxPin; uint32_t txTimeouts=0; + unsigned long recoveryPeriod=0; + unsigned long lastRecoveryCheck=0; }; #endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 2f44706..c0bfad5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -110,12 +110,13 @@ GwLog logger(LOGLEVEL,NULL); GwConfigHandler config(&logger); #include "Nmea2kTwai.h" +static const unsigned long CAN_RECOVERY_PERIOD=3000; //ms class Nmea2kTwaiLog : public Nmea2kTwai{ private: GwLog* logger; public: - Nmea2kTwaiLog(gpio_num_t _TxPin, gpio_num_t _RxPin, GwLog *l): - Nmea2kTwai(_TxPin,_RxPin),logger(l){} + Nmea2kTwaiLog(gpio_num_t _TxPin, gpio_num_t _RxPin, unsigned long recoveryPeriod,GwLog *l): + Nmea2kTwai(_TxPin,_RxPin,recoveryPeriod),logger(l){} virtual void logDebug(int level, const char *fmt,...){ va_list args; va_start(args,fmt); @@ -125,7 +126,7 @@ class Nmea2kTwaiLog : public Nmea2kTwai{ }; -Nmea2kTwai &NMEA2000=*(new Nmea2kTwaiLog(ESP32_CAN_TX_PIN,ESP32_CAN_RX_PIN,&logger)); +Nmea2kTwai &NMEA2000=*(new Nmea2kTwaiLog(ESP32_CAN_TX_PIN,ESP32_CAN_RX_PIN,CAN_RECOVERY_PERIOD,&logger)); #ifdef GWBUTTON_PIN bool fixedApPass=false; @@ -838,8 +839,7 @@ void handleSendAndRead(bool handleRead){ TimeMonitor monitor(20,0.2); unsigned long lastHeapReport=0; -unsigned long lastCanRecovery=0; -static const unsigned long CAN_RECOVERY_PERIOD=3000; //ms +unsigned long lastCanStatus=0; void loop() { monitor.reset(); GWSYNCHRONIZED(&mainLock); @@ -848,6 +848,7 @@ void loop() { gwWifi.loop(); unsigned long now=millis(); monitor.setTime(2); + NMEA2000.checkRecovery(); if (HEAP_REPORT_TIME > 0 && now > (lastHeapReport+HEAP_REPORT_TIME)){ lastHeapReport=now; if (logger.isActive(GwLog::DEBUG)){ @@ -858,8 +859,8 @@ void loop() { logger.logDebug(GwLog::DEBUG,"Main loop %s",monitor.getLog().c_str()); } } - if (now > (lastCanRecovery + CAN_RECOVERY_PERIOD)){ - lastCanRecovery=now; + if (now > (lastCanStatus + CAN_RECOVERY_PERIOD)){ + lastCanStatus=now; Nmea2kTwai::Status canState=NMEA2000.getStatus(); logger.logDebug(GwLog::DEBUG, "can state %s, rxerr %d, txerr %d, txfail %d, txtimeout %d, rxmiss %d, rxoverrun %d", @@ -870,16 +871,6 @@ void loop() { canState.tx_timeouts, canState.rx_missed, canState.rx_overrun); - if (canState.state != Nmea2kTwai::ST_RUNNING){ - if (canState.state == Nmea2kTwai::ST_BUS_OFF){ - bool rt=NMEA2000.startRecovery(); - logger.logDebug(GwLog::LOG,"start can recovery - result %d",(int)rt); - } - if (canState.state == Nmea2kTwai::ST_STOPPED){ - bool rt=NMEA2000.CANOpen(); - logger.logDebug(GwLog::LOG,"restart can driver - result %d",(int)rt); - } - } } monitor.setTime(3); channels.allChannels([](GwChannel *c){