1 /* 2 // Copyright (c) 2018 Intel Corporation 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 */ 16 17 #include "stepwisecontroller.hpp" 18 19 #include "ec/stepwise.hpp" 20 #include "errors/exception.hpp" 21 #include "util.hpp" 22 #include "zone.hpp" 23 24 #include <algorithm> 25 #include <chrono> 26 #include <cmath> 27 #include <iostream> 28 #include <map> 29 #include <memory> 30 #include <thread> 31 #include <vector> 32 33 namespace pid_control 34 { 35 36 void StepwiseController::process(void) 37 { 38 // Get input value 39 double input = inputProc(); 40 41 ec::StepwiseInfo info = getStepwiseInfo(); 42 43 double output = lastOutput; 44 45 // Calculate new output if hysteresis allows 46 if (std::isnan(output)) 47 { 48 output = ec::stepwise(info, input); 49 lastInput = input; 50 } 51 else if ((input - lastInput) > info.positiveHysteresis) 52 { 53 output = ec::stepwise(info, input); 54 lastInput = input; 55 } 56 else if ((lastInput - input) > info.negativeHysteresis) 57 { 58 output = ec::stepwise(info, input); 59 lastInput = input; 60 } 61 62 lastOutput = output; 63 // Output new value 64 outputProc(output); 65 66 return; 67 } 68 69 std::unique_ptr<Controller> StepwiseController::createStepwiseController( 70 ZoneInterface* owner, const std::string& id, 71 const std::vector<std::string>& inputs, const ec::StepwiseInfo& initial) 72 { 73 // StepwiseController requires at least 1 input 74 if (inputs.empty()) 75 { 76 throw ControllerBuildException("Stepwise controller missing inputs"); 77 return nullptr; 78 } 79 80 auto thermal = std::make_unique<StepwiseController>(id, inputs, owner); 81 82 ec::StepwiseInfo& info = thermal->getStepwiseInfo(); 83 84 info = initial; 85 86 return thermal; 87 } 88 89 double StepwiseController::inputProc(void) 90 { 91 double value = std::numeric_limits<double>::lowest(); 92 for (const auto& in : _inputs) 93 { 94 value = std::max(value, _owner->getCachedValue(in)); 95 } 96 return value; 97 } 98 99 void StepwiseController::outputProc(double value) 100 { 101 if (getStepwiseInfo().isCeiling) 102 { 103 _owner->addRPMCeiling(value); 104 } 105 else 106 { 107 _owner->addSetPoint(value); 108 } 109 return; 110 } 111 112 } // namespace pid_control 113