Repository navigation
Expand file tree
/
Copy pathStateMachine.cpp
More file actions
140 lines (114 loc) · 4.61 KB
/
Copy pathStateMachine.cpp
File metadata and controls
140 lines (114 loc) · 4.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include "StateMachine.h"
// --- CONSTRUCTOR ---
StateMachine::StateMachine(Aether_HAL* halPtr, PID_Controller* pidPtr, MovingAverage* filterPtr) {
this->hal = halPtr;
this->pid = pidPtr;
this->filter = filterPtr;
// Initialize state
this->currentState = STATE_IDLE;
this->_debug_distance_adc = 0.0f;
this->_debug_pwm_duty = 0.0f;
}
// --- INITIALIZATION ---
void StateMachine::init() {
currentState = STATE_IDLE;
hal->setCoilPower(0.0f);
hal->setLed(false);
hal->setWarningLed(false);
thermalProtection.reset();
}
// --- MAIN LOOP (Called by ISR) ---
void StateMachine::update() {
// 1. HARDWARE READ & FILTERING
int raw = hal->readSensorRaw();
float filtered = filter->process((float)raw);
// 2. FEEDFORWARD COMPENSATION (Coil Noise Cancellation)
// The coil magnetic field affects the sensor reading. We must subtract/add
// this "self-sensing" noise to get the true position of the magnet.
// We use the PWM duty from the *previous* cycle as an estimate of current field strength.
float coil_noise_correction = _debug_pwm_duty * Config::Hardware::HALL_COIL_COUPLING;
// Corrected value: The "True" position of the angel
float current_val = filtered + coil_noise_correction;
// Update telemetry variable (for SerialManager)
_debug_distance_adc = current_val;
// 3. THERMAL PROTECTION
// Update the thermal model with current power usage
bool temp_safe = thermalProtection.update(_debug_pwm_duty);
float current_temp = thermalProtection.getTemperature();
// Visual Warning if temp is getting high
if (current_temp > Config::Control::Thermal::WARNING_TEMP_C) {
hal->setWarningLed(true);
} else {
hal->setWarningLed(false);
}
// Emergency Cut-off if temp is critical
if (!temp_safe && currentState != STATE_ERROR) {
currentState = STATE_ERROR;
}
// 4. STATE MACHINE LOGIC
switch (currentState) {
case STATE_IDLE:
// System is ready but coil is off
hal->setCoilPower(0.0f);
hal->setLed(false);
_debug_pwm_duty = 0.0f;
// Hand-over detection: If the angel is brought close to the target manually
// Condition: Current Value > (Target - Threshold)
if (current_val > (Config::Control::TARGET_ADC - Config::Control::IDLE_THRESHOLD)) {
pid->reset(); // Reset Integral term to avoid jumps
currentState = STATE_LEVITATING;
}
break;
case STATE_LEVITATING:
{
// Execute Control Loop
float output = pid->compute(Config::Control::TARGET_ADC, current_val);
// Actuate Hardware
hal->setCoilPower(output);
hal->setLed(true); // Status LED ON indicates active control
// Save output for next cycle (Feedforward) and Telemetry
_debug_pwm_duty = output;
// Safety Check: Is the angel still within controllable range?
if (isAngelInRange(current_val)) {
lastTimeInRange = millis();
}
// If angel is out of range for too long -> Safety Shutdown
if ((millis() - lastTimeInRange) > Config::Control::FALL_TIMEOUT_MS) {
currentState = STATE_ERROR;
}
}
break;
case STATE_ERROR:
// Safety Lockout State (Overheat or Drop)
hal->setCoilPower(0.0f);
_debug_pwm_duty = 0.0f;
// Blink LED to indicate error
if ((millis() / 200) % 2 == 0) hal->setLed(true); else hal->setLed(false);
// Auto-Reset Logic:
// If the magnet is removed (value drops significantly below target),
// reset to IDLE state to allow a new attempt.
if (current_val < (Config::Control::TARGET_ADC - 200)) {
currentState = STATE_IDLE;
}
break;
}
}
// --- HELPER METHODS ---
bool StateMachine::isAngelInRange(float raw_value) {
// Check if the value is within the physical safety bounds defined in JSON
if (raw_value > Config::Control::SAFETY_MIN_ADC &&
raw_value < Config::Control::SAFETY_MAX_ADC) {
return true;
}
return false;
}
// --- TELEMETRY GETTERS ---
float StateMachine::getRawDistance() const {
return _debug_distance_adc;
}
float StateMachine::getPWMDuty() const {
return _debug_pwm_duty;
}
float StateMachine::getTemperature() const {
return thermalProtection.getTemperature();
}