diff --git a/Software/Software.ino b/Software/Software.ino index 90bb5900..be74b27c 100644 --- a/Software/Software.ino +++ b/Software/Software.ino @@ -135,6 +135,14 @@ unsigned long negativeStartTime = 0; unsigned long timeSpentInFaultedMode = 0; #endif +#ifdef EQUIPMENT_STOP_BUTTON +volatile unsigned long equipment_button_press_time = 0; // Time when button is pressed +const unsigned long equipment_button_long_press_duration = 5000; // 5 seconds for long press +int equipment_button_lastState = LOW; // the previous state from the input pin +int equipment_button_currentState; // the current reading from the input pin +unsigned long equipment_button_pressedTime = 0; +unsigned long equipment_button_releasedTime = 0; +#endif TaskHandle_t main_loop_task; TaskHandle_t connectivity_loop_task; @@ -163,6 +171,9 @@ void setup() { init_battery(); +#ifdef EQUIPMENT_STOP_BUTTON + init_equipment_stop_button(); +#endif // BOOT button at runtime is used as an input for various things pinMode(0, INPUT_PULLUP); @@ -235,6 +246,8 @@ void core_loop(void* task_time_us) { while (true) { START_TIME_MEASUREMENT(all); START_TIME_MEASUREMENT(comm); + monitor_equipment_stop_button(); + // Input, Runs as fast as possible receive_can_native(); // Receive CAN messages from native CAN port #ifdef CAN_FD @@ -546,6 +559,40 @@ void init_battery() { #endif } +#ifdef EQUIPMENT_STOP_BUTTON + +void monitor_equipment_stop_button() { + // read the state of the switch/button: + equipment_button_currentState = digitalRead(EQUIPMENT_STOP_PIN); + + if (equipment_button_lastState == LOW && equipment_button_currentState == HIGH) // button is pressed + equipment_button_pressedTime = millis(); + else if (equipment_button_lastState == HIGH && equipment_button_currentState == LOW) { // button is released + equipment_button_releasedTime = millis(); + + long pressDuration = equipment_button_releasedTime - equipment_button_pressedTime; + + if (pressDuration < equipment_button_long_press_duration) { + // Short press detected, trigger emergency stop + setBatteryPause(true, true, true); + } else { + // Long press detected, reset equipment stop state + setBatteryPause(false, false, false); + } + } + + // save the the last state + equipment_button_lastState = equipment_button_currentState; +} + +void init_equipment_stop_button() { + + //using external pulldown resistors + pinMode(EQUIPMENT_STOP_PIN, INPUT); +} + +#endif + #ifdef CAN_FD // Functions #ifdef DEBUG_CANFD_DATA diff --git a/Software/USER_SETTINGS.h b/Software/USER_SETTINGS.h index a05ae685..9325957c 100644 --- a/Software/USER_SETTINGS.h +++ b/Software/USER_SETTINGS.h @@ -65,6 +65,7 @@ #define MDNSRESPONDER //Enable this line to enable MDNS, allows battery monitor te be found by .local address. Requires WEBSERVER to be enabled. #define LOAD_SAVED_SETTINGS_ON_BOOT //Enable this line to read settings stored via the webserver on boot (overrides Wifi/battery settings set below) //#define FUNCTION_TIME_MEASUREMENT // Enable this to record execution times and present them in the web UI (WARNING, raises CPU load, do not use for production) +//#define EQUIPMENT_STOP_BUTTON // Enable this to have a emergengy/equipment stop button connected to board /* MQTT options */ // #define MQTT // Enable this line to enable MQTT diff --git a/Software/src/devboard/hal/hw_lilygo.h b/Software/src/devboard/hal/hw_lilygo.h index 65ee569f..d4d7ce2c 100644 --- a/Software/src/devboard/hal/hw_lilygo.h +++ b/Software/src/devboard/hal/hw_lilygo.h @@ -65,6 +65,9 @@ #define LED_PIN 4 #define LED_MAX_BRIGHTNESS 40 +// Equipment stop pin +#define EQUIPMENT_STOP_PIN 35 + /* ----- Error checks below, don't change (can't be moved to separate file) ----- */ #ifndef HW_CONFIGURED #define HW_CONFIGURED @@ -78,6 +81,18 @@ #endif #endif +#ifdef EQUIPMENT_STOP_BUTTON +#ifdef DUAL_CAN +#error EQUIPMENT_STOP_BUTTON and DUAL_CAN cannot coexist due to overlapping GPIO pin usage +#endif +#ifdef CAN_FD +#error EQUIPMENT_STOP_BUTTON and CAN_FD cannot coexist due to overlapping GPIO pin usage +#endif +#ifdef CHADEMO_BATTERY +#error EQUIPMENT_STOP_BUTTON and CHADEMO_BATTERY cannot coexist due to overlapping GPIO pin usage +#endif +#endif + #ifdef BMW_I3_BATTERY #ifdef CONTACTOR_CONTROL #error GPIO PIN 25 cannot be used for both BMWi3 Wakeup and contactor control. Disable CONTACTOR_CONTROL diff --git a/Software/src/devboard/hal/hw_stark.h b/Software/src/devboard/hal/hw_stark.h index 7bc45a54..5e26f559 100644 --- a/Software/src/devboard/hal/hw_stark.h +++ b/Software/src/devboard/hal/hw_stark.h @@ -58,6 +58,9 @@ GPIOs on extra header #define LED_PIN 4 #define LED_MAX_BRIGHTNESS 40 +// Equipment stop pin +#define EQUIPMENT_STOP_PIN 2 + /* ----- Error checks below, don't change (can't be moved to separate file) ----- */ #ifndef HW_CONFIGURED #define HW_CONFIGURED diff --git a/Software/src/devboard/safety/safety.cpp b/Software/src/devboard/safety/safety.cpp index acb91540..32788e2b 100644 --- a/Software/src/devboard/safety/safety.cpp +++ b/Software/src/devboard/safety/safety.cpp @@ -239,6 +239,7 @@ void setBatteryPause(bool pause_battery, bool pause_CAN, bool emergency_stop) { /// @brief handle emulator pause status /// @return true if CAN messages should be sent to battery, false if not void emulator_pause_state_send_CAN_battery() { + bool previous_allowed_to_send_CAN = allowed_to_send_CAN; if (emulator_pause_status == NORMAL) { allowed_to_send_CAN = true; @@ -256,6 +257,14 @@ void emulator_pause_state_send_CAN_battery() { } allowed_to_send_CAN = (!emulator_pause_CAN_send_ON || emulator_pause_status == NORMAL); + + if (previous_allowed_to_send_CAN && !allowed_to_send_CAN) { + //completely force stop the CAN communication + ESP32Can.CANStop(); + } else if (!previous_allowed_to_send_CAN && allowed_to_send_CAN) { + //resume CAN communication + ESP32Can.CANInit(); + } } std::string get_emulator_pause_status() { diff --git a/Software/src/devboard/safety/safety.h b/Software/src/devboard/safety/safety.h index 4823f006..0020cd81 100644 --- a/Software/src/devboard/safety/safety.h +++ b/Software/src/devboard/safety/safety.h @@ -2,6 +2,7 @@ #define SAFETY_H #include #include +#include "../../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h" #define MAX_CAN_FAILURES 50 diff --git a/Software/src/devboard/webserver/webserver.cpp b/Software/src/devboard/webserver/webserver.cpp index 7852b3d1..7a04feb3 100644 --- a/Software/src/devboard/webserver/webserver.cpp +++ b/Software/src/devboard/webserver/webserver.cpp @@ -933,9 +933,6 @@ void onOTAStart() { clear_event(EVENT_OTA_UPDATE_TIMEOUT); ota_active = true; - //completely force stop the CAN communication - ESP32Can.CANStop(); - ota_timeout_timer.reset(); } @@ -968,8 +965,6 @@ void onOTAEnd(bool success) { #endif // DEBUG_VIA_USB //try to Resume the battery pause and CAN communication setBatteryPause(false, false); - //resume CAN communication - ESP32Can.CANInit(); } }