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 "tuning.hpp" 22 #include "util.hpp" 23 #include "zone.hpp" 24 25 #include <algorithm> 26 #include <chrono> 27 #include <cmath> 28 #include <iostream> 29 #include <map> 30 #include <memory> 31 #include <thread> 32 #include <vector> 33 34 namespace pid_control 35 { 36 37 void StepwiseController::process(void) 38 { 39 // Get input value 40 double input = inputProc(); 41 42 ec::StepwiseInfo info = getStepwiseInfo(); 43 44 double output = lastOutput; 45 46 // Calculate new output if hysteresis allows 47 if (std::isnan(output)) 48 { 49 output = ec::stepwise(info, input); 50 lastInput = input; 51 } 52 else if ((input - lastInput) > info.positiveHysteresis) 53 { 54 output = ec::stepwise(info, input); 55 lastInput = input; 56 } 57 else if ((lastInput - input) > info.negativeHysteresis) 58 { 59 output = ec::stepwise(info, input); 60 lastInput = input; 61 } 62 63 lastOutput = output; 64 // Output new value 65 outputProc(output); 66 67 return; 68 } 69 70 std::unique_ptr<Controller> StepwiseController::createStepwiseController( 71 ZoneInterface* owner, const std::string& id, 72 const std::vector<std::string>& inputs, const ec::StepwiseInfo& initial) 73 { 74 // StepwiseController requires at least 1 input 75 if (inputs.empty()) 76 { 77 throw ControllerBuildException("Stepwise controller missing inputs"); 78 } 79 80 auto thermal = std::make_unique<StepwiseController>(id, inputs, owner); 81 thermal->setStepwiseInfo(initial); 82 83 return thermal; 84 } 85 86 double StepwiseController::inputProc(void) 87 { 88 double value = std::numeric_limits<double>::lowest(); 89 for (const auto& in : _inputs) 90 { 91 value = std::max(value, _owner->getCachedValue(in)); 92 } 93 94 if (debugEnabled) 95 { 96 std::cerr << getID() 97 << " choose the maximum temperature value: " << value << "\n"; 98 } 99 100 return value; 101 } 102 103 void StepwiseController::outputProc(double value) 104 { 105 if (getStepwiseInfo().isCeiling) 106 { 107 _owner->addRPMCeiling(value); 108 } 109 else 110 { 111 _owner->addSetPoint(value, _id); 112 if (debugEnabled) 113 { 114 std::cerr << getID() << " stepwise output pwm: " << value << "\n"; 115 } 116 } 117 return; 118 } 119 120 } // namespace pid_control 121