Limit changes per second

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.

Greetings

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.

1 Like

very nice, I´ll try

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.