3
0
Fork 0

Add GasolineGenerator class and configuration for generator management

- Implement GasolineGenerator class with methods for initialization, startup, shutdown, and state management.
- Introduce GasolineGeneratorConfig structure for configuration parameters.
- Update main.cpp to initialize and use the GasolineGenerator instance.
- Modify platformio.ini to include build flags for debugging and versioning.
This commit is contained in:
Siwat Sirichai 2025-06-08 22:05:04 +07:00
parent 7dbf37007a
commit 6ac762b1ec
6 changed files with 286 additions and 0 deletions

View file

@ -13,4 +13,5 @@ platform = espressif32
board = wt32-eth01 board = wt32-eth01
framework = arduino framework = arduino
lib_deps = siwats/ESPMegaPROR3@^2.9.5 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 monitor_speed = 115200

191
src/GasolineGenerator.cpp Normal file
View file

@ -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();
}
}
}

75
src/GasolineGenerator.hpp Normal file
View file

@ -0,0 +1,75 @@
#include <DigitalOutputCard.hpp>
#include <DigitalInputCard.hpp>
/**
* @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);
};

0
src/config.hpp Normal file
View file

View file

@ -2,6 +2,8 @@
ESPMegaPRO espmega = ESPMegaPRO(); ESPMegaPRO espmega = ESPMegaPRO();
GasolineGenerator generator;
void setup() void setup()
{ {
// Initialize both displayports // Initialize both displayports
@ -48,9 +50,24 @@ void setup()
ESP_LOGV("OS", "Registering Cards with IoT"); ESP_LOGV("OS", "Registering Cards with IoT");
espmega.iot->registerCard(0); espmega.iot->registerCard(0);
espmega.iot->registerCard(1); 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() void loop()
{ {
espmega.loop(); espmega.loop();
generator.loop();
} }

View file

@ -1,6 +1,8 @@
#pragma once #pragma once
#include "config.hpp"
#include <ESPMegaProOS.hpp> #include <ESPMegaProOS.hpp>
#include <ETH.h> #include <ETH.h>
#include "GasolineGenerator.hpp"
#define INTERNAL_DISPLAY_UART Serial #define INTERNAL_DISPLAY_UART Serial
#define INTERNAL_DISPLAY_BAUDRATE 115200 #define INTERNAL_DISPLAY_BAUDRATE 115200