Applying a setpoint curve

I'm writing because perhaps someone knows a better way of implementing setpoint curves based on a known value. Basically what I'm calculating there is the charging power for a battery on a SoC value based on certain conditions. In this case environmental, but I'd like to implement something more.

if (!msg.payload.hasOwnProperty("capacity"))
    msg.payload.capacity = global.get("settings.battery.capacity") || 0;

if (msg.payload.capacity == 0) {
    node.status({ fill: "red", shape: "dot", text: "Error!" });
    msg.payload.setpoint = 10000;
    return msg;
}

var c = Math.round(msg.payload.consumed_ah * -100) / 100;

const absminin = 0;
const absmaxin = msg.payload.capacity;

if (c < absminin) c = absminin;
if (c > absmaxin) c = absmaxin;

if (!msg.hasOwnProperty("battery_chargeCurve"))
    msg.battery_chargeCurve = global.get("settings.battery.chargeCurve") || 0;

// Consumed Ah to Charging Watts
const mappings = [
    [[[100, 80], [80, 30], [30, 10], [10, 0]], [[5825, 4500], [3000, 1000], [1000, 0], [0, 0]]], // Winter
    [[[100, 80], [80, 30], [30, 10], [10, 0]], [[4500, 3500], [3500, 500], [500, 0], [0, 0]]],  // Overcast / Raining
    [[[100, 80], [80, 30], [30, 10], [10, 0]], [[3500, 750], [750, 500], [500, 0], [0, 0]]],  // Spring / Autumm
    [[[100, 80], [80, 30], [30, 10], [10, 0]], [[2000, 500], [500, 300], [300, 0], [0, 0]]]   // Summer
];

// Different mapping on conditions, weather, season, etc...
const m = mappings[msg.battery_chargeCurve];

var minin = 0, maxin = 0, minout = 0, maxout = 0
for (let i = 0; i < m[0].length; i++) {
    if (i == 0 && c >= m[0][i][0]) {
        minin = m[0][i][0];
        maxin = m[0][i][0];
        minout = m[1][i][0];
        maxout = m[1][i][0];
        break;
    }
    else if (c < m[0][i][0] && c >= m[0][i][1]) {
        minin = m[0][i][0];
        maxin = m[0][i][1];
        minout = m[1][i][0];
        maxout = m[1][i][1];
        break;
    }
}

msg.payload.setpoint = Math.round(((c - minin) / (maxin - minin) * (maxout - minout)) + minout);

if (minin == 0 && maxin == 0 && minout == 0 && maxout == 0)
    node.status({ fill: "red", shape: "dot", text: 'c: ' + c + ', m: ' + m });
else
    node.status({ fill: "green", shape: "dot", text: 'c: ' + c + ', in: ' + minin + "-" + maxin + ', out: ' + minout + "-" + maxout + ", sp: " + msg.payload.setpoint });

//TODO: Add override based on current voltage and a parametrized max.
//TODO: Control charge limit based on season.

return msg;

Here I'm using a fixed set of curves and calculating intermediate points between two values. I'd better like to have only a set of points and not a pair, and get values as if those points where defining a bezier curve, but I don't know how to do it.
I would like to be able to edit those points ad define the curve in a x,y form.

Any suggestions? :blush:

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