used ChatGPT to add comments and proper Headers to all SourceFiles

This commit is contained in:
Marcel Peterkau 2024-01-09 12:54:05 +01:00
parent 62cc2bf982
commit f52f4103f6
21 changed files with 945 additions and 99 deletions

View File

@ -1,3 +1,16 @@
/**
* @file can.h
*
* @brief Header file for Controller Area Network (CAN) functionality in the ChainLube application.
*
* This file provides functions and structures related to Controller Area Network (CAN)
* communication for the ChainLube project. It includes functions for initializing CAN,
* processing CAN messages, and retrieving wheel speed from CAN data.
*
* @author Marcel Peterkau
* @date 09.01.2024
*/
#ifndef _CAN_H_ #ifndef _CAN_H_
#define _CAN_H_ #define _CAN_H_
@ -9,6 +22,7 @@
#include "dtc.h" #include "dtc.h"
#include "debugger.h" #include "debugger.h"
// CAN frame structure definition
struct can_frame struct can_frame
{ {
unsigned long can_id; unsigned long can_id;
@ -16,8 +30,9 @@ struct can_frame
uint8_t data[8] __attribute__((aligned(8))); uint8_t data[8] __attribute__((aligned(8)));
}; };
// Function prototypes
void Init_CAN(); void Init_CAN();
void CAN_Process(); void CAN_Process();
uint32_t Process_CAN_WheelSpeed(); uint32_t Process_CAN_WheelSpeed();
#endif #endif

View File

@ -1,3 +1,16 @@
/**
* @file common.h
*
* @brief Header file for common definitions and macros in the ChainLube application.
*
* This file defines common macros, GPIO configurations, and other shared constants
* for the ChainLube project. It includes definitions for GPIO pins, OTA delays, pulse lengths,
* and other common settings used across the project.
*
* @author Marcel Peterkau
* @date 09.01.2024
*/
#ifndef _COMMON_H_ #ifndef _COMMON_H_
#define _COMMON_H_ #define _COMMON_H_
@ -5,6 +18,7 @@
#define QUOTE(x) Q(x) #define QUOTE(x) Q(x)
#define SET_BIT(value, bitPosition) ((value) |= (1U << (bitPosition))) #define SET_BIT(value, bitPosition) ((value) |= (1U << (bitPosition)))
// Conditional compilation based on PCB revision
#if PCB_REV == 1 #if PCB_REV == 1
#define GPIO_BUTTON D7 #define GPIO_BUTTON D7
#define GPIO_LED D8 #define GPIO_LED D8
@ -40,17 +54,17 @@
#define LUBE_PULSE_LENGHT_MS 160 #define LUBE_PULSE_LENGHT_MS 160
#define LUBE_PULSE_PAUSE_MS 340 #define LUBE_PULSE_PAUSE_MS 340
// Pump pulse parameters
// -> 2Hz PumpPulse // -> 2Hz PumpPulse
// -> 49,7cc / h @ 2Hz // -> 49.7cc / h @ 2Hz
// -> 49,7 ml / h @ 2Hz // -> 49.7 ml / h @ 2Hz
// -> 828,4µl / min @ 2Hz // -> 828.4µl / min @ 2Hz
// -> 828,3µl / 60s // -> 828.3µl / 60s
// -> 13,81µl / 1s // -> 13.81µl / 1s
// -> 6,90µl / Pulse // -> 6.90µl / Pulse
#define DEFAULT_PUMP_DOSE 7 #define DEFAULT_PUMP_DOSE 7
#define STARTUP_DELAY 5000 #define STARTUP_DELAY 5000
#define SHUTDOWN_DELAY_MS 5000 #define SHUTDOWN_DELAY_MS 5000
#endif #endif

View File

@ -1,3 +1,17 @@
/**
* @file config.h
*
* @brief Header file for configuration settings and EEPROM operations in the ChainLube application.
*
* This file defines configuration settings for the ChainLube project, including default values,
* EEPROM structures, and functions for EEPROM operations. It also defines enums for different sources
* of speed input, GPS baud rates, and CAN bus sources. Additionally, it includes functions for EEPROM handling
* such as storing, retrieving, and formatting configuration data.
*
* @author Marcel Peterkau
* @date 09.01.2024
*/
#ifndef _CONFIG_H_ #ifndef _CONFIG_H_
#define _CONFIG_H_ #define _CONFIG_H_
@ -14,6 +28,7 @@
#define EEPROM_SIZE_BYTES I2C_DEVICESIZE_24LC256 #define EEPROM_SIZE_BYTES I2C_DEVICESIZE_24LC256
#endif #endif
// Enum for different sources of speed input
typedef enum SpeedSource_e typedef enum SpeedSource_e
{ {
#ifdef FEATURE_ENABLE_TIMER #ifdef FEATURE_ENABLE_TIMER
@ -24,6 +39,7 @@ typedef enum SpeedSource_e
SOURCE_CAN SOURCE_CAN
} SpeedSource_t; } SpeedSource_t;
// String representation of SpeedSource enum
const char SpeedSourceString[][8] = { const char SpeedSourceString[][8] = {
#ifdef FEATURE_ENABLE_TIMER #ifdef FEATURE_ENABLE_TIMER
"Timer", "Timer",
@ -33,32 +49,37 @@ const char SpeedSourceString[][8] = {
"CAN-Bus" "CAN-Bus"
}; };
const size_t SpeedSourceString_Elements = sizeof(SpeedSourceString) / sizeof(SpeedSourceString[0]);
// Enum for GPS baud rates
typedef enum GPSBaudRate_e typedef enum GPSBaudRate_e
{ {
BAUD_9600, BAUD_9600,
BAUD_115200 BAUD_115200
} GPSBaudRate_t; } GPSBaudRate_t;
// String representation of GPSBaudRate enum
const char GPSBaudRateString[][7] = { const char GPSBaudRateString[][7] = {
"9600", "9600",
"115200"}; "115200"};
const size_t GPSBaudRateString_Elements = sizeof(GPSBaudRateString) / sizeof(GPSBaudRateString[0]); const size_t GPSBaudRateString_Elements = sizeof(GPSBaudRateString) / sizeof(GPSBaudRateString[0]);
// Enum for CAN bus sources
typedef enum CANSource_e typedef enum CANSource_e
{ {
KTM_890_ADV_R_2021, KTM_890_ADV_R_2021,
KTM_1290_SD_R_2023 KTM_1290_SD_R_2023
} CANSource_t; } CANSource_t;
// String representation of CANSource enum
const char CANSourceString[][30] = { const char CANSourceString[][30] = {
"KTM 890 Adventure R (2021)", "KTM 890 Adventure R (2021)",
"KTM 1290 Superduke R (2023)"}; "KTM 1290 Superduke R (2023)"};
const size_t CANSourceString_Elements = sizeof(CANSourceString) / sizeof(CANSourceString[0]); const size_t CANSourceString_Elements = sizeof(CANSourceString) / sizeof(CANSourceString[0]);
const size_t SpeedSourceString_Elements = sizeof(SpeedSourceString) / sizeof(SpeedSourceString[0]); // Structure for persistence data stored in EEPROM
typedef struct typedef struct
{ {
uint16_t writeCycleCounter = 0; uint16_t writeCycleCounter = 0;
@ -69,6 +90,7 @@ typedef struct
uint32_t checksum = 0; uint32_t checksum = 0;
} persistenceData_t; } persistenceData_t;
// Structure for configuration settings stored in EEPROM
typedef struct typedef struct
{ {
uint8_t EEPROM_Version = 0; uint8_t EEPROM_Version = 0;
@ -92,6 +114,7 @@ typedef struct
uint32_t checksum = 0; uint32_t checksum = 0;
} LubeConfig_t; } LubeConfig_t;
// Default configuration settings
const LubeConfig_t LubeConfig_defaults = { const LubeConfig_t LubeConfig_defaults = {
0, 8000, 4000, 320, DEFAULT_PUMP_DOSE, 30, 1, 150, 70, 18, 2000, 25, SOURCE_IMPULSE, 0, 8000, 4000, 320, DEFAULT_PUMP_DOSE, 30, 1, 150, 70, 18, 2000, 25, SOURCE_IMPULSE,
BAUD_115200, BAUD_115200,
@ -117,4 +140,4 @@ uint32_t ConfigSanityCheck(bool autocorrect = false);
extern LubeConfig_t LubeConfig; extern LubeConfig_t LubeConfig;
extern persistenceData_t PersistenceData; extern persistenceData_t PersistenceData;
extern uint16_t eePersistenceMarker; extern uint16_t eePersistenceMarker;
#endif // _CONFIG_H_ #endif // _CONFIG_H_

View File

@ -1,9 +1,21 @@
/**
* @file debugger.h
*
* @brief Header file for debugging functions and status in the ChainLube application.
*
* This file declares functions and status definitions for debugging purposes in the ChainLube project.
* It includes functions to print system information, WiFi information, format EEPROM data,
* handle debug messages, and manage the status of different debug ports.
*
* @author Marcel Peterkau
* @date 09.01.2024
*/
#ifndef _DEBUGGER_H_ #ifndef _DEBUGGER_H_
#define _DEBUGGER_H_ #define _DEBUGGER_H_
#include <Arduino.h> #include <Arduino.h>
#include "webui.h" #include "webui.h"
const char PROGMEM helpCmd[] = "sysinfo - System Info\n" const char PROGMEM helpCmd[] = "sysinfo - System Info\n"
"netinfo - WiFi Info\n" "netinfo - WiFi Info\n"
"formatPDS - Format Persistence EEPROM Data\n" "formatPDS - Format Persistence EEPROM Data\n"

View File

@ -1,3 +1,16 @@
/**
* @file dtc.h
*
* @brief Header file for handling Diagnostic Trouble Codes (DTC) in the ChainLube application.
*
* This file provides definitions and functions for handling Diagnostic Trouble Codes (DTC)
* in the ChainLube project. It includes structures for DTC entries, severity levels,
* and functions for DTC maintenance and processing. DTCs are used to track system errors and issues.
*
* @author Marcel Peterkau
* @date 09.01.2024
*/
#ifndef _DTC_H_ #ifndef _DTC_H_
#define _DTC_H_ #define _DTC_H_

View File

@ -1,4 +1,18 @@
// Auto-generated by script on 2023-12-04 02:10:49 /**
* @file dtc_defs.h
*
* @brief Header file for Diagnostic Trouble Code (DTC) definitions in the ChainLube application.
*
* This file contains definitions for Diagnostic Trouble Codes (DTC) in the ChainLube project.
* It includes enums for DTC active status, severity levels, and specific DTC codes.
* The file also defines an array of DTC definitions and a timestamp indicating the generation time.
*
* @note This file is auto-generated by a script on 2024-01-09 12:08:43.
*
* @author Marcel Peterkau
* @date 09.01.2024
*/
#ifndef DTC_DEFS_H #ifndef DTC_DEFS_H
#define DTC_DEFS_H #define DTC_DEFS_H
@ -66,6 +80,6 @@ const DTC_t dtc_definitions[] = {
{ DTC_LAST_DTC , DTC_NONE } // Last Error { DTC_LAST_DTC , DTC_NONE } // Last Error
}; };
const uint32_t dtc_generation_timestamp = 1701652249; const uint32_t dtc_generation_timestamp = 1704798523;
#endif // DTC_DEFS_H #endif // DTC_DEFS_H

View File

@ -1,4 +1,18 @@
// Auto-generated by script on {{ timestamp }} /**
* @file dtc_defs.h
*
* @brief Header file for Diagnostic Trouble Code (DTC) definitions in the ChainLube application.
*
* This file contains definitions for Diagnostic Trouble Codes (DTC) in the ChainLube project.
* It includes enums for DTC active status, severity levels, and specific DTC codes.
* The file also defines an array of DTC definitions and a timestamp indicating the generation time.
*
* @note This file is auto-generated by a script on {{ timestamp }}.
*
* @author Marcel Peterkau
* @date 09.01.2024
*/
#ifndef DTC_DEFS_H #ifndef DTC_DEFS_H
#define DTC_DEFS_H #define DTC_DEFS_H

View File

@ -1,3 +1,16 @@
/**
* @file globals.h
*
* @brief Header file for global variables and enums in the ChainLube application.
*
* This file contains declarations for global variables and enums used in the ChainLube application.
* It includes enums for system status and EEPROM-related requests, as well as a struct for global variables.
* The file also defines a struct for constants and initializes it with firmware and required flash version information.
*
* @author Marcel Peterkau
* @date 09.01.2024
*/
#ifndef _GLOBALS_H_ #ifndef _GLOBALS_H_
#define _GLOBALS_H_ #define _GLOBALS_H_
@ -29,29 +42,29 @@ typedef enum eEERequest
typedef struct Globals_s typedef struct Globals_s
{ {
tSystem_Status systemStatus = sysStat_Startup; tSystem_Status systemStatus = sysStat_Startup; /**< Current system status */
tSystem_Status resumeStatus = sysStat_Startup; tSystem_Status resumeStatus = sysStat_Startup; /**< Status to resume after rain mode */
char systemStatustxt[16] = ""; char systemStatustxt[16] = ""; /**< Text representation of system status */
uint16_t purgePulses = 0; uint16_t purgePulses = 0; /**< Number of purge pulses */
eEERequest requestEEAction = EE_IDLE; eEERequest requestEEAction = EE_IDLE;; /**< EEPROM-related request */
char DeviceName[33]; char DeviceName[33]; /**< Device name */
char FlashVersion[10]; char FlashVersion[10]; /**< Flash version */
uint16_t eePersistanceAdress; uint16_t eePersistanceAdress; /**< EEPROM persistence address */
uint8_t TankPercentage; uint8_t TankPercentage; /**< Tank percentage */
bool hasDTC; bool hasDTC; /**< Flag indicating the presence of Diagnostic Trouble Codes (DTC) */
bool measurementActive; bool measurementActive; /**< Flag indicating active measurement */
uint32_t measuredPulses; uint32_t measuredPulses; /**< Number of measured pulses */
} Globals_t; } Globals_t;
extern Globals_t globals; extern Globals_t globals; /**< Global variable struct */
typedef struct Constants_s typedef struct Constants_s
{ {
uint8_t FW_Version_major; uint8_t FW_Version_major; /**< Firmware version major number */
uint8_t FW_Version_minor; uint8_t FW_Version_minor; /**< Firmware version minor number */
uint8_t Required_Flash_Version_major; uint8_t Required_Flash_Version_major; /**< Required flash version major number */
uint8_t Required_Flash_Version_minor; uint8_t Required_Flash_Version_minor; /**< Required flash version minor number */
char GitHash[11]; char GitHash[11]; /**< Git hash string */
} Constants_t; } Constants_t;
const Constants_t constants PROGMEM = { const Constants_t constants PROGMEM = {
@ -60,6 +73,9 @@ const Constants_t constants PROGMEM = {
GIT_REV // Git-Hash-String GIT_REV // Git-Hash-String
}; };
/**
* @brief Initializes global variables.
*/
void initGlobals(); void initGlobals();
#endif #endif // _GLOBALS_H_

View File

@ -1,3 +1,17 @@
/**
* @file gps.h
*
* @brief Header file for GPS-related functions in the ChainLube application.
*
* This file contains declarations for functions related to GPS (Global Positioning System) functionality
* within the ChainLube application. It includes the initialization of the GPS module and processing of GPS
* data to calculate wheel speed. Additionally, it references other necessary header files for configuration,
* common definitions, diagnostics, and debugging.
*
* @author Marcel Peterkau
* @date 09.01.2024
*/
#ifndef _GPS_H_ #ifndef _GPS_H_
#define _GPS_H_ #define _GPS_H_
@ -7,7 +21,16 @@
#include "dtc.h" #include "dtc.h"
#include "debugger.h" #include "debugger.h"
/**
* @brief Initializes the GPS module.
*/
void Init_GPS(); void Init_GPS();
/**
* @brief Processes GPS data to calculate wheel speed.
*
* @return Calculated wheel speed in millimeters per second.
*/
uint32_t Process_GPS_WheelSpeed(); uint32_t Process_GPS_WheelSpeed();
#endif #endif // _GPS_H_

View File

@ -1,3 +1,16 @@
/**
* @file led_colors.h
*
* @brief Header file defining color values for LEDs in the ChainLube application.
*
* This file contains color definitions in hexadecimal format for various states and events of LEDs
* used in the ChainLube application. It provides a convenient way to reference specific colors for
* different visual indications in the system.
*
* @author Marcel Peterkau
* @date 09.01.2024
*/
#ifndef _LED_COLORS_H_ #ifndef _LED_COLORS_H_
#define _LED_COLORS_H_ #define _LED_COLORS_H_
@ -19,17 +32,14 @@
#define COLOR_AMBER 0xFF6400 #define COLOR_AMBER 0xFF6400
#define COLOR_WARM_WHITE 0xFDF5E6 #define COLOR_WARM_WHITE 0xFDF5E6
#define LED_DEFAULT_COLOR COLOR_WARM_WHITE #define LED_DEFAULT_COLOR COLOR_WARM_WHITE
#define LED_STARTUP_NORMAL COLOR_WARM_WHITE #define LED_STARTUP_NORMAL COLOR_WARM_WHITE
#define LED_STARTUP_TANKWARN COLOR_AMBER #define LED_STARTUP_TANKWARN COLOR_AMBER
#define LED_NORMAL_COLOR COLOR_GREEN #define LED_NORMAL_COLOR COLOR_GREEN
#define LED_RAIN_COLOR COLOR_BLUE #define LED_RAIN_COLOR COLOR_BLUE
#define LED_WIFI_BLINK COLOR_YELLOW #define LED_WIFI_BLINK COLOR_YELLOW
#define LED_PURGE_COLOR COLOR_MAGENTA #define LED_PURGE_COLOR COLOR_MAGENTA
#define LED_ERROR_BLINK COLOR_RED #define LED_ERROR_BLINK COLOR_RED
#define LED_SHUTDOWN_BLINK COLOR_CYAN #define LED_SHUTDOWN_BLINK COLOR_CYAN
#endif /* _LED_COLORS_H_ */ #endif /* _LED_COLORS_H_ */

View File

@ -1,3 +1,15 @@
/**
* @file lubeapp.h
*
* @brief Header file for the ChainLube application functions.
*
* This file contains function declarations related to the main functionality of the ChainLube
* application. It includes functions for running the application and generating lubrication pulses.
*
* @author Marcel Peterkau
* @date 09.01.2024
*/
#ifndef _LUBEAPP_H_ #ifndef _LUBEAPP_H_
#define _LUBEAPP_H_ #define _LUBEAPP_H_
@ -12,4 +24,4 @@
void RunLubeApp(uint32_t add_milimeters); void RunLubeApp(uint32_t add_milimeters);
void LubePulse(); void LubePulse();
#endif #endif /* _LUBEAPP_H_ */

View File

@ -1,3 +1,15 @@
/**
* @file sanitycheck.h
*
* @brief Header file for sanity checks and configuration validation in the ChainLube application.
*
* This file contains checks and validations to ensure that the configuration and features of the
* ChainLube application are compatible with the selected PCB revision and defined parameters.
*
* @author Marcel Peterkau
* @date 09.01.2024
*/
#ifndef _SANITYCHECK_H_ #ifndef _SANITYCHECK_H_
#define _SANITYCHECK_H_ #define _SANITYCHECK_H_
@ -34,4 +46,4 @@
#error "You must define an WIFI_AP_PASSWORD for Standalone AP-Mode" #error "You must define an WIFI_AP_PASSWORD for Standalone AP-Mode"
#endif #endif
#endif //_SANITYCHECK_H_ #endif // _SANITYCHECK_H_

View File

@ -1,3 +1,16 @@
/**
* @file webui.h
*
* @brief Header file for the web-based user interface (WebUI) in the ChainLube application.
*
* This file contains declarations for functions related to the initialization and processing of the
* web-based user interface (WebUI). It includes the necessary libraries and dependencies for handling
* web server functionality, asynchronous JSON operations, and live debugging through WebSockets.
*
* @author Marcel Peterkau
* @date 09.01.2024
*/
#ifndef _WEBUI_H_ #ifndef _WEBUI_H_
#define _WEBUI_H_ #define _WEBUI_H_
@ -22,4 +35,4 @@ void Webserver_Process();
void Websocket_PushLiveDebug(String Message); void Websocket_PushLiveDebug(String Message);
#endif #endif // _WEBUI_H_

View File

@ -1,3 +1,17 @@
/**
* @file can.cpp
*
* @brief Implementation file for CAN-related functions in the ChainLube application.
*
* This file contains the implementation of functions related to CAN (Controller Area Network)
* communication within the ChainLube application. It includes the initialization of the CAN module,
* setup of masks and filters, and processing of CAN messages. Additionally, a debug message function
* is included if CAN debugging is enabled.
*
* @author Your Name
* @date Date
*/
#include "can.h" #include "can.h"
MCP_CAN CAN0(GPIO_CS_CAN); MCP_CAN CAN0(GPIO_CS_CAN);
@ -6,9 +20,14 @@ MCP_CAN CAN0(GPIO_CS_CAN);
void sendCANDebugMessage(); void sendCANDebugMessage();
#endif #endif
/**
* @brief Initializes the CAN module, sets masks, and filters based on the configured CAN source.
*
* This function initializes the CAN module, sets masks and filters based on the configured CAN source
* in the application settings, and sets the CAN module in normal mode for communication.
*/
void Init_CAN() void Init_CAN()
{ {
if (CAN0.begin(MCP_STDEXT, CAN_500KBPS, MCP_16MHZ) != CAN_OK) if (CAN0.begin(MCP_STDEXT, CAN_500KBPS, MCP_16MHZ) != CAN_OK)
MaintainDTC(DTC_CAN_TRANSCEIVER_FAILED, true); MaintainDTC(DTC_CAN_TRANSCEIVER_FAILED, true);
@ -30,6 +49,11 @@ void Init_CAN()
CAN0.setMode(MCP_NORMAL); CAN0.setMode(MCP_NORMAL);
} }
/**
* @brief Processes CAN messages and sends a CAN debug message periodically.
*
* This function processes CAN messages and sends a CAN debug message periodically based on a time interval.
*/
void CAN_Process() void CAN_Process()
{ {
static uint32_t previousMillis = 0; static uint32_t previousMillis = 0;
@ -40,7 +64,15 @@ void CAN_Process()
previousMillis = millis(); previousMillis = millis();
} }
} }
/**
* @brief Processes CAN messages to determine the wheel speed based on the configured CAN source.
*
* This function reads incoming CAN messages and extracts the rear wheel speed information.
* The wheel speed is then converted to millimeters per second based on the configured CAN source.
* The function also monitors the CAN signal for potential issues and triggers diagnostic trouble codes (DTCs).
*
* @return The calculated distance traveled in millimeters since the last call.
*/
uint32_t Process_CAN_WheelSpeed() uint32_t Process_CAN_WheelSpeed()
{ {
#define FACTOR_RWP_KMH_890ADV 18 // Divider to convert Raw Data to km/h #define FACTOR_RWP_KMH_890ADV 18 // Divider to convert Raw Data to km/h
@ -87,6 +119,13 @@ uint32_t Process_CAN_WheelSpeed()
} }
#ifdef CAN_DEBUG_MESSAGE #ifdef CAN_DEBUG_MESSAGE
/**
* @brief Sends periodic CAN debug messages for monitoring and diagnostics.
*
* This function sends periodic CAN debug messages containing various system information for monitoring and diagnostics.
* The information includes system status, timestamps, tank percentage, DTC flags, and other relevant data.
* The debug messages are sent with a configurable multiplexer to broadcast different types of information in each cycle.
*/
void sendCANDebugMessage() void sendCANDebugMessage()
{ {
#define MAX_DEBUG_MULTIPLEXER 6 #define MAX_DEBUG_MULTIPLEXER 6

View File

@ -1,24 +1,51 @@
/**
* @file config.cpp
* @brief Implementation of EEPROM and configuration-related functions.
*
* This file contains functions for managing EEPROM storage and handling configuration data.
* It includes the definitions of configuration structures, EEPROM access, and utility functions.
*/
#include "config.h" #include "config.h"
#include "debugger.h" #include "debugger.h"
// Instance of I2C_eeprom for EEPROM access
I2C_eeprom ee(0x50, EEPROM_SIZE_BYTES); I2C_eeprom ee(0x50, EEPROM_SIZE_BYTES);
// Configuration and persistence data structures
LubeConfig_t LubeConfig; LubeConfig_t LubeConfig;
persistenceData_t PersistenceData; persistenceData_t PersistenceData;
const uint16_t eeVersion = 2; // inc
// EEPROM version identifier
const uint16_t eeVersion = 2; // Increment this version when changing EEPROM structures
// Flag indicating whether EEPROM is available
boolean eeAvailable = false; boolean eeAvailable = false;
// Offsets within EEPROM for LubeConfig and PersistenceData
const uint16_t startofLubeConfig = 16; const uint16_t startofLubeConfig = 16;
const uint16_t startofPersistence = 16 + sizeof(LubeConfig) + (sizeof(LubeConfig) % 16); const uint16_t startofPersistence = 16 + sizeof(LubeConfig) + (sizeof(LubeConfig) % 16);
// Function prototype to check EEPROM availability
boolean checkEEPROMavailable(); boolean checkEEPROMavailable();
/**
* @brief Initializes EEPROM and checks its availability.
*
* This function initializes the EEPROM using the I2C_eeprom instance and checks if it's available.
*/
void InitEEPROM() void InitEEPROM()
{ {
ee.begin(); ee.begin();
checkEEPROMavailable(); checkEEPROMavailable();
} }
/**
* @brief Processes EEPROM actions based on the request from the global state.
*
* This function processes EEPROM actions based on the request from the global state.
* It performs actions such as saving, loading, and formatting EEPROM data for both configuration and persistence.
*/
void EEPROM_Process() void EEPROM_Process()
{ {
switch (globals.requestEEAction) switch (globals.requestEEAction)
@ -37,7 +64,7 @@ void EEPROM_Process()
FormatConfig_EEPROM(); FormatConfig_EEPROM();
globals.requestEEAction = EE_IDLE; globals.requestEEAction = EE_IDLE;
GetConfig_EEPROM(); GetConfig_EEPROM();
Debug_pushMessage("Formated EEPROM CFG\n"); Debug_pushMessage("Formatted EEPROM CFG\n");
break; break;
case EE_PDS_SAVE: case EE_PDS_SAVE:
StorePersistence_EEPROM(); StorePersistence_EEPROM();
@ -53,7 +80,7 @@ void EEPROM_Process()
FormatPersistence_EEPROM(); FormatPersistence_EEPROM();
globals.requestEEAction = EE_IDLE; globals.requestEEAction = EE_IDLE;
GetPersistence_EEPROM(); GetPersistence_EEPROM();
Debug_pushMessage("Formated EEPROM PDS\n"); Debug_pushMessage("Formatted EEPROM PDS\n");
break; break;
case EE_FORMAT_ALL: case EE_FORMAT_ALL:
FormatConfig_EEPROM(); FormatConfig_EEPROM();
@ -61,7 +88,7 @@ void EEPROM_Process()
GetConfig_EEPROM(); GetConfig_EEPROM();
GetPersistence_EEPROM(); GetPersistence_EEPROM();
globals.requestEEAction = EE_IDLE; globals.requestEEAction = EE_IDLE;
Debug_pushMessage("Formated EEPROM ALL\n"); Debug_pushMessage("Formatted EEPROM ALL\n");
break; break;
case EE_ALL_SAVE: case EE_ALL_SAVE:
StorePersistence_EEPROM(); StorePersistence_EEPROM();
@ -75,22 +102,36 @@ void EEPROM_Process()
} }
} }
/**
* @brief Stores the configuration data in EEPROM.
*
* This function calculates the checksum for the configuration data, updates it, and stores it in EEPROM.
* It also performs a sanity check on the configuration and raises a diagnostic trouble code (DTC) if needed.
*/
void StoreConfig_EEPROM() void StoreConfig_EEPROM()
{ {
LubeConfig.checksum = 0; LubeConfig.checksum = 0;
LubeConfig.checksum = Checksum_EEPROM((uint8_t *)&LubeConfig, sizeof(LubeConfig)); LubeConfig.checksum = Checksum_EEPROM((uint8_t *)&LubeConfig, sizeof(LubeConfig));
if (!checkEEPROMavailable()) if (!checkEEPROMavailable())
return; return;
ee.updateBlock(startofLubeConfig, (uint8_t *)&LubeConfig, sizeof(LubeConfig)); ee.updateBlock(startofLubeConfig, (uint8_t *)&LubeConfig, sizeof(LubeConfig));
uint32_t ConfigSanityCheckResult = ConfigSanityCheck(false); uint32_t ConfigSanityCheckResult = ConfigSanityCheck(false);
if (ConfigSanityCheckResult > 0) if (ConfigSanityCheckResult > 0)
{ {
MaintainDTC(DTC_EEPROM_CFG_SANITY, true, ConfigSanityCheckResult); MaintainDTC(DTC_EEPROM_CFG_SANITY, true, ConfigSanityCheckResult);
} }
} }
/**
* @brief Retrieves the configuration data from EEPROM.
*
* This function reads the configuration data from EEPROM, performs a checksum validation,
* and conducts a sanity check on the configuration. It raises a diagnostic trouble code (DTC) if needed.
*/
void GetConfig_EEPROM() void GetConfig_EEPROM()
{ {
if (!checkEEPROMavailable()) if (!checkEEPROMavailable())
@ -105,15 +146,23 @@ void GetConfig_EEPROM()
{ {
MaintainDTC(DTC_EEPROM_CFG_BAD, true); MaintainDTC(DTC_EEPROM_CFG_BAD, true);
} }
LubeConfig.checksum = checksum; LubeConfig.checksum = checksum;
uint32_t ConfigSanityCheckResult = ConfigSanityCheck(false); uint32_t ConfigSanityCheckResult = ConfigSanityCheck(false);
if (ConfigSanityCheckResult > 0) if (ConfigSanityCheckResult > 0)
{ {
MaintainDTC(DTC_EEPROM_CFG_SANITY, true, ConfigSanityCheckResult); MaintainDTC(DTC_EEPROM_CFG_SANITY, true, ConfigSanityCheckResult);
} }
} }
/**
* @brief Stores the persistence data in EEPROM.
*
* This function increments the write cycle counter, performs a checksum calculation on the persistence data,
* and stores it in EEPROM. It also handles EEPROM page movement when needed.
*/
void StorePersistence_EEPROM() void StorePersistence_EEPROM()
{ {
if (PersistenceData.writeCycleCounter >= 0xFFF0) if (PersistenceData.writeCycleCounter >= 0xFFF0)
@ -130,6 +179,13 @@ void StorePersistence_EEPROM()
ee.updateBlock(globals.eePersistanceAdress, (uint8_t *)&PersistenceData, sizeof(PersistenceData)); ee.updateBlock(globals.eePersistanceAdress, (uint8_t *)&PersistenceData, sizeof(PersistenceData));
} }
/**
* @brief Retrieves the persistence data from EEPROM.
*
* This function reads the EEPROM to get the start address of the persistence data.
* If the start address is out of range, it resets and stores defaults. Otherwise,
* it reads from EEPROM and checks if the data is correct.
*/
void GetPersistence_EEPROM() void GetPersistence_EEPROM()
{ {
if (!checkEEPROMavailable()) if (!checkEEPROMavailable())
@ -159,6 +215,11 @@ void GetPersistence_EEPROM()
} }
} }
/**
* @brief Formats the configuration partition in EEPROM.
*
* This function resets the configuration data to defaults and stores it in EEPROM.
*/
void FormatConfig_EEPROM() void FormatConfig_EEPROM()
{ {
Debug_pushMessage("Formatting Config-Partition\n"); Debug_pushMessage("Formatting Config-Partition\n");
@ -167,6 +228,11 @@ void FormatConfig_EEPROM()
StoreConfig_EEPROM(); StoreConfig_EEPROM();
} }
/**
* @brief Formats the persistence partition in EEPROM.
*
* This function resets the persistence data to defaults and stores it in EEPROM.
*/
void FormatPersistence_EEPROM() void FormatPersistence_EEPROM()
{ {
Debug_pushMessage("Formatting Persistance-Partition\n"); Debug_pushMessage("Formatting Persistance-Partition\n");
@ -174,7 +240,13 @@ void FormatPersistence_EEPROM()
// memset(&PersistenceData, 0, sizeof(PersistenceData)); // memset(&PersistenceData, 0, sizeof(PersistenceData));
StorePersistence_EEPROM(); StorePersistence_EEPROM();
} }
/**
* @brief Moves the persistence page in EEPROM.
*
* This function adjusts the persistence page address and resets the write cycle counter.
*
* @param reset If true, the function resets the persistence page address to the start of the partition.
*/
void MovePersistencePage_EEPROM(boolean reset) void MovePersistencePage_EEPROM(boolean reset)
{ {
if (!checkEEPROMavailable()) if (!checkEEPROMavailable())
@ -183,7 +255,7 @@ void MovePersistencePage_EEPROM(boolean reset)
globals.eePersistanceAdress += sizeof(PersistenceData); globals.eePersistanceAdress += sizeof(PersistenceData);
PersistenceData.writeCycleCounter = 0; PersistenceData.writeCycleCounter = 0;
// check if we reached the End of the EEPROM and Startover at the beginning // Check if we reached the end of the EEPROM and start over at the beginning
if ((globals.eePersistanceAdress + sizeof(PersistenceData)) > ee.getDeviceSize() || reset) if ((globals.eePersistanceAdress + sizeof(PersistenceData)) > ee.getDeviceSize() || reset)
{ {
globals.eePersistanceAdress = startofPersistence; globals.eePersistanceAdress = startofPersistence;
@ -192,25 +264,45 @@ void MovePersistencePage_EEPROM(boolean reset)
ee.updateBlock(0, (uint8_t *)&globals.eePersistanceAdress, sizeof(globals.eePersistanceAdress)); ee.updateBlock(0, (uint8_t *)&globals.eePersistanceAdress, sizeof(globals.eePersistanceAdress));
} }
/**
* @brief Calculate CRC-32 checksum for a block of data.
*
* This function implements the CRC-32 algorithm.
*
* @param data Pointer to the data block.
* @param len Length of the data block in bytes.
* @return CRC-32 checksum.
*/
uint32_t Checksum_EEPROM(uint8_t const *data, size_t len) uint32_t Checksum_EEPROM(uint8_t const *data, size_t len)
{ {
if (data == NULL) if (data == NULL)
return 0; return 0;
uint32_t crc, mask;
crc = 0xFFFFFFFF; uint32_t crc = 0xFFFFFFFF;
uint32_t mask;
while (len--) while (len--)
{ {
crc ^= *data++; crc ^= *data++;
for (uint8_t k = 0; k < 8; k++) for (uint8_t k = 0; k < 8; k++)
{ {
mask = -(crc & 1); mask = -(crc & 1);
crc = (crc >> 1) ^ (0xEDB88320 & mask); crc = (crc >> 1) ^ (0xEDB88320 & mask);
} }
} }
return ~crc; return ~crc;
} }
/**
* @brief Dump a portion of EEPROM contents for debugging.
*
* This function prints the contents of a specified portion of EEPROM in a formatted way.
*
* @param memoryAddress Starting address in EEPROM.
* @param length Number of bytes to dump.
*/
void dumpEEPROM(uint16_t memoryAddress, uint16_t length) void dumpEEPROM(uint16_t memoryAddress, uint16_t length)
{ {
#define BLOCK_TO_LENGTH 16 #define BLOCK_TO_LENGTH 16
@ -220,42 +312,79 @@ void dumpEEPROM(uint16_t memoryAddress, uint16_t length)
char ascii_buf[BLOCK_TO_LENGTH + 1]; char ascii_buf[BLOCK_TO_LENGTH + 1];
sprintf(ascii_buf, "%*s", BLOCK_TO_LENGTH, "ASCII"); sprintf(ascii_buf, "%*s", BLOCK_TO_LENGTH, "ASCII");
// Print column headers
Debug_pushMessage(PSTR("\nAddress ")); Debug_pushMessage(PSTR("\nAddress "));
for (int x = 0; x < BLOCK_TO_LENGTH; x++) for (int x = 0; x < BLOCK_TO_LENGTH; x++)
Debug_pushMessage("%3d", x); Debug_pushMessage("%3d", x);
// Align address and length to BLOCK_TO_LENGTH boundaries
memoryAddress = memoryAddress / BLOCK_TO_LENGTH * BLOCK_TO_LENGTH; memoryAddress = memoryAddress / BLOCK_TO_LENGTH * BLOCK_TO_LENGTH;
length = (length + BLOCK_TO_LENGTH - 1) / BLOCK_TO_LENGTH * BLOCK_TO_LENGTH; length = (length + BLOCK_TO_LENGTH - 1) / BLOCK_TO_LENGTH * BLOCK_TO_LENGTH;
// Iterate through the specified portion of EEPROM
for (unsigned int i = 0; i < length; i++) for (unsigned int i = 0; i < length; i++)
{ {
int blockpoint = memoryAddress % BLOCK_TO_LENGTH; int blockpoint = memoryAddress % BLOCK_TO_LENGTH;
// Print ASCII representation header for each block
if (blockpoint == 0) if (blockpoint == 0)
{ {
ascii_buf[BLOCK_TO_LENGTH] = 0; ascii_buf[BLOCK_TO_LENGTH] = 0;
Debug_pushMessage(" %s", ascii_buf); Debug_pushMessage(" %s", ascii_buf);
Debug_pushMessage("\n0x%05X:", memoryAddress); Debug_pushMessage("\n0x%05X:", memoryAddress);
} }
// Read and print each byte
ascii_buf[blockpoint] = ee.readByte(memoryAddress); ascii_buf[blockpoint] = ee.readByte(memoryAddress);
Debug_pushMessage(" %02X", ascii_buf[blockpoint]); Debug_pushMessage(" %02X", ascii_buf[blockpoint]);
// Replace non-printable characters with dots in ASCII representation
if (ascii_buf[blockpoint] < 0x20 || ascii_buf[blockpoint] > 0x7E) if (ascii_buf[blockpoint] < 0x20 || ascii_buf[blockpoint] > 0x7E)
ascii_buf[blockpoint] = '.'; ascii_buf[blockpoint] = '.';
memoryAddress++; memoryAddress++;
} }
// Print a new line at the end of the dump
Debug_pushMessage("\n"); Debug_pushMessage("\n");
} }
/**
* @brief Check if EEPROM is available and connected.
*
* This function checks if the EEPROM is available and connected. If not, it triggers
* a diagnostic trouble code (DTC) indicating the absence of EEPROM.
*
* @return true if EEPROM is available, false otherwise.
*/
boolean checkEEPROMavailable() boolean checkEEPROMavailable()
{ {
// Check if EEPROM is connected
if (!ee.isConnected()) if (!ee.isConnected())
{ {
// Trigger DTC for no EEPROM found
MaintainDTC(DTC_NO_EEPROM_FOUND, true); MaintainDTC(DTC_NO_EEPROM_FOUND, true);
return false; return false;
} }
// Clear DTC for no EEPROM found since it's available now
MaintainDTC(DTC_NO_EEPROM_FOUND, false); MaintainDTC(DTC_NO_EEPROM_FOUND, false);
// EEPROM is available
return true; return true;
} }
/**
* @brief Perform sanity check on configuration settings.
*
* This function checks the validity of various configuration settings and returns a bitmask
* indicating which settings need to be reset. If autocorrect is enabled, it resets the settings
* to their default values.
*
* @param autocorrect If true, automatically correct invalid settings by resetting to defaults.
* @return A bitmask indicating which settings need to be reset.
*/
uint32_t ConfigSanityCheck(bool autocorrect) uint32_t ConfigSanityCheck(bool autocorrect)
{ {
uint32_t setting_reset_bits = 0; uint32_t setting_reset_bits = 0;
@ -332,7 +461,7 @@ uint32_t ConfigSanityCheck(bool autocorrect)
LubeConfig.DistancePerRevolution_mm = LubeConfig_defaults.DistancePerRevolution_mm; LubeConfig.DistancePerRevolution_mm = LubeConfig_defaults.DistancePerRevolution_mm;
} }
} }
if (!(LubeConfig.BleedingPulses > 0) || !(LubeConfig.BleedingPulses < 1001)) if (!(LubeConfig.BleedingPulses > 0) || !(LubeConfig.BleedingPulses < 1001))
{ {
SET_BIT(setting_reset_bits, 10); SET_BIT(setting_reset_bits, 10);
@ -360,5 +489,6 @@ uint32_t ConfigSanityCheck(bool autocorrect)
if (autocorrect) if (autocorrect)
LubeConfig.CANSource = LubeConfig_defaults.CANSource; LubeConfig.CANSource = LubeConfig_defaults.CANSource;
} }
// Return the bitmask indicating which settings need to be reset
return setting_reset_bits; return setting_reset_bits;
} }

View File

@ -1,3 +1,16 @@
/**
* @file debugger.cpp
* @brief Implementation of debugging functions for monitoring and diagnostics.
*
* This file contains the implementation of various debugging functions to monitor
* and diagnose the system. It includes functions to print system information, WiFi
* details, EEPROM status, dump configuration settings, dump persistence data, show
* Diagnostic Trouble Codes (DTCs), and more.
*
* @author Marcel Peterkau
* @date 09.04.2024
*/
#include "debugger.h" #include "debugger.h"
DebugStatus_t DebuggerStatus[dbg_cntElements]; DebugStatus_t DebuggerStatus[dbg_cntElements];
@ -15,32 +28,45 @@ void Debug_ShowDTCs();
void Debug_dumpGlobals(); void Debug_dumpGlobals();
void Debug_printHelp(); void Debug_printHelp();
/**
* @brief Initializes the debugger by setting the initial status for different debug ports.
* Serial debug output is turned off.
*/
void initDebugger() void initDebugger()
{ {
// Set the initial status of debug ports
DebuggerStatus[dbg_Serial] = disabled; DebuggerStatus[dbg_Serial] = disabled;
DebuggerStatus[dbg_Webui] = disabled; DebuggerStatus[dbg_Webui] = disabled;
// Disable serial debug output
Serial.setDebugOutput(false); Serial.setDebugOutput(false);
} }
/**
* @brief Processes incoming debug commands from the Serial interface.
* It reads characters from Serial and interprets them as commands.
* The recognized commands are processed accordingly.
*/
void Debug_Process() void Debug_Process()
{ {
// Enumeration for tracking the state of input processing
typedef enum InputProcessed_e typedef enum InputProcessed_e
{ {
IDLE, IDLE, ///< No command processing is in progress
CMD_COMPLETE, CMD_COMPLETE, ///< Received a complete command
CMD_ABORT, CMD_ABORT, ///< Received an abort command (Esc)
CMD_OVERFLOW CMD_OVERFLOW ///< Input buffer overflow occurred
} InputProcessed_t; } InputProcessed_t;
static unsigned int inputCnt = 0; static unsigned int inputCnt = 0; ///< Counter for characters in the input buffer
static char inputBuffer[32]; static char inputBuffer[32]; ///< Buffer to store the received characters
InputProcessed_t InputProcessed = IDLE; InputProcessed_t InputProcessed = IDLE; ///< State variable for input processing
// Check if there are characters available in the Serial input buffer
if (Serial.available()) if (Serial.available())
{ {
char inputChar = Serial.read(); char inputChar = Serial.read();
// Process the received character based on its value
switch (inputChar) switch (inputChar)
{ {
case '\n': case '\n':
@ -55,7 +81,7 @@ void Debug_Process()
InputProcessed = CMD_ABORT; InputProcessed = CMD_ABORT;
break; break;
case 0x21 ... 0x7E: // its a real letter or sign and not some control-chars case 0x21 ... 0x7E: // it's a real letter or sign and not some control-chars
inputBuffer[inputCnt] = inputChar; inputBuffer[inputCnt] = inputChar;
inputCnt++; inputCnt++;
break; break;
@ -64,6 +90,7 @@ void Debug_Process()
break; break;
} }
// Check for input buffer overflow
if (inputCnt > sizeof(inputBuffer)) if (inputCnt > sizeof(inputBuffer))
{ {
inputCnt = 0; inputCnt = 0;
@ -72,6 +99,7 @@ void Debug_Process()
} }
} }
// Process the command based on the detected state of input processing
switch (InputProcessed) switch (InputProcessed)
{ {
case CMD_ABORT: case CMD_ABORT:
@ -83,7 +111,7 @@ void Debug_Process()
break; break;
case CMD_OVERFLOW: case CMD_OVERFLOW:
Debug_pushMessage("input Buffer overflow\n"); Debug_pushMessage("Input buffer overflow\n");
break; break;
default: default:
@ -91,32 +119,53 @@ void Debug_Process()
} }
InputProcessed = IDLE; InputProcessed = IDLE;
} }
/**
* @brief Sets the status of a specific debug port (Serial or WebUI).
* Updates the status in the DebuggerStatus array and provides debug messages.
*
* @param port The debug port to set the status for (dbg_Serial or dbg_Webui).
* @param status The status to set (enabled or disabled).
*/
void SetDebugportStatus(DebugPorts_t port, DebugStatus_t status) void SetDebugportStatus(DebugPorts_t port, DebugStatus_t status)
{ {
// Display a debug message based on the provided status
if (status == disabled) if (status == disabled)
Debug_pushMessage("disable DebugPort %s\n", sDebugPorts[port]); Debug_pushMessage("Disable DebugPort %s\n", sDebugPorts[port]);
// Update the status in the DebuggerStatus array
DebuggerStatus[port] = status; DebuggerStatus[port] = status;
// Display a debug message based on the updated status
if (status == enabled) if (status == enabled)
Debug_pushMessage("enabled DebugPort %s\n", sDebugPorts[port]); Debug_pushMessage("Enabled DebugPort %s\n", sDebugPorts[port]);
} }
/**
* @brief Pushes a formatted debug message to the enabled debug ports (Serial or WebUI).
*
* @param format The format string for the debug message.
* @param ... Additional arguments for formatting the message.
*/
void Debug_pushMessage(const char *format, ...) void Debug_pushMessage(const char *format, ...)
{ {
// Check if either the Serial or WebUI debug port is enabled
if ((DebuggerStatus[dbg_Serial] == enabled) || (DebuggerStatus[dbg_Webui] == enabled)) if ((DebuggerStatus[dbg_Serial] == enabled) || (DebuggerStatus[dbg_Webui] == enabled))
{ {
char buff[64]; char buff[64]; // Buffer to hold the formatted message
va_list arg; va_list arg; // Variable argument list for vsnprintf
va_start(arg, format); va_start(arg, format);
// Format the message and store it in the buffer
vsnprintf(buff, sizeof(buff), format, arg); vsnprintf(buff, sizeof(buff), format, arg);
va_end(arg); va_end(arg);
// Send the message to the Serial debug port if enabled
if (DebuggerStatus[dbg_Serial] == enabled) if (DebuggerStatus[dbg_Serial] == enabled)
{ {
Serial.print(buff); Serial.print(buff);
} }
// Push the message to the WebUI debug port if enabled
if (DebuggerStatus[dbg_Webui] == enabled) if (DebuggerStatus[dbg_Webui] == enabled)
{ {
Websocket_PushLiveDebug(String(buff)); Websocket_PushLiveDebug(String(buff));
@ -124,12 +173,22 @@ void Debug_pushMessage(const char *format, ...)
} }
} }
/**
* @brief Pushes a formatted CAN debug message to the enabled debug ports (Serial or WebUI).
*
* @param id CAN message ID.
* @param dlc Data Length Code of the CAN message.
* @param data Pointer to the data array of the CAN message.
*/
void pushCANDebug(uint32_t id, uint8_t dlc, uint8_t *data) void pushCANDebug(uint32_t id, uint8_t dlc, uint8_t *data)
{ {
// Check if either the Serial or WebUI debug port is enabled
if ((DebuggerStatus[dbg_Serial] == enabled) || (DebuggerStatus[dbg_Webui] == enabled)) if ((DebuggerStatus[dbg_Serial] == enabled) || (DebuggerStatus[dbg_Webui] == enabled))
{ {
char buff[100]; char buff[100]; // Buffer to hold the formatted message
char *p = buff; char *p = buff; // Pointer to navigate the buffer
// Format the CAN message information into the buffer
p += snprintf(p, sizeof(buff), "CAN: 0x%08X | %d | ", id, dlc); p += snprintf(p, sizeof(buff), "CAN: 0x%08X | %d | ", id, dlc);
for (int i = 0; i < dlc; i++) for (int i = 0; i < dlc; i++)
{ {
@ -138,10 +197,13 @@ void pushCANDebug(uint32_t id, uint8_t dlc, uint8_t *data)
*(p++) = '\n'; *(p++) = '\n';
*p = '\0'; *p = '\0';
// Send the formatted CAN message to the Serial debug port if enabled
if (DebuggerStatus[dbg_Serial] == enabled) if (DebuggerStatus[dbg_Serial] == enabled)
{ {
Serial.print(buff); Serial.print(buff);
} }
// Push the formatted CAN message to the WebUI debug port if enabled
if (DebuggerStatus[dbg_Webui] == enabled) if (DebuggerStatus[dbg_Webui] == enabled)
{ {
Websocket_PushLiveDebug(String(buff)); Websocket_PushLiveDebug(String(buff));
@ -149,8 +211,14 @@ void pushCANDebug(uint32_t id, uint8_t dlc, uint8_t *data)
} }
} }
/**
* @brief Processes a debug command and performs corresponding actions.
*
* @param command The debug command to be processed.
*/
void processCmdDebug(String command) void processCmdDebug(String command)
{ {
// Check the received command and execute corresponding actions
if (command == "help") if (command == "help")
Debug_printHelp(); Debug_printHelp();
else if (command == "sysinfo") else if (command == "sysinfo")
@ -193,18 +261,29 @@ void processCmdDebug(String command)
Debug_pushMessage("unknown Command\n"); Debug_pushMessage("unknown Command\n");
} }
/**
* @brief Formats the Config-EEPROM and resets it to default values.
* Prints a debug message after formatting.
*/
void Debug_formatCFG() void Debug_formatCFG()
{ {
Debug_pushMessage("Formatting Config-EEPROM and reseting to default\n"); Debug_pushMessage("Formatting Config-EEPROM and resetting to default\n");
FormatConfig_EEPROM(); FormatConfig_EEPROM();
} }
/**
* @brief Formats the Persistence-EEPROM and resets it to default values.
* Prints a debug message after formatting.
*/
void Debug_formatPersistence() void Debug_formatPersistence()
{ {
Debug_pushMessage("Formatting Persistence-EEPROM and reseting to default\n"); Debug_pushMessage("Formatting Persistence-EEPROM and resetting to default\n");
FormatPersistence_EEPROM(); FormatPersistence_EEPROM();
} }
/**
* @brief Prints system information and status to the debug output.
*/
void Debug_printSystemInfo() void Debug_printSystemInfo()
{ {
Debug_pushMessage("Souko's ChainOiler Mk1\n"); Debug_pushMessage("Souko's ChainOiler Mk1\n");
@ -224,10 +303,13 @@ void Debug_printSystemInfo()
: ideMode == FM_DOUT ? "DOUT" : ideMode == FM_DOUT ? "DOUT"
: "UNKNOWN")); : "UNKNOWN"));
Debug_pushMessage("OTA-Pass: %s\n", QUOTE(ADMIN_PASSWORD)); Debug_pushMessage("OTA-Pass: %s\n", QUOTE(ADMIN_PASSWORD));
Debug_pushMessage("Git-Revison: %s\n", constants.GitHash); Debug_pushMessage("Git-Revision: %s\n", constants.GitHash);
Debug_pushMessage("Sw-Version: %d.%02d\n", constants.FW_Version_major, constants.FW_Version_minor); Debug_pushMessage("Sw-Version: %d.%02d\n", constants.FW_Version_major, constants.FW_Version_minor);
} }
/**
* @brief Dumps the current configuration parameters to the debug output.
*/
void Debug_dumpConfig() void Debug_dumpConfig()
{ {
Debug_pushMessage("DistancePerLube_Default: %d\n", LubeConfig.DistancePerLube_Default); Debug_pushMessage("DistancePerLube_Default: %d\n", LubeConfig.DistancePerLube_Default);
@ -237,7 +319,7 @@ void Debug_dumpConfig()
Debug_pushMessage("TankRemindAtPercentage: %d\n", LubeConfig.TankRemindAtPercentage); Debug_pushMessage("TankRemindAtPercentage: %d\n", LubeConfig.TankRemindAtPercentage);
Debug_pushMessage("PulsePerRevolution: %d\n", LubeConfig.PulsePerRevolution); Debug_pushMessage("PulsePerRevolution: %d\n", LubeConfig.PulsePerRevolution);
Debug_pushMessage("TireWidth_mm: %d\n", LubeConfig.TireWidth_mm); Debug_pushMessage("TireWidth_mm: %d\n", LubeConfig.TireWidth_mm);
Debug_pushMessage("TireWidthHeight_Ratio: %d\n", LubeConfig.TireWidth_mm); Debug_pushMessage("TireWidthHeight_Ratio: %d\n", LubeConfig.TireWidthHeight_Ratio);
Debug_pushMessage("RimDiameter_Inch: %d\n", LubeConfig.RimDiameter_Inch); Debug_pushMessage("RimDiameter_Inch: %d\n", LubeConfig.RimDiameter_Inch);
Debug_pushMessage("DistancePerRevolution_mm: %d\n", LubeConfig.DistancePerRevolution_mm); Debug_pushMessage("DistancePerRevolution_mm: %d\n", LubeConfig.DistancePerRevolution_mm);
Debug_pushMessage("BleedingPulses: %d\n", LubeConfig.BleedingPulses); Debug_pushMessage("BleedingPulses: %d\n", LubeConfig.BleedingPulses);
@ -247,6 +329,9 @@ void Debug_dumpConfig()
Debug_pushMessage("checksum: 0x%08X\n", LubeConfig.checksum); Debug_pushMessage("checksum: 0x%08X\n", LubeConfig.checksum);
} }
/**
* @brief Dumps the global variables and their values to the debug output.
*/
void Debug_dumpGlobals() void Debug_dumpGlobals()
{ {
Debug_pushMessage("systemStatus: %d\n", globals.systemStatus); Debug_pushMessage("systemStatus: %d\n", globals.systemStatus);
@ -261,6 +346,9 @@ void Debug_dumpGlobals()
Debug_pushMessage("hasDTC: %d\n", globals.hasDTC); Debug_pushMessage("hasDTC: %d\n", globals.hasDTC);
} }
/**
* @brief Dumps the persistence data variables and their values to the debug output.
*/
void Debug_dumpPersistance() void Debug_dumpPersistance()
{ {
Debug_pushMessage("writeCycleCounter: %d\n", PersistenceData.writeCycleCounter); Debug_pushMessage("writeCycleCounter: %d\n", PersistenceData.writeCycleCounter);
@ -270,12 +358,21 @@ void Debug_dumpPersistance()
Debug_pushMessage("PSD Adress: 0x%04X\n", globals.eePersistanceAdress); Debug_pushMessage("PSD Adress: 0x%04X\n", globals.eePersistanceAdress);
} }
/**
* @brief Prints information related to WiFi to the debug output.
*/
void Debug_printWifiInfo() void Debug_printWifiInfo()
{ {
// Add relevant code here if needed
} }
/**
* @brief Checks the EEPROM data integrity by calculating and comparing checksums.
* Prints the result to the debug output.
*/
void Debug_CheckEEPOM() void Debug_CheckEEPOM()
{ {
// Check PersistenceData EEPROM checksum
uint32_t checksum = PersistenceData.checksum; uint32_t checksum = PersistenceData.checksum;
PersistenceData.checksum = 0; PersistenceData.checksum = 0;
@ -290,6 +387,7 @@ void Debug_CheckEEPOM()
PersistenceData.checksum = checksum; PersistenceData.checksum = checksum;
// Check LubeConfig EEPROM checksum
checksum = LubeConfig.checksum; checksum = LubeConfig.checksum;
LubeConfig.checksum = 0; LubeConfig.checksum = 0;
@ -304,24 +402,32 @@ void Debug_CheckEEPOM()
LubeConfig.checksum = checksum; LubeConfig.checksum = checksum;
} }
/**
* @brief Displays Diagnostic Trouble Codes (DTCs) along with their timestamps,
* status, and severity in a formatted manner.
*/
void Debug_ShowDTCs() void Debug_ShowDTCs()
{ {
char buff_timestamp[16]; // Format: DD-hh:mm:ss:xxx char buff_timestamp[16]; // Format: DD-hh:mm:ss:xxx
char buff_active[9]; char buff_active[9];
// Header for the DTC display
Debug_pushMessage("\n timestamp | DTC-Nr. | status | severity\n"); Debug_pushMessage("\n timestamp | DTC-Nr. | status | severity\n");
// Iterate through DTCStorage and display each entry
for (uint32_t i = 0; i < MAX_DTC_STORAGE; i++) for (uint32_t i = 0; i < MAX_DTC_STORAGE; i++)
{ {
if (DTCStorage[i].Number < DTC_LAST_DTC) if (DTCStorage[i].Number < DTC_LAST_DTC)
{ {
// Format timestamp
sprintf(buff_timestamp, "%02d-%02d:%02d:%02d:%03d", sprintf(buff_timestamp, "%02d-%02d:%02d:%02d:%03d",
DTCStorage[i].timestamp / 86400000, // Days DTCStorage[i].timestamp / 86400000, // Days
DTCStorage[i].timestamp / 360000 % 24, // Hours DTCStorage[i].timestamp / 360000 % 24, // Hours
DTCStorage[i].timestamp / 60000 % 60, // Minutes DTCStorage[i].timestamp / 60000 % 60, // Minutes
DTCStorage[i].timestamp / 1000 % 60, // Seconds DTCStorage[i].timestamp / 1000 % 60, // Seconds
DTCStorage[i].timestamp % 1000); // milliseconds DTCStorage[i].timestamp % 1000); // Milliseconds
// Determine DTC status
if (DTCStorage[i].active == DTC_ACTIVE) if (DTCStorage[i].active == DTC_ACTIVE)
strcpy(buff_active, "active"); strcpy(buff_active, "active");
else if (DTCStorage[i].active == DTC_PREVIOUS) else if (DTCStorage[i].active == DTC_PREVIOUS)
@ -329,19 +435,28 @@ void Debug_ShowDTCs()
else else
strcpy(buff_active, "none"); strcpy(buff_active, "none");
// Display DTC information
Debug_pushMessage("%s %7d %8s %8d\n", buff_timestamp, DTCStorage[i].Number, buff_active); Debug_pushMessage("%s %7d %8s %8d\n", buff_timestamp, DTCStorage[i].Number, buff_active);
} }
} }
} }
/**
* @brief Displays the help commands for debugging through Serial or WebUI.
* Each command is printed individually in a formatted manner.
*/
void Debug_printHelp() void Debug_printHelp()
{ {
char buff[64]; char buff[64];
for (unsigned int i = sizeof(helpCmd) / 63; i < sizeof(helpCmd) / 63; i++) // Iterate through helpCmd and display each command
for (unsigned int i = 0; i < sizeof(helpCmd) / 63; i++)
{ {
// Copy a portion of helpCmd to buff for display
memcpy_P(buff, (helpCmd + (i * 63)), 63); memcpy_P(buff, (helpCmd + (i * 63)), 63);
buff[63] = 0; buff[63] = 0;
// Display the help command
Debug_pushMessage(buff); Debug_pushMessage(buff);
} }
} }

View File

@ -1,14 +1,37 @@
/**
* @file dtc.cpp
* @brief Implementation of functions related to Diagnostic Trouble Codes (DTCs).
*
* This file contains the implementation of functions that manage the status
* and registration of Diagnostic Trouble Codes in the system.
*
* @author Marcel Peterkau
* @date 09.01.2024
*/
#include "dtc.h" #include "dtc.h"
#include "debugger.h" #include "debugger.h"
DTCEntry_t DTCStorage[MAX_DTC_STORAGE]; DTCEntry_t DTCStorage[MAX_DTC_STORAGE];
// Function implementations...
/**
* @brief Maintains the status of Diagnostic Trouble Codes (DTCs) in the DTCStorage array.
* Updates the status of existing DTCs or adds new ones based on their activity.
*
* @param DTC_no The number of the Diagnostic Trouble Code.
* @param active Indicates whether the DTC is active (true) or inactive (false).
* @param DebugValue Additional debugging information associated with the DTC.
*/
void MaintainDTC(DTCNum_t DTC_no, boolean active, uint32_t DebugValue) void MaintainDTC(DTCNum_t DTC_no, boolean active, uint32_t DebugValue)
{ {
// Iterate through the existing DTCs in the storage
for (int i = 0; i < MAX_DTC_STORAGE; i++) for (int i = 0; i < MAX_DTC_STORAGE; i++)
{ {
// Check if the DTC with the specified number exists
if (DTCStorage[i].Number == DTC_no) if (DTCStorage[i].Number == DTC_no)
{ {
// If the DTC is active and was not active before, update its status
if (active && DTCStorage[i].active != DTC_ACTIVE) if (active && DTCStorage[i].active != DTC_ACTIVE)
{ {
Debug_pushMessage("DTC gone active: %d, DebugVal: %d\n", DTC_no, DebugValue); Debug_pushMessage("DTC gone active: %d, DebugVal: %d\n", DTC_no, DebugValue);
@ -16,21 +39,23 @@ void MaintainDTC(DTCNum_t DTC_no, boolean active, uint32_t DebugValue)
DTCStorage[i].active = DTC_ACTIVE; DTCStorage[i].active = DTC_ACTIVE;
DTCStorage[i].debugVal = DebugValue; DTCStorage[i].debugVal = DebugValue;
} }
// If the DTC is not active anymore, update its status to previous
if (!active && DTCStorage[i].active == DTC_ACTIVE) if (!active && DTCStorage[i].active == DTC_ACTIVE)
{ {
Debug_pushMessage("DTC gone previous: %d\n", DTC_no); Debug_pushMessage("DTC gone previous: %d\n", DTC_no);
DTCStorage[i].active = DTC_PREVIOUS; DTCStorage[i].active = DTC_PREVIOUS;
} }
return; return; // DTC found and processed, exit the function
} }
} }
// DTC was not found with upper iteration, but is active // DTC was not found in the existing storage, but it is active,
// so we need to look for free space to store DTC // so look for free space to store the new DTC
if (active == true) if (active == true)
{ {
for (int i = 0; i < MAX_DTC_STORAGE; i++) for (int i = 0; i < MAX_DTC_STORAGE; i++)
{ {
// Check for an empty slot in the storage
if (DTCStorage[i].Number == DTC_LAST_DTC) if (DTCStorage[i].Number == DTC_LAST_DTC)
{ {
Debug_pushMessage("new DTC registered: %d, DebugVal: %d\n", DTC_no, DebugValue); Debug_pushMessage("new DTC registered: %d, DebugVal: %d\n", DTC_no, DebugValue);
@ -38,12 +63,20 @@ void MaintainDTC(DTCNum_t DTC_no, boolean active, uint32_t DebugValue)
DTCStorage[i].timestamp = millis(); DTCStorage[i].timestamp = millis();
DTCStorage[i].active = DTC_ACTIVE; DTCStorage[i].active = DTC_ACTIVE;
DTCStorage[i].debugVal = DebugValue; DTCStorage[i].debugVal = DebugValue;
return; return; // New DTC registered, exit the function
} }
} }
} }
} }
/**
* @brief Clears a specific Diagnostic Trouble Code (DTC) entry.
*
* This function clears the information related to a specific DTC entry,
* setting its status to inactive and timestamp to zero.
*
* @param DTC_no The Diagnostic Trouble Code number to be cleared.
*/
void ClearDTC(DTCNum_t DTC_no) void ClearDTC(DTCNum_t DTC_no)
{ {
for (int i = 0; i < MAX_DTC_STORAGE; i++) for (int i = 0; i < MAX_DTC_STORAGE; i++)
@ -57,6 +90,12 @@ void ClearDTC(DTCNum_t DTC_no)
} }
} }
/**
* @brief Clears all Diagnostic Trouble Code (DTC) entries.
*
* This function clears all DTC entries, setting their status to inactive and
* timestamps to zero.
*/
void ClearAllDTC() void ClearAllDTC()
{ {
for (int i = 0; i < MAX_DTC_STORAGE; i++) for (int i = 0; i < MAX_DTC_STORAGE; i++)
@ -67,6 +106,15 @@ void ClearAllDTC()
} }
} }
/**
* @brief Gets the last recorded Diagnostic Trouble Code (DTC) number.
*
* This function retrieves the DTC number of the last recorded DTC based on the
* timestamp. Optionally, it can filter only active DTCs.
*
* @param only_active If true, considers only active DTCs; otherwise, considers all.
* @return The DTC number of the last recorded DTC or DTC_LAST_DTC if none found.
*/
DTCNum_t getlastDTC(boolean only_active) DTCNum_t getlastDTC(boolean only_active)
{ {
int8_t pointer = -1; int8_t pointer = -1;
@ -87,6 +135,15 @@ DTCNum_t getlastDTC(boolean only_active)
return pointer >= 0 ? DTCStorage[pointer].Number : DTC_LAST_DTC; return pointer >= 0 ? DTCStorage[pointer].Number : DTC_LAST_DTC;
} }
/**
* @brief Gets the severity level for a specific Diagnostic Trouble Code (DTC).
*
* This function looks up the severity level associated with the provided DTC code
* from the predefined list of DTC definitions.
*
* @param targetCode The DTC code for which to retrieve the severity.
* @return The severity level of the specified DTC or DTC_NONE if not found.
*/
DTCSeverity_t getSeverityForDTC(DTCNum_t targetCode) DTCSeverity_t getSeverityForDTC(DTCNum_t targetCode)
{ {
for (int i = 0; i < DTC_LAST_DTC; i++) for (int i = 0; i < DTC_LAST_DTC; i++)
@ -99,6 +156,16 @@ DTCSeverity_t getSeverityForDTC(DTCNum_t targetCode)
return DTC_NONE; return DTC_NONE;
} }
/**
* @brief Processes Diagnostic Trouble Codes (DTCs) and updates system status accordingly.
*
* This function checks for the presence of active DTCs and adjusts the system status
* based on the severity of the most critical DTC. If a critical DTC is detected,
* the system status is set to sysStat_Error, potentially triggering a system shutdown.
*
* @note The function also preserves the original system status when transitioning to an error state
* and restores it when all DTCs are cleared.
*/
void DTC_Process() void DTC_Process()
{ {
static tSystem_Status preserverSysStatusError; static tSystem_Status preserverSysStatusError;
@ -120,10 +187,10 @@ void DTC_Process()
else else
{ {
globals.hasDTC = false; globals.hasDTC = false;
if (globals.systemStatus == sysStat_Error) if (globals.systemStatus == sysStat_Error)
{ {
globals.systemStatus = preserverSysStatusError; globals.systemStatus = preserverSysStatusError;
} }
} }
} }

View File

@ -1,7 +1,23 @@
/**
* @file globals.cpp
* @brief Implementation of global variables and initialization functions.
*
* This file defines and initializes the global variables used throughout the project.
* The global variables are encapsulated in the Globals_t structure. The initGlobals function
* is responsible for initializing these variables to their default values during system startup.
*/
#include "globals.h" #include "globals.h"
// Global instance of the Globals_t structure
Globals_t globals; Globals_t globals;
/**
* @brief Initializes global variables to default values during system startup.
*
* This function sets the initial values for various global variables, ensuring proper
* initialization of system-wide parameters.
*/
void initGlobals() void initGlobals()
{ {
globals.purgePulses = 0; globals.purgePulses = 0;

View File

@ -1,7 +1,26 @@
/**
* @file gps.cpp
*
* @brief Implementation file for GPS-related functions in the ChainLube application.
*
* This file contains the implementation of functions related to GPS functionality within the ChainLube
* application. It includes the initialization of the GPS module, processing GPS data for wheel speed,
* and maintaining Diagnostic Trouble Codes (DTCs) based on GPS communication status.
*
* @author Marcel Peterkau
* @date 09.01.2024
*/
#include "gps.h" #include "gps.h"
TinyGPSPlus gps; TinyGPSPlus gps;
/**
* @brief Initializes the GPS module with the specified baud rate.
*
* This function initializes the GPS module with the baud rate configured in the application settings.
* It also prints a debug message indicating the initialization status.
*/
void Init_GPS() void Init_GPS()
{ {
uint32_t baudrate; uint32_t baudrate;
@ -22,6 +41,15 @@ void Init_GPS()
Serial.begin(baudrate); Serial.begin(baudrate);
} }
/**
* @brief Processes GPS data to calculate rear wheel speed and returns the distance traveled.
*
* This function processes GPS data received from the GPS module, calculates the rear wheel speed in
* kilometers per hour, and returns the distance traveled based on the speed and time elapsed since
* the last valid speed measurement.
*
* @return The distance traveled in millimeters since the last GPS speed measurement.
*/
uint32_t Process_GPS_WheelSpeed() uint32_t Process_GPS_WheelSpeed()
{ {
static uint32_t lastRecTimestamp; static uint32_t lastRecTimestamp;
@ -49,7 +77,9 @@ uint32_t Process_GPS_WheelSpeed()
lastRecTimestamp = millis(); lastRecTimestamp = millis();
} }
} }
// Maintain DTC for no GPS data received within a certain time frame
MaintainDTC(DTC_NO_GPS_SERIAL, (millis() > lastRecTimestamp + 10000)); MaintainDTC(DTC_NO_GPS_SERIAL, (millis() > lastRecTimestamp + 10000));
return 0; return 0;
} }

View File

@ -1,28 +1,56 @@
/**
* @file lubeapp.cpp
*
* @brief Implementation file for the ChainLube application logic.
*
* This file contains the implementation of the ChainLube application logic, including functions
* for running the main application, initiating lubrication pulses, and maintaining system status.
* Global variables related to lubrication pulses are also defined in this file.
*
* @author Marcel Peterkau
* @date 09.01.2024
*/
#include "lubeapp.h" #include "lubeapp.h"
uint32_t lubePulseTimestamp = 0; uint32_t lubePulseTimestamp = 0;
/**
* @brief Runs the main logic of the ChainLube application based on the current system status.
*
* This function is responsible for executing the main logic of the ChainLube application. It calculates
* the tank percentage, maintains Diagnostic Trouble Codes (DTCs) related to the tank level, updates travel
* distances, triggers lubrication pulses, and handles the behavior based on the current system status
* (Startup, Normal, Rain, Purge, Error, Shutdown). It also manages the pin state of the lube pump.
*
* @param add_milimeters The additional distance traveled in millimeters to be processed by the application.
*/
void RunLubeApp(uint32_t add_milimeters) void RunLubeApp(uint32_t add_milimeters)
{ {
// Calculate and update tank percentage
globals.TankPercentage = PersistenceData.tankRemain_microL / (LubeConfig.tankCapacity_ml * 10); globals.TankPercentage = PersistenceData.tankRemain_microL / (LubeConfig.tankCapacity_ml * 10);
// Maintain DTCs related to tank level
MaintainDTC(DTC_TANK_EMPTY, (PersistenceData.tankRemain_microL < LubeConfig.amountPerDose_microL)); MaintainDTC(DTC_TANK_EMPTY, (PersistenceData.tankRemain_microL < LubeConfig.amountPerDose_microL));
MaintainDTC(DTC_TANK_LOW, (globals.TankPercentage < LubeConfig.TankRemindAtPercentage)); MaintainDTC(DTC_TANK_LOW, (globals.TankPercentage < LubeConfig.TankRemindAtPercentage));
// Add traveled Distance in mm // Add traveled distance in millimeters
PersistenceData.TravelDistance_highRes_mm += add_milimeters; PersistenceData.TravelDistance_highRes_mm += add_milimeters;
PersistenceData.odometer_mm += add_milimeters; PersistenceData.odometer_mm += add_milimeters;
// Update odometer if necessary
if (PersistenceData.odometer_mm >= 1000000) if (PersistenceData.odometer_mm >= 1000000)
{ {
PersistenceData.odometer++; PersistenceData.odometer++;
PersistenceData.odometer_mm = 0; PersistenceData.odometer_mm = 0;
} }
// Handle different system statuses
switch (globals.systemStatus) switch (globals.systemStatus)
{ {
case sysStat_Startup: case sysStat_Startup:
strcpy_P(globals.systemStatustxt, PSTR("Startup")); strcpy_P(globals.systemStatustxt, PSTR("Startup"));
// Transition to Normal status after startup delay
if (millis() > STARTUP_DELAY) if (millis() > STARTUP_DELAY)
{ {
globals.systemStatus = sysStat_Normal; globals.systemStatus = sysStat_Normal;
@ -32,6 +60,7 @@ void RunLubeApp(uint32_t add_milimeters)
case sysStat_Normal: case sysStat_Normal:
strcpy_P(globals.systemStatustxt, PSTR("Normal")); strcpy_P(globals.systemStatustxt, PSTR("Normal"));
// Trigger lube pulse if traveled distance exceeds the configured limit
if (PersistenceData.TravelDistance_highRes_mm / 1000 > LubeConfig.DistancePerLube_Default) if (PersistenceData.TravelDistance_highRes_mm / 1000 > LubeConfig.DistancePerLube_Default)
{ {
LubePulse(); LubePulse();
@ -41,16 +70,20 @@ void RunLubeApp(uint32_t add_milimeters)
case sysStat_Rain: case sysStat_Rain:
strcpy_P(globals.systemStatustxt, PSTR("Rain")); strcpy_P(globals.systemStatustxt, PSTR("Rain"));
// Trigger lube pulse if traveled distance exceeds the configured limit in Rain mode
if (PersistenceData.TravelDistance_highRes_mm / 1000 > LubeConfig.DistancePerLube_Rain) if (PersistenceData.TravelDistance_highRes_mm / 1000 > LubeConfig.DistancePerLube_Rain)
{ {
LubePulse(); LubePulse();
PersistenceData.TravelDistance_highRes_mm = 0; PersistenceData.TravelDistance_highRes_mm = 0;
} }
break; break;
case sysStat_Purge: case sysStat_Purge:
strcpy_P(globals.systemStatustxt, PSTR("Purge")); strcpy_P(globals.systemStatustxt, PSTR("Purge"));
// Execute lube pulses during the Purge status
if (globals.purgePulses > 0) if (globals.purgePulses > 0)
{ {
// Check if enough time has passed since the last lube pulse
if (lubePulseTimestamp + LUBE_PULSE_PAUSE_MS < millis()) if (lubePulseTimestamp + LUBE_PULSE_PAUSE_MS < millis())
{ {
LubePulse(); LubePulse();
@ -60,35 +93,48 @@ void RunLubeApp(uint32_t add_milimeters)
} }
else else
{ {
// Transition back to the previous status after completing purge pulses
globals.systemStatus = globals.resumeStatus; globals.systemStatus = globals.resumeStatus;
} }
break; break;
case sysStat_Error: case sysStat_Error:
strcpy_P(globals.systemStatustxt, PSTR("Error")); strcpy_P(globals.systemStatustxt, PSTR("Error"));
break; break;
case sysStat_Shutdown: case sysStat_Shutdown:
strcpy_P(globals.systemStatustxt, PSTR("Shutdown")); strcpy_P(globals.systemStatustxt, PSTR("Shutdown"));
break; break;
default: default:
break; break;
} }
// maintain Pin-State of Lube-Pump // Maintain Pin-State of Lube-Pump
if (lubePulseTimestamp > millis()) if (lubePulseTimestamp > millis())
digitalWrite(GPIO_PUMP, HIGH); digitalWrite(GPIO_PUMP, HIGH);
else else
digitalWrite(GPIO_PUMP, LOW); digitalWrite(GPIO_PUMP, LOW);
} }
/**
* @brief Initiates a lubrication pulse if there is sufficient oil remaining in the tank.
*
* This function checks if there is enough oil remaining in the tank to perform a lubrication pulse.
* If there is sufficient oil, it updates the lubePulseTimestamp to trigger the pulse and decreases
* the tank oil level by the configured amount per dose (LubeConfig.amountPerDose_microL).
*/
void LubePulse() void LubePulse()
{ {
if (PersistenceData.tankRemain_microL > 0) // Only Lube if theres Oil remaining! // Only initiate a lubrication pulse if there is oil remaining in the tank
if (PersistenceData.tankRemain_microL > 0)
{ {
lubePulseTimestamp = millis() + LUBE_PULSE_LENGHT_MS; lubePulseTimestamp = millis() + LUBE_PULSE_LENGHT_MS;
if (PersistenceData.tankRemain_microL < LubeConfig.amountPerDose_microL) // Prevent underrun and shiftover // Prevent underrun and shift over by adjusting the tank oil level
if (PersistenceData.tankRemain_microL < LubeConfig.amountPerDose_microL)
PersistenceData.tankRemain_microL = 0; PersistenceData.tankRemain_microL = 0;
else else
PersistenceData.tankRemain_microL = PersistenceData.tankRemain_microL - LubeConfig.amountPerDose_microL; PersistenceData.tankRemain_microL -= LubeConfig.amountPerDose_microL;
} }
} }

View File

@ -1,3 +1,18 @@
/**
* @file main.cpp
*
* @brief Main source file for the Souko's ChainLube Mk1 ESP8266 project.
*
* This file includes necessary libraries, defines configuration options, and declares global variables
* and function prototypes. It sets up essential components, initializes peripherals, and defines
* callbacks for interrupt service routines (ISRs) and timers. The main setup function configures the
* project, and the loop function handles the main execution loop, performing various tasks based on
* the configured options.
*
* @author Marcel Peterkau
* @date 09.01.2024
*/
#include <Arduino.h> #include <Arduino.h>
#include <Wire.h> #include <Wire.h>
#ifdef FEATURE_ENABLE_OLED #ifdef FEATURE_ENABLE_OLED
@ -57,28 +72,49 @@ Ticker WiFiMaintainConnectionTicker(wifiMaintainConnectionTicker_callback, 1000,
#endif #endif
Ticker EEPROMCyclicPDSTicker(EEPROMCyclicPDS_callback, 60000, 0, MILLIS); Ticker EEPROMCyclicPDSTicker(EEPROMCyclicPDS_callback, 60000, 0, MILLIS);
/**
* @brief Initializes the ESP8266 project, configuring various components and setting up required services.
*
* This setup function is responsible for initializing the ESP8266 project, including setting the CPU frequency,
* configuring WiFi settings, initializing DTC storage, handling WiFi client functionality (if enabled),
* initializing the Serial communication, setting up an OLED display (if enabled), initializing EEPROM,
* loading configuration and persistence data from EEPROM, initializing LEDs, setting up the chosen speed source
* (CAN, GPS, Impulse), configuring GPIO pins, setting up Over-The-Air (OTA) updates, initializing the web user interface,
* initializing global variables, starting cyclic EEPROM updates for Persistence Data Structure (PDS), and printing
* initialization status messages to Serial.
*/
void setup() void setup()
{ {
// Set CPU frequency to 80MHz
system_update_cpu_freq(SYS_CPU_80MHZ); system_update_cpu_freq(SYS_CPU_80MHZ);
// Generate a unique device name based on ESP chip ID
snprintf(globals.DeviceName, 32, HOST_NAME, ESP.getChipId()); snprintf(globals.DeviceName, 32, HOST_NAME, ESP.getChipId());
// Disable WiFi persistent storage
WiFi.persistent(false); WiFi.persistent(false);
ClearAllDTC(); // Init DTC-Storage // Initialize and clear Diagnostic Trouble Code (DTC) storage
ClearAllDTC();
#ifdef FEATURE_ENABLE_WIFI_CLIENT #ifdef FEATURE_ENABLE_WIFI_CLIENT
// Configure WiFi settings for client mode if enabled
WiFi.mode(WIFI_STA); WiFi.mode(WIFI_STA);
WiFi.setHostname(globals.DeviceName); WiFi.setHostname(globals.DeviceName);
wifiMulti.addAP(QUOTE(WIFI_SSID_CLIENT), QUOTE(WIFI_PASSWORD_CLIENT)); wifiMulti.addAP(QUOTE(WIFI_SSID_CLIENT), QUOTE(WIFI_PASSWORD_CLIENT));
WiFiMaintainConnectionTicker.start(); WiFiMaintainConnectionTicker.start();
#else #else
// Disable WiFi if WiFi client feature is not enabled
WiFi.mode(WIFI_OFF); WiFi.mode(WIFI_OFF);
#endif #endif
// Initialize Serial communication
Serial.begin(115200); Serial.begin(115200);
Serial.print("\n\nSouko's ChainLube Mk1\n"); Serial.print("\n\nSouko's ChainLube Mk1\n");
Serial.print(globals.DeviceName); Serial.print(globals.DeviceName);
#ifdef FEATURE_ENABLE_OLED #ifdef FEATURE_ENABLE_OLED
// Initialize OLED display if enabled
u8x8.begin(); u8x8.begin();
u8x8.setFont(u8x8_font_chroma48medium8_r); u8x8.setFont(u8x8_font_chroma48medium8_r);
u8x8.clearDisplay(); u8x8.clearDisplay();
@ -87,14 +123,17 @@ void setup()
Serial.print("\nDisplay-Init done"); Serial.print("\nDisplay-Init done");
#endif #endif
// Initialize EEPROM, load configuration, and persistence data from EEPROM
InitEEPROM(); InitEEPROM();
GetConfig_EEPROM(); GetConfig_EEPROM();
GetPersistence_EEPROM(); GetPersistence_EEPROM();
Serial.print("\nEE-Init done"); Serial.print("\nEE-Init done");
// Initialize LEDs
leds.begin(); leds.begin();
Serial.print("\nLED-Init done"); Serial.print("\nLED-Init done");
// Initialize based on the chosen speed source (CAN, GPS, Impulse)
switch (LubeConfig.SpeedSource) switch (LubeConfig.SpeedSource)
{ {
case SOURCE_CAN: case SOURCE_CAN:
@ -115,13 +154,18 @@ void setup()
} }
Serial.print("\nSource-Init done"); Serial.print("\nSource-Init done");
// Configure GPIO pins for button and pump control
pinMode(GPIO_BUTTON, INPUT_PULLUP); pinMode(GPIO_BUTTON, INPUT_PULLUP);
pinMode(GPIO_PUMP, OUTPUT); pinMode(GPIO_PUMP, OUTPUT);
// Set up OTA updates
ArduinoOTA.setPort(8266); ArduinoOTA.setPort(8266);
ArduinoOTA.setHostname(globals.DeviceName); ArduinoOTA.setHostname(globals.DeviceName);
ArduinoOTA.setPassword(QUOTE(ADMIN_PASSWORD)); ArduinoOTA.setPassword(QUOTE(ADMIN_PASSWORD));
#ifdef FEATURE_ENABLE_OLED #ifdef FEATURE_ENABLE_OLED
// Set up OTA callbacks for OLED display if enabled
ArduinoOTA.onStart([]() ArduinoOTA.onStart([]()
{ {
u8x8.clearDisplay(); u8x8.clearDisplay();
@ -148,20 +192,40 @@ void setup()
u8x8.drawString(0, 0, "OTA-Restart"); u8x8.drawString(0, 0, "OTA-Restart");
u8x8.refreshDisplay(); }); u8x8.refreshDisplay(); });
#endif #endif
// Begin OTA updates
ArduinoOTA.begin(); ArduinoOTA.begin();
Serial.print("\nOTA-Init done"); Serial.print("\nOTA-Init done");
// Initialize the web user interface
initWebUI(); initWebUI();
Serial.print("\nWebUI-Init done"); Serial.print("\nWebUI-Init done");
// Initialize global variables
initGlobals(); initGlobals();
Serial.print("\nglobals-Init done"); Serial.print("\nglobals-Init done");
// Start cyclic EEPROM updates for Persistence Data Structure (PDS)
EEPROMCyclicPDSTicker.start(); EEPROMCyclicPDSTicker.start();
Serial.print("\nSetup Done\n"); Serial.print("\nSetup Done\n");
} }
/**
* @brief Main execution loop for the ESP8266 project, performing various tasks based on configuration.
*
* This loop function handles different tasks based on the configured source of speed data (impulse, CAN, time, GPS).
* It calculates wheel distance, runs the lubrication application, updates the OLED display (if enabled),
* processes CAN messages, handles button input, manages LED behavior, performs EEPROM-related tasks, handles
* webserver operations, processes Diagnostic Trouble Codes (DTC), and manages debugging. Additionally, it
* integrates functionalities such as Over-The-Air (OTA) updates, cyclic EEPROM updates for Persistence Data
* Structure (PDS), WiFi connection maintenance, and system shutdown handling.
*/
void loop() void loop()
{ {
// Variable to store calculated wheel distance
uint32_t wheelDistance = 0; uint32_t wheelDistance = 0;
// Switch based on the configured speed source
switch (LubeConfig.SpeedSource) switch (LubeConfig.SpeedSource)
{ {
case SOURCE_IMPULSE: case SOURCE_IMPULSE:
@ -180,14 +244,22 @@ void loop()
break; break;
} }
// Run lubrication application with the calculated wheel distance
RunLubeApp(wheelDistance); RunLubeApp(wheelDistance);
#ifdef FEATURE_ENABLE_OLED #ifdef FEATURE_ENABLE_OLED
// Update OLED display if enabled
Display_Process(); Display_Process();
#endif #endif
// Process CAN messages if the speed source is not impulse
if (LubeConfig.SpeedSource != SOURCE_IMPULSE) if (LubeConfig.SpeedSource != SOURCE_IMPULSE)
{ {
CAN_Process(); CAN_Process();
} }
// Process button input, manage LED behavior, perform EEPROM tasks, handle webserver operations,
// process Diagnostic Trouble Codes (DTC), and manage debugging
Button_Process(); Button_Process();
LED_Process(); LED_Process();
EEPROM_Process(); EEPROM_Process();
@ -195,18 +267,35 @@ void loop()
DTC_Process(); DTC_Process();
Debug_Process(); Debug_Process();
// Handle OTA updates and update cyclic EEPROM tasks for Persistence Data Structure (PDS)
ArduinoOTA.handle(); ArduinoOTA.handle();
EEPROMCyclicPDSTicker.update(); EEPROMCyclicPDSTicker.update();
#ifdef FEATURE_ENABLE_WIFI_CLIENT #ifdef FEATURE_ENABLE_WIFI_CLIENT
// Update WiFi connection maintenance ticker if WiFi client feature is enabled
WiFiMaintainConnectionTicker.update(); WiFiMaintainConnectionTicker.update();
#endif #endif
// Perform system shutdown if the status is set to shutdown
if (globals.systemStatus == sysStat_Shutdown) if (globals.systemStatus == sysStat_Shutdown)
SystemShutdown(); SystemShutdown(false);
// Yield to allow other tasks to run
yield(); yield();
} }
/**
* @brief Converts an IPAddress object to a String representation.
*
* This function takes an IPAddress object and converts it into a String representing
* the IPv4 address. Each octet of the address is separated by a dot.
*
* @param ipAddress The IPAddress object to be converted.
* @return A String representing the IPv4 address.
*/
String IpAddress2String(const IPAddress &ipAddress) String IpAddress2String(const IPAddress &ipAddress)
{ {
// Concatenate each octet of the IPAddress with dots in between
return String(ipAddress[0]) + String(".") + return String(ipAddress[0]) + String(".") +
String(ipAddress[1]) + String(".") + String(ipAddress[1]) + String(".") +
String(ipAddress[2]) + String(".") + String(ipAddress[2]) + String(".") +
@ -214,42 +303,80 @@ String IpAddress2String(const IPAddress &ipAddress)
} }
#ifdef FEATURE_ENABLE_WIFI_CLIENT #ifdef FEATURE_ENABLE_WIFI_CLIENT
/**
* @brief Callback function for maintaining WiFi connection and handling connection failures.
*
* This callback function is used by a ticker to periodically check the WiFi connection status.
* If the device is not connected to WiFi, it counts connection failures. If the number of failures
* exceeds a defined threshold, the function triggers the initiation of an Access Point (AP) mode
* using the `toggleWiFiAP` function.
*/
void wifiMaintainConnectionTicker_callback() void wifiMaintainConnectionTicker_callback()
{ {
// Static variables to track WiFi connection failure count and maximum allowed failures
static uint32_t WiFiFailCount = 0; static uint32_t WiFiFailCount = 0;
const uint32_t WiFiFailMax = 20; const uint32_t WiFiFailMax = 20;
// Check if the device is connected to WiFi
if (wifiMulti.run(connectTimeoutMs) == WL_CONNECTED) if (wifiMulti.run(connectTimeoutMs) == WL_CONNECTED)
{ {
return; return; // Exit if connected
} }
else else
{ {
// Increment WiFi connection failure count
if (WiFiFailCount < WiFiFailMax) if (WiFiFailCount < WiFiFailMax)
{ {
WiFiFailCount++; WiFiFailCount++;
} }
else else
{ {
// Trigger AP mode if the maximum failures are reached
Debug_pushMessage("WiFi not connected! - Start AP"); Debug_pushMessage("WiFi not connected! - Start AP");
toggleWiFiAP(); toggleWiFiAP();
} }
} }
} }
#endif #endif
/**
* @brief Callback function for cyclically storing Persistence Data Structure (PDS) to EEPROM.
*
* This callback function is invoked periodically to store the Persistence Data Structure (PDS)
* to the EEPROM. It ensures that essential data is saved persistently, allowing the system to
* recover its state after power cycles or resets.
*/
void EEPROMCyclicPDS_callback() void EEPROMCyclicPDS_callback()
{ {
StorePersistence_EEPROM(); StorePersistence_EEPROM();
} }
/**
* @brief Interrupt Service Routine (ISR) triggered by wheel speed sensor pulses.
*
* This ISR is called whenever a pulse is detected from the wheel speed sensor. It increments
* the `wheel_pulse` variable, which is used to track the number of pulses received.
*/
void trigger_ISR() void trigger_ISR()
{ {
wheel_pulse++; wheel_pulse++;
} }
/**
* @brief Manages LED behavior based on the current system status and user overrides.
*
* This function handles LED behavior, including startup animations, confirmation animations for
* normal and rain modes, indication for purge, error, shutdown, and normal operation. It supports
* user overrides to set a specific LED color. The LED status is determined by the current system
* status, and specific LED patterns are displayed accordingly.
*
* @param override Flag indicating whether to override the LED behavior (0: No override, 1: Override, 2: Resume previous state).
* @param SetColor The color to set when overriding the LED behavior.
*/
void LED_Process(uint8_t override, uint32_t SetColor) void LED_Process(uint8_t override, uint32_t SetColor)
{ {
// Enumeration to represent LED status
typedef enum typedef enum
{ {
LED_Startup, LED_Startup,
@ -263,17 +390,20 @@ void LED_Process(uint8_t override, uint32_t SetColor)
LED_Override LED_Override
} tLED_Status; } tLED_Status;
// Static variables to track LED status, system status, override color, and previous LED status
static tSystem_Status oldSysStatus = sysStat_Startup; static tSystem_Status oldSysStatus = sysStat_Startup;
static tLED_Status LED_Status = LED_Startup; static tLED_Status LED_Status = LED_Startup;
static uint32_t LED_override_color = 0; static uint32_t LED_override_color = 0;
static tLED_Status LED_ResumeOverrideStatus = LED_Startup; static tLED_Status LED_ResumeOverrideStatus = LED_Startup;
// Variables for managing LED animation timing
uint8_t color = 0; uint8_t color = 0;
uint32_t timer = 0; uint32_t timer = 0;
uint32_t animtimer = 0; uint32_t animtimer = 0;
static uint32_t timestamp = 0; static uint32_t timestamp = 0;
timer = millis(); timer = millis();
// Handle LED overrides
if (override == 1) if (override == 1)
{ {
if (LED_Status != LED_Override) if (LED_Status != LED_Override)
@ -294,6 +424,7 @@ void LED_Process(uint8_t override, uint32_t SetColor)
} }
} }
// Update LED status when system status changes
if (oldSysStatus != globals.systemStatus) if (oldSysStatus != globals.systemStatus)
{ {
switch (globals.systemStatus) switch (globals.systemStatus)
@ -330,6 +461,7 @@ void LED_Process(uint8_t override, uint32_t SetColor)
oldSysStatus = globals.systemStatus; oldSysStatus = globals.systemStatus;
} }
// Handle different LED statuses
switch (LED_Status) switch (LED_Status)
{ {
case LED_Startup: case LED_Startup:
@ -433,28 +565,47 @@ void LED_Process(uint8_t override, uint32_t SetColor)
} }
leds.show(); leds.show();
} }
#ifdef FEATURE_ENABLE_OLED #ifdef FEATURE_ENABLE_OLED
/**
* @brief Manages the display content based on the current system status and updates the OLED display.
*
* This function handles the content to be displayed on the OLED screen, taking into account the
* current system status. It clears the display and prints relevant information such as system mode,
* remaining lubrication distance, tank level, WiFi status, speed source, and IP address. Additionally,
* it refreshes the OLED display with the updated content.
*/
void Display_Process() void Display_Process()
{ {
// Static variable to track the previous system status
static tSystem_Status oldSysStatus = sysStat_Startup; static tSystem_Status oldSysStatus = sysStat_Startup;
// Check if the system status has changed since the last update
if (oldSysStatus != globals.systemStatus) if (oldSysStatus != globals.systemStatus)
{ {
// Clear the display and print the system title when the status changes
u8x8.clearDisplay(); u8x8.clearDisplay();
u8x8.drawString(0, 0, "KTM ChainLube V1"); u8x8.drawString(0, 0, "KTM ChainLube V1");
oldSysStatus = globals.systemStatus; oldSysStatus = globals.systemStatus;
} }
// Set the cursor position for displaying information on the OLED screen
u8x8.setCursor(0, 1); u8x8.setCursor(0, 1);
// Calculate remaining lubrication distance based on system mode
uint32_t DistRemain = globals.systemStatus == sysStat_Normal ? LubeConfig.DistancePerLube_Default : LubeConfig.DistancePerLube_Rain; uint32_t DistRemain = globals.systemStatus == sysStat_Normal ? LubeConfig.DistancePerLube_Default : LubeConfig.DistancePerLube_Rain;
DistRemain = DistRemain - (PersistenceData.TravelDistance_highRes_mm / 1000); DistRemain = DistRemain - (PersistenceData.TravelDistance_highRes_mm / 1000);
// Display relevant information on the OLED screen based on system status
u8x8.printf(PSTR("Mode: %10s\n"), globals.systemStatustxt); u8x8.printf(PSTR("Mode: %10s\n"), globals.systemStatustxt);
if (globals.systemStatus == sysStat_Error) if (globals.systemStatus == sysStat_Error)
{ {
// Display the last Diagnostic Trouble Code (DTC) in case of an error
u8x8.printf(PSTR("last DTC: %6d\n"), getlastDTC(false)); u8x8.printf(PSTR("last DTC: %6d\n"), getlastDTC(false));
} }
else else
{ {
// Display information such as next lubrication distance, tank level, WiFi status, speed source, and IP address
u8x8.printf(PSTR("next Lube: %4dm\n"), DistRemain); u8x8.printf(PSTR("next Lube: %4dm\n"), DistRemain);
u8x8.printf(PSTR("Tank: %8dml\n"), PersistenceData.tankRemain_microL / 1000); u8x8.printf(PSTR("Tank: %8dml\n"), PersistenceData.tankRemain_microL / 1000);
u8x8.printf(PSTR("WiFi: %10s\n"), (WiFi.getMode() == WIFI_AP ? "AP" : WiFi.getMode() == WIFI_OFF ? "OFF" u8x8.printf(PSTR("WiFi: %10s\n"), (WiFi.getMode() == WIFI_AP ? "AP" : WiFi.getMode() == WIFI_OFF ? "OFF"
@ -463,18 +614,29 @@ void Display_Process()
u8x8.printf(PSTR("Source: %8s\n"), SpeedSourceString[LubeConfig.SpeedSource]); u8x8.printf(PSTR("Source: %8s\n"), SpeedSourceString[LubeConfig.SpeedSource]);
u8x8.printf("%s\n", WiFi.localIP().toString().c_str()); u8x8.printf("%s\n", WiFi.localIP().toString().c_str());
} }
// Refresh the OLED display with the updated content
u8x8.refreshDisplay(); u8x8.refreshDisplay();
} }
#endif #endif
/**
* @brief Processes the button input and performs corresponding actions based on button state and timing.
*
* This function handles the button input, detecting button presses and executing actions based on
* predefined time delays. Actions include toggling WiFi, starting purge, toggling operating modes,
* and displaying feedback through LEDs. The function utilizes an enumeration to track button actions
* and manages the timing for different actions.
*/
void Button_Process() void Button_Process()
{ {
// Time delays for different button actions
#define BUTTON_ACTION_DELAY_TOGGLEMODE 500 #define BUTTON_ACTION_DELAY_TOGGLEMODE 500
#define BUTTON_ACTION_DELAY_PURGE 3500 #define BUTTON_ACTION_DELAY_PURGE 3500
#define BUTTON_ACTION_DELAY_WIFI 6500 #define BUTTON_ACTION_DELAY_WIFI 6500
#define BUTTON_ACTION_DELAY_NOTHING 9500 #define BUTTON_ACTION_DELAY_NOTHING 9500
// Enumeration to represent button actions
typedef enum buttonAction_e typedef enum buttonAction_e
{ {
BTN_INACTIVE, BTN_INACTIVE,
@ -484,15 +646,18 @@ void Button_Process()
BTN_STARTPURGE BTN_STARTPURGE
} buttonAction_t; } buttonAction_t;
// Static variables to track button state and timing
static uint32_t buttonTimestamp = 0; static uint32_t buttonTimestamp = 0;
static buttonAction_t buttonAction = BTN_INACTIVE; static buttonAction_t buttonAction = BTN_INACTIVE;
// Check if button is pressed (LOW)
if (digitalRead(GPIO_BUTTON) == LOW) if (digitalRead(GPIO_BUTTON) == LOW)
{ {
// Update button timestamp on the first button press
if (buttonTimestamp == 0) if (buttonTimestamp == 0)
buttonTimestamp = millis(); buttonTimestamp = millis();
// Check and execute actions based on predefined time delays
if (buttonTimestamp + BUTTON_ACTION_DELAY_NOTHING < millis()) if (buttonTimestamp + BUTTON_ACTION_DELAY_NOTHING < millis())
{ {
LED_Process(1, COLOR_WARM_WHITE); LED_Process(1, COLOR_WARM_WHITE);
@ -515,8 +680,9 @@ void Button_Process()
buttonAction = BTN_TOGGLEMODE; buttonAction = BTN_TOGGLEMODE;
} }
} }
else else // Button is released
{ {
// Execute corresponding actions based on the detected button action
if (buttonAction != BTN_INACTIVE) if (buttonAction != BTN_INACTIVE)
{ {
switch (buttonAction) switch (buttonAction)
@ -544,6 +710,7 @@ void Button_Process()
globals.systemStatus = sysStat_Normal; globals.systemStatus = sysStat_Normal;
globals.resumeStatus = sysStat_Normal; globals.resumeStatus = sysStat_Normal;
break; break;
default: default:
break; break;
} }
@ -555,28 +722,49 @@ void Button_Process()
Debug_pushMessage("Nothing or invalid\n"); Debug_pushMessage("Nothing or invalid\n");
break; break;
} }
// Display feedback through LEDs
LED_Process(2); LED_Process(2);
} }
// Reset button state and timestamp
buttonAction = BTN_INACTIVE; buttonAction = BTN_INACTIVE;
buttonTimestamp = 0; buttonTimestamp = 0;
} }
} }
/**
* @brief Toggles the WiFi functionality based on the current status.
*
* This function manages the WiFi state, either turning it off or starting it as an Access Point (AP),
* depending on the current mode. If the WiFi is turned off, it can be started in AP mode with the
* device name and password configured. Additionally, it may stop certain operations related to WiFi
* maintenance or display debug messages based on the defined features.
*
* @param shutdown Flag indicating whether the system is in a shutdown state.
*/
void toggleWiFiAP(bool shutdown) void toggleWiFiAP(bool shutdown)
{ {
// Check if WiFi is currently active
if (WiFi.getMode() != WIFI_OFF) if (WiFi.getMode() != WIFI_OFF)
{ {
// Turn off WiFi
WiFi.mode(WIFI_OFF); WiFi.mode(WIFI_OFF);
Debug_pushMessage("WiFi turned off\n"); Debug_pushMessage("WiFi turned off\n");
// Stop WiFi maintenance connection ticker if enabled
#ifdef FEATURE_ENABLE_WIFI_CLIENT #ifdef FEATURE_ENABLE_WIFI_CLIENT
WiFiMaintainConnectionTicker.stop(); WiFiMaintainConnectionTicker.stop();
#endif #endif
} }
else else
{ {
// Start WiFi in Access Point (AP) mode
WiFi.mode(WIFI_AP); WiFi.mode(WIFI_AP);
WiFi.softAPConfig(IPAddress(WIFI_AP_IP_GW), IPAddress(WIFI_AP_IP_GW), IPAddress(255, 255, 255, 0)); WiFi.softAPConfig(IPAddress(WIFI_AP_IP_GW), IPAddress(WIFI_AP_IP_GW), IPAddress(255, 255, 255, 0));
WiFi.softAP(globals.DeviceName, QUOTE(WIFI_AP_PASSWORD)); WiFi.softAP(globals.DeviceName, QUOTE(WIFI_AP_PASSWORD));
// Stop WiFi maintenance connection ticker if enabled and display debug messages
#ifdef FEATURE_ENABLE_WIFI_CLIENT #ifdef FEATURE_ENABLE_WIFI_CLIENT
WiFiMaintainConnectionTicker.stop(); WiFiMaintainConnectionTicker.stop();
Debug_pushMessage("WiFi AP started, stopped Maintain-Timer\n"); Debug_pushMessage("WiFi AP started, stopped Maintain-Timer\n");
@ -586,19 +774,34 @@ void toggleWiFiAP(bool shutdown)
} }
} }
/**
* @brief Performs necessary tasks before shutting down and optionally restarts the ESP.
*
* This function initiates a system shutdown, performing tasks such as storing configuration
* and persistence data to EEPROM before shutting down. If a restart is requested, the ESP
* will be restarted; otherwise, the system will enter an indefinite loop.
*
* @param restart Flag indicating whether to restart the ESP after shutdown (default: false).
*/
void SystemShutdown(bool restart) void SystemShutdown(bool restart)
{ {
static uint32_t shutdown_delay = 0; static uint32_t shutdown_delay = 0;
// Initialize shutdown delay on the first call
if (shutdown_delay == 0) if (shutdown_delay == 0)
{ {
shutdown_delay = millis() + SHUTDOWN_DELAY_MS; shutdown_delay = millis() + SHUTDOWN_DELAY_MS;
Serial.printf("Shutdown requested - Restarting in %d seconds\n", SHUTDOWN_DELAY_MS / 1000); Serial.printf("Shutdown requested - Restarting in %d seconds\n", SHUTDOWN_DELAY_MS / 1000);
} }
// Check if the shutdown delay has elapsed
if (shutdown_delay < millis()) if (shutdown_delay < millis())
{ {
// Store configuration and persistence data to EEPROM
StoreConfig_EEPROM(); StoreConfig_EEPROM();
StorePersistence_EEPROM(); StorePersistence_EEPROM();
// Perform restart if requested, otherwise enter an indefinite loop
if (restart) if (restart)
ESP.restart(); ESP.restart();
else else
@ -607,6 +810,15 @@ void SystemShutdown(bool restart)
} }
} }
/**
* @brief Processes the impulses from the wheel speed sensor and converts them into traveled distance.
*
* This function takes the pulse count from the wheel speed sensor and converts it into distance
* traveled in millimeters. The conversion is based on the configured parameters such as the number
* of pulses per revolution and the distance traveled per revolution.
*
* @return The calculated distance traveled in millimeters.
*/
uint32_t Process_Impulse_WheelSpeed() uint32_t Process_Impulse_WheelSpeed()
{ {
uint32_t add_milimeters = 0; uint32_t add_milimeters = 0;