ngardiner / TWCManager

Control power delivered by a Tesla Wall Charger using two wires screwed into its RS-485 terminals.
The Unlicense
130 stars 55 forks source link

[feature request] add parameter and option for utilising export limited solar #259

Open alexeiw123 opened 3 years ago

alexeiw123 commented 3 years ago

solar installations are often larger than the export limit applied to them from the utility. Many EMS will allow the system to generate at its maximum while the difference between export limit and generation is being used within the house. That energy is essentially free (can't export it, use it or lose it).

If there were a parameter for export limit e.g. 10 kW and a parameter for generation threshold to start charging e.g. 8 kW then we could automatically enable charging to maximise utilisation of the free energy. This would start charging when generation is over 8 kW as there is no way to tell if a system is able to generate more than 10 kW without adding load or having some direct API flag from the EMS.

MikeBishop commented 3 years ago

This can be implemented with policy restrictions, if you're using an EMS module that exposes properties. For example,

    "restrictions":{
      "Track Green Energy":{
        "match": [ "modules.TeslaPowerwall2.generatedW" ],
        "condition": [ "gte" ],
        "value": [ 8000 ]
      }
    },

...would do it if you're using a Tesla Powerwall. We should probably add a way to address core things like total generation and total consumption from policies so this isn't dependent on a particular EMS, though.

ngardiner commented 3 years ago

Yes, this is a good idea and should be pretty easy to do.

Surprisingly we don't have getGeneration() as a defined function for policy modules as @MikeBishop has pointed out. This is an easy add, and will allow us to use generation values easily in the policy. Setting the generation threshold will have to be manual, no way for us to determine the provider's cutoff for export.

I'll start by adding in getGeneration to the Policy module, but the one issue here that I can see which stops this from being universally available as a default policy is that the policy restriction above can't be easily turned on/off via a boolean switch. Maybe we should add a field that is evaluated first which determines if the restriction is enforced or not (it could be defauled to true to not cause any backwards compatibility issues) and then only if the "enabled" condition of the restrictions entry evaluates to true do we then enforce the restriction?

If we did both of these, it could be a default part of the policy and we could have a dedicated config for it in the config file.

MikeBishop commented 3 years ago

Maybe add the restriction comparing to a config variable that defaults to -1? Then it's functionally the same as now -- generation will never return a negative number, even if it's zero.

alexeiw123 commented 3 years ago

forgive me for not diving into ways to modify the existing code myself - I'm not a developer and am really riding on the coat tails of others to achieve the desired outcomes at my place!

I have been using the "greenEnergyAmpsOffset" variable to prevent charging until generation is close to my export limit and crudely get the desired outcome. Of course, I am using a fair bit of energy that could still be exported, mostly due to charge speed increasing as my generation increases (I am on 3 phase, so minimum of 6A is still 4.3 kW). I understand a policy could be set using charge_amps to limit the maximum current while chasing the export limited solar, however it's beyond my skillset to get this working.

I think the main variables required to let TWC do the work are:

I am hopeful that this can be done using policy restrictions and getGeneration() as mentioned above, I'll have to play with that if it's added.

Anyway - this marked up graphic of my enphase data in 15s intervals shows the results of today's testing.

image

MikeBishop commented 3 years ago

Looking at this again, I think I see the right way to configure what you're trying to achieve:

See if that gets you where you're looking to be.

MikeBishop commented 3 years ago

(I edited the above; don't update your config based on the e-mail notification without seeing the edits.)

alexeiw123 commented 3 years ago

Looking at this again, I think I see the right way to configure what you're trying to achieve:

  • greenEnergyAmpsOffset set to your export limit as a negative number; or perhaps 1A closer to zero?
  • greenEnergyFlexAmps set to the same as minAmpsPerTWC
  • useFlexAmpsToStartCharge set to true

See if that gets you where you're looking to be.

Thank you for taking the time to consider this. I had mostly come to the same conclusion in my testing yesterday afternoon (or at least on the same path). Just waiting for the sun to get high enough to test this out today.

Will report back later today - now to go for a drive so I have low enough SoC to test!

alexeiw123 commented 3 years ago

Two wins and two behaviours that I can't explain. (I have edited and updated this throughout the day).

Wins:

Strange behaviour 1:

Perhaps (likely) I'm missing something here. greenEnergyAmpsOffset is 13A (9360W) greenEnergyFlexAmps is 6A (4320W) useFlexAmpsToStartCharge is true

Image is showing consumption is 6.9 kW above generation, shouldn't this have caused the car to stop charging until the house consumption reduced?

image

Strange behaviour 2:

Apr 27 14:20:49 TWCManager python3[465]: 14:20:49 TWCManager 20 Slave TWC 2679: Delivered 2973 kWh, voltage per phase: (245, 248, 248).
Apr 27 14:21:08 TWCManager python3[465]: 14:21:08 TWCManager 20 Green energy generates 7961W, Consumption 14288W (Other Load 9501W, Charger Load 4787W)
Apr 27 14:21:08 TWCManager python3[465]: 14:21:08 TWCManager 20 Limiting charging to 10.74A - 10.74A = 0.00A.
Apr 27 14:21:08 TWCManager python3[465]: 14:21:08 TWCManager 20 Charge when above 6A (minAmpsPerTWC).
Apr 27 14:21:40 TWCManager python3[465]: 14:21:40 TWCManager 20 Green energy generates 7841W, Consumption 14306W (Other Load 9564W, Charger Load 4742W)
Apr 27 14:21:40 TWCManager python3[465]: 14:21:40 TWCManager 20 Limiting charging to 10.58A - 10.58A = 0.00A.
Apr 27 14:21:40 TWCManager python3[465]: 14:21:40 TWCManager 20 Charge when above 6A (minAmpsPerTWC).
Apr 27 14:21:47 TWCManager python3[465]: 14:21:47 TWCMaster  20 Charge Session Stopped for Slave TWC 2679
Apr 27 14:21:47 TWCManager python3[465]: 14:21:47 TWCSlave   20 SHB 2679: 03 00.00/06.00A 0000 0000  M: 00 00.00/00.00A 0000 0000
Apr 27 14:21:47 TWCManager python3[465]: 14:21:47 TWCSlave   20 Slave power for TWCID b'&y', status: 3
Apr 27 14:21:53 TWCManager python3[465]: 14:21:53 TeslaAPI   20 Dave is done charging or already trying to charge.  Stop asking to start charging.
Apr 27 14:21:53 TWCManager python3[465]: 14:21:53 TWCManager 20 Slave TWC 2679: Delivered 2973 kWh, voltage per phase: (247, 249, 248).
Apr 27 14:22:08 TWCManager python3[465]: 14:22:08 TWCManager 20 Green energy generates 7767W, Consumption 9895W (Other Load 9895W, Charger Load 0W)
Apr 27 14:22:08 TWCManager python3[465]: 14:22:08 TWCManager 20 Limiting charging to 10.44A - 10.44A = 0.00A.
Apr 27 14:22:08 TWCManager python3[465]: 14:22:08 TWCManager 20 Charge when above 6A (minAmpsPerTWC).

Marked up image shows the plot of generation and consumption. I have highlighted the load that was the car charging. You can see on this that charging continued when generation was below 10 kW and also when other significant loads were on in the house.

image

ngardiner commented 3 years ago

@MikeBishop is by far the expert on charge policy but I suspect this would be because greenEnergyFlexAmps == minAmpsPerTWC and therefore we'd meet criteria to start charging as long as we were even 1 watt above the 10kW export limit? In @alexeiw123's case, you'd want to start charging if the generation - consumption (including the 10kW "base" consumption) was at a certain base level, and then scale up from there, but not necessarily that your flex would equal your minAmps, as in that case you may as well just drop your artificial consumption down by 6A as you'd always charge at anything above 10kW generation?

The graph shows charging starts at 10am as the generation crosses the 10kW mark for the first time. But because the flexAmps == minAmps, the charging seems as if it would be self sustaining? If flexAmps was less than minAmps, there would always need to be a generation margin above the artificial consumption value to sustain charge.

Let's say greenEnergyFlexAmps = 5 and minAmpsPerTWC = 6, then the minimum criteria to start charging would be 1A of excess generation after consumption. I think this would be a safer config, both because it's less likely to charge down 6A into exportable generation just as you skim 10kW of generation (and in turn, will lose a bit more non exportable energy, but this is the tradeoff that exists) and most importantly, that defines a hard cut-off that you must meet in generation before flexAmps will allow the vehicle to charge?

Also, we really should document examples of things like this once we solve them.... I'll make sure we do because there's so many permutations out there of setups and we tend to find one-off solutions to them, but as solar panels get cheaper and with batteries still not universally affordable this is going to be a common occurrence, especially here in Australia with our residential solar adoption rates.

MikeBishop commented 3 years ago

Ideally, if the car could sink arbitrary amounts of current, we want to charge with anything over the export limit. The fictitious consumption addresses that, basically by considering your export to be part of the load that needs to be satisfied first. The two problems with that are that a) you have to have a little bit of extra draw to discover if there's capacity beyond the limit, and b) the car actually does have a minimum amount of power it can draw. So you make your fictitious consumption 1A less than the limit, so the car will draw that extra amount and provide discovery. Flex starting addresses the other -- the car will draw its minimum as soon as it determines it could draw anything.

If you make FlexAmps be much less than the minAmps, you won't be able to discover that there's additional production capacity available. You could reasonably reduce it by whatever is normal load in your house, but you risk curbed production otherwise. Maybe make the flex be slightly less than minAmpsPerTWC, so that zero is clearly outside the allowed range? 5A should do the trick, or perhaps even 5.9A. The trouble with three-phase charging in this case is that even a small amount of current is a large amount of power -- my single-phase install can go down to a minimum of 1.5kW when it wants to keep charging but not draw very much.

alexeiw123 commented 3 years ago

Much better testing this morning based on the advice provided.

Started with greenEnergyFlexAmps = 5, minAmpsPerTWC = 6 and greenEnergyAmpsOffset = 13 Export limit was hit without the car starting and very low consumption in the house (300W)

I updated the values to:

greenEnergyFlexAmps = 5.9, minAmpsPerTWC = 6 and greenEnergyAmpsOffset = 12.3

This lowered the trigger point and the car was able to start charging while the generation was export limited, then generation increased from there. There may have been a little hysteresis but could also have been the washing machine adding to load at the time.

I then tested turning on the AC and sure enough, as the consumption picked up, the car stopped charging.

I had planned to save my SoC for the afternoon dip below the export limit, but as you can see, the rain came over.

image

ngardiner commented 3 years ago

Great to hear, @alexeiw123. The graph so far certainly is promising, and it's great that it is showing promise with 5.9 as this reduces the initial loss in non-exportable generation. It may even be possible to drive that number a little closer, although at some point the margin could become too small to be effective as the stopgap against continuing to charge off flex, so it is probably best to slowly walk it up rather than going straight to 5.99 for example.

Looking forward to see how it performs on a full cycle, once you have a chance to go for a nice long drive :)

alexeiw123 commented 3 years ago

Great conditions for testing today with clouds passing over and generation running above and below the export limit.

Was getting some hysteresis when generation was around the 10 kW mark. I have set greenEnergyLatch = 3 as I expect that this will keep the car charging until the conditions to stop have been met for a full 3 minutes. @MikeBishop does this also apply with flex charging?

I'm also going to install an isolator on 2 of the 3 phases so that I can drop to single phase for majority of the time and get a more usable minimum charge rate.

image

MikeBishop commented 3 years ago

Latching is about when the conditions for the policy are no longer met; it doesn't have any impact on when a policy is active, but deciding not to offer current. So if you'd set a restriction such that Track Green Energy was only active when production was above 8kW, greenEnergyLatch would keep it in the TGE policy for three minutes even if you had a sudden drop in production.

You might try the code in #270, which will limit how frequently the system can start/stop charging to reduce bouncing like this. However, as currently designed, it can equally choose not to start charging if you recently stopped, which might not be what you want. It's mostly about waiting for the system to stabilize, not so much about keeping the car charging.

alexeiw123 commented 3 years ago

Thanks @MikeBishop I took a look at your code in in #270 but am cautious to make too many changes for which I can't debug myself, I'm still getting my head around git and how it all works! I'm not sure if I make those changes at my end, how that affect further git pull requests? I suspect something like this would get merged at some point?

Anyway - over the weekend I made it so I can switch my wall charger to single phase charging, so that the minimum charge speed is greatly reduced and as such I can more discretely capture that energy above the 10 kW export limit (highlighted red dashed line). As you can see, the charge speed is much closer matching the shape of the generation curve above 10 kW. Ignore that bit around lunch time, I was playing with the 'charge now' button.

Is the best answer to stopping the bouncing a time delay, or would it be to set a buffer on the TGE policy to avoid hysteresis? E.g. if I have greenEnergyAmpsOffset set at 13A, with a 0.2 A buffer we could start charging at 13A offset but not stop charging until it drops to 12.8A and avoid that hysteresis. image

I also noticed that the calculation of power and current from my EMS (3 phase enphase) is messed up once I have the charger in single phase. Seems that it is assuming my household generation and consumption is also single phase, so I have to multiply my greenEnergyAmpsOffset value by 3, to target just below my export limit. I know the single phase TWC with 3 phase power would be rare. 3 phase TWC with single phase solar would be common enough though. I'm not sure if this needs it's own issue and whether that needs to be fixed in the enphase module, or elsewhere.