|
2 | 2 |
|
3 | 3 | #include <GaggiMateController.h> |
4 | 4 |
|
5 | | -DimmedPump::DimmedPump(uint8_t ssr_pin, uint8_t sense_pin) |
6 | | - : _ssr_pin(ssr_pin), _sense_pin(sense_pin), _psm(_sense_pin, _ssr_pin, 100, FALLING, 1, 4) { |
| 5 | +DimmedPump::DimmedPump(uint8_t ssr_pin, uint8_t sense_pin, PressureSensor *pressure_sensor) |
| 6 | + : _ssr_pin(ssr_pin), _sense_pin(sense_pin), _psm(_sense_pin, _ssr_pin, 100, FALLING, 1, 4), _pressureSensor(pressure_sensor) { |
7 | 7 | _psm.set(0); |
| 8 | + _pressureGains.push_back(0.002f); |
| 9 | + _pressureGains.push_back(0.005f); |
| 10 | + _pressureGains.push_back(0.01f); |
| 11 | + _pressureGains.push_back(0.02f); |
| 12 | + _pressureGains.push_back(0.03f); |
| 13 | + _pressureGains.push_back(0.15f); |
| 14 | + _pressureGains.push_back(0.20f); |
| 15 | + _pressureGains.push_back(0.15f); |
| 16 | + _pressureGains.push_back(0.1f); |
| 17 | + _pressureGains.push_back(0.09f); |
| 18 | + _pressureGains.push_back(0.085f); |
| 19 | + _pressureGains.push_back(0.08f); |
| 20 | + _pressureGains.push_back(0.07f); |
8 | 21 | } |
9 | 22 |
|
10 | | -void DimmedPump::setup() { xTaskCreate(loopTask, "DimmedPump::loop", configMINIMAL_STACK_SIZE * 4, this, 1, &taskHandle); } |
| 23 | +void DimmedPump::setup() { |
| 24 | + _cps = _psm.cps(); |
| 25 | + if (_cps > 70) { |
| 26 | + _psm.setDivider(2); |
| 27 | + _cps = _psm.cps(); |
| 28 | + } |
| 29 | + xTaskCreate(loopTask, "DimmedPump::loop", configMINIMAL_STACK_SIZE * 4, this, 1, &taskHandle); |
| 30 | +} |
11 | 31 |
|
12 | | -void DimmedPump::loop() {} |
| 32 | +void DimmedPump::loop() { |
| 33 | + _currentPressure = _pressureSensor->getPressure(); |
| 34 | + updatePower(); |
| 35 | +} |
| 36 | + |
| 37 | +void DimmedPump::calibrate() { |
| 38 | + _pressureGains.clear(); |
| 39 | + _opvPressure = 0; |
| 40 | + float lastPressure = 0; |
| 41 | + float lastRoundedPressure = 0; |
| 42 | + _currentPressure = _pressureSensor->getPressure(); |
| 43 | + _psm.set(10); |
| 44 | + vTaskDelay(100); |
| 45 | + do { |
| 46 | + vTaskDelay(100); |
| 47 | + lastRoundedPressure = round(_currentPressure - 0.5); |
| 48 | + lastPressure = _currentPressure; |
| 49 | + _currentPressure = _pressureSensor->getPressure(); |
| 50 | + if (round(_currentPressure - 0.5) > lastRoundedPressure) { |
| 51 | + float gain = (_currentPressure - lastPressure) * 10.0f / (static_cast<float>(_cps) / 10.0f); |
| 52 | + ESP_LOGI("DimmedPump", "Gain: %.6f at %.6f bar", gain, round(_currentPressure - 0.5)); |
| 53 | + _pressureGains.push_back(gain); |
| 54 | + } |
| 55 | + } while (_currentPressure > lastPressure - 0.1 || _currentPressure < 4.0f); |
| 56 | + _opvPressure = _currentPressure; |
| 57 | + |
| 58 | + ESP_LOGI("DimmedPump", "Finished calibration"); |
| 59 | + ESP_LOGI("DimmedPump", "Power line frequency: %d", _cps); |
| 60 | + ESP_LOGI("DimmedPump", "OPV Pressure: %.2f", _opvPressure); |
| 61 | + ESP_LOGI("DimmedPump", "Gains:"); |
| 62 | + for (auto gain : _pressureGains) { |
| 63 | + ESP_LOGI("DimmedPump", " %.6f", gain); |
| 64 | + } |
| 65 | + _psm.set(0); |
| 66 | +} |
13 | 67 |
|
14 | 68 | void DimmedPump::setPower(float setpoint) { |
15 | 69 | ESP_LOGV(LOG_TAG, "Setting power to %2f", setpoint); |
16 | | - _power = setpoint; |
17 | | - _psm.set(static_cast<int>(setpoint)); |
| 70 | + _mode = ControlMode::POWER; |
| 71 | + _power = std::clamp(setpoint, 0.0f, 100.0f); |
| 72 | + _psm.set(static_cast<int>(_power)); |
18 | 73 | } |
19 | 74 |
|
20 | 75 | void DimmedPump::loopTask(void *arg) { |
21 | 76 | auto *pump = static_cast<DimmedPump *>(arg); |
22 | 77 | while (true) { |
23 | 78 | pump->loop(); |
24 | | - vTaskDelay(10 / portTICK_PERIOD_MS); |
| 79 | + vTaskDelay(50 / portTICK_PERIOD_MS); |
25 | 80 | } |
26 | 81 | } |
| 82 | + |
| 83 | +void DimmedPump::updatePower() { |
| 84 | + float newPower = _power; |
| 85 | + |
| 86 | + switch (_mode) { |
| 87 | + case ControlMode::PRESSURE: |
| 88 | + newPower = calculatePowerForPressure(_targetPressure, _currentPressure, _flowLimit); |
| 89 | + ESP_LOGI("DimmedPump", "Calculating power for pressure: %.2f", newPower); |
| 90 | + break; |
| 91 | + |
| 92 | + case ControlMode::FLOW: |
| 93 | + newPower = calculatePowerForFlow(_targetFlow, _currentPressure, _pressureLimit); |
| 94 | + break; |
| 95 | + |
| 96 | + case ControlMode::POWER: |
| 97 | + _psm.set(static_cast<int>(_power)); |
| 98 | + break; |
| 99 | + } |
| 100 | + |
| 101 | + if (newPower != _power && _mode != ControlMode::POWER) { |
| 102 | + newPower = std::clamp(newPower, 0.0f, 100.0f); |
| 103 | + _power = 0.8f * _power + 0.2f * newPower; |
| 104 | + _psm.set(static_cast<int>(_power)); |
| 105 | + } |
| 106 | +} |
| 107 | + |
| 108 | +float DimmedPump::calculateFlowRate(float pressure) const { |
| 109 | + float flow = BASE_FLOW_RATE; |
| 110 | + float pressurePercentage = pressure / MAX_PRESSURE; |
| 111 | + return flow * pressurePercentage; |
| 112 | +} |
| 113 | + |
| 114 | +float DimmedPump::calculatePowerForPressure(float targetPressure, float currentPressure, float flowLimit) { |
| 115 | + float error = targetPressure - currentPressure; |
| 116 | + float baseResponse = 0.0f; |
| 117 | + float pressureGain = _currentPressure - _lastPressure; |
| 118 | + float pressureLoss = _expectedPressureGain - pressureGain; |
| 119 | + float pressureLevel = std::clamp(round(_currentPressure), 0.0f, static_cast<float>(_pressureGains.size())); |
| 120 | + float pressureGainPerTick = _pressureGains[pressureLevel]; |
| 121 | + float maxPressureGain = pressureGainPerTick * static_cast<float>(_cps) / 20.0f; |
| 122 | + ESP_LOGI("DimmedPump", "Pressure: %.2f, Gain: %.6f, Expected Gain: %.6f, Pressure Loss: %.6f, Error: %.6f, Per Tick: %.6f", |
| 123 | + currentPressure, pressureGain, _expectedPressureGain, pressureLoss, error, pressureGainPerTick); |
| 124 | + if (error + pressureLoss > maxPressureGain) { |
| 125 | + baseResponse = 100.0f; |
| 126 | + } else if (error + pressureLoss > 0.0f) { |
| 127 | + float desiredGain = std::clamp(error + pressureLoss, 0.0f, maxPressureGain); |
| 128 | + float gainRatio = desiredGain / maxPressureGain; |
| 129 | + baseResponse = gainRatio * 100.0f; |
| 130 | + } |
| 131 | + _lastPressure = currentPressure; |
| 132 | + _expectedPressureGain = baseResponse * static_cast<float>(_cps) / 100.0f / 20.0f * pressureGainPerTick; |
| 133 | + |
| 134 | + if (flowLimit > 0.0f) { |
| 135 | + float maxFlowPower = calculatePowerForFlow(flowLimit, currentPressure, 100.0f); |
| 136 | + return std::min(baseResponse, maxFlowPower); |
| 137 | + } |
| 138 | + |
| 139 | + ESP_LOGI("DimmedPump", "Return: %f", baseResponse); |
| 140 | + return baseResponse; |
| 141 | +} |
| 142 | + |
| 143 | +float DimmedPump::calculatePowerForFlow(float targetFlow, float currentPressure, float pressureLimit) const { |
| 144 | + float maxFlow = calculateFlowRate(currentPressure) * _cps; |
| 145 | + float powerRatio = std::clamp(targetFlow / maxFlow, 0.0f, 1.0f); |
| 146 | + float basePower = powerRatio * 100.0f; |
| 147 | + |
| 148 | + if (pressureLimit > 0 && currentPressure > pressureLimit) { |
| 149 | + return 0.0f; |
| 150 | + } |
| 151 | + |
| 152 | + return basePower; |
| 153 | +} |
| 154 | + |
| 155 | +void DimmedPump::setFlowTarget(float targetFlow, float pressureLimit) { |
| 156 | + _mode = ControlMode::FLOW; |
| 157 | + _targetFlow = targetFlow; |
| 158 | + _pressureLimit = pressureLimit; |
| 159 | +} |
| 160 | + |
| 161 | +void DimmedPump::setPressureTarget(float targetPressure, float flowLimit) { |
| 162 | + _mode = ControlMode::PRESSURE; |
| 163 | + _targetPressure = targetPressure; |
| 164 | + _flowLimit = flowLimit; |
| 165 | +} |
0 commit comments