xref: /openbmc/phosphor-pid-control/pid/stepwisecontroller.cpp (revision 608304da320f232b9adc591301581a5fa5949fff)
122c257abSJames Feist /*
222c257abSJames Feist // Copyright (c) 2018 Intel Corporation
322c257abSJames Feist //
422c257abSJames Feist // Licensed under the Apache License, Version 2.0 (the "License");
522c257abSJames Feist // you may not use this file except in compliance with the License.
622c257abSJames Feist // You may obtain a copy of the License at
722c257abSJames Feist //
822c257abSJames Feist //      http://www.apache.org/licenses/LICENSE-2.0
922c257abSJames Feist //
1022c257abSJames Feist // Unless required by applicable law or agreed to in writing, software
1122c257abSJames Feist // distributed under the License is distributed on an "AS IS" BASIS,
1222c257abSJames Feist // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1322c257abSJames Feist // See the License for the specific language governing permissions and
1422c257abSJames Feist // limitations under the License.
1522c257abSJames Feist */
1622c257abSJames Feist 
1722c257abSJames Feist #include "stepwisecontroller.hpp"
1822c257abSJames Feist 
1922c257abSJames Feist #include "ec/stepwise.hpp"
20734f9535SJames Feist #include "errors/exception.hpp"
2122c257abSJames Feist #include "util.hpp"
2222c257abSJames Feist #include "zone.hpp"
2322c257abSJames Feist 
2422c257abSJames Feist #include <algorithm>
2522c257abSJames Feist #include <chrono>
263dfaafdaSJames Feist #include <cmath>
2722c257abSJames Feist #include <iostream>
2822c257abSJames Feist #include <map>
2922c257abSJames Feist #include <memory>
3022c257abSJames Feist #include <thread>
3122c257abSJames Feist #include <vector>
3222c257abSJames Feist 
3322c257abSJames Feist void StepwiseController::process(void)
3422c257abSJames Feist {
3522c257abSJames Feist     // Get input value
365f59c0fdSPatrick Venture     double input = inputProc();
3722c257abSJames Feist 
383dfaafdaSJames Feist     ec::StepwiseInfo info = get_stepwise_info();
3922c257abSJames Feist 
405f59c0fdSPatrick Venture     double output = lastOutput;
413dfaafdaSJames Feist 
423dfaafdaSJames Feist     // Calculate new output if hysteresis allows
433dfaafdaSJames Feist     if (std::isnan(output))
443dfaafdaSJames Feist     {
453dfaafdaSJames Feist         output = ec::stepwise(info, input);
463dfaafdaSJames Feist         lastInput = input;
473dfaafdaSJames Feist     }
483dfaafdaSJames Feist     else if ((input - lastInput) > info.positiveHysteresis)
493dfaafdaSJames Feist     {
503dfaafdaSJames Feist         output = ec::stepwise(info, input);
513dfaafdaSJames Feist         lastInput = input;
523dfaafdaSJames Feist     }
533dfaafdaSJames Feist     else if ((lastInput - input) > info.negativeHysteresis)
543dfaafdaSJames Feist     {
553dfaafdaSJames Feist         output = ec::stepwise(info, input);
563dfaafdaSJames Feist         lastInput = input;
573dfaafdaSJames Feist     }
583dfaafdaSJames Feist 
593dfaafdaSJames Feist     lastOutput = output;
6022c257abSJames Feist     // Output new value
61563a356fSPatrick Venture     outputProc(output);
6222c257abSJames Feist 
6322c257abSJames Feist     return;
6422c257abSJames Feist }
6522c257abSJames Feist 
66563a356fSPatrick Venture std::unique_ptr<Controller> StepwiseController::createStepwiseController(
6722c257abSJames Feist     ZoneInterface* owner, const std::string& id,
6822c257abSJames Feist     const std::vector<std::string>& inputs, const ec::StepwiseInfo& initial)
6922c257abSJames Feist {
70734f9535SJames Feist     // StepwiseController requires at least 1 input
71734f9535SJames Feist     if (inputs.empty())
7222c257abSJames Feist     {
73734f9535SJames Feist         throw ControllerBuildException("Stepwise controller missing inputs");
7422c257abSJames Feist         return nullptr;
7522c257abSJames Feist     }
7622c257abSJames Feist 
7722c257abSJames Feist     auto thermal = std::make_unique<StepwiseController>(id, inputs, owner);
7822c257abSJames Feist 
7922c257abSJames Feist     ec::StepwiseInfo& info = thermal->get_stepwise_info();
8022c257abSJames Feist 
8122c257abSJames Feist     info = initial;
8222c257abSJames Feist 
8322c257abSJames Feist     return thermal;
8422c257abSJames Feist }
8522c257abSJames Feist 
865f59c0fdSPatrick Venture double StepwiseController::inputProc(void)
8722c257abSJames Feist {
88734f9535SJames Feist     double value = std::numeric_limits<double>::lowest();
89734f9535SJames Feist     for (const auto& in : _inputs)
90734f9535SJames Feist     {
91734f9535SJames Feist         value = std::max(value, _owner->getCachedValue(in));
92734f9535SJames Feist     }
935f59c0fdSPatrick Venture     return value;
9422c257abSJames Feist }
9522c257abSJames Feist 
965f59c0fdSPatrick Venture void StepwiseController::outputProc(double value)
9722c257abSJames Feist {
98*608304daSJames Feist     if (get_stepwise_info().isCeiling)
99*608304daSJames Feist     {
100*608304daSJames Feist         _owner->addRPMCeiling(value);
101*608304daSJames Feist     }
102*608304daSJames Feist     else
103*608304daSJames Feist     {
10422c257abSJames Feist         _owner->addRPMSetPoint(value);
105*608304daSJames Feist     }
10622c257abSJames Feist     return;
10722c257abSJames Feist }
108