xref: /openbmc/phosphor-pid-control/pid/stepwisecontroller.cpp (revision c51ba919f6c6aab412574af0849db268609c4136)
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"
21*c51ba919SBonnie Lo #include "tuning.hpp"
2222c257abSJames Feist #include "util.hpp"
2322c257abSJames Feist #include "zone.hpp"
2422c257abSJames Feist 
2522c257abSJames Feist #include <algorithm>
2622c257abSJames Feist #include <chrono>
273dfaafdaSJames Feist #include <cmath>
2822c257abSJames Feist #include <iostream>
2922c257abSJames Feist #include <map>
3022c257abSJames Feist #include <memory>
3122c257abSJames Feist #include <thread>
3222c257abSJames Feist #include <vector>
3322c257abSJames Feist 
34a076487aSPatrick Venture namespace pid_control
35a076487aSPatrick Venture {
36a076487aSPatrick Venture 
3722c257abSJames Feist void StepwiseController::process(void)
3822c257abSJames Feist {
3922c257abSJames Feist     // Get input value
405f59c0fdSPatrick Venture     double input = inputProc();
4122c257abSJames Feist 
42eb428204SPatrick Venture     ec::StepwiseInfo info = getStepwiseInfo();
4322c257abSJames Feist 
445f59c0fdSPatrick Venture     double output = lastOutput;
453dfaafdaSJames Feist 
463dfaafdaSJames Feist     // Calculate new output if hysteresis allows
473dfaafdaSJames Feist     if (std::isnan(output))
483dfaafdaSJames Feist     {
493dfaafdaSJames Feist         output = ec::stepwise(info, input);
503dfaafdaSJames Feist         lastInput = input;
513dfaafdaSJames Feist     }
523dfaafdaSJames Feist     else if ((input - lastInput) > info.positiveHysteresis)
533dfaafdaSJames Feist     {
543dfaafdaSJames Feist         output = ec::stepwise(info, input);
553dfaafdaSJames Feist         lastInput = input;
563dfaafdaSJames Feist     }
573dfaafdaSJames Feist     else if ((lastInput - input) > info.negativeHysteresis)
583dfaafdaSJames Feist     {
593dfaafdaSJames Feist         output = ec::stepwise(info, input);
603dfaafdaSJames Feist         lastInput = input;
613dfaafdaSJames Feist     }
623dfaafdaSJames Feist 
633dfaafdaSJames Feist     lastOutput = output;
6422c257abSJames Feist     // Output new value
65563a356fSPatrick Venture     outputProc(output);
6622c257abSJames Feist 
6722c257abSJames Feist     return;
6822c257abSJames Feist }
6922c257abSJames Feist 
70563a356fSPatrick Venture std::unique_ptr<Controller> StepwiseController::createStepwiseController(
7122c257abSJames Feist     ZoneInterface* owner, const std::string& id,
7222c257abSJames Feist     const std::vector<std::string>& inputs, const ec::StepwiseInfo& initial)
7322c257abSJames Feist {
74734f9535SJames Feist     // StepwiseController requires at least 1 input
75734f9535SJames Feist     if (inputs.empty())
7622c257abSJames Feist     {
77734f9535SJames Feist         throw ControllerBuildException("Stepwise controller missing inputs");
7822c257abSJames Feist         return nullptr;
7922c257abSJames Feist     }
8022c257abSJames Feist 
8122c257abSJames Feist     auto thermal = std::make_unique<StepwiseController>(id, inputs, owner);
82a5cf2086SPatrick Venture     thermal->setStepwiseInfo(initial);
8322c257abSJames Feist 
8422c257abSJames Feist     return thermal;
8522c257abSJames Feist }
8622c257abSJames Feist 
875f59c0fdSPatrick Venture double StepwiseController::inputProc(void)
8822c257abSJames Feist {
89734f9535SJames Feist     double value = std::numeric_limits<double>::lowest();
90734f9535SJames Feist     for (const auto& in : _inputs)
91734f9535SJames Feist     {
92734f9535SJames Feist         value = std::max(value, _owner->getCachedValue(in));
93734f9535SJames Feist     }
94*c51ba919SBonnie Lo 
95*c51ba919SBonnie Lo     if (debugEnabled)
96*c51ba919SBonnie Lo     {
97*c51ba919SBonnie Lo         std::cerr << getID()
98*c51ba919SBonnie Lo                   << " choose the maximum temperature value: " << value << "\n";
99*c51ba919SBonnie Lo     }
100*c51ba919SBonnie Lo 
1015f59c0fdSPatrick Venture     return value;
10222c257abSJames Feist }
10322c257abSJames Feist 
1045f59c0fdSPatrick Venture void StepwiseController::outputProc(double value)
10522c257abSJames Feist {
106eb428204SPatrick Venture     if (getStepwiseInfo().isCeiling)
107608304daSJames Feist     {
108608304daSJames Feist         _owner->addRPMCeiling(value);
109608304daSJames Feist     }
110608304daSJames Feist     else
111608304daSJames Feist     {
112ccc8bb62SNirav Shah         _owner->addSetPoint(value, _id);
113*c51ba919SBonnie Lo         if (debugEnabled)
114*c51ba919SBonnie Lo         {
115*c51ba919SBonnie Lo             std::cerr << getID() << " stepwise output pwm: " << value << "\n";
116*c51ba919SBonnie Lo         }
117608304daSJames Feist     }
11822c257abSJames Feist     return;
11922c257abSJames Feist }
120a076487aSPatrick Venture 
121a076487aSPatrick Venture } // namespace pid_control
122