mirror of
https://github.com/hatlabs/SH-ESP32-nmea2000-gateway.git
synced 2025-05-16 07:30:19 -07:00
Merge pull request #9 from hatlabs/bus_off_2
Try to recover from BUS-OFF
This commit is contained in:
commit
09a8cabceb
@ -21,6 +21,7 @@ lib_deps =
|
|||||||
ttlappalainen/NMEA2000-library
|
ttlappalainen/NMEA2000-library
|
||||||
ttlappalainen/NMEA2000_esp32
|
ttlappalainen/NMEA2000_esp32
|
||||||
Adafruit SSD1306
|
Adafruit SSD1306
|
||||||
|
pfeerick/elapsedMillis
|
||||||
|
|
||||||
[espressif32_base]
|
[espressif32_base]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
|
59
src/main.cpp
59
src/main.cpp
@ -15,6 +15,8 @@
|
|||||||
#include <esp_int_wdt.h>
|
#include <esp_int_wdt.h>
|
||||||
#include <esp_task_wdt.h>
|
#include <esp_task_wdt.h>
|
||||||
|
|
||||||
|
#include "elapsedMillis.h"
|
||||||
|
|
||||||
using namespace reactesp;
|
using namespace reactesp;
|
||||||
|
|
||||||
ReactESP app;
|
ReactESP app;
|
||||||
@ -22,6 +24,8 @@ ReactESP app;
|
|||||||
#define SCREEN_WIDTH 128 // OLED display width, in pixels
|
#define SCREEN_WIDTH 128 // OLED display width, in pixels
|
||||||
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
|
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
|
||||||
|
|
||||||
|
#define RECOVERY_RETRY_MS 1000 // How long to attempt CAN bus recovery
|
||||||
|
|
||||||
TwoWire *i2c;
|
TwoWire *i2c;
|
||||||
|
|
||||||
Stream *read_stream = &Serial;
|
Stream *read_stream = &Serial;
|
||||||
@ -33,20 +37,26 @@ Adafruit_SSD1306 *display;
|
|||||||
|
|
||||||
tNMEA2000 *nmea2000;
|
tNMEA2000 *nmea2000;
|
||||||
|
|
||||||
|
int num_n2k_messages = 0;
|
||||||
|
int num_actisense_messages = 0;
|
||||||
|
elapsedMillis time_since_last_can_rx = 0;
|
||||||
|
|
||||||
|
// Time after which we should reboot if we haven't received any CAN messages
|
||||||
|
#define MAX_RX_WAIT_TIME_MS 30000
|
||||||
|
|
||||||
void ToggleLed() {
|
void ToggleLed() {
|
||||||
static bool led_state = false;
|
static bool led_state = false;
|
||||||
digitalWrite(LED_BUILTIN, led_state);
|
digitalWrite(LED_BUILTIN, led_state);
|
||||||
led_state = !led_state;
|
led_state = !led_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
int num_n2k_messages = 0;
|
|
||||||
void HandleStreamN2kMsg(const tN2kMsg &message) {
|
void HandleStreamN2kMsg(const tN2kMsg &message) {
|
||||||
// N2kMsg.Print(&Serial);
|
// N2kMsg.Print(&Serial);
|
||||||
num_n2k_messages++;
|
num_n2k_messages++;
|
||||||
|
time_since_last_can_rx = 0;
|
||||||
ToggleLed();
|
ToggleLed();
|
||||||
}
|
}
|
||||||
|
|
||||||
int num_actisense_messages = 0;
|
|
||||||
void HandleStreamActisenseMsg(const tN2kMsg &message) {
|
void HandleStreamActisenseMsg(const tN2kMsg &message) {
|
||||||
// N2kMsg.Print(&Serial);
|
// N2kMsg.Print(&Serial);
|
||||||
num_actisense_messages++;
|
num_actisense_messages++;
|
||||||
@ -56,6 +66,29 @@ void HandleStreamActisenseMsg(const tN2kMsg &message) {
|
|||||||
|
|
||||||
String can_state;
|
String can_state;
|
||||||
|
|
||||||
|
void RecoverFromCANBusOff() {
|
||||||
|
// This recovery routine first discussed in
|
||||||
|
// https://www.esp32.com/viewtopic.php?t=5010 and also implemented in
|
||||||
|
// https://github.com/wellenvogel/esp32-nmea2000
|
||||||
|
static bool recovery_in_progress = false;
|
||||||
|
static elapsedMillis recovery_timer;
|
||||||
|
if (recovery_in_progress && recovery_timer < RECOVERY_RETRY_MS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
recovery_in_progress = true;
|
||||||
|
recovery_timer = 0;
|
||||||
|
// Abort transmission
|
||||||
|
MODULE_CAN->CMR.B.AT = 1;
|
||||||
|
// read SR after write to CMR to settle register changes
|
||||||
|
(void)MODULE_CAN->SR.U;
|
||||||
|
|
||||||
|
// Reset error counters
|
||||||
|
MODULE_CAN->TXERR.U = 127;
|
||||||
|
MODULE_CAN->RXERR.U = 0;
|
||||||
|
// Release Reset mode
|
||||||
|
MODULE_CAN->MOD.B.RM = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void PollCANStatus() {
|
void PollCANStatus() {
|
||||||
// CAN controller registers are SJA1000 compatible.
|
// CAN controller registers are SJA1000 compatible.
|
||||||
// Bus status value 0 indicates bus-on; value 1 indicates bus-off.
|
// Bus status value 0 indicates bus-on; value 1 indicates bus-off.
|
||||||
@ -67,13 +100,8 @@ void PollCANStatus() {
|
|||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
can_state = "BUS-OFF";
|
can_state = "BUS-OFF";
|
||||||
// try to automatically recover by rebooting
|
// try to automatically recover
|
||||||
app.onDelay(2000, []() {
|
RecoverFromCANBusOff();
|
||||||
esp_task_wdt_init(1, true);
|
|
||||||
esp_task_wdt_add(NULL);
|
|
||||||
while (true)
|
|
||||||
;
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -131,12 +159,21 @@ void setup() {
|
|||||||
|
|
||||||
// No need to parse the messages at every single loop iteration; 1 ms will do
|
// No need to parse the messages at every single loop iteration; 1 ms will do
|
||||||
app.onRepeat(1, []() {
|
app.onRepeat(1, []() {
|
||||||
|
PollCANStatus();
|
||||||
nmea2000->ParseMessages();
|
nmea2000->ParseMessages();
|
||||||
actisense_reader.ParseMessages();
|
actisense_reader.ParseMessages();
|
||||||
});
|
});
|
||||||
|
|
||||||
// enable CAN status polling
|
app.onRepeat(100, []() {
|
||||||
app.onRepeat(100, []() { PollCANStatus(); });
|
if (time_since_last_can_rx > MAX_RX_WAIT_TIME_MS) {
|
||||||
|
// No CAN messages received in a while; reboot
|
||||||
|
esp_task_wdt_init(1, true);
|
||||||
|
esp_task_wdt_add(NULL);
|
||||||
|
while (true) {
|
||||||
|
// wait for watchdog to trigger
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// initialize the display
|
// initialize the display
|
||||||
i2c = new TwoWire(0);
|
i2c = new TwoWire(0);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user