Merge pull request #125 from helgeerbe/powerlimiter

Translations for powerlimiter admin; Pylontech CAN Pins in Device manager; other fixes & enhancements
This commit is contained in:
helgeerbe 2023-03-07 21:13:48 +01:00 committed by GitHub
commit 6dd34a8401
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 79 additions and 26 deletions

View File

@ -271,6 +271,8 @@ This can be achieved by copying one of the [env:....] sections from 'platformio.
-DHOYMILES_PIN_CS=5
-DVICTRON_PIN_TX=21
-DVICTRON_PIN_RX=22
-DPYLONTECH_PIN_RX=27
-DPYLONTECH_PIN_TX=14
```
It is recommended to make all changes only in the 'platformio_override.ini', this is your personal copy.
You can also change the pins by creating a custom [device profile](docs/DeviceProfiles.md).

View File

@ -31,6 +31,8 @@ struct PinMapping_t {
uint8_t display_reset;
uint8_t victron_tx;
uint8_t victron_rx;
uint8_t battery_rx;
uint8_t battery_tx;
};
class PinMappingClass {
@ -42,6 +44,7 @@ public:
bool isValidNrf24Config();
bool isValidEthConfig();
bool isValidVictronConfig();
bool isValidBatteryConfig();
private:
PinMapping_t _pinMapping;

View File

@ -17,7 +17,8 @@
class PylontechCanReceiverClass {
public:
void init();
void init(int8_t rx, int8_t tx);
void enable();
void loop();
void parseCanPackets();
void mqtt();

View File

@ -55,6 +55,8 @@ build_flags = ${env.build_flags}
-DHOYMILES_PIN_CS=5
-DVICTRON_PIN_TX=21
-DVICTRON_PIN_RX=22
-DPYLONTECH_PIN_RX=27
-DPYLONTECH_PIN_TX=14
[env:olimex_esp32_poe]

View File

@ -64,6 +64,8 @@ PinMappingClass::PinMappingClass()
_pinMapping.victron_tx = VICTRON_PIN_TX;
_pinMapping.victron_rx = VICTRON_PIN_RX;
_pinMapping.battery_rx = PYLONTECH_PIN_RX;
_pinMapping.battery_tx = PYLONTECH_PIN_TX;
}
PinMapping_t& PinMappingClass::get()
@ -119,6 +121,9 @@ bool PinMappingClass::init(const String& deviceMapping)
_pinMapping.victron_rx = doc[i]["victron"]["rx"] | VICTRON_PIN_RX;
_pinMapping.victron_tx = doc[i]["victron"]["tx"] | VICTRON_PIN_TX;
_pinMapping.battery_rx = doc[i]["battery"]["rx"] | PYLONTECH_PIN_RX;
_pinMapping.battery_tx = doc[i]["battery"]["tx"] | PYLONTECH_PIN_TX;
return true;
}
}
@ -146,3 +151,9 @@ bool PinMappingClass::isValidVictronConfig()
return _pinMapping.victron_rx > 0
&& _pinMapping.victron_tx > 0;
}
bool PinMappingClass::isValidBatteryConfig()
{
return _pinMapping.battery_rx > 0
&& _pinMapping.battery_tx > 0;
}

View File

@ -48,8 +48,6 @@ void PowerLimiterClass::init()
void PowerLimiterClass::onMqttMessage(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total)
{
MessageOutput.printf("PowerLimiterClass: Received MQTT message on topic: %s\r\n", topic);
CONFIG_T& config = Configuration.get();
if (strcmp(topic, config.PowerLimiter_MqttTopicPowerMeter1) == 0) {
@ -109,11 +107,10 @@ void PowerLimiterClass::loop()
float acPower = inverter->Statistics()->getChannelFieldValue(TYPE_AC, (ChannelNum_t) config.PowerLimiter_InverterChannelId, FLD_PAC);
float correctedDcVoltage = dcVoltage + (acPower * config.PowerLimiter_VoltageLoadCorrectionFactor);
if ((_consumeSolarPowerOnly && isStartThresholdReached(inverter))
|| !canUseDirectSolarPower()) {
if ((_consumeSolarPowerOnly && isStartThresholdReached(inverter))) {
// The battery is full enough again, use the full battery power from now on.
_consumeSolarPowerOnly = false;
} else if (!_consumeSolarPowerOnly && !isStopThresholdReached(inverter) && canUseDirectSolarPower()) {
} else if (!_consumeSolarPowerOnly && isStopThresholdReached(inverter) && canUseDirectSolarPower()) {
// The battery voltage dropped too low
_consumeSolarPowerOnly = true;
}
@ -224,7 +221,7 @@ bool PowerLimiterClass::canUseDirectSolarPower()
uint16_t PowerLimiterClass::getDirectSolarPower()
{
if (!this->canUseDirectSolarPower()) {
if (!canUseDirectSolarPower()) {
return 0;
}
@ -249,7 +246,7 @@ bool PowerLimiterClass::isStartThresholdReached(std::shared_ptr<InverterAbstract
{
CONFIG_T& config = Configuration.get();
// If the Battery interface is enabled, use the SOC value
// Check if the Battery interface is enabled and the SOC start threshold is reached
if (config.Battery_Enabled
&& config.PowerLimiter_BatterySocStartThreshold > 0.0
&& (millis() - Battery.stateOfChargeLastUpdate) < 60000
@ -270,7 +267,7 @@ bool PowerLimiterClass::isStopThresholdReached(std::shared_ptr<InverterAbstract>
{
CONFIG_T& config = Configuration.get();
// If the Battery interface is enabled, use the SOC value
// Check if the Battery interface is enabled and the SOC stop threshold is reached
if (config.Battery_Enabled
&& config.PowerLimiter_BatterySocStopThreshold > 0.0
&& (millis() - Battery.stateOfChargeLastUpdate) < 60000

View File

@ -9,16 +9,21 @@
PylontechCanReceiverClass PylontechCanReceiver;
void PylontechCanReceiverClass::init()
void PylontechCanReceiverClass::init(int8_t rx, int8_t tx)
{
CAN.setPins(rx, tx);
CONFIG_T& config = Configuration.get();
if (!config.Battery_Enabled) {
return;
}
CAN.setPins(PYLONTECH_PIN_RX, PYLONTECH_PIN_TX);
enable();
}
void PylontechCanReceiverClass::enable()
{
if (!CAN.begin(500E3)) {
Hoymiles.getMessageOutput()->println("Starting CAN failed!");
}

View File

@ -108,6 +108,6 @@ void WebApiBatteryClass::onAdminPost(AsyncWebServerRequest* request)
request->send(response);
if (config.Battery_Enabled) {
PylontechCanReceiver.init();
PylontechCanReceiver.enable();
}
}

View File

@ -73,6 +73,10 @@ void WebApiDeviceClass::onDeviceAdminGet(AsyncWebServerRequest* request)
victronPinObj[F("rx")] = pin.victron_rx;
victronPinObj[F("tx")] = pin.victron_tx;
JsonObject batteryPinObj = curPin.createNestedObject("battery");
batteryPinObj[F("rx")] = pin.battery_rx;
batteryPinObj[F("tx")] = pin.battery_tx;
response->setLength();
request->send(response);
}

View File

@ -7,6 +7,7 @@
#include "InverterSettings.h"
#include "MessageOutput.h"
#include "VeDirectFrameHandler.h"
#include "PylontechCanReceiver.h"
#include "MqttHandleDtu.h"
#include "MqttHandleHass.h"
#include "MqttHandleVedirectHass.h"
@ -20,7 +21,6 @@
#include "Utils.h"
#include "WebApi.h"
#include "PowerLimiter.h"
#include "PylontechCanReceiver.h"
#include "defaults.h"
#include <Arduino.h>
#include <LittleFS.h>
@ -149,8 +149,15 @@ void setup()
// Dynamic power limiter
PowerLimiter.init();
// Pylontech / CAN bus
PylontechCanReceiver.init();
// Initialize Pylontech Battery / CAN bus
MessageOutput.println(F("Initialize Pylontech battery interface... "));
if (PinMapping.isValidBatteryConfig()) {
MessageOutput.printf("Pylontech Battery rx = %d, tx = %d\r\n", pin.battery_rx, pin.battery_tx);
PylontechCanReceiver.init(pin.battery_rx, pin.battery_tx);
MessageOutput.println(F("done"));
} else {
MessageOutput.println(F("Invalid pin config"));
}
}
void loop()

View File

@ -447,6 +447,12 @@
"Save": "@:dtuadmin.Save"
},
"powerlimiteradmin": {
"PowerLimiterSettings": "Power Limiter Einstellungen",
"PowerLimiterConfiguration": "Power Limiter Konfiguration",
"General": "Allgemein",
"Enable": "Aktiviert",
"EnableSolarPasstrough": "Aktiviere Solar Pass-trough",
"SolarpasstroughInfo": "Diese Einstellung aktiviert die direkte Weitergabe der aktuell vom Laderegler gemeldeten Solarleistung an den Wechselrichter um eine unnötige Speicherung zu vermeiden und die Energieverluste zu minimieren.",
"InverterId": "Wechselrichter ID",
"InverterIdHint": "Wähle den Wechselrichter an dem die Batterie hängt.",
"InverterChannelId": "Kanal ID",
@ -454,8 +460,23 @@
"TargetPowerConsumption": "Erlaubter Stromverbrauch",
"TargetPowerConsumptionHint": "Angestrebter erlaubter Stromverbrauch.",
"TargetPowerConsumptionHysteresis": "Hysterese für den Zielstromverbrauch",
"TargetPowerConsumptionHysteresisHint": "Wert um den der Zielstromverbrauch schwanken darf, ohne dass nachgeregelt wird."
"TargetPowerConsumptionHysteresisHint": "Wert um den der Zielstromverbrauch schwanken darf, ohne dass nachgeregelt wird.",
"LowerPowerLimit": "Unteres Leistungslimit",
"UpperPowerLimit": "Oberes Leistungslimit",
"PowerMeters": "Leistungsmesser - MQTT",
"MqttTopicPowerMeter1": "MQTT topic - Power meter #1",
"MqttTopicPowerMeter2": "MQTT topic - Power meter #2 (Optional)",
"MqttTopicPowerMeter3": "MQTT topic - Power meter #3 (Optional)",
"BatterySocStartThreshold": "Akku SOC - Start",
"BatterySocStopThreshold": "Akku SOC - Stop",
"VoltageStartThreshold": "DC Spannung - Start",
"VoltageStopThreshold": "DC Spannung - Stop",
"VoltageLoadCorrectionFactor": "DC Spannung - Lastkorrekturfaktor",
"BatterySocInfo": "<b>Hinweis:</b> Der Battery SOC (State of charge) -Wert kann nur benutzt werden wenn das Battery CAN Bus Interface aktiviert ist. Wenn die Batterie innerhalb der letzten Minute keine Werte geschickt hat, werden als Fallback-Option die Spannungseinstellungen verwendet.",
"InverterIsBehindPowerMeter": "Welchselrichter ist hinter Leistungsmesser",
"Battery": "DC / Akku",
"VoltageLoadCorrectionInfo": "<b>Hinweis:</b> Wenn Leistung von der Batterie abgegeben wird, bricht normalerweise die Spannung etwas ein. Damit nicht vorzeitig der Wechelrichter ausgeschaltet wird sobald der \"Stop\"-Schwellenwert erreicht wird, wird der hier angegebene Korrekturfaktor mit einberechnet. Korrigierte Spannung = DC Spannung + (Aktuelle Leistung (W) + Korrekturfaktor).",
"Save": "@:dtuadmin.Save"
},
"batteryadmin": {
"BatterySettings": "Batterie Einstellungen",

View File

@ -451,7 +451,7 @@
"PowerLimiterConfiguration": "Power Limiter Configuration",
"General": "General",
"Enable": "Enable",
"EnableSolarPasstrough": "Enable Solar Passtrough",
"EnableSolarPasstrough": "Enable Solar-Passtrough",
"SolarpasstroughInfo": "When the sun is shining, this setting enables the sychronization of the inverter limit with the current solar power of the Victron MPPT charger. This optimizes battery degradation and loses.",
"InverterId": "Inverter ID",
"InverterIdHint": "Select proper inverter ID where battery is connected to.",
@ -461,12 +461,12 @@
"TargetPowerConsumptionHint": "Set the grid power consumption the limiter tries to achieve.",
"TargetPowerConsumptionHysteresis": "Hysteresis for power consumption",
"TargetPowerConsumptionHysteresisHint": "Value around which the target power consumption fluctuates without readjustment.",
"LowerPowerLimit": "Lower power limit / continuous feed",
"LowerPowerLimit": "Lower power limit",
"UpperPowerLimit": "Upper power limit",
"PowerMeters": "Power meters - MQTT",
"MqttTopicPowerMeter1": "MQTT topic - Power meter #1",
"MqttTopicPowerMeter2": "MQTT topic - Power meter #2",
"MqttTopicPowerMeter3": "MQTT topic - Power meter #3",
"MqttTopicPowerMeter2": "MQTT topic - Power meter #2 (optional)",
"MqttTopicPowerMeter3": "MQTT topic - Power meter #3 (optional)",
"BatterySocStartThreshold": "Battery SOC - Start threshold",
"BatterySocStopThreshold": "Battery SOC - Stop threshold",
"VoltageStartThreshold": "DC Voltage - Start threshold",

Binary file not shown.

Binary file not shown.

Binary file not shown.