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_
#define _CAN_H_
@ -9,6 +22,7 @@
#include "dtc.h"
#include "debugger.h"
// CAN frame structure definition
struct can_frame
{
unsigned long can_id;
@ -16,8 +30,9 @@ struct can_frame
uint8_t data[8] __attribute__((aligned(8)));
};
// Function prototypes
void Init_CAN();
void CAN_Process();
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_
#define _COMMON_H_
@ -5,6 +18,7 @@
#define QUOTE(x) Q(x)
#define SET_BIT(value, bitPosition) ((value) |= (1U << (bitPosition)))
// Conditional compilation based on PCB revision
#if PCB_REV == 1
#define GPIO_BUTTON D7
#define GPIO_LED D8
@ -40,17 +54,17 @@
#define LUBE_PULSE_LENGHT_MS 160
#define LUBE_PULSE_PAUSE_MS 340
// Pump pulse parameters
// -> 2Hz PumpPulse
// -> 49,7cc / h @ 2Hz
// -> 49,7 ml / h @ 2Hz
// -> 828,4µl / min @ 2Hz
// -> 828,3µl / 60s
// -> 13,81µl / 1s
// -> 6,90µl / Pulse
// -> 49.7cc / h @ 2Hz
// -> 49.7 ml / h @ 2Hz
// -> 828.4µl / min @ 2Hz
// -> 828.3µl / 60s
// -> 13.81µl / 1s
// -> 6.90µl / Pulse
#define DEFAULT_PUMP_DOSE 7
#define STARTUP_DELAY 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_
#define _CONFIG_H_
@ -14,6 +28,7 @@
#define EEPROM_SIZE_BYTES I2C_DEVICESIZE_24LC256
#endif
// Enum for different sources of speed input
typedef enum SpeedSource_e
{
#ifdef FEATURE_ENABLE_TIMER
@ -24,6 +39,7 @@ typedef enum SpeedSource_e
SOURCE_CAN
} SpeedSource_t;
// String representation of SpeedSource enum
const char SpeedSourceString[][8] = {
#ifdef FEATURE_ENABLE_TIMER
"Timer",
@ -33,32 +49,37 @@ const char SpeedSourceString[][8] = {
"CAN-Bus"
};
const size_t SpeedSourceString_Elements = sizeof(SpeedSourceString) / sizeof(SpeedSourceString[0]);
// Enum for GPS baud rates
typedef enum GPSBaudRate_e
{
BAUD_9600,
BAUD_115200
} GPSBaudRate_t;
// String representation of GPSBaudRate enum
const char GPSBaudRateString[][7] = {
"9600",
"115200"};
const size_t GPSBaudRateString_Elements = sizeof(GPSBaudRateString) / sizeof(GPSBaudRateString[0]);
// Enum for CAN bus sources
typedef enum CANSource_e
{
KTM_890_ADV_R_2021,
KTM_1290_SD_R_2023
} CANSource_t;
// String representation of CANSource enum
const char CANSourceString[][30] = {
"KTM 890 Adventure R (2021)",
"KTM 1290 Superduke R (2023)"};
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
{
uint16_t writeCycleCounter = 0;
@ -69,6 +90,7 @@ typedef struct
uint32_t checksum = 0;
} persistenceData_t;
// Structure for configuration settings stored in EEPROM
typedef struct
{
uint8_t EEPROM_Version = 0;
@ -92,6 +114,7 @@ typedef struct
uint32_t checksum = 0;
} LubeConfig_t;
// Default configuration settings
const LubeConfig_t LubeConfig_defaults = {
0, 8000, 4000, 320, DEFAULT_PUMP_DOSE, 30, 1, 150, 70, 18, 2000, 25, SOURCE_IMPULSE,
BAUD_115200,
@ -117,4 +140,4 @@ uint32_t ConfigSanityCheck(bool autocorrect = false);
extern LubeConfig_t LubeConfig;
extern persistenceData_t PersistenceData;
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_
#define _DEBUGGER_H_
#include <Arduino.h>
#include "webui.h"
const char PROGMEM helpCmd[] = "sysinfo - System Info\n"
"netinfo - WiFi Info\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_
#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
#define DTC_DEFS_H
@ -66,6 +80,6 @@ const DTC_t dtc_definitions[] = {
{ 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

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
#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_
#define _GLOBALS_H_
@ -29,29 +42,29 @@ typedef enum eEERequest
typedef struct Globals_s
{
tSystem_Status systemStatus = sysStat_Startup;
tSystem_Status resumeStatus = sysStat_Startup;
char systemStatustxt[16] = "";
uint16_t purgePulses = 0;
eEERequest requestEEAction = EE_IDLE;
char DeviceName[33];
char FlashVersion[10];
uint16_t eePersistanceAdress;
uint8_t TankPercentage;
bool hasDTC;
bool measurementActive;
uint32_t measuredPulses;
tSystem_Status systemStatus = sysStat_Startup; /**< Current system status */
tSystem_Status resumeStatus = sysStat_Startup; /**< Status to resume after rain mode */
char systemStatustxt[16] = ""; /**< Text representation of system status */
uint16_t purgePulses = 0; /**< Number of purge pulses */
eEERequest requestEEAction = EE_IDLE;; /**< EEPROM-related request */
char DeviceName[33]; /**< Device name */
char FlashVersion[10]; /**< Flash version */
uint16_t eePersistanceAdress; /**< EEPROM persistence address */
uint8_t TankPercentage; /**< Tank percentage */
bool hasDTC; /**< Flag indicating the presence of Diagnostic Trouble Codes (DTC) */
bool measurementActive; /**< Flag indicating active measurement */
uint32_t measuredPulses; /**< Number of measured pulses */
} Globals_t;
extern Globals_t globals;
extern Globals_t globals; /**< Global variable struct */
typedef struct Constants_s
{
uint8_t FW_Version_major;
uint8_t FW_Version_minor;
uint8_t Required_Flash_Version_major;
uint8_t Required_Flash_Version_minor;
char GitHash[11];
uint8_t FW_Version_major; /**< Firmware version major number */
uint8_t FW_Version_minor; /**< Firmware version minor number */
uint8_t Required_Flash_Version_major; /**< Required flash version major number */
uint8_t Required_Flash_Version_minor; /**< Required flash version minor number */
char GitHash[11]; /**< Git hash string */
} Constants_t;
const Constants_t constants PROGMEM = {
@ -60,6 +73,9 @@ const Constants_t constants PROGMEM = {
GIT_REV // Git-Hash-String
};
/**
* @brief Initializes global variables.
*/
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_
#define _GPS_H_
@ -7,7 +21,16 @@
#include "dtc.h"
#include "debugger.h"
/**
* @brief Initializes the GPS module.
*/
void Init_GPS();
/**
* @brief Processes GPS data to calculate wheel speed.
*
* @return Calculated wheel speed in millimeters per second.
*/
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_
#define _LED_COLORS_H_
@ -19,17 +32,14 @@
#define COLOR_AMBER 0xFF6400
#define COLOR_WARM_WHITE 0xFDF5E6
#define LED_DEFAULT_COLOR COLOR_WARM_WHITE
#define LED_STARTUP_NORMAL COLOR_WARM_WHITE
#define LED_STARTUP_TANKWARN COLOR_AMBER
#define LED_NORMAL_COLOR COLOR_GREEN
#define LED_RAIN_COLOR COLOR_BLUE
#define LED_NORMAL_COLOR COLOR_GREEN
#define LED_RAIN_COLOR COLOR_BLUE
#define LED_WIFI_BLINK COLOR_YELLOW
#define LED_PURGE_COLOR COLOR_MAGENTA
#define LED_ERROR_BLINK COLOR_RED
#define LED_SHUTDOWN_BLINK COLOR_CYAN
#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_
#define _LUBEAPP_H_
@ -12,4 +24,4 @@
void RunLubeApp(uint32_t add_milimeters);
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_
#define _SANITYCHECK_H_
@ -34,4 +46,4 @@
#error "You must define an WIFI_AP_PASSWORD for Standalone AP-Mode"
#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_
#define _WEBUI_H_
@ -22,4 +35,4 @@ void Webserver_Process();
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"
MCP_CAN CAN0(GPIO_CS_CAN);
@ -6,9 +20,14 @@ MCP_CAN CAN0(GPIO_CS_CAN);
void sendCANDebugMessage();
#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()
{
if (CAN0.begin(MCP_STDEXT, CAN_500KBPS, MCP_16MHZ) != CAN_OK)
MaintainDTC(DTC_CAN_TRANSCEIVER_FAILED, true);
@ -30,6 +49,11 @@ void Init_CAN()
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()
{
static uint32_t previousMillis = 0;
@ -40,7 +64,15 @@ void CAN_Process()
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()
{
#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
/**
* @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()
{
#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 "debugger.h"
// Instance of I2C_eeprom for EEPROM access
I2C_eeprom ee(0x50, EEPROM_SIZE_BYTES);
// Configuration and persistence data structures
LubeConfig_t LubeConfig;
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;
// Offsets within EEPROM for LubeConfig and PersistenceData
const uint16_t startofLubeConfig = 16;
const uint16_t startofPersistence = 16 + sizeof(LubeConfig) + (sizeof(LubeConfig) % 16);
// Function prototype to check EEPROM availability
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()
{
ee.begin();
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()
{
switch (globals.requestEEAction)
@ -37,7 +64,7 @@ void EEPROM_Process()
FormatConfig_EEPROM();
globals.requestEEAction = EE_IDLE;
GetConfig_EEPROM();
Debug_pushMessage("Formated EEPROM CFG\n");
Debug_pushMessage("Formatted EEPROM CFG\n");
break;
case EE_PDS_SAVE:
StorePersistence_EEPROM();
@ -53,7 +80,7 @@ void EEPROM_Process()
FormatPersistence_EEPROM();
globals.requestEEAction = EE_IDLE;
GetPersistence_EEPROM();
Debug_pushMessage("Formated EEPROM PDS\n");
Debug_pushMessage("Formatted EEPROM PDS\n");
break;
case EE_FORMAT_ALL:
FormatConfig_EEPROM();
@ -61,7 +88,7 @@ void EEPROM_Process()
GetConfig_EEPROM();
GetPersistence_EEPROM();
globals.requestEEAction = EE_IDLE;
Debug_pushMessage("Formated EEPROM ALL\n");
Debug_pushMessage("Formatted EEPROM ALL\n");
break;
case EE_ALL_SAVE:
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()
{
LubeConfig.checksum = 0;
LubeConfig.checksum = Checksum_EEPROM((uint8_t *)&LubeConfig, sizeof(LubeConfig));
if (!checkEEPROMavailable())
return;
ee.updateBlock(startofLubeConfig, (uint8_t *)&LubeConfig, sizeof(LubeConfig));
uint32_t ConfigSanityCheckResult = ConfigSanityCheck(false);
if (ConfigSanityCheckResult > 0)
{
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()
{
if (!checkEEPROMavailable())
@ -105,15 +146,23 @@ void GetConfig_EEPROM()
{
MaintainDTC(DTC_EEPROM_CFG_BAD, true);
}
LubeConfig.checksum = checksum;
uint32_t ConfigSanityCheckResult = ConfigSanityCheck(false);
if (ConfigSanityCheckResult > 0)
{
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()
{
if (PersistenceData.writeCycleCounter >= 0xFFF0)
@ -130,6 +179,13 @@ void StorePersistence_EEPROM()
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()
{
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()
{
Debug_pushMessage("Formatting Config-Partition\n");
@ -167,6 +228,11 @@ void FormatConfig_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()
{
Debug_pushMessage("Formatting Persistance-Partition\n");
@ -174,7 +240,13 @@ void FormatPersistence_EEPROM()
// memset(&PersistenceData, 0, sizeof(PersistenceData));
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)
{
if (!checkEEPROMavailable())
@ -183,7 +255,7 @@ void MovePersistencePage_EEPROM(boolean reset)
globals.eePersistanceAdress += sizeof(PersistenceData);
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)
{
globals.eePersistanceAdress = startofPersistence;
@ -192,25 +264,45 @@ void MovePersistencePage_EEPROM(boolean reset)
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)
{
if (data == NULL)
return 0;
uint32_t crc, mask;
crc = 0xFFFFFFFF;
uint32_t crc = 0xFFFFFFFF;
uint32_t mask;
while (len--)
{
crc ^= *data++;
for (uint8_t k = 0; k < 8; k++)
{
mask = -(crc & 1);
crc = (crc >> 1) ^ (0xEDB88320 & mask);
}
}
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)
{
#define BLOCK_TO_LENGTH 16
@ -220,42 +312,79 @@ void dumpEEPROM(uint16_t memoryAddress, uint16_t length)
char ascii_buf[BLOCK_TO_LENGTH + 1];
sprintf(ascii_buf, "%*s", BLOCK_TO_LENGTH, "ASCII");
// Print column headers
Debug_pushMessage(PSTR("\nAddress "));
for (int x = 0; x < BLOCK_TO_LENGTH; x++)
Debug_pushMessage("%3d", x);
// Align address and length to BLOCK_TO_LENGTH boundaries
memoryAddress = memoryAddress / 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++)
{
int blockpoint = memoryAddress % BLOCK_TO_LENGTH;
// Print ASCII representation header for each block
if (blockpoint == 0)
{
ascii_buf[BLOCK_TO_LENGTH] = 0;
Debug_pushMessage(" %s", ascii_buf);
Debug_pushMessage("\n0x%05X:", memoryAddress);
}
// Read and print each byte
ascii_buf[blockpoint] = ee.readByte(memoryAddress);
Debug_pushMessage(" %02X", ascii_buf[blockpoint]);
// Replace non-printable characters with dots in ASCII representation
if (ascii_buf[blockpoint] < 0x20 || ascii_buf[blockpoint] > 0x7E)
ascii_buf[blockpoint] = '.';
memoryAddress++;
}
// Print a new line at the end of the dump
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()
{
// Check if EEPROM is connected
if (!ee.isConnected())
{
// Trigger DTC for no EEPROM found
MaintainDTC(DTC_NO_EEPROM_FOUND, true);
return false;
}
// Clear DTC for no EEPROM found since it's available now
MaintainDTC(DTC_NO_EEPROM_FOUND, false);
// EEPROM is available
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 setting_reset_bits = 0;
@ -332,7 +461,7 @@ uint32_t ConfigSanityCheck(bool autocorrect)
LubeConfig.DistancePerRevolution_mm = LubeConfig_defaults.DistancePerRevolution_mm;
}
}
if (!(LubeConfig.BleedingPulses > 0) || !(LubeConfig.BleedingPulses < 1001))
{
SET_BIT(setting_reset_bits, 10);
@ -360,5 +489,6 @@ uint32_t ConfigSanityCheck(bool autocorrect)
if (autocorrect)
LubeConfig.CANSource = LubeConfig_defaults.CANSource;
}
// Return the bitmask indicating which settings need to be reset
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"
DebugStatus_t DebuggerStatus[dbg_cntElements];
@ -15,32 +28,45 @@ void Debug_ShowDTCs();
void Debug_dumpGlobals();
void Debug_printHelp();
/**
* @brief Initializes the debugger by setting the initial status for different debug ports.
* Serial debug output is turned off.
*/
void initDebugger()
{
// Set the initial status of debug ports
DebuggerStatus[dbg_Serial] = disabled;
DebuggerStatus[dbg_Webui] = disabled;
// Disable serial debug output
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()
{
// Enumeration for tracking the state of input processing
typedef enum InputProcessed_e
{
IDLE,
CMD_COMPLETE,
CMD_ABORT,
CMD_OVERFLOW
IDLE, ///< No command processing is in progress
CMD_COMPLETE, ///< Received a complete command
CMD_ABORT, ///< Received an abort command (Esc)
CMD_OVERFLOW ///< Input buffer overflow occurred
} InputProcessed_t;
static unsigned int inputCnt = 0;
static char inputBuffer[32];
InputProcessed_t InputProcessed = IDLE;
static unsigned int inputCnt = 0; ///< Counter for characters in the input buffer
static char inputBuffer[32]; ///< Buffer to store the received characters
InputProcessed_t InputProcessed = IDLE; ///< State variable for input processing
// Check if there are characters available in the Serial input buffer
if (Serial.available())
{
char inputChar = Serial.read();
// Process the received character based on its value
switch (inputChar)
{
case '\n':
@ -55,7 +81,7 @@ void Debug_Process()
InputProcessed = CMD_ABORT;
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;
inputCnt++;
break;
@ -64,6 +90,7 @@ void Debug_Process()
break;
}
// Check for input buffer overflow
if (inputCnt > sizeof(inputBuffer))
{
inputCnt = 0;
@ -72,6 +99,7 @@ void Debug_Process()
}
}
// Process the command based on the detected state of input processing
switch (InputProcessed)
{
case CMD_ABORT:
@ -83,7 +111,7 @@ void Debug_Process()
break;
case CMD_OVERFLOW:
Debug_pushMessage("input Buffer overflow\n");
Debug_pushMessage("Input buffer overflow\n");
break;
default:
@ -91,32 +119,53 @@ void Debug_Process()
}
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)
{
// Display a debug message based on the provided status
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;
// Display a debug message based on the updated status
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, ...)
{
// Check if either the Serial or WebUI debug port is enabled
if ((DebuggerStatus[dbg_Serial] == enabled) || (DebuggerStatus[dbg_Webui] == enabled))
{
char buff[64];
va_list arg;
char buff[64]; // Buffer to hold the formatted message
va_list arg; // Variable argument list for vsnprintf
va_start(arg, format);
// Format the message and store it in the buffer
vsnprintf(buff, sizeof(buff), format, arg);
va_end(arg);
// Send the message to the Serial debug port if enabled
if (DebuggerStatus[dbg_Serial] == enabled)
{
Serial.print(buff);
}
// Push the message to the WebUI debug port if enabled
if (DebuggerStatus[dbg_Webui] == enabled)
{
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)
{
// Check if either the Serial or WebUI debug port is enabled
if ((DebuggerStatus[dbg_Serial] == enabled) || (DebuggerStatus[dbg_Webui] == enabled))
{
char buff[100];
char *p = buff;
char buff[100]; // Buffer to hold the formatted message
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);
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 = '\0';
// Send the formatted CAN message to the Serial debug port if enabled
if (DebuggerStatus[dbg_Serial] == enabled)
{
Serial.print(buff);
}
// Push the formatted CAN message to the WebUI debug port if enabled
if (DebuggerStatus[dbg_Webui] == enabled)
{
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)
{
// Check the received command and execute corresponding actions
if (command == "help")
Debug_printHelp();
else if (command == "sysinfo")
@ -193,18 +261,29 @@ void processCmdDebug(String command)
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()
{
Debug_pushMessage("Formatting Config-EEPROM and reseting to default\n");
Debug_pushMessage("Formatting Config-EEPROM and resetting to default\n");
FormatConfig_EEPROM();
}
/**
* @brief Formats the Persistence-EEPROM and resets it to default values.
* Prints a debug message after formatting.
*/
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();
}
/**
* @brief Prints system information and status to the debug output.
*/
void Debug_printSystemInfo()
{
Debug_pushMessage("Souko's ChainOiler Mk1\n");
@ -224,10 +303,13 @@ void Debug_printSystemInfo()
: ideMode == FM_DOUT ? "DOUT"
: "UNKNOWN"));
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);
}
/**
* @brief Dumps the current configuration parameters to the debug output.
*/
void Debug_dumpConfig()
{
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("PulsePerRevolution: %d\n", LubeConfig.PulsePerRevolution);
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("DistancePerRevolution_mm: %d\n", LubeConfig.DistancePerRevolution_mm);
Debug_pushMessage("BleedingPulses: %d\n", LubeConfig.BleedingPulses);
@ -247,6 +329,9 @@ void Debug_dumpConfig()
Debug_pushMessage("checksum: 0x%08X\n", LubeConfig.checksum);
}
/**
* @brief Dumps the global variables and their values to the debug output.
*/
void Debug_dumpGlobals()
{
Debug_pushMessage("systemStatus: %d\n", globals.systemStatus);
@ -261,6 +346,9 @@ void Debug_dumpGlobals()
Debug_pushMessage("hasDTC: %d\n", globals.hasDTC);
}
/**
* @brief Dumps the persistence data variables and their values to the debug output.
*/
void Debug_dumpPersistance()
{
Debug_pushMessage("writeCycleCounter: %d\n", PersistenceData.writeCycleCounter);
@ -270,12 +358,21 @@ void Debug_dumpPersistance()
Debug_pushMessage("PSD Adress: 0x%04X\n", globals.eePersistanceAdress);
}
/**
* @brief Prints information related to WiFi to the debug output.
*/
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()
{
// Check PersistenceData EEPROM checksum
uint32_t checksum = PersistenceData.checksum;
PersistenceData.checksum = 0;
@ -290,6 +387,7 @@ void Debug_CheckEEPOM()
PersistenceData.checksum = checksum;
// Check LubeConfig EEPROM checksum
checksum = LubeConfig.checksum;
LubeConfig.checksum = 0;
@ -304,24 +402,32 @@ void Debug_CheckEEPOM()
LubeConfig.checksum = checksum;
}
/**
* @brief Displays Diagnostic Trouble Codes (DTCs) along with their timestamps,
* status, and severity in a formatted manner.
*/
void Debug_ShowDTCs()
{
char buff_timestamp[16]; // Format: DD-hh:mm:ss:xxx
char buff_active[9];
// Header for the DTC display
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++)
{
if (DTCStorage[i].Number < DTC_LAST_DTC)
{
// Format timestamp
sprintf(buff_timestamp, "%02d-%02d:%02d:%02d:%03d",
DTCStorage[i].timestamp / 86400000, // Days
DTCStorage[i].timestamp / 360000 % 24, // Hours
DTCStorage[i].timestamp / 60000 % 60, // Minutes
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)
strcpy(buff_active, "active");
else if (DTCStorage[i].active == DTC_PREVIOUS)
@ -329,19 +435,28 @@ void Debug_ShowDTCs()
else
strcpy(buff_active, "none");
// Display DTC information
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()
{
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);
buff[63] = 0;
// Display the help command
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 "debugger.h"
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)
{
// Iterate through the existing DTCs in the storage
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 the DTC is active and was not active before, update its status
if (active && DTCStorage[i].active != DTC_ACTIVE)
{
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].debugVal = DebugValue;
}
// If the DTC is not active anymore, update its status to previous
if (!active && DTCStorage[i].active == DTC_ACTIVE)
{
Debug_pushMessage("DTC gone previous: %d\n", DTC_no);
DTCStorage[i].active = DTC_PREVIOUS;
}
return;
return; // DTC found and processed, exit the function
}
}
// DTC was not found with upper iteration, but is active
// so we need to look for free space to store DTC
// DTC was not found in the existing storage, but it is active,
// so look for free space to store the new DTC
if (active == true)
{
for (int i = 0; i < MAX_DTC_STORAGE; i++)
{
// Check for an empty slot in the storage
if (DTCStorage[i].Number == DTC_LAST_DTC)
{
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].active = DTC_ACTIVE;
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)
{
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()
{
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)
{
int8_t pointer = -1;
@ -87,6 +135,15 @@ DTCNum_t getlastDTC(boolean only_active)
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)
{
for (int i = 0; i < DTC_LAST_DTC; i++)
@ -99,6 +156,16 @@ DTCSeverity_t getSeverityForDTC(DTCNum_t targetCode)
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()
{
static tSystem_Status preserverSysStatusError;
@ -120,10 +187,10 @@ void DTC_Process()
else
{
globals.hasDTC = false;
if (globals.systemStatus == sysStat_Error)
{
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"
// Global instance of the Globals_t structure
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()
{
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"
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()
{
uint32_t baudrate;
@ -22,6 +41,15 @@ void Init_GPS()
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()
{
static uint32_t lastRecTimestamp;
@ -49,7 +77,9 @@ uint32_t Process_GPS_WheelSpeed()
lastRecTimestamp = millis();
}
}
// Maintain DTC for no GPS data received within a certain time frame
MaintainDTC(DTC_NO_GPS_SERIAL, (millis() > lastRecTimestamp + 10000));
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"
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)
{
// Calculate and update tank percentage
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_LOW, (globals.TankPercentage < LubeConfig.TankRemindAtPercentage));
// Add traveled Distance in mm
// Add traveled distance in millimeters
PersistenceData.TravelDistance_highRes_mm += add_milimeters;
PersistenceData.odometer_mm += add_milimeters;
// Update odometer if necessary
if (PersistenceData.odometer_mm >= 1000000)
{
PersistenceData.odometer++;
PersistenceData.odometer_mm = 0;
}
// Handle different system statuses
switch (globals.systemStatus)
{
case sysStat_Startup:
strcpy_P(globals.systemStatustxt, PSTR("Startup"));
// Transition to Normal status after startup delay
if (millis() > STARTUP_DELAY)
{
globals.systemStatus = sysStat_Normal;
@ -32,6 +60,7 @@ void RunLubeApp(uint32_t add_milimeters)
case sysStat_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)
{
LubePulse();
@ -41,16 +70,20 @@ void RunLubeApp(uint32_t add_milimeters)
case sysStat_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)
{
LubePulse();
PersistenceData.TravelDistance_highRes_mm = 0;
}
break;
case sysStat_Purge:
strcpy_P(globals.systemStatustxt, PSTR("Purge"));
// Execute lube pulses during the Purge status
if (globals.purgePulses > 0)
{
// Check if enough time has passed since the last lube pulse
if (lubePulseTimestamp + LUBE_PULSE_PAUSE_MS < millis())
{
LubePulse();
@ -60,35 +93,48 @@ void RunLubeApp(uint32_t add_milimeters)
}
else
{
// Transition back to the previous status after completing purge pulses
globals.systemStatus = globals.resumeStatus;
}
break;
case sysStat_Error:
strcpy_P(globals.systemStatustxt, PSTR("Error"));
break;
case sysStat_Shutdown:
strcpy_P(globals.systemStatustxt, PSTR("Shutdown"));
break;
default:
break;
}
// maintain Pin-State of Lube-Pump
// Maintain Pin-State of Lube-Pump
if (lubePulseTimestamp > millis())
digitalWrite(GPIO_PUMP, HIGH);
else
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()
{
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;
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;
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 <Wire.h>
#ifdef FEATURE_ENABLE_OLED
@ -57,28 +72,49 @@ Ticker WiFiMaintainConnectionTicker(wifiMaintainConnectionTicker_callback, 1000,
#endif
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()
{
// Set CPU frequency to 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());
// Disable WiFi persistent storage
WiFi.persistent(false);
ClearAllDTC(); // Init DTC-Storage
// Initialize and clear Diagnostic Trouble Code (DTC) storage
ClearAllDTC();
#ifdef FEATURE_ENABLE_WIFI_CLIENT
// Configure WiFi settings for client mode if enabled
WiFi.mode(WIFI_STA);
WiFi.setHostname(globals.DeviceName);
wifiMulti.addAP(QUOTE(WIFI_SSID_CLIENT), QUOTE(WIFI_PASSWORD_CLIENT));
WiFiMaintainConnectionTicker.start();
#else
// Disable WiFi if WiFi client feature is not enabled
WiFi.mode(WIFI_OFF);
#endif
// Initialize Serial communication
Serial.begin(115200);
Serial.print("\n\nSouko's ChainLube Mk1\n");
Serial.print(globals.DeviceName);
#ifdef FEATURE_ENABLE_OLED
// Initialize OLED display if enabled
u8x8.begin();
u8x8.setFont(u8x8_font_chroma48medium8_r);
u8x8.clearDisplay();
@ -87,14 +123,17 @@ void setup()
Serial.print("\nDisplay-Init done");
#endif
// Initialize EEPROM, load configuration, and persistence data from EEPROM
InitEEPROM();
GetConfig_EEPROM();
GetPersistence_EEPROM();
Serial.print("\nEE-Init done");
// Initialize LEDs
leds.begin();
Serial.print("\nLED-Init done");
// Initialize based on the chosen speed source (CAN, GPS, Impulse)
switch (LubeConfig.SpeedSource)
{
case SOURCE_CAN:
@ -115,13 +154,18 @@ void setup()
}
Serial.print("\nSource-Init done");
// Configure GPIO pins for button and pump control
pinMode(GPIO_BUTTON, INPUT_PULLUP);
pinMode(GPIO_PUMP, OUTPUT);
// Set up OTA updates
ArduinoOTA.setPort(8266);
ArduinoOTA.setHostname(globals.DeviceName);
ArduinoOTA.setPassword(QUOTE(ADMIN_PASSWORD));
#ifdef FEATURE_ENABLE_OLED
// Set up OTA callbacks for OLED display if enabled
ArduinoOTA.onStart([]()
{
u8x8.clearDisplay();
@ -148,20 +192,40 @@ void setup()
u8x8.drawString(0, 0, "OTA-Restart");
u8x8.refreshDisplay(); });
#endif
// Begin OTA updates
ArduinoOTA.begin();
Serial.print("\nOTA-Init done");
// Initialize the web user interface
initWebUI();
Serial.print("\nWebUI-Init done");
// Initialize global variables
initGlobals();
Serial.print("\nglobals-Init done");
// Start cyclic EEPROM updates for Persistence Data Structure (PDS)
EEPROMCyclicPDSTicker.start();
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()
{
// Variable to store calculated wheel distance
uint32_t wheelDistance = 0;
// Switch based on the configured speed source
switch (LubeConfig.SpeedSource)
{
case SOURCE_IMPULSE:
@ -180,14 +244,22 @@ void loop()
break;
}
// Run lubrication application with the calculated wheel distance
RunLubeApp(wheelDistance);
#ifdef FEATURE_ENABLE_OLED
// Update OLED display if enabled
Display_Process();
#endif
// Process CAN messages if the speed source is not impulse
if (LubeConfig.SpeedSource != SOURCE_IMPULSE)
{
CAN_Process();
}
// Process button input, manage LED behavior, perform EEPROM tasks, handle webserver operations,
// process Diagnostic Trouble Codes (DTC), and manage debugging
Button_Process();
LED_Process();
EEPROM_Process();
@ -195,18 +267,35 @@ void loop()
DTC_Process();
Debug_Process();
// Handle OTA updates and update cyclic EEPROM tasks for Persistence Data Structure (PDS)
ArduinoOTA.handle();
EEPROMCyclicPDSTicker.update();
#ifdef FEATURE_ENABLE_WIFI_CLIENT
// Update WiFi connection maintenance ticker if WiFi client feature is enabled
WiFiMaintainConnectionTicker.update();
#endif
// Perform system shutdown if the status is set to shutdown
if (globals.systemStatus == sysStat_Shutdown)
SystemShutdown();
SystemShutdown(false);
// Yield to allow other tasks to run
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)
{
// Concatenate each octet of the IPAddress with dots in between
return String(ipAddress[0]) + String(".") +
String(ipAddress[1]) + String(".") +
String(ipAddress[2]) + String(".") +
@ -214,42 +303,80 @@ String IpAddress2String(const IPAddress &ipAddress)
}
#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()
{
// Static variables to track WiFi connection failure count and maximum allowed failures
static uint32_t WiFiFailCount = 0;
const uint32_t WiFiFailMax = 20;
// Check if the device is connected to WiFi
if (wifiMulti.run(connectTimeoutMs) == WL_CONNECTED)
{
return;
return; // Exit if connected
}
else
{
// Increment WiFi connection failure count
if (WiFiFailCount < WiFiFailMax)
{
WiFiFailCount++;
}
else
{
// Trigger AP mode if the maximum failures are reached
Debug_pushMessage("WiFi not connected! - Start AP");
toggleWiFiAP();
}
}
}
#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()
{
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()
{
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)
{
// Enumeration to represent LED status
typedef enum
{
LED_Startup,
@ -263,17 +390,20 @@ void LED_Process(uint8_t override, uint32_t SetColor)
LED_Override
} tLED_Status;
// Static variables to track LED status, system status, override color, and previous LED status
static tSystem_Status oldSysStatus = sysStat_Startup;
static tLED_Status LED_Status = LED_Startup;
static uint32_t LED_override_color = 0;
static tLED_Status LED_ResumeOverrideStatus = LED_Startup;
// Variables for managing LED animation timing
uint8_t color = 0;
uint32_t timer = 0;
uint32_t animtimer = 0;
static uint32_t timestamp = 0;
timer = millis();
// Handle LED overrides
if (override == 1)
{
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)
{
switch (globals.systemStatus)
@ -330,6 +461,7 @@ void LED_Process(uint8_t override, uint32_t SetColor)
oldSysStatus = globals.systemStatus;
}
// Handle different LED statuses
switch (LED_Status)
{
case LED_Startup:
@ -433,28 +565,47 @@ void LED_Process(uint8_t override, uint32_t SetColor)
}
leds.show();
}
#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()
{
// Static variable to track the previous system status
static tSystem_Status oldSysStatus = sysStat_Startup;
// Check if the system status has changed since the last update
if (oldSysStatus != globals.systemStatus)
{
// Clear the display and print the system title when the status changes
u8x8.clearDisplay();
u8x8.drawString(0, 0, "KTM ChainLube V1");
oldSysStatus = globals.systemStatus;
}
// Set the cursor position for displaying information on the OLED screen
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;
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);
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));
}
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("Tank: %8dml\n"), PersistenceData.tankRemain_microL / 1000);
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("%s\n", WiFi.localIP().toString().c_str());
}
// Refresh the OLED display with the updated content
u8x8.refreshDisplay();
}
#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()
{
// Time delays for different button actions
#define BUTTON_ACTION_DELAY_TOGGLEMODE 500
#define BUTTON_ACTION_DELAY_PURGE 3500
#define BUTTON_ACTION_DELAY_WIFI 6500
#define BUTTON_ACTION_DELAY_NOTHING 9500
// Enumeration to represent button actions
typedef enum buttonAction_e
{
BTN_INACTIVE,
@ -484,15 +646,18 @@ void Button_Process()
BTN_STARTPURGE
} buttonAction_t;
// Static variables to track button state and timing
static uint32_t buttonTimestamp = 0;
static buttonAction_t buttonAction = BTN_INACTIVE;
// Check if button is pressed (LOW)
if (digitalRead(GPIO_BUTTON) == LOW)
{
// Update button timestamp on the first button press
if (buttonTimestamp == 0)
buttonTimestamp = millis();
// Check and execute actions based on predefined time delays
if (buttonTimestamp + BUTTON_ACTION_DELAY_NOTHING < millis())
{
LED_Process(1, COLOR_WARM_WHITE);
@ -515,8 +680,9 @@ void Button_Process()
buttonAction = BTN_TOGGLEMODE;
}
}
else
else // Button is released
{
// Execute corresponding actions based on the detected button action
if (buttonAction != BTN_INACTIVE)
{
switch (buttonAction)
@ -544,6 +710,7 @@ void Button_Process()
globals.systemStatus = sysStat_Normal;
globals.resumeStatus = sysStat_Normal;
break;
default:
break;
}
@ -555,28 +722,49 @@ void Button_Process()
Debug_pushMessage("Nothing or invalid\n");
break;
}
// Display feedback through LEDs
LED_Process(2);
}
// Reset button state and timestamp
buttonAction = BTN_INACTIVE;
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)
{
// Check if WiFi is currently active
if (WiFi.getMode() != WIFI_OFF)
{
// Turn off WiFi
WiFi.mode(WIFI_OFF);
Debug_pushMessage("WiFi turned off\n");
// Stop WiFi maintenance connection ticker if enabled
#ifdef FEATURE_ENABLE_WIFI_CLIENT
WiFiMaintainConnectionTicker.stop();
#endif
}
else
{
// Start WiFi in Access Point (AP) mode
WiFi.mode(WIFI_AP);
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));
// Stop WiFi maintenance connection ticker if enabled and display debug messages
#ifdef FEATURE_ENABLE_WIFI_CLIENT
WiFiMaintainConnectionTicker.stop();
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)
{
static uint32_t shutdown_delay = 0;
// Initialize shutdown delay on the first call
if (shutdown_delay == 0)
{
shutdown_delay = millis() + SHUTDOWN_DELAY_MS;
Serial.printf("Shutdown requested - Restarting in %d seconds\n", SHUTDOWN_DELAY_MS / 1000);
}
// Check if the shutdown delay has elapsed
if (shutdown_delay < millis())
{
// Store configuration and persistence data to EEPROM
StoreConfig_EEPROM();
StorePersistence_EEPROM();
// Perform restart if requested, otherwise enter an indefinite loop
if (restart)
ESP.restart();
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 add_milimeters = 0;