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 return nullptr; 79 } 80 81 auto thermal = std::make_unique<StepwiseController>(id, inputs, owner); 82 thermal->setStepwiseInfo(initial); 83 84 return thermal; 85 } 86 87 double StepwiseController::inputProc(void) 88 { 89 double value = std::numeric_limits<double>::lowest(); 90 for (const auto& in : _inputs) 91 { 92 value = std::max(value, _owner->getCachedValue(in)); 93 } 94 95 if (debugEnabled) 96 { 97 std::cerr << getID() 98 << " choose the maximum temperature value: " << value << "\n"; 99 } 100 101 return value; 102 } 103 104 void StepwiseController::outputProc(double value) 105 { 106 if (getStepwiseInfo().isCeiling) 107 { 108 _owner->addRPMCeiling(value); 109 } 110 else 111 { 112 _owner->addSetPoint(value, _id); 113 if (debugEnabled) 114 { 115 std::cerr << getID() << " stepwise output pwm: " << value << "\n"; 116 } 117 } 118 return; 119 } 120 121 } // namespace pid_control 122