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

Generic SML based power meters support #146

Merged

Conversation

qubeck
Copy link

@qubeck qubeck commented Mar 27, 2023

Add support for generic reading of SML based power meters by taking OBIS 1.8.0 & 2.8.0 lists for import & export of energy and OBIS 16.7.0 list for signed power value.

To not conflict with any upcoming extensions of the power meter class the power meter source was set to 99 for this extension.

helgeerbe and others added 2 commits March 27, 2023 10:59
…king OBIS 16.7.1 for power (using mod. SML Parser lib. by olliiiver)
@Adminius
Copy link

For my undesrtanding, is it for IR Power Merers, like "Volkszähler"?

In general, I'would switch UART-based-PowerMeters, like SML and SDM to software serial.
they don't need high bitrate, 9600-19200 is good possible with SoftwareSerial.
The reason is: I will add support for JK BMS (maybe JBD also), and thoose needs 115200bps UART. In this case only HW Serial ist possible, but no one is free :/

Maybe Victron 19200bps is also possible with SW-Serial. More than one Victron is also not really possible because of UARTs

@helgeerbe
Copy link
Owner

I want to extend viltron interface to use more than one charger and that hard and software serial could be used.

@Adminius
Copy link

@berni2288 which power meter ID are you using fot HTTP(S)?
I would say, we can change IDs to sort:
0: MQTT
1: HTTP(S)
20: SDM 1ph
21: SDM 3ph
22: SML

something like that, so we can add more PowerMeters in beetween.

@berni2288
Copy link
Collaborator

I've taken 3, but I don't really care :) maybe change this to an enum so this can be changed easily at one place.

@qubeck
Copy link
Author

qubeck commented Mar 28, 2023

@Adminius Exactly. It's aimed for powermeters that fan out their data using SML via 9600 8N1 serial - IR signal.
I choosed the OBIS 16.7.0 since the majority of them are supporting it see also:
compatibility list of: "ELV ES-IEC, Stromzählerausleser"

Regarding the usage of the SoftwareSerial: Yes my first intention was also to use this, since only rx is required and the baudrate is low. Unfortunately I got unexpected byte errors from time to time in real operation when hoymiles module was active. But the main reason to go with HardwareSerial for now was that since the update of the new compile settings the EspSoftwareSerial doesn't compile anymore if 'gnu++11' is disabled via 'build_unflags' in platformio.ini.

@Adminius
Copy link

EspSoftwareSerial doesn't compile anymore if 'gnu++11' is disabled via 'build_unflags' in platformio.ini

yeah... this is what I already found with SDM integration...
There newer version (8.0.1) available, we have to test it

@qubeck
Copy link
Author

qubeck commented Mar 28, 2023

There newer version (8.0.1) available, we have to test it

Thanks for the hint!, Just tried that and it compiles now again. But the unexpected byte problem remains a thing.
One solution would be to keep polling for the next SML byte for the time period the whole SML list is expected to arrive. I'm on it...

@Adminius
Copy link

I see, SML in the list... D0 would be next possiblity.
1000 impulses/kWh can be also made for some cheap power meters... but it es very inaccurate:
http://ssb22.user.srcf.net/elec/imp.html

@qubeck
Copy link
Author

qubeck commented Mar 28, 2023

The switch to software serial usage is complete. I set its buffer sizes to a value that should make sense. Which in turn reduced the observed SML unexpected state significantly.

@Adminius
Copy link

@qubeck look at my comments about _powerMeterTotalPower = _powerMeter1Power + _powerMeter2Power + _powerMeter3Power;

@qubeck
Copy link
Author

qubeck commented Mar 28, 2023

@Adminius sorry but I can't see any, at least there are none visible to me. Strange...

@Adminius
Copy link

you don't need _powerMeterTotalPower = _powerMeter1Power + _powerMeter2Power + _powerMeter3Power;
that's done in float PowerMeterClass::getPowerTotal().
_powerMeterTotalPower isn't used (we have to remove it)

@qubeck
Copy link
Author

qubeck commented Mar 28, 2023

That's why I changes also "float PowerMeterClass::getPowerTotal()" to only return "_powerMeterTotalPower"

And all of the powers are applied source individually in the loop. That way it's much more cleaner.
At least it appears to me. But feel free to change it if you really want.

In SML 16.7.0 case there are also no phase specific powers so putting it in to one of the phase powers to get responded by getPowerTotal() would be a little bit confusing.

@Adminius
Copy link

That's why I changes also "float PowerMeterClass::getPowerTotal()" to only return "_powerMeterTotalPower"

PowerMeter is from me and I had it this way at the beginning (that's why _powerMeterTotalPower is there).
In my opinion it was better to separate it in dedicated function.
The idea behind it:
Each time if at least one of 3 power values is changed, we caluclute a sum and it is not relavant if need this sum an not.
With functinon, we build a sum only if we really need it (on function call).
I did it, because I tested it with my SmartPI MQTT PowerMerer. It sends all 3 power values each second via MQTT. That means, we build as sum 3 times per second.
With a dedicated function only 1-2 times per 10 second (power limiter + mqtt output)

@qubeck
Copy link
Author

qubeck commented Mar 28, 2023

I see your point, well may be in that case an alternative would be something like:
float PowerMeterClass::getPowerTotal() { return (_powerMeterTotalPower > 0) ? _powerMeterTotalPower : _powerMeter1Power + _powerMeter2Power + _powerMeter3Power; }

And total power would be only applied by meter sources that do not have individual readings.

@Adminius
Copy link

_powerMeterTotalPower > 0

If you have a real "zero export" ("Nulleinspeisung"), _powerMeterTotalPower = 0 and also _powerMeterTotalPower < 0 are valid values...

@qubeck
Copy link
Author

qubeck commented Mar 28, 2023

Yes, of course... So we need to flag that case by something like:
_powerMeterTotalPowerOnly = true; at init

Also I see that the mqtt subscriptions there are also source specific and need to be turned of in that case.

@Adminius
Copy link

kW theoretically only... never heard that Power meters in home applications usung kW

But you also see why I'm using first power 1 und other 2 are 0 in single phase SDM implementation. Easiest solution, without flags and so on ;)

@qubeck
Copy link
Author

qubeck commented Mar 28, 2023

Well since it gets also published via mqtt it can become confusing eventually. Especially in the case where powermeeters could have pos. and neg. readings for each phase but do not present that power transparently.

@Adminius
Copy link

Adminius commented Mar 28, 2023

Well, mqtt publishes power1, power2, power3 and powertotal.
power1 should not be power L1, power2 ist not L2 and so on 😉
The number represents power source number and not phase number ;)

@qubeck qubeck force-pushed the generic_sml_powermeter_support branch from 9b58c28 to 6f84c31 Compare March 28, 2023 16:45
@qubeck
Copy link
Author

qubeck commented Mar 28, 2023

Should not be power L1 ...L3? Sure they doesn't have to be... but the calls to the SDM lib for the _powerMeter...Power are:
_powerMeter1Power = static_cast<float>(sdm.readVal(SDM_PHASE_1_POWER, _address)); _powerMeter2Power = static_cast<float>(sdm.readVal(SDM_PHASE_2_POWER, _address)); _powerMeter3Power = static_cast<float>(sdm.readVal(SDM_PHASE_3_POWER, _address));

So they are implicit phase power readings. But yeah that can be any power reading of course and is physically determined eventually. In the end they are added up like anyone would do with phase power readings...

@Adminius
Copy link

In case of SDM this are 3 phases=3 power sources.
In MQTT case, theoretically, it can be up to 3 different powermeters...

@qubeck
Copy link
Author

qubeck commented Mar 29, 2023

I simplified the code to make it more smoother to integrate into the existing module.

Btw. I observed some interesting behavior at trying to configure zero export with the power limiter. It appears that the inverter internally distributes the applied power limit across all DC channels. e.g. with only 1x producing DC channel (in my case @ HM-600) this results in the power limit gets applied with long delay over time, since only a fraction of the requested power limit becomes active on the actual producing DC channel when power limiter kicks in.

This can be improved by taking the number of actually producing DC channels into account to increase the applied power limit artificially. Just saying... I'll experiment with a slight modification to the power limiter as soon the weather becomes better. But this is of course a topic for an other discussion...

@berni2288
Copy link
Collaborator

Btw. I observed some interesting behavior at trying to configure zero export with the power limiter. It appears that the inverter internally distributes the applied power limit across all DC channels. e.g. with only 1x producing DC channel (in my case @ HM-600)

It would be interesting if this PR fixes your problem: #154
Maybe you can try it out :)

@berni2288 berni2288 added the enhancement New feature or request label Apr 2, 2023
@madmartin
Copy link

madmartin commented Apr 4, 2023

@Adminius Exactly. It's aimed for powermeters that fan out their data using SML via 9600 8N1 serial - IR signal. I choosed the OBIS 16.7.0 since the majority of them are supporting it see also: compatibility list of: "ELV ES-IEC, Stromzählerausleser"

Regarding the usage of the SoftwareSerial: Yes my first intention was also to use this, since only rx is required and the baudrate is low. Unfortunately I got unexpected byte errors from time to time in real operation when hoymiles module was active. But the main reason to go with HardwareSerial for now was that since the update of the new compile settings the EspSoftwareSerial doesn't compile anymore if 'gnu++11' is disabled via 'build_unflags' in platformio.ini.

Hi,
my personal opinion is that implementing this into here is absolutely waste of time. You can connect your serial IR reader to an esp8266 or esp32 and use tasmota - this works wonderful and is well maintained.
This needs hardware for less than 10 Euro and IMHO not worth the time to be implemented here.
Read tasmota doc and you see that implementing the SML stuff is a lot of code - so why repeat this here?

https://tasmota.github.io/docs/Smart-Meter-Interface/

Finally, since #153, the powermeterclass retrieves the values from tasmota via http(s).

@Adminius
Copy link

Adminius commented Apr 4, 2023

@madmartin

  1. you need additional ESP8266/ESP32 + power supply
  2. you need stable WiFi connection for both ESPs
    With this implementation you can setup one ESP32 as stand alone and all-in-one solution, completely offline.

@qubeck qubeck force-pushed the generic_sml_powermeter_support branch from d1640f8 to d06196a Compare April 4, 2023 20:01
@qubeck
Copy link
Author

qubeck commented Apr 4, 2023

  • aligned the code with current dev, with slight change on condition with "config.PowerMeter_Enabled" in onMqttMessage().
  • added SOURCE_SML (==4)
  • added explicit return if "!config.PowerMeter_Enabled" and more source dependent init/begin calls to modules in PowerMeterClass::init()

I think now would be the best time for a review and merge before it diverge any further...

@@ -15,6 +15,15 @@ PowerMeterClass PowerMeter;

SDM sdm(Serial2, 9600, NOT_A_PIN, SERIAL_8N1, SDM_RX_PIN, SDM_TX_PIN);

#define USE_SW_SERIAL
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder... what's the point of this constant that can't be overriden via build parameters?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The decision about using the HW/SW serial wasn't made back then. So I left the option. But yeah I will remove it.

float _powerMeterImport = 0.0;
float _powerMeterExport = 0.0;

bool _powerMeterOnlyTotalPowerAvailable = false;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not fully sure if that's a good idea. It's inconsistent behavior with the other Power meters where you currently can only set the power per phase.
Also I don't understand why all member variables are starting with _powerMeter? PowerMeter is already part of the class name.

I guess we will need some refactoring of the Power meters, it's becoming a bit messy already (not your fault).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I introduced that flag because SML power reading obtained from OBIS 16.7.0 list can not be related to any specific phase. It's the signed sum of all and I didn't want to confuse anything an put it into one of the phases.
Especially, because that powers are getting published...

@@ -215,10 +215,11 @@ export default defineComponent({
dataLoading: true,
powerMeterConfigList: {} as PowerMeterConfig,
powerMeterSourceList: [
{ key: 3, value: this.$t('powermeteradmin.typeHTTP') },
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might not've looked aesthetic in the code, but it was put on top on purpose because typeHTTP is probably the most used one :) But it's ok, we can also order it by number if you would like to.

@berni2288 berni2288 merged commit 00def1d into helgeerbe:development Apr 7, 2023
Copy link

github-actions bot commented Apr 7, 2024

This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new discussion or issue for related concerns.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 7, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants