frequenz-floss / frequenz-api-microgrid

gRPC+protobuf specification and Python bindings for the Frequenz Microgrid API
https://frequenz-floss.github.io/frequenz-api-microgrid/
MIT License
6 stars 6 forks source link

Allow Specifying DC Energy Source for Hybrid Inverters #258

Open tiyash-basu-frequenz opened 1 week ago

tiyash-basu-frequenz commented 1 week ago

What's needed?

So far, the RPC SetComponentPowerActive only allows setting the total active power of a component without differentiating between the sources (PV arrays and batteries) when dealing with hybrid inverters.

This limitation primarily affects scenarios where more granular control is required, especially during discharging operations, as clients may need to specify whether the energy is drawn from the battery or the PV arrays.

We need a way to specify the DC energy source when issuing discharge commands.

We do not need to specify the DC component for

Proposed solution

Proposal 1

This approach is about asking the user specifics for hybrid-inverter-discharges, and ignoring this input for other cases.

message SetComponentPowerActiveRequest {
  ...

  // This is the field being added.
  // For PV and battery inverters, this field will be ignored
  // For hybrid inverters, for charge commands, this field will be ignored.
  // For hybrid inverters, for discharge commands, this field is mandatory.
  ComponentPowerSource source = 4;
}

enum ComponentPowerSource {
  // Default
  COMPONENT_POWER_SOURCE_UNSPECIFIED = 0;

  // When the PV arrrays should be used as the energy source.
  COMPONENT_POWER_SOURCE_PV = 1;

  // When the batteries should be used as the energy source.
  COMPONENT_POWER_SOURCE_BATTERY = 2;
}

Proposal 2

This approach is about using defaults as much as possible.

message SetComponentPowerActiveRequest {
  ...

  // This is the field being added.
  // For PV inverters, specifying battery will result in an error.
  // For battery inverters, specifying PV will result in an error.
  // For hybrid inverters,
  //   - specifying PV for charging will result in an error.
  //   - specifying nothing for discharging will result in preferring the PV, and any excess goes to batteries.
  //   - specifying PV or batteries will result in the input being chosen as the preferred source.
  ComponentPowerPreferredSource source = 4;
}

enum ComponentPowerPreferredSource {
  // Default
  COMPONENT_POWER_PREFERRED_SOURCE_UNSPECIFIED = 0;

  // When the PV arrays should be preferred as the energy source.
  COMPONENT_POWER_PREFERRED_SOURCE_PV = 1;

  // When the batteries should be preferred as the energy source.
  COMPONENT_POWER_PREFERRED_SOURCE_BATTERY = 2;
}

Proposal 3

This is a combination of the above two:

message SetComponentPowerActiveRequest {
  ...

  // This is the field being added.
  // For PV inverters, specifying battery will result in an error.
  // For battery inverters, specifying PV will result in an error.
  // For hybrid inverters,
  // ...
  ComponentPowerSource source = 4;
}

enum ComponentPowerSource {
  // Default. Results in PV being preferred.
  COMPONENT_POWER_SOURCE_UNSPECIFIED = 0;

  // When only the PV arrays should be used as the energy source.
  // Commands exceeding the limits of the PV arrays will result in an error.
  COMPONENT_POWER_SOURCE_PV_ONLY = 1;

  // When the PV arrays should be used as the preferred energy source,
  // and any leftover power is pulled from batteries.
  COMPONENT_POWER_SOURCE_PV_PREFERRED = 2;

  // When only the batteries should be used as the energy source.
  // Commands exceeding the limits of the batteries will result in an error.
  COMPONENT_POWER_SOURCE_BATTERY_ONLY = 3;

  // When the batteries should be used as the preferred energy source,
  // and any leftover power is pulled from PV, as much as possible.
  COMPONENT_POWER_SOURCE_BATTERY_PREFERRED = 2;
}

One implication of this approach is that the underlying controller should be responsible for maintaining a steady AC output if the PV power fluctuates.

Use cases

No response

Alternatives and workarounds

No response

Additional context

No response

llucax commented 1 week ago

I guess it is hard to represent variants like this, but I wonder if it wouldn't make more sense to have an explicit enum value IGNORE (and error if this is used with hybrid inverters) or even if making UNSPECIFIED a valid value, and for hybrid inverters make that mean "let the microgrid service decide". Also UNSPECIFIED can mean both sources, if not wouldn't it make sense to have a BOTH too? What happens if you have a bound of 1kw for PV and 1kw for battery, and you want to discharge 2kw. With the current proposal you'll have to make 2 calls, right?

I think it would make sense to allow using UNSPECIFIED for "I don't care from where, just gimme the power!".

tiyash-basu-frequenz commented 1 week ago

I wonder if it wouldn't make more sense to have an explicit enum value IGNORE (and error if this is used with hybrid inverters) or even if making UNSPECIFIED a valid value, and for hybrid inverters make that mean "let the microgrid service decide".

I am inclined towards UNSPECIFIED, in line with protobuf's philosophy.

Also UNSPECIFIED can mean both sources, if not wouldn't it make sense to have a BOTH too?

UNSPECIFIED means just default. We could stick to using UNSPECIFIED, and define a default - say prefer PV if available, and excess gets pulled from battery. Users can specify to prefer batteries. That would change the protobuf field name and message name slightly (in the proposal), but the structure would stay the same.

Also, this is only relevant for hybrid-inverter-discharge. For every other case, there is only one option. In this scheme, if a user specifies to prefer PV source for battery inverters, or battery source for PV inverters, the API returns an error.

(I added a 2nd proposal for this approach. I have a slight preference for this one)

What happens if you have a bound of 1kw for PV and 1kw for battery, and you want to discharge 2kw. With the current proposal you'll have to make 2 calls, right?

Yes, and that is also the case for say 1kW charge and 1kVAr inductive command. I do not see a problem with this approach. Also, clubbing everything in a single RPC does not lead to any benefit on the hardware side. Instead that potentially makes the RPCs more complicated.

llucax commented 1 week ago

I also like proposal 2 better, it seems more clear about default behaviour and error conditions :+1:

llucax commented 1 week ago

So proposal 2 also means it is not exclusive, right? If I ask for 2kW and prefer battery, the battery can only provide 1kW but the PV can provide the remaining 2kW, I will still get 2kW, part from the battery and part from the PV, right?

I'm wondering if there could be cases where we really don't want to touch one of the sources, for example we don't want to discharge the battery, maybe if would make sense to have some bool enforce_preferred_source option, and when it is enabled, if I preferred PV and ask for 2kW but the PV can only provide 1kW, I get only 1kW and the battery is not discharged.

shsms commented 1 week ago

One implication of this approach is that the underlying controller should be responsible for maintaining a steady AC output if the PV power fluctuates.

If I'm understanding this correctly, I don't think it makes sense to implement the preference/switch-over logic in the lower-level apps, because they would get in the way of application needs.

It might not be so bad to require the source category to always be specified, especially if such control is possible with hybrid inverters.

tiyash-basu-frequenz commented 1 week ago

So proposal 2 also means it is not exclusive, right? If I ask for 2kW and prefer battery, the battery can only provide 1kW but the PV can provide the remaining 2kW, I will still get 2kW, part from the battery and part from the PV, right?

That's right.

tiyash-basu-frequenz commented 1 week ago

I added a 3rd proposal.

This potentially addresses the concerns about not selecting sources exclusively, while maintaining the flexibility of having preferences.

shsms commented 1 week ago

Oh, I think I'm getting the issue now. If I send a battery-only command, and then a pv-only command, then the battery-only command would go away right?

So if I want to discharge from both, I'd have to set preferred power, because there can be only one power value in a command to an inverter at a time. Is that right?

shsms commented 1 week ago

And similarly, I can't produce from PV to charge the battery, if both are connected to the same hybrid inverter, right?

tiyash-basu-frequenz commented 1 week ago

Oh, I think I'm getting the issue now. If I send a battery-only command, and then a pv-only command, then the battery-only command would go away right? So if I want to discharge from both, I'd have to set preferred power, because there can be only one power value in a command to an inverter at a time. Is that right?

In terms of proposal 3, that is correct.

And similarly, I can't produce from PV to charge the battery, if both are connected to the same hybrid inverter, right?

Oh that's an interesting case, which I forgot about 🤦 I think we should approach this as a combination of two separate inverters into one. By that logic, sending a battery-only command should not override a PV-only command, and vice versa. So, something like this might happen:

  1. client sends discharge-pv-10kW => AC power becomes -10kW
  2. client then sends charge-battery-3kW => AC power becomes -7kW
  3. then 60 seconds of no activity since 1 => AC feed-in increases, assuming PV can produce more that 10kW, say to -17kW
  4. then 60 seconds of no activity since 2 => AC power becomes -20kW

What do you think?

llucax commented 6 days ago

Yeah, if the device supports it, I agree that from the client control PoV it would be best to treat it as 2 separate inverters. At least from the SDK PoV I don't think we will benefit from having the preferences, as PV and batteries will normally be used via PV or battery pools. Using set power commands that can use both will actually complicate things quite a bit in the SDK, so it would be great if we can avoid it.

That said, from the PoV of a very simple app that maybe uses the microgrid API client directly, having the preferred mode might be useful, but from the SDK perspective I don't think we even need it.

thomas-nicolai-frequenz commented 2 days ago

So seeing the above proposals it seems its possible to just set the source of where the energy is coming from by choosing the battery and say wether it should be charge from DC or AC or both. I think we should investigate that before we can draw a conclusion. It might not be possible to say I want to charge a battery from solar but rather just DC but I might be mistaken.