mirror of https://github.com/arendst/Tasmota.git
95 lines
2.9 KiB
C++
95 lines
2.9 KiB
C++
|
/**
|
||
|
* Copyright 2018 Colin Law
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*
|
||
|
* See Timeprop.h for Usage
|
||
|
*
|
||
|
**/
|
||
|
|
||
|
|
||
|
#include "Timeprop.h"
|
||
|
|
||
|
void Timeprop::initialise( int cycleTime, int deadTime, unsigned char invert, float fallbackPower, int maxUpdateInterval,
|
||
|
unsigned long nowSecs) {
|
||
|
m_cycleTime = cycleTime;
|
||
|
m_deadTime = deadTime;
|
||
|
m_invert = invert;
|
||
|
m_fallbackPower = fallbackPower;
|
||
|
m_maxUpdateInterval = maxUpdateInterval;
|
||
|
|
||
|
m_dtoc = (float)deadTime/cycleTime;
|
||
|
m_opState = 0;
|
||
|
setPower(m_fallbackPower, nowSecs);
|
||
|
}
|
||
|
|
||
|
/* set current power required 0:1, given power and current time in seconds */
|
||
|
void Timeprop::setPower( float power, unsigned long nowSecs ) {
|
||
|
if (power < 0.0) {
|
||
|
power = 0.0;
|
||
|
} else if (power >= 1.0) {
|
||
|
power = 1.0;
|
||
|
}
|
||
|
m_power = power;
|
||
|
m_lastPowerUpdateTime = nowSecs;
|
||
|
};
|
||
|
|
||
|
/* called regularly to provide new output value */
|
||
|
/* returns new o/p state 0, 1 */
|
||
|
int Timeprop::tick( unsigned long nowSecs) {
|
||
|
int newState;
|
||
|
float wave;
|
||
|
float direction;
|
||
|
float effectivePower;
|
||
|
|
||
|
// check whether too long has elapsed since power was last updated
|
||
|
if (m_maxUpdateInterval > 0 && nowSecs - m_lastPowerUpdateTime > m_maxUpdateInterval) {
|
||
|
// yes, go to fallback power
|
||
|
setPower(m_fallbackPower, nowSecs);
|
||
|
}
|
||
|
|
||
|
wave = (nowSecs % m_cycleTime)/(float)m_cycleTime;
|
||
|
// determine direction of travel and convert to triangular wave
|
||
|
if (wave < 0.5) {
|
||
|
direction = 1; // on the way up
|
||
|
wave = wave*2;
|
||
|
} else {
|
||
|
direction = -1; // on the way down
|
||
|
wave = (1 - wave)*2;
|
||
|
}
|
||
|
// if a dead_time has been supplied for this o/p then adjust power accordingly
|
||
|
if (m_deadTime > 0 && m_power > 0.0 && m_power < 1.0) {
|
||
|
effectivePower = (1.0-2.0*m_dtoc)*m_power + m_dtoc;
|
||
|
} else {
|
||
|
effectivePower = m_power;
|
||
|
}
|
||
|
// cope with end cases in case values outside 0..1
|
||
|
if (effectivePower <= 0.0) {
|
||
|
newState = 0; // no heat
|
||
|
} else if (effectivePower >= 1.0) {
|
||
|
newState = 1; // full heat
|
||
|
} else {
|
||
|
// only allow power to come on on the way down and off on the way up, to reduce short pulses
|
||
|
if (effectivePower >= wave && direction == -1) {
|
||
|
newState = 1;
|
||
|
} else if (effectivePower <= wave && direction == 1) {
|
||
|
newState = 0;
|
||
|
} else {
|
||
|
// otherwise leave it as it is
|
||
|
newState = m_opState;
|
||
|
}
|
||
|
}
|
||
|
m_opState = newState;
|
||
|
return m_invert ? (1-m_opState) : m_opState;
|
||
|
}
|