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 void StepwiseController::process(void) 34 { 35 // Get input value 36 double input = inputProc(); 37 38 ec::StepwiseInfo info = get_stepwise_info(); 39 40 double output = lastOutput; 41 42 // Calculate new output if hysteresis allows 43 if (std::isnan(output)) 44 { 45 output = ec::stepwise(info, input); 46 lastInput = input; 47 } 48 else if ((input - lastInput) > info.positiveHysteresis) 49 { 50 output = ec::stepwise(info, input); 51 lastInput = input; 52 } 53 else if ((lastInput - input) > info.negativeHysteresis) 54 { 55 output = ec::stepwise(info, input); 56 lastInput = input; 57 } 58 59 lastOutput = output; 60 // Output new value 61 outputProc(output); 62 63 return; 64 } 65 66 std::unique_ptr<Controller> StepwiseController::createStepwiseController( 67 ZoneInterface* owner, const std::string& id, 68 const std::vector<std::string>& inputs, const ec::StepwiseInfo& initial) 69 { 70 // StepwiseController requires at least 1 input 71 if (inputs.empty()) 72 { 73 throw ControllerBuildException("Stepwise controller missing inputs"); 74 return nullptr; 75 } 76 77 auto thermal = std::make_unique<StepwiseController>(id, inputs, owner); 78 79 ec::StepwiseInfo& info = thermal->get_stepwise_info(); 80 81 info = 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 return value; 94 } 95 96 void StepwiseController::outputProc(double value) 97 { 98 if (get_stepwise_info().isCeiling) 99 { 100 _owner->addRPMCeiling(value); 101 } 102 else 103 { 104 _owner->addSetPoint(value); 105 } 106 return; 107 } 108