Hi, i´m searching for a node/function/controller which I can use to limit the rate of change per second.
I tried node-red-contrib-pid - but I can't deal with it.
The background is as follows: I have two grid storage systems.
One should regulate automatically (every second) as usually, and the other should be adjusted to the value of the other system. But without it should come to control oscillations - slowly, f.e. with 200W/s rate of change.
Do you mean that you have values coming in and you want the output of the node to have a limited rate of change? If so then this function may help.
// Limits the slew rate incoming payload values
// optionally sending intermediate values at specified rate
let maxRate = 2/60; // max slew rate units/minute
let sendIntermediates = false; // whether to send intermediate values
let period = 1000; // period in millisecs to send new values (if sendIntermediates)
let jumpThreshold = 0.25; // if the step asked for is more that this then goes immediately to that value
var newValue = Number(msg.payload);
var timer = context.get('timer') || 0;
// check the value is a number
if (!isNaN(newValue) && isFinite(newValue)) {
var target = msg.payload;
context.set('target', target);
// set last value to new one if first time through
var lastValue = context.get('lastValue');
if (typeof lastValue == "undefined" || lastValue === null) {
lastValue = newValue;
context.set('lastValue', newValue);
}
// calc new value
msg.payload = calcOutput();
// stop the timer
if (timer) {
clearTimeout(timer);
context.set('timer', null);
}
// restart it if required to send intermediate values
if (sendIntermediates) {
timer = setInterval(function(){
// the timer has run down calculate next value and send it
var newValue = calcOutput();
if (newValue != context.get('lastValueSent')) {
context.set('lastValueSent', newValue);
node.send({payload: newValue});
}
},period);
context.set('timer', timer);
}
context.set('lastValueSent', msg.payload);
} else {
// payload is not a number so ignore it
// also stop the timer as we don't know what to send any more
if (timer) {
clearTimeout(timer);
context.set('timer', null);
}
msg = null;
}
return msg;
// determines the required output value
function calcOutput() {
var lastValue = context.get('lastValue');
var target = context.get('target');
// set to current value if first time through or step > threshold
if (typeof lastValue == "undefined" || lastValue === null) lastValue = target;
var now = new Date();
var lastTime = context.get('lastTime') || now;
// limit value to last value +- rate * time
var maxDelta = (now.getTime() - lastTime.getTime()) * maxRate / (60 * 1000);
if (Math.abs(target - lastValue) > jumpThreshold) {
// step > threshold so go there imediately
newValue = target;
} else if (target > lastValue) {
newValue = Math.min( lastValue + maxDelta, target);
} else {
newValue = Math.max( lastValue - maxDelta, target);
}
context.set('lastValue', newValue);
context.set('lastTime', now);
return newValue;
}
Adjust the four values at the front of the function to the values that you want.