560 lines
24 KiB
C++
560 lines
24 KiB
C++
#include "Plunger.h"
|
|
#include <Arduino.h> // For millis(), delay()
|
|
|
|
void Plunger::_transitionToState(PlungerState newState)
|
|
{
|
|
if (_currentState == newState)
|
|
return; // No change, do nothing further.
|
|
|
|
Log.verboseln("[%s] State transition: %s -> %s", name.c_str(), _plungerStateToString(_currentState), _plungerStateToString(newState));
|
|
PlungerState oldState = _currentState;
|
|
|
|
// Specific exit logic for states
|
|
if (oldState == PlungerState::POST_FLOW) {
|
|
// Clean up if we are LEAVING post_flow, regardless of destination
|
|
_currentPostFlowState = PostFlowState::NONE;
|
|
_postFlowSubStateTimer.detach();
|
|
}
|
|
|
|
// Default timer resets, will be overridden by specific states if needed
|
|
// unsigned long newOperationStartTimeMs = 0; // Not needed here anymore
|
|
// unsigned long newCurrentMaxOperationTimeMs = 0; // Not needed here anymore
|
|
|
|
if (newState != PlungerState::JAMMED)
|
|
{
|
|
_jammedStartTimeMs = 0;
|
|
}
|
|
|
|
if (newState == PlungerState::IDLE ||
|
|
newState == PlungerState::STOPPING ||
|
|
newState == PlungerState::JAMMED ||
|
|
newState == PlungerState::RESETTING_JAM ||
|
|
newState == PlungerState::HOMING_AUTO || // Joystick hold reset for auto states too
|
|
newState == PlungerState::PLUNGING_AUTO)
|
|
{
|
|
_joystickHoldStartTimeMs = 0;
|
|
}
|
|
|
|
// Specific entry logic for states
|
|
if (newState == PlungerState::POST_FLOW) {
|
|
Log.infoln("[%s] Initiating POST_FLOW sequence.", name.c_str());
|
|
_vfdStop(); // Initial stop as per PostFlowState::POST_FLOW_STOPPING
|
|
_currentPostFlowState = PostFlowState::POST_FLOW_STOPPING;
|
|
_postFlowSubStateTimer.once_ms(_settings.postFlowStoppingWaitMs, &Plunger::_postFlowSubStateTimerRelay, this);
|
|
}
|
|
|
|
if (newState == PlungerState::IDLE || newState == PlungerState::STOPPING) // General cleanup for IDLE/STOPPING
|
|
{
|
|
_currentFillState = FillState::NONE;
|
|
_fillSubStateTimer.detach();
|
|
_currentPostFlowState = PostFlowState::NONE; // Also clean up post-flow sub-state if not already handled by exit logic
|
|
_postFlowSubStateTimer.detach();
|
|
}
|
|
|
|
// Specific state initializations for timers
|
|
if (newState == PlungerState::HOMING_MANUAL || newState == PlungerState::HOMING_AUTO ||
|
|
newState == PlungerState::PLUNGING_MANUAL || newState == PlungerState::PLUNGING_AUTO)
|
|
{
|
|
// These states might have their own max operation times from the moment they are entered.
|
|
// Or, if a general max time for these states is desired from entry:
|
|
// newOperationStartTimeMs = millis();
|
|
// newCurrentMaxOperationTimeMs = SOME_DEFAULT_MAX_FOR_THESE_STATES; // if applicable
|
|
}
|
|
|
|
_currentState = newState; // Set the new state now
|
|
_lastStateChangeTimeMs = millis(); // Set last state change time now
|
|
|
|
// Initialize/reset operation timers. They will be set specifically if the new state involves timed motor operation,
|
|
// or by the functions that start specific motor movements within a larger state (e.g., FILLING sub-states).
|
|
_operationStartTimeMs = 0;
|
|
_currentMaxOperationTimeMs = 0;
|
|
|
|
// Specific entry logic for states regarding operation timers
|
|
switch (newState)
|
|
{
|
|
case PlungerState::HOMING_MANUAL:
|
|
case PlungerState::HOMING_AUTO:
|
|
case PlungerState::PLUNGING_MANUAL:
|
|
case PlungerState::PLUNGING_AUTO:
|
|
_operationStartTimeMs = millis();
|
|
_currentMaxOperationTimeMs = _settings.defaultMaxOperationDurationMs; // Use from _settings
|
|
break;
|
|
|
|
case PlungerState::FILLING:
|
|
_fillOperationStartTimeMs = millis(); // For the overall fill operation.
|
|
// Moving sub-states (PLUNGING, HOMING) will set their own _operationStartTimeMs
|
|
// and _currentMaxOperationTimeMs for the generic timeout check.
|
|
break;
|
|
|
|
case PlungerState::POST_FLOW:
|
|
Log.infoln("[%s] Initiating POST_FLOW sequence.", name.c_str());
|
|
_vfdStop();
|
|
_currentPostFlowState = PostFlowState::POST_FLOW_STOPPING;
|
|
_postFlowSubStateTimer.once_ms(_settings.postFlowStoppingWaitMs, &Plunger::_postFlowSubStateTimerRelay, this);
|
|
// POST_FLOW_STARTING sub-state will set its own _operationStartTimeMs and _currentMaxOperationTimeMs.
|
|
break;
|
|
|
|
default:
|
|
// For states like IDLE, STOPPING, JAMMED, RESETTING_JAM, timers remain 0.
|
|
break;
|
|
}
|
|
|
|
if (newState == PlungerState::IDLE || newState == PlungerState::STOPPING) // General cleanup for IDLE/STOPPING
|
|
{
|
|
_currentFillState = FillState::NONE;
|
|
_fillSubStateTimer.detach();
|
|
_currentPostFlowState = PostFlowState::NONE; // Also clean up post-flow sub-state if not already handled by exit logic
|
|
_postFlowSubStateTimer.detach();
|
|
}
|
|
|
|
// Specific state initializations for timers were here, now handled in switch or state handlers
|
|
|
|
// Apply the determined timer values - ALREADY DONE IN SWITCH OR STATE HANDLERS
|
|
// _operationStartTimeMs = newOperationStartTimeMs;
|
|
// _currentMaxOperationTimeMs = newCurrentMaxOperationTimeMs;
|
|
|
|
if (newState == PlungerState::HOMING_AUTO || newState == PlungerState::PLUNGING_AUTO)
|
|
{
|
|
_joystickReleasedSinceAutoStart = false;
|
|
}
|
|
|
|
owner->onError(id, static_cast<short>(newState));
|
|
}
|
|
|
|
void Plunger::_handleIdleState()
|
|
{
|
|
Joystick::E_POSITION joyDir = static_cast<Joystick::E_POSITION>(_joystick->getValue());
|
|
if (joyDir == Joystick::E_POSITION::UP && _lastJoystickDirection != Joystick::E_POSITION::UP)
|
|
{
|
|
_joystickHoldStartTimeMs = millis();
|
|
_vfdStartReverse(static_cast<uint16_t>(_settings.speedSlowHz * 100.0f));
|
|
_transitionToState(PlungerState::HOMING_MANUAL);
|
|
}
|
|
else if (joyDir == Joystick::E_POSITION::DOWN && _lastJoystickDirection != Joystick::E_POSITION::DOWN)
|
|
{
|
|
_joystickHoldStartTimeMs = millis();
|
|
_vfdStartForward(static_cast<uint16_t>(_calculatedPlungingSpeedHz));
|
|
_transitionToState(PlungerState::PLUNGING_MANUAL);
|
|
}
|
|
else if (joyDir == Joystick::E_POSITION::LEFT && _lastJoystickDirection != Joystick::E_POSITION::LEFT)
|
|
{
|
|
if (_currentState == PlungerState::IDLE) {
|
|
_joystickHoldStartTimeMs = millis();
|
|
_joystickFillHoldTimer.once_ms(_settings.fillJoystickHoldDurationMs, &Plunger::_joystickFillHoldTimerRelay, this);
|
|
}
|
|
}
|
|
else if (_lastJoystickDirection == Joystick::E_POSITION::LEFT && joyDir != Joystick::E_POSITION::LEFT)
|
|
{
|
|
if (_joystickHoldStartTimeMs != 0) {
|
|
_joystickFillHoldTimer.detach();
|
|
_joystickHoldStartTimeMs = 0;
|
|
}
|
|
}
|
|
else if (joyDir == Joystick::E_POSITION::RIGHT && _lastJoystickDirection != Joystick::E_POSITION::RIGHT)
|
|
{
|
|
_joystickHoldStartTimeMs = millis();
|
|
_joystickRecordHoldTimer.once_ms(_settings.recordHoldDurationMs, &Plunger::_joystickRecordHoldTimerRelay, this);
|
|
}
|
|
else if (_lastJoystickDirection == Joystick::E_POSITION::RIGHT && joyDir != Joystick::E_POSITION::RIGHT)
|
|
{
|
|
_joystickRecordHoldTimer.detach();
|
|
unsigned long heldDuration = (_joystickHoldStartTimeMs > 0) ? (millis() - _joystickHoldStartTimeMs) : 0;
|
|
_joystickHoldStartTimeMs = 0;
|
|
if (heldDuration < _settings.recordHoldDurationMs && heldDuration > 50) {
|
|
if (_recordedPlungeDurationMs > 0) {
|
|
_transitionToState(PlungerState::REPLAY);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (_vfd->isRunning() && _joystickHoldStartTimeMs == 0 && joyDir == Joystick::E_POSITION::CENTER && _currentState == PlungerState::IDLE)
|
|
{
|
|
Log.warningln("[%s] IDLE: VFD unexpectedly running. Stopping.", name.c_str());
|
|
_vfdStop();
|
|
}
|
|
}
|
|
|
|
void Plunger::_handleHomingManualState()
|
|
{
|
|
Joystick::E_POSITION joyDir = static_cast<Joystick::E_POSITION>(_joystick->getValue());
|
|
unsigned long currentTimeMs = millis();
|
|
if (joyDir == Joystick::E_POSITION::UP)
|
|
{
|
|
if (_autoModeEnabled && _joystickHoldStartTimeMs > 0 && (currentTimeMs - _joystickHoldStartTimeMs > _settings.autoModeHoldDurationMs)) // Use from _settings
|
|
{
|
|
_transitionToState(PlungerState::HOMING_AUTO);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_transitionToState(PlungerState::STOPPING);
|
|
}
|
|
}
|
|
|
|
void Plunger::_handleHomingAutoState()
|
|
{
|
|
Joystick::E_POSITION joyDir = static_cast<Joystick::E_POSITION>(_joystick->getValue());
|
|
Joystick::E_POSITION initialDir = Joystick::E_POSITION::UP; // For homing
|
|
|
|
if (!_joystickReleasedSinceAutoStart)
|
|
{ // Phase 1: Joystick hasn't been centered yet since auto start
|
|
if (joyDir == initialDir)
|
|
{
|
|
// Still holding initial direction, all good.
|
|
}
|
|
else if (joyDir == Joystick::E_POSITION::CENTER)
|
|
{
|
|
_joystickReleasedSinceAutoStart = true; // First release to center, mark and continue.
|
|
}
|
|
else
|
|
{
|
|
_transitionToState(PlungerState::STOPPING);
|
|
}
|
|
}
|
|
else
|
|
{ // Phase 2: Joystick has been centered at least once
|
|
if (joyDir != Joystick::E_POSITION::CENTER)
|
|
{
|
|
// Joystick moved away from CENTER after being released there. This is the "change again". Abort.
|
|
_transitionToState(PlungerState::STOPPING);
|
|
}
|
|
// If joyDir is still CENTER, do nothing, continue auto mode.
|
|
}
|
|
}
|
|
|
|
void Plunger::_handlePlungingManualState()
|
|
{
|
|
Joystick::E_POSITION joyDir = static_cast<Joystick::E_POSITION>(_joystick->getValue());
|
|
unsigned long currentTimeMs = millis();
|
|
|
|
if (joyDir == Joystick::E_POSITION::DOWN)
|
|
{
|
|
if (_autoModeEnabled && _joystickHoldStartTimeMs > 0 && (currentTimeMs - _joystickHoldStartTimeMs > _settings.autoModeHoldDurationMs)) // Use from _settings
|
|
{
|
|
_transitionToState(PlungerState::PLUNGING_AUTO);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_transitionToState(PlungerState::STOPPING);
|
|
}
|
|
}
|
|
|
|
void Plunger::_handlePlungingAutoState()
|
|
{
|
|
Joystick::E_POSITION joyDir = static_cast<Joystick::E_POSITION>(_joystick->getValue());
|
|
Joystick::E_POSITION initialDir = Joystick::E_POSITION::DOWN; // For plunging
|
|
|
|
if (!_joystickReleasedSinceAutoStart)
|
|
{ // Phase 1: Joystick hasn't been centered yet since auto start
|
|
if (joyDir == initialDir)
|
|
{
|
|
// Still holding initial direction, all good.
|
|
}
|
|
else if (joyDir == Joystick::E_POSITION::CENTER)
|
|
{
|
|
_joystickReleasedSinceAutoStart = true; // First release to center, mark and continue.
|
|
}
|
|
else
|
|
{
|
|
// Moved from initial direction to something other than CENTER. Abort.
|
|
_transitionToState(PlungerState::STOPPING);
|
|
}
|
|
}
|
|
else
|
|
{ // Phase 2: Joystick has been centered at least once
|
|
if (joyDir != Joystick::E_POSITION::CENTER)
|
|
{
|
|
_transitionToState(PlungerState::STOPPING);
|
|
}
|
|
// If joyDir is still CENTER, do nothing, continue auto mode.
|
|
}
|
|
}
|
|
|
|
void Plunger::_handleStoppingState()
|
|
{
|
|
_vfdStop();
|
|
_joystickHoldStartTimeMs = 0;
|
|
_transitionToState(PlungerState::IDLE);
|
|
}
|
|
|
|
void Plunger::_handleJammedState()
|
|
{
|
|
_vfdResetJam();
|
|
_vfdStop();
|
|
_joystickHoldStartTimeMs = 0;
|
|
_transitionToState(PlungerState::RESETTING_JAM);
|
|
Joystick::E_POSITION joyDir = static_cast<Joystick::E_POSITION>(_joystick->getValue());
|
|
}
|
|
|
|
void Plunger::_handleResettingJamState()
|
|
{
|
|
Joystick::E_POSITION joyDir = static_cast<Joystick::E_POSITION>(_joystick->getValue());
|
|
if (joyDir == Joystick::E_POSITION::UP && _lastJoystickDirection != Joystick::E_POSITION::UP)
|
|
{
|
|
_vfdResetJam();
|
|
_joystickHoldStartTimeMs = millis();
|
|
_vfdStartReverse(static_cast<uint16_t>(_settings.speedSlowHz * 100.0f));
|
|
_transitionToState(PlungerState::HOMING_MANUAL);
|
|
}
|
|
else if (joyDir == Joystick::E_POSITION::CENTER)
|
|
{
|
|
// User is waiting or deciding, do nothing, VFD is stopped from _handleJammedState
|
|
}
|
|
else if (joyDir != Joystick::E_POSITION::UP && _lastJoystickDirection == Joystick::E_POSITION::CENTER)
|
|
{
|
|
// Joystick moved from CENTER to something other than UP (e.g., DOWN, LEFT, RIGHT)
|
|
// This is considered an intentional action to exit the JAMMED/RESETTING_JAM sequence without homing.
|
|
Log.infoln("[%s] Resetting Jam: Joystick moved from CENTER not to UP. Returning to IDLE. Manual VFD reset might be needed.", name.c_str());
|
|
_vfdResetJam(); // Attempt reset one last time just in case
|
|
_transitionToState(PlungerState::IDLE);
|
|
}
|
|
// If joystick remains UP, or moves from UP to CENTER then back to UP, it stays in HOMING_MANUAL (or transitions there)
|
|
// If joystick is moved from UP to CENTER and stays CENTER, HOMING_MANUAL will transition to STOPPING then IDLE.
|
|
}
|
|
|
|
void Plunger::_handleRecordState()
|
|
{
|
|
Joystick::E_POSITION joyDir = static_cast<Joystick::E_POSITION>(_joystick->getValue());
|
|
if (_recordModeStartTimeMs == 0) {
|
|
// Log.infoln("[%s] RECORD: Starting plunge.", name.c_str());
|
|
_vfdStartForward(static_cast<uint16_t>(_calculatedPlungingSpeedHz));
|
|
_recordModeStartTimeMs = millis(); // For calculating recorded duration
|
|
_operationStartTimeMs = millis(); // For generic timeout check
|
|
_currentMaxOperationTimeMs = _settings.maxRecordDurationMs; // Use from _settings
|
|
}
|
|
if (joyDir != Joystick::E_POSITION::RIGHT) {
|
|
_vfdStop();
|
|
_recordedPlungeDurationMs = millis() - _recordModeStartTimeMs;
|
|
Log.infoln("[%s] RECORD complete. Duration: %lu ms.", name.c_str(), _recordedPlungeDurationMs);
|
|
_recordModeStartTimeMs = 0;
|
|
_operationStartTimeMs = 0;
|
|
_currentMaxOperationTimeMs = 0;
|
|
_transitionToState(PlungerState::IDLE);
|
|
return;
|
|
}
|
|
}
|
|
|
|
void Plunger::_handleReplayState()
|
|
{
|
|
if (_operationStartTimeMs == 0) { // First entry or re-entry after interruption for some reason
|
|
if (_recordedPlungeDurationMs <= 50) { // Check for a minimal valid duration
|
|
Log.warningln("[%s] REPLAY: Invalid or zero replay duration (%lu ms). -> IDLE", name.c_str(), _recordedPlungeDurationMs);
|
|
_transitionToState(PlungerState::IDLE);
|
|
return;
|
|
}
|
|
Log.infoln("[%s] REPLAY: Plunging for %lu ms.", name.c_str(), _recordedPlungeDurationMs);
|
|
_vfdStartForward(static_cast<uint16_t>(_calculatedPlungingSpeedHz));
|
|
_operationStartTimeMs = millis(); // For generic timeout check
|
|
_currentMaxOperationTimeMs = _recordedPlungeDurationMs; // Specific timeout for replay
|
|
_replayPlungeTimer.once_ms(_recordedPlungeDurationMs, &Plunger::_replayPlungeTimerRelay, this);
|
|
}
|
|
Joystick::E_POSITION joyDir = static_cast<Joystick::E_POSITION>(_joystick->getValue());
|
|
if (joyDir != Joystick::E_POSITION::CENTER && _operationStartTimeMs != 0) {
|
|
Log.infoln("[%s] REPLAY: Interrupted by joystick.", name.c_str());
|
|
_vfdStop();
|
|
_replayPlungeTimer.detach();
|
|
_operationStartTimeMs = 0;
|
|
_transitionToState(PlungerState::STOPPING);
|
|
}
|
|
}
|
|
|
|
void Plunger::_handleFillingState()
|
|
{
|
|
Joystick::E_POSITION joyDir = static_cast<Joystick::E_POSITION>(_joystick->getValue());
|
|
// Log.verboseln("[%s] FILLING: JoyDir=%d, ReleasedSinceStart=%d, FillState=%s",
|
|
// name.c_str(), static_cast<int>(joyDir),
|
|
// _joystickReleasedSinceAutoStart,
|
|
// _fillStateToString(_currentFillState)); // DEBUG REMOVED
|
|
|
|
if (_currentState != PlungerState::FILLING) {
|
|
// Log.warningln("[%s] FILLING: Unexpected current state %s! -> IDLE", name.c_str(), _plungerStateToString(_currentState)); // DEBUG REMOVED (can be a regular warning if this case is problematic)
|
|
_currentFillState = FillState::NONE;
|
|
_fillSubStateTimer.detach();
|
|
_transitionToState(PlungerState::IDLE);
|
|
return;
|
|
}
|
|
|
|
if (!_joystickReleasedSinceAutoStart && joyDir == Joystick::E_POSITION::CENTER) {
|
|
// Log.infoln("[%s] FILLING: Joystick detected at CENTER. Setting ReleasedSinceAutoStart = true.", name.c_str()); // DEBUG REMOVED
|
|
_joystickReleasedSinceAutoStart = true;
|
|
}
|
|
|
|
if (_joystickReleasedSinceAutoStart && joyDir != Joystick::E_POSITION::CENTER) {
|
|
// Log.infoln("[%s] FILLING sequence: Interrupted by joystick (JoyDir=%d after release). Current FillState: %s -> STOPPING",
|
|
// name.c_str(), static_cast<int>(joyDir), _fillStateToString(_currentFillState)); // DEBUG REMOVED (original log was info, can be restored if needed)
|
|
_vfdStop();
|
|
_fillSubStateTimer.detach();
|
|
_currentFillState = FillState::NONE;
|
|
_transitionToState(PlungerState::STOPPING);
|
|
return;
|
|
}
|
|
// ... (placeholder for total fill operation timeout can remain commented)
|
|
}
|
|
|
|
// Static relay implementations for Ticker callbacks
|
|
void Plunger::_joystickRecordHoldTimerRelay(Plunger* pThis) {
|
|
if (pThis) {
|
|
pThis->_onJoystickRecordHoldTimeout();
|
|
}
|
|
}
|
|
|
|
void Plunger::_replayPlungeTimerRelay(Plunger* pThis) {
|
|
if (pThis) {
|
|
pThis->_onReplayPlungeTimeout();
|
|
}
|
|
}
|
|
|
|
void Plunger::_fillSubStateTimerRelay(Plunger* pThis) {
|
|
if (pThis) {
|
|
pThis->_onFillSubStateTimeout();
|
|
}
|
|
}
|
|
|
|
// Actual timer event handler implementations
|
|
void Plunger::_onJoystickRecordHoldTimeout() {
|
|
if (static_cast<Joystick::E_POSITION>(_joystick->getValue()) == Joystick::E_POSITION::RIGHT && _currentState == PlungerState::IDLE) {
|
|
Log.infoln("[%s] RECORD initiated from joystick.", name.c_str());
|
|
_transitionToState(PlungerState::RECORD);
|
|
}
|
|
_joystickHoldStartTimeMs = 0;
|
|
}
|
|
|
|
void Plunger::_onReplayPlungeTimeout() {
|
|
this->_vfdStop();
|
|
this->_operationStartTimeMs = 0;
|
|
|
|
if (_settings.enablePostFlow) {
|
|
Log.infoln("[%s] Replay plunge finished. Post-flow enabled. -> POST_FLOW", name.c_str());
|
|
this->_transitionToState(PlungerState::POST_FLOW);
|
|
} else {
|
|
Log.infoln("[%s] Replay plunge finished. Post-flow disabled. -> IDLE", name.c_str());
|
|
this->_transitionToState(PlungerState::IDLE);
|
|
}
|
|
}
|
|
|
|
void Plunger::_onFillSubStateTimeout() {
|
|
if (_currentState != PlungerState::FILLING) {
|
|
Log.warningln("[%s] Fill Sub-State Timeout: Not in FILLING state. Aborting timer logic.", name.c_str());
|
|
_fillSubStateTimer.detach();
|
|
_currentFillState = FillState::NONE;
|
|
return;
|
|
}
|
|
switch (_currentFillState) {
|
|
case FillState::PLUNGED:
|
|
// Log.infoln("[%s] Fill Sub-State: PLUNGED wait over. -> HOMING.", name.c_str());
|
|
_currentFillState = FillState::HOMING;
|
|
_vfdStartReverse(static_cast<uint16_t>(_settings.speedFillHomeHz * 100.0f));
|
|
_operationStartTimeMs = millis();
|
|
_currentMaxOperationTimeMs = _settings.defaultMaxOperationDurationMs;
|
|
break;
|
|
case FillState::HOMED:
|
|
Log.infoln("[%s] FILLING sequence complete.", name.c_str());
|
|
_currentFillState = FillState::NONE;
|
|
_transitionToState(PlungerState::IDLE);
|
|
break;
|
|
default:
|
|
Log.warningln("[%s] Fill Sub-State Timeout: Unhandled FillState: %s in PlungerState: %s. Aborting. -> IDLE",
|
|
name.c_str(), _fillStateToString(_currentFillState), _plungerStateToString(_currentState));
|
|
_fillSubStateTimer.detach();
|
|
_currentFillState = FillState::NONE;
|
|
_transitionToState(PlungerState::IDLE);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Ticker relay and handler for Fill joystick hold
|
|
void Plunger::_joystickFillHoldTimerRelay(Plunger* pThis) {
|
|
if (pThis) {
|
|
pThis->_onJoystickFillHoldTimeout();
|
|
}
|
|
}
|
|
|
|
void Plunger::_onJoystickFillHoldTimeout() {
|
|
if (static_cast<Joystick::E_POSITION>(_joystick->getValue()) == Joystick::E_POSITION::LEFT && _currentState == PlungerState::IDLE) {
|
|
Log.infoln("[%s] FILLING sequence initiated from joystick.", name.c_str());
|
|
// _fillOperationStartTimeMs is set in _transitionToState(FILLING)
|
|
_currentFillState = FillState::PLUNGING;
|
|
_vfdStartForward(static_cast<uint16_t>(_settings.speedFillPlungeHz * 100.0f));
|
|
_operationStartTimeMs = millis();
|
|
_currentMaxOperationTimeMs = _settings.defaultMaxOperationDurationMs;
|
|
_joystickReleasedSinceAutoStart = false;
|
|
_transitionToState(PlungerState::FILLING);
|
|
}
|
|
_joystickHoldStartTimeMs = 0;
|
|
}
|
|
|
|
void Plunger::_handlePostFlowState()
|
|
{
|
|
Joystick::E_POSITION joyDir = static_cast<Joystick::E_POSITION>(_joystick->getValue());
|
|
|
|
// Check for joystick interruption - applies to all post-flow sub-states
|
|
if (_joystickReleasedSinceAutoStart && joyDir != Joystick::E_POSITION::CENTER) {
|
|
Log.infoln("[%s] POST_FLOW sequence: Interrupted by joystick. -> STOPPING", name.c_str());
|
|
_currentPostFlowState = PostFlowState::NONE; // Ensure cleanup
|
|
_postFlowSubStateTimer.detach();
|
|
_transitionToState(PlungerState::STOPPING);
|
|
return;
|
|
}
|
|
// Further joystick interaction logic might be needed depending on if held-down joy needs to abort etc.
|
|
|
|
// Sub-state specific logic is primarily handled by the timer timeout (_onPostFlowSubStateTimeout)
|
|
// This loop handler can be used for continuous checks if any sub-state needs them (e.g., monitoring current outside of _checkVfdForJam)
|
|
// For now, most logic is event-driven by the timer.
|
|
}
|
|
|
|
void Plunger::_onPostFlowSubStateTimeout()
|
|
{
|
|
if (_currentState != PlungerState::POST_FLOW) {
|
|
Log.warningln("[%s] Post-Flow Sub-State Timeout: Not in POST_FLOW state (%s). Aborting timer logic.", name.c_str(), _plungerStateToString(_currentState));
|
|
_postFlowSubStateTimer.detach();
|
|
_currentPostFlowState = PostFlowState::NONE;
|
|
return;
|
|
}
|
|
|
|
Log.verboseln("[%s] Post-Flow sub-state timeout. Current sub-state: %d", name.c_str(), static_cast<int>(_currentPostFlowState));
|
|
|
|
switch (_currentPostFlowState)
|
|
{
|
|
case PostFlowState::POST_FLOW_STOPPING:
|
|
Log.infoln("[%s] Post-Flow: STOPPING wait complete. -> STARTING post-flow press.", name.c_str());
|
|
_currentPostFlowState = PostFlowState::POST_FLOW_STARTING;
|
|
_vfdStartForward(static_cast<uint16_t>(_settings.postFlowSpeedHz * 100.0f));
|
|
_postFlowStartTimeMs = millis();
|
|
_operationStartTimeMs = _postFlowStartTimeMs;
|
|
_currentMaxOperationTimeMs = _settings.postFlowDurationMs;
|
|
_postFlowSubStateTimer.once_ms(_settings.postFlowDurationMs, &Plunger::_postFlowSubStateTimerRelay, this);
|
|
break;
|
|
|
|
case PostFlowState::POST_FLOW_STARTING:
|
|
Log.infoln("[%s] Post-Flow: STARTING (pressing) complete. -> COMPLETE wait.", name.c_str());
|
|
_vfdStop();
|
|
_currentPostFlowState = PostFlowState::POST_FLOW_COMPLETE;
|
|
_postFlowSubStateTimer.once_ms(_settings.postFlowCompleteWaitMs, &Plunger::_postFlowSubStateTimerRelay, this);
|
|
break;
|
|
|
|
case PostFlowState::POST_FLOW_COMPLETE:
|
|
Log.infoln("[%s] Post-Flow: COMPLETE wait finished. Post-flow sequence fully complete. -> IDLE", name.c_str());
|
|
_currentPostFlowState = PostFlowState::NONE;
|
|
_transitionToState(PlungerState::IDLE);
|
|
break;
|
|
|
|
case PostFlowState::NONE:
|
|
default:
|
|
Log.warningln("[%s] Post-Flow Sub-State Timeout: Unhandled/NONE PostFlowState: %d. -> IDLE",
|
|
name.c_str(), static_cast<int>(_currentPostFlowState));
|
|
_postFlowSubStateTimer.detach();
|
|
_currentPostFlowState = PostFlowState::NONE;
|
|
_transitionToState(PlungerState::IDLE);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Static relay for post-flow sub-state timer
|
|
void Plunger::_postFlowSubStateTimerRelay(Plunger* pThis) {
|
|
if (pThis) {
|
|
pThis->_onPostFlowSubStateTimeout();
|
|
}
|
|
}
|
|
|