diff --git a/platformio.ini b/platformio.ini index 8a2dbea..7d9ae57 100644 --- a/platformio.ini +++ b/platformio.ini @@ -13,4 +13,5 @@ platform = espressif32 board = wt32-eth01 framework = arduino lib_deps = siwats/ESPMegaPROR3@^2.9.5 +build_flags = -DCORE_DEBUG_LEVEL=0 -DSW_VERSION='"generator-dev-1.0.0"' -DBOARD_MODEL='"ESPMegaPRO R3.3c"' monitor_speed = 115200 \ No newline at end of file diff --git a/src/GasolineGenerator.cpp b/src/GasolineGenerator.cpp new file mode 100644 index 0000000..6559b4c --- /dev/null +++ b/src/GasolineGenerator.cpp @@ -0,0 +1,191 @@ +#include "GasolineGenerator.hpp" + +GasolineGenerator::GasolineGenerator() +{ + +} + +void GasolineGenerator::initialize(DigitalInputCard* inputCard, DigitalOutputCard* outputCard, const GasolineGeneratorConfig &config) +{ + this->config = &config; + this->inputCard = inputCard; + this->outputCard = outputCard; + + // Initialize all outputs to safe state + setIgnitionSystem(false); + setStarter(false); + setCarburetorValve(false); // Close for startup + + // Set debounce time for power output sensor if enabled + if (config.usePowerOutputSensor && config.powerOutputSensorPin >= 0) + { + this->inputCard->setDebounceTime(config.powerOutputSensorPin, POWER_SENSOR_DEBOUNCE_MS); + } + + // Register input change callback + this->inputCard->registerCallback([this](uint8_t pin, bool state) + { this->handleInputChanges(pin, state); }); + + state = GeneratorState::STOPPED; +} + +void GasolineGenerator::loop() +{ + unsigned long currentTime = millis(); + + switch (state) + { + case GeneratorState::STARTING: + handleStartupSequence(currentTime); + break; + + case GeneratorState::RUNNING: + // Monitor engine status and handle any issues + if (config->usePowerOutputSensor && config->powerOutputSensorPin >= 0) + { + bool hasPowerOutput = inputCard->digitalRead(config->powerOutputSensorPin); + if (!hasPowerOutput) + { + // Engine stopped unexpectedly - no power output detected + isEngineRunning = false; + shutdown(); + } + } + break; + + case GeneratorState::SHUTTING_DOWN: + // Complete shutdown sequence + state = GeneratorState::STOPPED; + break; + + case GeneratorState::STOPPED: + default: + // Nothing to do in stopped state + break; + } +} + +void GasolineGenerator::start() +{ + if (state != GeneratorState::STOPPED) + { + return; // Already starting or running + } + + state = GeneratorState::STARTING; + startupStartTime = millis(); + ignitionStartTime = 0; + isEngineRunning = false; + starterEngaged = false; + + // Step 1: Close carburetor valve for rich mixture + setCarburetorValve(false); + + // Step 2: Power up ignition system + setIgnitionSystem(true); + ignitionStartTime = millis(); +} + +void GasolineGenerator::shutdown() +{ + // Turn off all systems + setStarter(false); + setIgnitionSystem(false); + setCarburetorValve(false); // Close carburetor valve + + state = GeneratorState::STOPPED; + isEngineRunning = false; +} + +void GasolineGenerator::setCarburetorValve(bool open) +{ + bool pinState = config->carburetorValveReverse ? !open : open; + outputCard->digitalWrite(config->carburetorValvePin, pinState); +} + +void GasolineGenerator::setIgnitionSystem(bool enable) +{ + outputCard->digitalWrite(config->ignitionSystemPowerRelayPin, enable); +} + +void GasolineGenerator::setStarter(bool enable) +{ + outputCard->digitalWrite(config->starterRelayPin, enable); + starterEngaged = enable; +} + +void GasolineGenerator::handleStartupSequence(unsigned long currentTime) +{ + // Step 3: After ignition delay, engage starter + if (ignitionStartTime > 0 && + (currentTime - ignitionStartTime) >= IGNITION_DELAY_MS && + !starterEngaged) + { + + setStarter(true); + } + + // Check if we have power output AND starter is off (engine is running independently) + if (config->usePowerOutputSensor && config->powerOutputSensorPin >= 0) + { + bool hasPowerOutput = inputCard->digitalRead(config->powerOutputSensorPin); + if (hasPowerOutput && !starterEngaged && !isEngineRunning) + { + onEngineStarted(); + } + } + else + { + // No power sensor - fallback to time-based detection + if ((currentTime - startupStartTime) >= (IGNITION_DELAY_MS + 3000) && !isEngineRunning) + { + onEngineStarted(); + } + } + + // Timeout protection - stop starter after maximum duration + if (ignitionStartTime > 0 && + (currentTime - ignitionStartTime) >= (IGNITION_DELAY_MS + STARTER_DURATION_MS)) + { + + setStarter(false); + + if (!isEngineRunning) + { + // Failed to start + shutdown(); + } + } +} + +void GasolineGenerator::onEngineStarted() +{ + isEngineRunning = true; + + // Turn off starter + setStarter(false); + + // Open carburetor valve for normal operation + setCarburetorValve(true); + + state = GeneratorState::RUNNING; +} + +void GasolineGenerator::handleInputChanges(uint8_t pin, bool state) +{ + // Handle power output sensor changes + if (pin == config->powerOutputSensorPin) + { + if (state && this->state == GeneratorState::STARTING && !starterEngaged && !isEngineRunning) + { + // Power detected during startup with starter off - engine has started successfully + onEngineStarted(); + } + else if (!state && this->state == GeneratorState::RUNNING) + { + // Power lost during operation - engine may have stopped + isEngineRunning = false; + shutdown(); + } + } +} \ No newline at end of file diff --git a/src/GasolineGenerator.hpp b/src/GasolineGenerator.hpp new file mode 100644 index 0000000..9b02add --- /dev/null +++ b/src/GasolineGenerator.hpp @@ -0,0 +1,75 @@ +#include +#include + +/** + * @brief Configuration structure for the Gasoline Generator. + * + * This structure holds the configuration parameters for the gasoline generator, + * including input and output cards, pin assignments, and sensor settings. + * It is used to initialize the GasolineGenerator class. + * * @note The `inputCard` and `outputCard` should be initialized before passing to the GasolineGenerator. + * * @note The `ignitionSystemPowerRelayPin`, `starterRelayPin`, and `carburetorValvePin` should be set to the correct GPIO pin numbers. + * * @note The `carburetorValveReverse` flag indicates whether the carburetor valve operates in reverse logic (0=open, 1=closed). + **/ + +struct GasolineGeneratorConfig +{ + int8_t ignitionSystemPowerRelayPin; // Pin for ignition system power relay + int8_t starterRelayPin; // Pin for starter relay + int8_t carburetorValvePin; // Pin for carburetor control + bool carburetorValveReverse; // If true, 0 means open, 1 means closed else 0 means closed, 1 means open + int8_t powerOutputSensorPin = -1; // Pin for monitoring generator power output (-1 to disable) + bool usePowerOutputSensor = false; // Enable/disable power output sensor monitoring +}; + +/** + * @brief Enumeration for the generator states. + * This enum defines the possible states of the gasoline generator. + */ +enum class GeneratorState { + STOPPED, + STARTING, + RUNNING, + SHUTTING_DOWN +}; + + +/** + * @brief Gasoline Generator class for managing a gasoline-powered generator. + * + * This class handles the ignition system, starter relay, and carburetor control + * For startup first it closes the carburetor valve, creating a rich air-fuel mixture, + * then it powers the ignition system, wait a bit then spin the starter relay to start the engine. + * After the engine starts, it opens the carburetor valve to allow normal operation. + */ +class GasolineGenerator +{ +public: + GasolineGenerator(); + void initialize(DigitalInputCard* inputCard, DigitalOutputCard* outputCard, const GasolineGeneratorConfig &config); + void loop(); + void start(); + void shutdown(); + +private: + const GasolineGeneratorConfig *config = nullptr; + DigitalInputCard *inputCard = nullptr; + DigitalOutputCard *outputCard = nullptr; + GeneratorState state = GeneratorState::STOPPED; + unsigned long startupStartTime = 0; + unsigned long ignitionStartTime = 0; + bool isEngineRunning = false; + bool starterEngaged = false; + + static const unsigned long IGNITION_DELAY_MS = 2000; // Time to wait after powering ignition system before engaging starter + static const unsigned long STARTER_DURATION_MS = 5000; // Time that the starter should be engaged + static const unsigned long CARBURETOR_OPEN_DELAY_MS = 1000; // Time to wait after engine start for the engine to stabilize before opening the carburetor valve + static const unsigned long POWER_SENSOR_DEBOUNCE_MS = 500; // Debounce time for power output sensor + + void setCarburetorValve(bool open); + void setIgnitionSystem(bool enable); + void setStarter(bool enable); + void handleStartupSequence(unsigned long currentTime); + void onEngineStarted(); + void handleInputChanges(uint8_t pin, bool state); +}; diff --git a/src/config.hpp b/src/config.hpp new file mode 100644 index 0000000..e69de29 diff --git a/src/main.cpp b/src/main.cpp index 67c98cd..234357b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,6 +2,8 @@ ESPMegaPRO espmega = ESPMegaPRO(); +GasolineGenerator generator; + void setup() { // Initialize both displayports @@ -48,9 +50,24 @@ void setup() ESP_LOGV("OS", "Registering Cards with IoT"); espmega.iot->registerCard(0); espmega.iot->registerCard(1); + + // Initialize generator + + GasolineGeneratorConfig generatorConfig; + generatorConfig.ignitionSystemPowerRelayPin = 0; + generatorConfig.starterRelayPin = 1; + generatorConfig.carburetorValvePin = 2; + generatorConfig.carburetorValveReverse = false; + generatorConfig.powerOutputSensorPin = -1; + generatorConfig.usePowerOutputSensor = false; + + generator.initialize(&espmega.inputs, &espmega.outputs, generatorConfig); + + ESP_LOGI("OS", "Initialization Complete"); } void loop() { espmega.loop(); + generator.loop(); } diff --git a/src/main.hpp b/src/main.hpp index e661088..bab9281 100644 --- a/src/main.hpp +++ b/src/main.hpp @@ -1,6 +1,8 @@ #pragma once +#include "config.hpp" #include #include +#include "GasolineGenerator.hpp" #define INTERNAL_DISPLAY_UART Serial #define INTERNAL_DISPLAY_BAUDRATE 115200 \ No newline at end of file