xref: /openbmc/phosphor-pid-control/pid/stepwisecontroller.cpp (revision ccc8bb62de792567666e5e178b625c4fa4e76f32)
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 
33a076487aSPatrick Venture namespace pid_control
34a076487aSPatrick Venture {
35a076487aSPatrick Venture 
3622c257abSJames Feist void StepwiseController::process(void)
3722c257abSJames Feist {
3822c257abSJames Feist     // Get input value
395f59c0fdSPatrick Venture     double input = inputProc();
4022c257abSJames Feist 
41eb428204SPatrick Venture     ec::StepwiseInfo info = getStepwiseInfo();
4222c257abSJames Feist 
435f59c0fdSPatrick Venture     double output = lastOutput;
443dfaafdaSJames Feist 
453dfaafdaSJames Feist     // Calculate new output if hysteresis allows
463dfaafdaSJames Feist     if (std::isnan(output))
473dfaafdaSJames Feist     {
483dfaafdaSJames Feist         output = ec::stepwise(info, input);
493dfaafdaSJames Feist         lastInput = input;
503dfaafdaSJames Feist     }
513dfaafdaSJames Feist     else if ((input - lastInput) > info.positiveHysteresis)
523dfaafdaSJames Feist     {
533dfaafdaSJames Feist         output = ec::stepwise(info, input);
543dfaafdaSJames Feist         lastInput = input;
553dfaafdaSJames Feist     }
563dfaafdaSJames Feist     else if ((lastInput - input) > info.negativeHysteresis)
573dfaafdaSJames Feist     {
583dfaafdaSJames Feist         output = ec::stepwise(info, input);
593dfaafdaSJames Feist         lastInput = input;
603dfaafdaSJames Feist     }
613dfaafdaSJames Feist 
623dfaafdaSJames Feist     lastOutput = output;
6322c257abSJames Feist     // Output new value
64563a356fSPatrick Venture     outputProc(output);
6522c257abSJames Feist 
6622c257abSJames Feist     return;
6722c257abSJames Feist }
6822c257abSJames Feist 
69563a356fSPatrick Venture std::unique_ptr<Controller> StepwiseController::createStepwiseController(
7022c257abSJames Feist     ZoneInterface* owner, const std::string& id,
7122c257abSJames Feist     const std::vector<std::string>& inputs, const ec::StepwiseInfo& initial)
7222c257abSJames Feist {
73734f9535SJames Feist     // StepwiseController requires at least 1 input
74734f9535SJames Feist     if (inputs.empty())
7522c257abSJames Feist     {
76734f9535SJames Feist         throw ControllerBuildException("Stepwise controller missing inputs");
7722c257abSJames Feist         return nullptr;
7822c257abSJames Feist     }
7922c257abSJames Feist 
8022c257abSJames Feist     auto thermal = std::make_unique<StepwiseController>(id, inputs, owner);
81a5cf2086SPatrick Venture     thermal->setStepwiseInfo(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 {
98eb428204SPatrick Venture     if (getStepwiseInfo().isCeiling)
99608304daSJames Feist     {
100608304daSJames Feist         _owner->addRPMCeiling(value);
101608304daSJames Feist     }
102608304daSJames Feist     else
103608304daSJames Feist     {
104*ccc8bb62SNirav Shah         _owner->addSetPoint(value, _id);
105608304daSJames Feist     }
10622c257abSJames Feist     return;
10722c257abSJames Feist }
108a076487aSPatrick Venture 
109a076487aSPatrick Venture } // namespace pid_control
110