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?