Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Soltaro Battery Handling Controller #1075

Merged
merged 37 commits into from
Mar 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
bdf4a95
fix calculation of capacity, adds a config field for module type
wgerbl Oct 18, 2019
8862866
changes type of control flag channels to boolean channels
wgerbl Oct 18, 2019
eb80598
remoce cell drift recogniton, adds error handling
wgerbl Oct 18, 2019
ca9ef3d
remove cluster version a, it's not used any longer
wgerbl Oct 23, 2019
3eb04a1
Merge branch 'develop' into feature/fix_soltaro
wgerbl Oct 23, 2019
c69f807
Merge branch 'develop' into feature/fix_soltaro
wgerbl Nov 6, 2019
fce1e28
removes callbacks, add reducing current if pole temperature gets too …
wgerbl Nov 6, 2019
71f8a3e
fix reset address
wgerbl Nov 8, 2019
86d8d55
bms cluster min cell voltage
wgerbl Nov 13, 2019
09bd917
Merge branch 'develop' into feature/fix_soltaro
wgerbl Nov 13, 2019
5ec4838
min cell for gridcon
wgerbl Nov 18, 2019
be9cb20
adds max cell voltage to cluster, formatting issues
wgerbl Nov 27, 2019
467a262
stops discharging in warning state
wgerbl Nov 27, 2019
e30c122
Merge branch 'develop' of https://github.com/OpenEMS/openems into dev…
wgerbl Nov 27, 2019
42603f7
Merge branch 'develop' into feature/limit_discharge_cell_voltage
wgerbl Nov 27, 2019
4afe8c3
Merge branch 'feature/fix_soltaro' into feature/limit_discharge_cell_…
wgerbl Nov 27, 2019
badc698
readjust DummyEss, checkstyle
wgerbl Nov 28, 2019
5d90aa0
Merge branch 'develop' into feature/limit_discharge_cell_voltage
sfeilmeier Dec 11, 2019
07a9726
started implementation changing to soltaro specification
wgerbl Dec 13, 2019
08f7530
Merge branch 'develop' of https://github.com/OpenEMS/openems into dev…
wgerbl Dec 13, 2019
0256c42
Merge branch 'feature/limit_discharge_cell_voltage' of https://github…
wgerbl Dec 13, 2019
48f0d07
no message
wgerbl Dec 20, 2019
e5c47d3
Merge branch 'develop' of https://github.com/OpenEMS/openems into dev…
wgerbl Jan 13, 2020
1e4c413
Merge branch 'develop' of https://github.com/OpenEMS/openems into dev…
wgerbl Jan 17, 2020
413145f
Merge branch 'develop' into feature/limit_discharge_cell_voltage
wgerbl Jan 17, 2020
7b20f44
removes the project for the limitdischarge cell voltage controller an…
wgerbl Jan 23, 2020
d51e607
corrects channel values for current
wgerbl Jan 23, 2020
f93117f
Merge branch 'develop' of https://github.com/OpenEMS/openems into dev…
wgerbl Jan 24, 2020
9eb42d4
Merge branch 'develop' into feature/soltaro_battery_handling_controller
wgerbl Jan 24, 2020
b49c3e8
modify pom
wgerbl Feb 3, 2020
fe08eed
finish impl
wgerbl Feb 3, 2020
0b44438
add channels for max cell voltage and max/min temperature
wgerbl Feb 3, 2020
6204f4f
format
wgerbl Mar 11, 2020
e7a22f4
Merge branch 'develop' into feature/soltaro_battery_handling_controller
wgerbl Mar 11, 2020
a4e9c70
Merge branch 'develop' into feature/soltaro_battery_handling_controller
sfeilmeier Mar 12, 2020
2e986ed
Reset non-related files to develop
sfeilmeier Mar 12, 2020
5d0f078
Code cleaning
sfeilmeier Mar 12, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions io.openems.edge.application/EdgeApp.bndrun
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
bnd.identity;id='io.openems.edge.controller.debug.log',\
bnd.identity;id='io.openems.edge.controller.ess.acisland',\
bnd.identity;id='io.openems.edge.controller.ess.delaycharge',\
bnd.identity;id='io.openems.edge.controller.ess.limitdischargecellvoltage',\
bnd.identity;id='io.openems.edge.controller.ess.limittotaldischarge',\
bnd.identity;id='io.openems.edge.controller.ess.onefullcycle',\
bnd.identity;id='io.openems.edge.controller.ess.predictivedelaycharge',\
Expand Down Expand Up @@ -146,7 +145,6 @@
io.openems.edge.controller.debug.log;version=snapshot,\
io.openems.edge.controller.ess.acisland;version=snapshot,\
io.openems.edge.controller.ess.delaycharge;version=snapshot,\
io.openems.edge.controller.ess.limitdischargecellvoltage;version=snapshot,\
io.openems.edge.controller.ess.limittotaldischarge;version=snapshot,\
io.openems.edge.controller.ess.onefullcycle;version=snapshot,\
io.openems.edge.controller.ess.predictivedelaycharge;version=snapshot,\
Expand Down Expand Up @@ -246,4 +244,4 @@
org.ops4j.pax.logging.pax-logging-service;version='[1.11.2,1.11.3)',\
org.osgi.service.event;version='[1.4.0,1.4.1)',\
org.osgi.service.metatype;version='[1.4.0,1.4.1)',\
rrd4j;version='[3.5.0,3.5.1)'
rrd4j;version='[3.5.0,3.5.1)'
5 changes: 4 additions & 1 deletion io.openems.edge.battery.soltaro/bnd.bnd
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@ Bundle-Version: 1.0.0.${tstamp}

-buildpath: \
${buildpath},\
com.google.gson,\
com.google.guava,\
io.openems.common,\
io.openems.edge.battery.api,\
io.openems.edge.bridge.modbus,\
io.openems.edge.common,\
io.openems.edge.controller.api,\
io.openems.edge.ess.api,\
slf4j.api

-testpath: \
${testpath}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
UNDEFINED: Undefined status is always reached when one of the values are undefined
NORMAL: If no limit is reached this is the normal state
LIMIT: If voltage or temperature limits are reached, charging or discharging will be denied
FORCE_CHARGE: If cell voltage is for a certain below a limit value, charging is forced
FULL_CHARGE: If battery is not charged or discharged for a certain time period a full charge has to be done
CHECK: If charging was forced, discharging is only allowed if SoC has increased
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<mxfile host="www.draw.io" modified="2020-01-24T07:59:58.218Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36" etag="_5l2mix5fm0cU8bwoYGL" version="12.5.5" type="device"><diagram id="wq3dryVzOJiqqxJbqPZI" name="Page-1">1Vtfd5owFP80PtZDEgjw2Kpde2bbrV3PtqcdjmbKDhoPxqn79AsSBEILOIXLnjSXm5Dc/O7fhB4ZLHYfQm81f+BTFvSwMd31yLCHMTKRI38iyj6m2IjEhFnoTxVTSnjx/zBFNBR140/ZOscoOA+Ev8oTJ3y5ZBORo3lhyLd5tp88yL915c1YgfAy8YIi9as/FfOY6mA7pd8xfzZP3oyoGz9ZeAmzWsl67k35NkMiox4ZhJyL+N9iN2BBJLxELnG/23eeHicWsqWo0+FHcPP52wxffR7uFn8m4+9PN6Z7lezGWuyTFbOpFIBq8lDM+YwvvWCUUm9CvllOWTSsIVspz5jzlSQiSfzFhNir3fQ2gkvSXCwC9VTOONx/U/0Pje9Ro28lzeEu+3C4V614rtEE35WBIq35JpywsoUrLHnhjIkSPvO4UxLijC+YnI/sF7LAE/7v/Dw8hbXZkU91vQ5Db59hWHF/KdaZkT9FBMmQqI2rMKOUxqTa1lbwE8PK8ss/8QySVmYpKekAlxOgcxQ1EHT6mNpZ+KAK8Bxan1joy4WzEA5R6BKIKkIA5SFAk3YyRDwv1SvFxsnQpPn3WBXQdHEZezPIVML77QUbJc7Xx+Ho9v5xNCxCNgikK4mguZ37gr2svMMmb6U3ywNPjclCwXblWCnurepA39ZqY5s6FpR4i3nGqTjaVmbRkJHk6YJygDWYSHRkNPjK6Bu4ygc0rca4TTU+VftsDUGW07w2EQMYJbaVixL+E3zQDuADldtmG5WxNxQ1FGzz7dPzYPRjcHf9/GEEap41adjQ1tmF0LsLagppyZKeJWREQa1b5PJQLow1+lQmZbA2ru7OWRA2TjdyrtuC1cKgKEGnOEAAHJBL4KCw0cTMbzQ2m0lpjhY8cYN2udsk1nn82MDl/Pq6T+avmA+mZ/Ln5tOQxlnd0biqygKAxmEQy0s04DsVZSmEy/gbAg5I2PRORbN7wAGpZ+ouG7cBBCWRTKYxvn+4/1JER4sphp5jHAu3YEkGgq7iulp63yfE+Zfwl+18EY9oqdbRdMv/6UhRowH9M2vqH0jZyNTrRhURC7LtMv6GqrawHt/o2/lqpIQmeCJWF1UgiZjpWnmrTspRVcHfUDhgdyeObPWAsy50LpK7nWuQWoGCWQgIHp+eH67HoBGBqUUEtcuOdmMRAWy9H05jrC67cMfQql7ltlZnt4w2Im7YKpkEi+Vk0XM4T3SBXXhdVJ2bmJ2l81bBNN6+jsddOJQxC0CuZx6bS5i6VAruExv6vJx22WpSrbRrum0kMiawGXQNJ48S2/mnlBoAJSCJDNUu5iB1K7LZxKRDYVaLBe66QLjI9YnijQdtp0lDR0r6e3DFLbnCvPS7vDo/xmX8DYV30KVC6pCcXftPbBrIWY3u+SoApV3TbANOtBBzDu5Gg4+g0SbFmtRM8HAT5I7mBbUEt6Ql50kZ5tDwzSOL4ynFm0cWGXOoBXkGha5W1011YarVuoutKlbTEvaGQkLYxKH7tWqQw2tLr9Ba5cix9Os+J/Kf+fGObKbflMXs6Zd5ZPQX</diagram></mxfile>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package io.openems.edge.battery.soltaro.single.versiona;
package io.openems.edge.battery.soltaro;

import io.openems.common.types.OptionsEnum;

public enum ChargeIndication implements OptionsEnum {
UNDEFINED(-1, "Undefined"), //
STANDING(0, "Standing"), //
/**
* 1 = Discharging
*/
DISCHARGING(1, "Discharging"), //
CHARGING(2, "Charging");

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package io.openems.edge.battery.soltaro;

import java.time.ZoneOffset;

import io.openems.common.types.OpenemsType;
import io.openems.edge.battery.api.Battery;
import io.openems.edge.common.channel.Channel;
import io.openems.edge.common.channel.Doc;

public interface SoltaroBattery extends Battery {

public static final ZoneOffset ZONE_OFFSET = ZoneOffset.UTC;
public static final long NANOS = 0;

public enum ChannelId implements io.openems.edge.common.channel.ChannelId {

CHARGE_INDICATION(Doc.of(ChargeIndication.values())), //
NOT_ACTIVE_SINCE(Doc.of(OpenemsType.LONG))//
;

private final Doc doc;

private ChannelId(Doc doc) {
this.doc = doc;
}

@Override
public Doc doc() {
return this.doc;
}
}
default Channel<ChargeIndication> getChargeIndication() {
return this.channel(ChannelId.CHARGE_INDICATION);
}

default Channel<Long> getNotActiveSince() {
return this.channel(ChannelId.NOT_ACTIVE_SINCE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import io.openems.edge.battery.soltaro.BatteryState;
import io.openems.edge.battery.soltaro.ModuleParameters;
import io.openems.edge.battery.soltaro.ResetState;
import io.openems.edge.battery.soltaro.SoltaroBattery;
import io.openems.edge.battery.soltaro.State;
import io.openems.edge.battery.soltaro.cluster.versionb.Enums.ContactorControl;
import io.openems.edge.battery.soltaro.cluster.versionb.Enums.RackUsage;
Expand Down Expand Up @@ -458,7 +459,7 @@ public void setStateMachineState(State state) {
protected ModbusProtocol defineModbusProtocol() {
ModbusProtocol protocol = new ModbusProtocol(this, new Task[] {
// -------- control registers of master --------------------------------------
new FC16WriteRegistersTask(0x1017, //
new FC16WriteRegistersTask(0x1004, //
m(ClusterChannelId.RESET, new UnsignedWordElement(0x1004)) //
), //

Expand Down Expand Up @@ -542,7 +543,7 @@ protected ModbusProtocol defineModbusProtocol() {

// -------- state registers of master --------------------------------------
new FC3ReadRegistersTask(0x1044, Priority.LOW, //
m(ClusterChannelId.CHARGE_INDICATION, new UnsignedWordElement(0x1044)), //
m(SoltaroBattery.ChannelId.CHARGE_INDICATION, new UnsignedWordElement(0x1044)), //
m(ClusterChannelId.SYSTEM_CURRENT, new UnsignedWordElement(0x1045), //
ElementToChannelConverter.SCALE_FACTOR_2), // TODO Check if scale factor is correct
new DummyRegisterElement(0x1046), //
Expand Down Expand Up @@ -662,20 +663,41 @@ protected void recalculateSoc() {

this.channel(Battery.ChannelId.SOC).setNextValue(soc);
}

protected void recalculateMaxCellVoltage() {
int max = Integer.MIN_VALUE;

for (SingleRack rack : this.racks.values()) {
max = Math.max(max, rack.getMaximalCellVoltage());
}
this.channel(Battery.ChannelId.MAX_CELL_VOLTAGE).setNextValue(max);
}

protected void recalculateMinCellVoltage() {

int minCellVoltage = Integer.MAX_VALUE;
int min = Integer.MAX_VALUE;

for (SingleRack rack : this.racks.values()) {
int mcv = rack.getMinimalCellVoltage();
if (mcv > 0) {
minCellVoltage = Math.min(minCellVoltage, mcv);
}
min = Math.min(min, rack.getMinimalCellVoltage());
}
this.channel(Battery.ChannelId.MIN_CELL_VOLTAGE).setNextValue(min);
}

protected void recalculateMaxCellTemperature() {
int max = Integer.MIN_VALUE;

for (SingleRack rack : this.racks.values()) {
max = Math.max(max, rack.getMaximalCellTemperature());
}
this.channel(Battery.ChannelId.MAX_CELL_TEMPERATURE).setNextValue(max);
}

protected void recalculateMinCellTemperature() {
int min = Integer.MAX_VALUE;

this.channel(Battery.ChannelId.MIN_CELL_VOLTAGE).setNextValue(minCellVoltage);
for (SingleRack rack : this.racks.values()) {
min = Math.min(min, rack.getMinimalCellTemperature());
}
this.channel(Battery.ChannelId.MIN_CELL_TEMPERATURE).setNextValue(min);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public enum ClusterChannelId implements io.openems.edge.common.channel.ChannelId
// EnumReadChannels
STATE_MACHINE(Doc.of(State.values()) //
.text("Current State of State-Machine")), //
CHARGE_INDICATION(Doc.of(Enums.ChargeIndication.values())), //
// CHARGE_INDICATION(Doc.of(ChargeIndication.values())), //
SYSTEM_RUNNING_STATE(Doc.of(Enums.RunningState.values())), //

// EnumWriteChannels
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,36 +62,6 @@ public OptionsEnum getUndefined() {
}
}

public enum ChargeIndication implements OptionsEnum {
UNDEFINED(-1, "Undefined"), //
STANDING(0, "Standby"), //
DISCHARGING(1, "Discharging"), //
CHARGING(2, "Charging");

private int value;
private String name;

private ChargeIndication(int value, String name) {
this.value = value;
this.name = name;
}

@Override
public int getValue() {
return value;
}

@Override
public String getName() {
return name;
}

@Override
public OptionsEnum getUndefined() {
return UNDEFINED;
}
}

public enum RunningState implements OptionsEnum {
UNDEFINED(-1, "Undefined"), //
NORMAL(0, "Normal"), // Allow discharge and charge
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import io.openems.common.channel.Unit;
import io.openems.common.types.OpenemsType;
import io.openems.edge.battery.soltaro.ChannelIdImpl;
import io.openems.edge.battery.soltaro.ChargeIndication;
import io.openems.edge.bridge.modbus.api.AbstractOpenemsModbusComponent;
import io.openems.edge.bridge.modbus.api.ElementToChannelConverter;
import io.openems.edge.bridge.modbus.api.element.AbstractModbusElement;
Expand Down Expand Up @@ -129,24 +130,34 @@ public Channel<?> getChannel(String key) {
}

public int getSoC() {
@SuppressWarnings("unchecked")
Optional<Integer> socOpt = (Optional<Integer>) this.channelMap.get(KEY_SOC).value().asOptional();
int soc = 0;
if (socOpt.isPresent()) {
soc = socOpt.get();
}
return soc;
return getIntFromChannel(KEY_SOC, 0);
}

public int getMinimalCellVoltage() {
return getIntFromChannel(KEY_MIN_CELL_VOLTAGE, -1);
}

public int getMaximalCellVoltage() {
return getIntFromChannel(KEY_MAX_CELL_VOLTAGE, -1);
}

public int getMinimalCellTemperature() {
return getIntFromChannel(KEY_MIN_CELL_TEMPERATURE, -1);
}

public int getMaximalCellTemperature() {
return getIntFromChannel(KEY_MAX_CELL_TEMPERATURE, -1);
}

private int getIntFromChannel(String key, int defaultValue) {
@SuppressWarnings("unchecked")
Optional<Integer> minCellOpt = (Optional<Integer>) this.channelMap.get(KEY_MIN_CELL_VOLTAGE).value()
Optional<Integer> opt = (Optional<Integer>) this.channelMap.get(key).value()
.asOptional();
int minCellVoltage = -1;
if (minCellOpt.isPresent()) {
minCellVoltage = minCellOpt.get();
int value = defaultValue;
if (opt.isPresent()) {
value = opt.get();
}
return minCellVoltage;
return value;
}

private Map<String, Channel<?>> createChannelMap() {
Expand Down Expand Up @@ -265,7 +276,7 @@ private Map<String, ChannelId> createChannelIdMap() {
this.addEntry(map, KEY_VOLTAGE, new IntegerDoc().unit(Unit.MILLIVOLT));
this.addEntry(map, KEY_CURRENT, new IntegerDoc().unit(Unit.MILLIAMPERE));

this.addEntry(map, KEY_CHARGE_INDICATION, Doc.of(Enums.ChargeIndication.values()));
this.addEntry(map, KEY_CHARGE_INDICATION, Doc.of(ChargeIndication.values()));
this.addEntry(map, KEY_SOC, new IntegerDoc().unit(Unit.PERCENT));
this.addEntry(map, KEY_SOH, new IntegerDoc().unit(Unit.PERCENT));
this.addEntry(map, KEY_MAX_CELL_VOLTAGE_ID, new IntegerDoc().unit(Unit.NONE));
Expand Down Expand Up @@ -402,25 +413,34 @@ public Collection<Task> getTasks() {

// State values
tasks.add(new FC3ReadRegistersTask(this.addressOffset + 0x100, Priority.HIGH, //
parent.map(channelIds.get(KEY_VOLTAGE), getUWE(0x100), ElementToChannelConverter.SCALE_FACTOR_MINUS_1), //
parent.map(channelIds.get(KEY_CURRENT), getUWE(0x101), ElementToChannelConverter.SCALE_FACTOR_MINUS_1), //
parent.map(channelIds.get(KEY_VOLTAGE), getUWE(0x100), ElementToChannelConverter.SCALE_FACTOR_2), //
parent.map(channelIds.get(KEY_CURRENT), getSWE(0x101), ElementToChannelConverter.SCALE_FACTOR_2), //
parent.map(channelIds.get(KEY_CHARGE_INDICATION), getUWE(0x102)), //
parent.map(channelIds.get(KEY_SOC), getUWE(0x103)). //
onUpdateCallback(val -> {
parent.recalculateSoc();
}), //
onUpdateCallback(val -> {
parent.recalculateSoc();
}), //
parent.map(channelIds.get(KEY_SOH), getUWE(0x104)), //
parent.map(channelIds.get(KEY_MAX_CELL_VOLTAGE_ID), getUWE(0x105)), //
parent.map(channelIds.get(KEY_MAX_CELL_VOLTAGE), getUWE(0x106)), //
parent.map(channelIds.get(KEY_MAX_CELL_VOLTAGE), getUWE(0x106)). //
onUpdateCallback(val -> {
parent.recalculateMaxCellVoltage();
}), //
parent.map(channelIds.get(KEY_MIN_CELL_VOLTAGE_ID), getUWE(0x107)), //
parent.map(channelIds.get(KEY_MIN_CELL_VOLTAGE), getUWE(0x108)). //
onUpdateCallback(val -> {
parent.recalculateMinCellVoltage();
}), //
onUpdateCallback(val -> {
parent.recalculateMinCellVoltage();
}), //
parent.map(channelIds.get(KEY_MAX_CELL_TEMPERATURE_ID), getUWE(0x109)), //
parent.map(channelIds.get(KEY_MAX_CELL_TEMPERATURE), getUWE(0x10A)), //
parent.map(channelIds.get(KEY_MAX_CELL_TEMPERATURE), getUWE(0x10A), ElementToChannelConverter.SCALE_FACTOR_MINUS_1). //
onUpdateCallback(val -> {
parent.recalculateMaxCellTemperature();
}), //
parent.map(channelIds.get(KEY_MIN_CELL_TEMPERATURE_ID), getUWE(0x10B)), //
parent.map(channelIds.get(KEY_MIN_CELL_TEMPERATURE), getUWE(0x10C)) //
parent.map(channelIds.get(KEY_MIN_CELL_TEMPERATURE), getUWE(0x10C), ElementToChannelConverter.SCALE_FACTOR_MINUS_1). //
onUpdateCallback(val -> {
parent.recalculateMinCellTemperature();
}) //
));

// Alarm levels
Expand Down
Loading