Bonjour a tous,
J’ai un panneau solaire avec un micro-onduleur SG300W dont les statistiques de production sont disponibles par un lien UART à 2.4GHz.
Une librairie arduino existe : https://github.com/atc1441/NETSGPClient/
J’avais fait un sketch arduino mais je voulais publier les infos dans HA.
Au niveau materiel, on utilise un module LC12S
Par exemple : https://www.satistronics.com/shop/product/180300-lc12s-uart-wireless-serial-transparent-transmition-128-channel-module-9312
Je partage le code que j’ai écris pour une cible WemosD1 mini + OLED 64x48 et qui est certainement perfectible
rx-sg300w.yaml
esphome:
name: rx-sg300w
includes:
- SG300W.h
libraries:
- NETSGPClient
- EspSoftwareSerial
esp8266:
board: d1_mini
# Enable logging
logger:
level: DEBUG
baud_rate: 115200
# Enable Home Assistant API
api:
ota:
password: "xxx"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
manual_ip:
static_ip: x.x.x.x
gateway: x.x.x.x
subnet: x.x.x.x
output_power: 10dB
fast_connect: true
power_save_mode: HIGH
web_server:
port: 80
captive_portal:
font:
- file: "fonts/FreeSans.ttf"
id: Free_font
size: 10
- file: "fonts/LiberationSans.ttf"
id: Lib_font
size: 10
i2c:
sda: D2
scl: D1
display:
- platform: ssd1306_i2c
model: "SSD1306 64x48"
reset_pin: D0
address: 0x3C
id: my_display
pages:
- id: page1
lambda: |-
it.printf(0, 0, id(Free_font), "Production PV");
it.printf(0, 11, id(Lib_font), "Vdc = %.1f V", id(pv_vdc).state);
it.printf(0, 22, id(Lib_font), "Adc = %.1f A", id(pv_adc).state);
it.printf(0, 33, id(Lib_font), "Wdc = %.1f W", id(pv_wdc).state);
- id: page2
lambda: |-
it.printf(0, 0, id(Free_font), "Production AC");
it.printf(0, 11, id(Lib_font), "Vac = %.1f V", id(pv_vac).state);
it.printf(0, 22, id(Lib_font), "Aac = %.1f A", id(pv_aac).state);
it.printf(0, 33, id(Lib_font), "Wac = %.1f W", id(pv_wac).state);
- id: page3
lambda: |-
it.printf(0, 0, id(Free_font), "Rendement");
it.printf(0, 22, id(Lib_font), "R = %.1f%%", id(pv_rend).state);
- id: page4
lambda: |-
it.print(0, 0, id(Free_font), "Prod. Totale");
it.printf(0, 22, id(Lib_font), "Wac = %.1f kW", id(pv_totalkW).state);
- id: page5
lambda: |-
it.print(0, 0, id(Free_font), "Temp");
it.printf(30, 22, id(Lib_font), "%d °C", id(pv_temp).state);
interval:
- interval: 3s
then:
- display.page.show_next: my_display
- component.update: my_display
sensor:
- platform: custom
lambda: |-
auto my_custom = new customUartSg300w();
App.register_component(my_custom);
return {my_custom->Vdc_sensor, my_custom->Adc_sensor, my_custom->Wdc_sensor, my_custom->Vac_sensor, my_custom->Aac_sensor, my_custom->Wac_sensor, my_custom->Wtot_sensor, my_custom->Temp_sensor, my_custom->Rend_sensor};
sensors:
- name: "Vdc"
unit_of_measurement: V
accuracy_decimals: 1
id: pv_vdc
- name: "Adc"
unit_of_measurement: A
accuracy_decimals: 2
id: pv_adc
- name: "Wdc"
unit_of_measurement: W
accuracy_decimals: 1
id: pv_wdc
- name: "Vac"
unit_of_measurement: V
accuracy_decimals: 1
id: pv_vac
- name: "Aac"
unit_of_measurement: A
accuracy_decimals: 1
id: pv_aac
- name: "Wac"
unit_of_measurement: V
accuracy_decimals: 1
id: pv_wac
- name: "Total_kW"
unit_of_measurement: kW
accuracy_decimals: 1
id: pv_totalkW
- name: "Temp"
unit_of_measurement: "°C"
id: pv_temp
- name: "Rendement"
unit_of_measurement: "%"
accuracy_decimals: 1
id: pv_rend
SG300W.h
#include "esphome.h"
#include "NETSGPClient.h"
#include <SoftwareSerial.h>
#define NETSGP_BUFFER_LENGTH 32
#define LC12S_PROG_PIN 13
#define LC12S_RX_PIN 14
#define LC12S_TX_PIN 12
#define LC12S_BAUDS 9600
#define inverterID xxxx
#define INTERVAL 10
class customUartSg300w : public Component, public Sensor {
public:
Sensor *Vdc_sensor = new Sensor();
Sensor *Adc_sensor = new Sensor();
Sensor *Wdc_sensor = new Sensor();
Sensor *Vac_sensor = new Sensor();
Sensor *Aac_sensor = new Sensor();
Sensor *Wac_sensor = new Sensor();
Sensor *Wtot_sensor = new Sensor();
Sensor *Temp_sensor = new Sensor();
Sensor *Rend_sensor = new Sensor();
//----------------------------------------------------------------------------
customUartSg300w() {
ESP_LOGD("customUartSg300w", "*******************");
ESP_LOGD("customUartSg300w", " Constructor");
Ser2 = new SoftwareSerial;
Ser2->begin(LC12S_BAUDS, SWSERIAL_8N1, LC12S_RX_PIN, LC12S_TX_PIN, false);
clientNETSGP = new NETSGPClient(*Ser2, LC12S_PROG_PIN);
ESP_LOGD("customUartSg300w", "*******************");
}
//----------------------------------------------------------------------------
void setup() override {
ESP_LOGD("customUartSg300w", "*******************");
ESP_LOGD("customUartSg300w", " Setup");
currentMillis = millis();
lastSendMillis = millis();
delay(1000);
if (!clientNETSGP->setDefaultRFSettings()) {
ESP_LOGD("customUartSg300w", "*** Could not set RF module to default settings ***");
} else {
ESP_LOGD("customUartSg300w", "Connection to RF Module LC12S: OK");
}
this->getSettings();
ESP_LOGD("customUartSg300w", "*******************");
}
//----------------------------------------------------------------------------
void loop() override {
currentMillis = millis();
if (currentMillis - lastSendMillis > INTERVAL * 1000) // interrogation INTERVAL sec
{
lastSendMillis = currentMillis;
this->getStatus();
this->publishSensors();
}
}
//----------------------------------------------------------------------------
void getSettings() {
LC12S_settings = clientNETSGP->readRFModuleSettings();
ESP_LOGD("customUartSg300w", "\n Module LC12S Settings: ");
ESP_LOGD("customUartSg300w", "moduleID: %X ", LC12S_settings.moduleID);
ESP_LOGD("customUartSg300w", "networkID: %d ", LC12S_settings.networkID);
ESP_LOGD("customUartSg300w", "rfChannel: %d ", LC12S_settings.rfChannel);
ESP_LOGD("customUartSg300w", "valid: %d ", LC12S_settings.valid);
ESP_LOGD("customUartSg300w", "rfPower: %d ", LC12S_settings.rfPower);
ESP_LOGD("customUartSg300w", "baudrate: %d ", LC12S_settings.baudrate);
}
//----------------------------------------------------------------------------
void getStatus() {
status = clientNETSGP->getStatus(inverterID);
if (status.valid) {
ESP_LOGD("customUartSg300w", "-------------------------------------");
ESP_LOGD("customUartSg300w", "Status Valid");
ESP_LOGD("customUartSg300w", "State: %d", status.state);
ESP_LOGD("customUartSg300w", "Vdc = %.1fV",status.dcVoltage);
ESP_LOGD("customUartSg300w", "Adc = %.1fA",status.dcCurrent);
ESP_LOGD("customUartSg300w", "Wdc = %.1fW",status.dcPower);
ESP_LOGD("customUartSg300w", "Vac = %.1fV",status.acVoltage);
ESP_LOGD("customUartSg300w", "Aac = %.1fA",status.acCurrent);
ESP_LOGD("customUartSg300w", "Wac = %.1fw",status.acPower);
ESP_LOGD("customUartSg300w", "TotW= %.1fW",status.totalGeneratedPower);
ESP_LOGD("customUartSg300w", "Temp= %d°C",status.temperature);
} else {
ESP_LOGD("customUartSg300w", "Status Non Valid");
}
}
//----------------------------------------------------------------------------
void publishSensors() {
Vdc_sensor->publish_state(status.dcVoltage);
Adc_sensor->publish_state(status.dcCurrent);
Wdc_sensor->publish_state(status.dcPower);
Vac_sensor->publish_state(status.acVoltage);
Aac_sensor->publish_state(status.acCurrent);
Wac_sensor->publish_state(status.acPower);
Wtot_sensor->publish_state(status.totalGeneratedPower);
Temp_sensor->publish_state((uint8_t)status.temperature);
if (status.dcPower > 0) {
Rend_sensor->publish_state(100*(status.dcPower - status.acPower)/status.dcPower);
} else {
Rend_sensor->publish_state(0);
}
}
//----------------------------------------------------------------------------
private:
char buffer[NETSGP_BUFFER_LENGTH];
SoftwareSerial * Ser2;
NETSGPClient * clientNETSGP;
NETSGPClient::InverterStatus status;
LC12S::Settings LC12S_settings;
uint32_t lastSendMillis;
uint32_t currentMillis;
};