1
0
mirror of https://github.com/thooge/esp32-nmea2000-obp60.git synced 2025-12-13 05:53:06 +01:00

add timer class for periodic runs

This commit is contained in:
andreas
2023-08-26 10:53:46 +02:00
parent e61cfac15e
commit 28431bfdcf
4 changed files with 105 additions and 52 deletions

View File

@@ -1,16 +1,16 @@
#include "Nmea2kTwai.h"
#include "driver/gpio.h"
#include "driver/twai.h"
#include "GwLog.h"
#define LOGID(id) ((id >> 8) & 0x1ffff)
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)
Nmea2kTwai::Nmea2kTwai(gpio_num_t _TxPin, gpio_num_t _RxPin, unsigned long recP, unsigned long logP):
tNMEA2000(),RxPin(_RxPin),TxPin(_TxPin)
{
lastRecoveryCheck=millis();
timers.addAction(logP,[this](){logStatus();});
timers.addAction(recP,[this](){checkRecovery();});
}
bool Nmea2kTwai::CANSendFrame(unsigned long id, unsigned char len, const unsigned char *buf, bool wait_sent)
@@ -120,26 +120,42 @@ Nmea2kTwai::Status Nmea2kTwai::getStatus(){
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);
}
if (canState.state != Nmea2kTwai::ST_RUNNING)
{
if (canState.state == Nmea2kTwai::ST_BUS_OFF)
{
strt = true;
bool rt = startRecovery();
logDebug(LOG_INFO, "twai BUS_OFF: start can recovery - result %d", (int)rt);
}
if (canState.state == Nmea2kTwai::ST_STOPPED)
{
bool rt = CANOpen();
logDebug(LOG_INFO, "twai STOPPED: restart can driver - result %d", (int)rt);
}
}
return strt;
}
void Nmea2kTwai::loop(){
timers.loop();
}
Nmea2kTwai::Status Nmea2kTwai::logStatus(){
Status canState=getStatus();
logDebug(LOG_INFO, "twai state %s, rxerr %d, txerr %d, txfail %d, txtimeout %d, rxmiss %d, rxoverrun %d",
stateStr(canState.state),
canState.rx_errors,
canState.tx_errors,
canState.tx_failed,
canState.tx_timeouts,
canState.rx_missed,
canState.rx_overrun);
return canState;
}
bool Nmea2kTwai::startRecovery(){
esp_err_t rt=twai_driver_uninstall();
if (rt != ESP_OK){

View File

@@ -1,11 +1,11 @@
#ifndef _NMEA2KTWAI_H
#define _NMEA2KTWAI_H
#include "NMEA2000.h"
#include "GwLog.h"
#include "GwTimer.h"
class Nmea2kTwai : public tNMEA2000{
public:
Nmea2kTwai(gpio_num_t _TxPin, gpio_num_t _RxPin, unsigned long recP=0);
Nmea2kTwai(gpio_num_t _TxPin, gpio_num_t _RxPin, unsigned long recP=0, unsigned long logPeriod=0);
typedef enum{
ST_STOPPED,
ST_RUNNING,
@@ -25,7 +25,7 @@ class Nmea2kTwai : public tNMEA2000{
STATE state=ST_ERROR;
} Status;
Status getStatus();
bool checkRecovery();
void loop();
static const char * stateStr(const STATE &st);
virtual bool CANOpen();
virtual ~Nmea2kTwai(){};
@@ -48,11 +48,12 @@ class Nmea2kTwai : public tNMEA2000{
private:
void initDriver();
bool startRecovery();
bool checkRecovery();
Status logStatus();
gpio_num_t TxPin;
gpio_num_t RxPin;
uint32_t txTimeouts=0;
unsigned long recoveryPeriod=0;
unsigned long lastRecoveryCheck=0;
GwIntervalRunner timers;
};
#endif

48
lib/timer/GwTimer.h Normal file
View File

@@ -0,0 +1,48 @@
#ifndef _GWTIMER_H
#define _GWTIMER_H
#include <vector>
#include <functional>
#include <Arduino.h>
class GwIntervalRunner{
public:
using RunFunction=std::function<void(void)>;
private:
class Run{
public:
unsigned long interval=0;
RunFunction runner;
unsigned long last=0;
Run(RunFunction r,unsigned long iv,unsigned long l=0):
runner(r),interval(iv),last(l){}
bool shouldRun(unsigned long now){
if ((last+interval) > now) return false;
last=now;
return true;
}
bool runIf(unsigned long now){
if (shouldRun(now)) {
runner();
return true;
}
return false;
}
};
std::vector<Run> runners;
unsigned long startTime=0;
public:
GwIntervalRunner(unsigned long now=millis()){
startTime=now;
}
void addAction(unsigned long interval,RunFunction run,unsigned long start=0){
if (start=0) start=startTime;
runners.push_back(Run(run,interval,start));
}
bool loop(unsigned long now=millis()){
bool rt=false;
for (auto it=runners.begin();it!=runners.end();it++){
if (it->runIf(now)) rt=true;
}
return rt;
}
};
#endif