Initialisation depot

This commit is contained in:
2025-11-30 09:58:00 +01:00
commit 56d8cd96c8
28 changed files with 3154 additions and 0 deletions

102
include/Config.h Normal file
View File

@@ -0,0 +1,102 @@
/**
* @file Config.h
* @brief Configuration management for the Locomotive Test Bench
*
* This module handles persistent storage of WiFi and system settings
* using ESP32's Preferences library (NVS - Non-Volatile Storage).
*
* @author Locomotive Test Bench Project
* @date 2025
*/
#ifndef CONFIG_H
#define CONFIG_H
#include <Arduino.h>
#include <Preferences.h>
/**
* @struct WiFiConfig
* @brief WiFi configuration parameters
*
* Stores both Access Point and Client mode settings.
*/
struct WiFiConfig {
String ssid; ///< WiFi network SSID (Client mode)
String password; ///< WiFi network password (Client mode)
bool isAPMode; ///< True = AP mode, False = Client mode
String apSSID; ///< Access Point SSID
String apPassword; ///< Access Point password (min 8 characters)
};
/**
* @struct SystemConfig
* @brief System operation configuration
*
* Stores current control mode and locomotive parameters.
*/
struct SystemConfig {
bool isDCCMode; ///< True = DCC digital, False = DC analog
uint16_t dccAddress; ///< DCC locomotive address (1-10239)
uint8_t speed; ///< Speed setting (0-100%)
uint8_t direction; ///< Direction: 0 = reverse, 1 = forward
uint32_t dccFunctions; ///< Bit field for DCC functions F0-F28
};
/**
* @class Config
* @brief Configuration manager with persistent storage
*
* Manages all configuration parameters and provides persistent
* storage using ESP32's NVS (Non-Volatile Storage) via Preferences.
*
* @note All settings are automatically saved to flash memory
* and persist across reboots.
*/
class Config {
public:
/**
* @brief Constructor - initializes with default values
*/
Config();
/**
* @brief Initialize preferences and load saved settings
*
* Must be called during setup() before using configuration.
* Loads previously saved settings from NVS.
*/
void begin();
/**
* @brief Save current configuration to NVS
*
* Writes all WiFi and system settings to persistent storage.
* Should be called after any configuration changes.
*/
void save();
/**
* @brief Load configuration from NVS
*
* Reads previously saved settings. Called automatically
* by begin(), but can be called manually to reload.
*/
void load();
/**
* @brief Reset all settings to defaults
*
* Clears all stored preferences and resets to factory defaults.
* Use with caution - all saved settings will be lost.
*/
void reset();
WiFiConfig wifi; ///< WiFi configuration settings
SystemConfig system; ///< System operation settings
private:
Preferences preferences; ///< ESP32 NVS preferences object
};
#endif

158
include/DCCGenerator.h Normal file
View File

@@ -0,0 +1,158 @@
/**
* @file DCCGenerator.h
* @brief NMRA DCC (Digital Command Control) signal generator
*
* Generates DCC protocol signals for controlling digital model locomotives.
* Implements NMRA DCC standard with support for:
* - Short addresses (1-127) and long addresses (128-10239)
* - 128-step speed control
* - Function control (F0-F12 implemented, expandable to F28)
*
* @note Requires external DCC booster circuit for track output
* @author Locomotive Test Bench Project
* @date 2025
*/
#ifndef DCC_GENERATOR_H
#define DCC_GENERATOR_H
#include <Arduino.h>
// Pin definitions for DCC output
#define DCC_PIN_A 32 ///< DCC Signal A output pin
#define DCC_PIN_B 33 ///< DCC Signal B output pin (inverted)
// DCC timing constants (microseconds) - NMRA standard
#define DCC_ONE_BIT_TOTAL_DURATION_MAX 64 ///< Max duration for '1' bit
#define DCC_ONE_BIT_TOTAL_DURATION_MIN 55 ///< Min duration for '1' bit
#define DCC_ZERO_BIT_TOTAL_DURATION_MAX 10000 ///< Max duration for '0' bit
#define DCC_ZERO_BIT_TOTAL_DURATION_MIN 95 ///< Min duration for '0' bit
#define DCC_ONE_BIT_PULSE_DURATION 58 ///< Half-cycle for '1' bit (58μs)
#define DCC_ZERO_BIT_PULSE_DURATION 100 ///< Half-cycle for '0' bit (100μs)
/**
* @class DCCGenerator
* @brief DCC protocol signal generator
*
* Generates NMRA-compliant DCC signals for digital locomotive control.
* Supports variable speed, direction, and function commands.
*
* @warning Output signals are low-power logic level.
* Requires external booster circuit for track connection.
*/
class DCCGenerator {
public:
/**
* @brief Constructor
*/
DCCGenerator();
/**
* @brief Initialize DCC generator hardware
*
* Configures output pins to idle state.
*/
void begin();
/**
* @brief Enable DCC signal generation
*
* Starts sending DCC packets to the track.
*/
void enable();
/**
* @brief Disable DCC signal generation
*
* Stops DCC output and sets pins to safe state.
*/
void disable();
/**
* @brief Set locomotive speed and direction
* @param address DCC address (1-10239)
* @param speed Speed value (0-100%)
* @param direction Direction: 0 = reverse, 1 = forward
*/
void setLocoSpeed(uint16_t address, uint8_t speed, uint8_t direction);
/**
* @brief Control DCC function
* @param address DCC address (1-10239)
* @param function Function number (0-28)
* @param state true = ON, false = OFF
*/
void setFunction(uint16_t address, uint8_t function, bool state);
/**
* @brief Update DCC signal generation
*
* Must be called regularly from main loop to send DCC packets.
* Sends speed and function packets at appropriate intervals.
*/
void update();
/**
* @brief Check if DCC is enabled
* @return true if DCC mode is active
*/
bool isEnabled() { return enabled; }
private:
bool enabled; ///< DCC generator enabled flag
uint16_t currentAddress; ///< Current locomotive address
uint8_t currentSpeed; ///< Current speed setting
uint8_t currentDirection; ///< Current direction (0=rev, 1=fwd)
uint32_t functionStates; ///< Function states bit field
unsigned long lastPacketTime; ///< Timestamp of last packet sent
static const unsigned long PACKET_INTERVAL = 30; ///< Packet interval (ms)
// DCC packet construction and transmission
/**
* @brief Send a complete DCC packet
* @param data Byte array containing packet data
* @param length Number of bytes in packet
*/
void sendPacket(uint8_t* data, uint8_t length);
/**
* @brief Send a single DCC bit
* @param value true = '1' bit, false = '0' bit
*/
void sendBit(bool value);
/**
* @brief Send DCC preamble (14 '1' bits)
*/
void sendPreamble();
/**
* @brief Send a single byte
* @param data Byte to send
*/
void sendByte(uint8_t data);
/**
* @brief Send speed command packet
*/
void sendSpeedPacket();
/**
* @brief Send function group packet
* @param group Function group number
*/
void sendFunctionPacket(uint8_t group);
/**
* @brief Calculate XOR checksum
* @param data Data bytes
* @param length Number of bytes
* @return XOR checksum byte
*/
uint8_t calculateChecksum(uint8_t* data, uint8_t length);
};
#endif

105
include/LEDIndicator.h Normal file
View File

@@ -0,0 +1,105 @@
/**
* @file LEDIndicator.h
* @brief WS2812 RGB LED status indicators
*
* Provides visual feedback using two WS2812 LEDs:
* - LED 0: Power status (Green = ON, Red = OFF)
* - LED 1: Mode indicator (Blue = DCC, Yellow = Analog)
*
* @author Locomotive Test Bench Project
* @date 2025
*/
#ifndef LED_INDICATOR_H
#define LED_INDICATOR_H
#include <Arduino.h>
#include <FastLED.h>
// Pin definition for WS2812 LEDs
#define LED_DATA_PIN 4 ///< Data pin for WS2812 strip
#define NUM_LEDS 2 ///< Number of LEDs (Power + Mode)
// LED indices
#define LED_POWER 0 ///< Power status indicator
#define LED_MODE 1 ///< Mode indicator (DCC/Analog)
/**
* @class LEDIndicator
* @brief Manages WS2812 RGB LED status displays
*
* Controls two LEDs for system status indication:
* - Power LED: Shows system power state with boot animation
* - Mode LED: Shows control mode with pulsing effect
*/
class LEDIndicator {
public:
/**
* @brief Constructor
*/
LEDIndicator();
/**
* @brief Initialize LED hardware
*
* Configures FastLED library and sets LEDs to off state.
*/
void begin();
/**
* @brief Update LED display
*
* Must be called regularly from main loop to update
* pulsing effects and animations.
*/
void update();
/**
* @brief Set power status
* @param on true = power on (green), false = off (red)
*/
void setPowerOn(bool on);
/**
* @brief Set operating mode
* @param isDCC true = DCC mode (blue), false = Analog (yellow)
*/
void setMode(bool isDCC);
/**
* @brief Set LED brightness
* @param brightness Brightness level (0-255)
*/
void setBrightness(uint8_t brightness);
/**
* @brief Play power-on animation sequence
*
* Shows 3-flash boot sequence on power LED.
*/
void powerOnSequence();
/**
* @brief Play mode change animation
*
* Smooth fade transition when switching modes.
*/
void modeChangeEffect();
private:
CRGB leds[NUM_LEDS]; ///< LED array
bool powerOn; ///< Power status flag
bool dccMode; ///< Mode flag (DCC/Analog)
uint8_t brightness; ///< Current brightness level
unsigned long lastUpdate; ///< Last update timestamp
uint8_t pulsePhase; ///< Pulse animation phase
// LED color definitions
static constexpr CRGB COLOR_POWER_ON = CRGB::Green; ///< Power ON color
static constexpr CRGB COLOR_POWER_OFF = CRGB::Red; ///< Power OFF color
static constexpr CRGB COLOR_DCC = CRGB::Blue; ///< DCC mode color
static constexpr CRGB COLOR_ANALOG = CRGB::Yellow; ///< Analog mode color
static constexpr CRGB COLOR_OFF = CRGB::Black; ///< LED off state
};
#endif

101
include/MotorController.h Normal file
View File

@@ -0,0 +1,101 @@
/**
* @file MotorController.h
* @brief DC motor control using LM18200 H-Bridge driver
*
* Provides bidirectional PWM motor control with brake functionality.
* Suitable for DC analog model locomotive control.
*
* @author Locomotive Test Bench Project
* @date 2025
*/
#ifndef MOTOR_CONTROLLER_H
#define MOTOR_CONTROLLER_H
#include <Arduino.h>
// Pin definitions for LM18200
// These can be adjusted based on your D1 Mini ESP32 wiring
#define MOTOR_PWM_PIN 25 ///< PWM signal output pin
#define MOTOR_DIR_PIN 26 ///< Direction control pin
#define MOTOR_BRAKE_PIN 27 ///< Brake control pin (active low)
/**
* @class MotorController
* @brief Controls DC motor via LM18200 H-Bridge
*
* Features:
* - Variable speed control (0-100%)
* - Bidirectional operation (forward/reverse)
* - Electronic braking
* - 20kHz PWM frequency for silent operation
* - 8-bit resolution (256 speed steps)
*/
class MotorController {
public:
/**
* @brief Constructor
*/
MotorController();
/**
* @brief Initialize motor controller hardware
*
* Configures GPIO pins and PWM channels.
* Sets motor to safe stopped state.
*/
void begin();
/**
* @brief Set motor speed and direction
* @param speed Speed value (0-100%)
* @param direction Direction: 0 = reverse, 1 = forward
*/
void setSpeed(uint8_t speed, uint8_t direction);
/**
* @brief Stop motor (coast to stop)
*
* Sets speed to zero and releases brake.
* Motor will coast to a stop.
*/
void stop();
/**
* @brief Apply electronic brake
*
* Activates LM18200 brake function for quick stop.
* More aggressive than stop().
*/
void brake();
/**
* @brief Update motor controller state
*
* Called from main loop for safety checks.
* Currently placeholder for future features.
*/
void update();
/**
* @brief Get current speed setting
* @return Speed (0-100%)
*/
uint8_t getCurrentSpeed() { return currentSpeed; }
/**
* @brief Get current direction
* @return Direction: 0 = reverse, 1 = forward
*/
uint8_t getCurrentDirection() { return currentDirection; }
private:
uint8_t currentSpeed; ///< Current speed setting (0-100)
uint8_t currentDirection; ///< Current direction (0=rev, 1=fwd)
static const int PWM_CHANNEL = 0; ///< ESP32 PWM channel
static const int PWM_FREQUENCY = 20000; ///< PWM frequency in Hz
static const int PWM_RESOLUTION = 8; ///< PWM resolution in bits
};
#endif

140
include/WebServer.h Normal file
View File

@@ -0,0 +1,140 @@
/**
* @file WebServer.h
* @brief Web server and REST API for remote control
*
* Provides web-based control interface with:
* - Responsive Bootstrap-based UI
* - RESTful API for control and configuration
* - LittleFS-based file serving
* - Real-time status updates
*
* @author Locomotive Test Bench Project
* @date 2025
*/
#ifndef WEB_SERVER_H
#define WEB_SERVER_H
#include <Arduino.h>
#include <ESPAsyncWebServer.h>
#include <AsyncTCP.h>
#include <ArduinoJson.h>
#include "Config.h"
#include "MotorController.h"
#include "DCCGenerator.h"
#include "LEDIndicator.h"
/**
* @class WebServerManager
* @brief Manages web server and API endpoints
*
* Serves web interface from LittleFS and provides REST API
* for controlling the locomotive test bench remotely.
*
* API Endpoints:
* - GET /api/status - Get current system status
* - POST /api/mode - Set control mode (analog/dcc)
* - POST /api/speed - Set speed and direction
* - POST /api/dcc/address - Set DCC address
* - POST /api/dcc/function - Control DCC functions
* - POST /api/wifi - Configure WiFi settings
*/
class WebServerManager {
public:
/**
* @brief Constructor
* @param cfg Pointer to Config object
* @param motor Pointer to MotorController
* @param dcc Pointer to DCCGenerator
* @param led Pointer to LEDIndicator
*/
WebServerManager(Config* cfg, MotorController* motor, DCCGenerator* dcc, LEDIndicator* led);
/**
* @brief Initialize web server
*
* Mounts LittleFS, sets up routes, and starts AsyncWebServer.
*/
void begin();
/**
* @brief Update web server (currently unused)
*
* AsyncWebServer handles requests asynchronously.
*/
void update();
private:
Config* config; ///< Configuration manager
MotorController* motorController; ///< Motor controller instance
DCCGenerator* dccGenerator; ///< DCC generator instance
LEDIndicator* ledIndicator; ///< LED indicator instance
AsyncWebServer server; ///< Async web server (port 80)
/**
* @brief Set up all HTTP routes and handlers
*/
void setupRoutes();
/**
* @brief Handle root page request
* @param request HTTP request object
*/
void handleRoot(AsyncWebServerRequest *request);
/**
* @brief Handle status request
* @param request HTTP request object
*/
void handleGetStatus(AsyncWebServerRequest *request);
/**
* @brief Handle mode change request
* @param request HTTP request object
*/
void handleSetMode(AsyncWebServerRequest *request);
/**
* @brief Handle speed setting request
* @param request HTTP request object
*/
void handleSetSpeed(AsyncWebServerRequest *request);
/**
* @brief Handle DCC function request
* @param request HTTP request object
*/
void handleSetFunction(AsyncWebServerRequest *request);
/**
* @brief Handle config retrieval request
* @param request HTTP request object
*/
void handleGetConfig(AsyncWebServerRequest *request);
/**
* @brief Handle WiFi configuration request
* @param request HTTP request object
*/
void handleSetWiFi(AsyncWebServerRequest *request);
/**
* @brief Handle restart request
* @param request HTTP request object
*/
void handleRestart(AsyncWebServerRequest *request);
/**
* @brief Get system status as JSON
* @return JSON string with status information
*/
String getStatusJSON();
/**
* @brief Get configuration as JSON
* @return JSON string with configuration
*/
String getConfigJSON();
};
#endif

87
include/WiFiManager.h Normal file
View File

@@ -0,0 +1,87 @@
/**
* @file WiFiManager.h
* @brief WiFi connection management for AP and Client modes
*
* Handles WiFi connectivity in both Access Point and Client modes,
* with automatic reconnection support.
*
* @author Locomotive Test Bench Project
* @date 2025
*/
#ifndef WIFI_MANAGER_H
#define WIFI_MANAGER_H
#include <Arduino.h>
#include <WiFi.h>
#include "Config.h"
/**
* @class WiFiManager
* @brief Manages WiFi connectivity and modes
*
* Provides WiFi functionality in two modes:
* - Access Point (AP): Creates standalone network
* - Client (STA): Connects to existing WiFi network
*
* Features automatic reconnection in client mode.
*/
class WiFiManager {
public:
/**
* @brief Constructor
* @param cfg Pointer to Config object for WiFi settings
*/
WiFiManager(Config* cfg);
/**
* @brief Initialize WiFi based on configuration
*
* Sets up either AP or Client mode based on config settings.
* Called during system startup.
*/
void begin();
/**
* @brief Set up Access Point mode
*
* Creates a standalone WiFi network using configured
* SSID and password. Default IP: 192.168.4.1
*/
void setupAccessPoint();
/**
* @brief Connect to existing WiFi network
*
* Attempts to connect as client to configured network.
* Falls back to AP mode if connection fails after 10 seconds.
*/
void connectToWiFi();
/**
* @brief Check if WiFi is connected
* @return true if connected (or AP mode active), false otherwise
*/
bool isConnected();
/**
* @brief Get current IP address
* @return IP address as string (AP IP or STA IP)
*/
String getIPAddress();
/**
* @brief Update WiFi status and handle reconnection
*
* Should be called regularly from main loop.
* Handles automatic reconnection in client mode.
*/
void update();
private:
Config* config; ///< Pointer to configuration object
unsigned long lastReconnectAttempt; ///< Timestamp of last reconnect attempt
static const unsigned long RECONNECT_INTERVAL = 30000; ///< Reconnect interval (30 seconds)
};
#endif