Hej
potrzebuję pomocy przy w zasadzie gotowym projekcie z github ( https://github.com/syssi/esphome-pipsolar)
wszystko śmiga tylko problem z parsowaniem odpowiedzi na QPIGS
Sending polling command : QPIGS with length 5 17:59:04 [D] [uart_debug:114] >>> 51:50:49:47:53:B7:A9:0D 17:59:05 [D] [uart_debug:114] <<< 28:32:31:37:2E:31:20:35:30:2E:30:20:32:31:37:2E:31:20:35:30:2E:30:20:30:31:39:35:20:30:31:38:31:20:30:30:33:20:32:39:39:20:30:30:2E:34:30:20:30:30:30:20:30:30:30:20:30:30:32:30:20:30:30:2E:30:20:30:30:30:2E:30:20:30:30:2E:30:30:20:30:30:30:30:30:20:30:30:30:31:30:30:30:30:20:30:30:20:30:30:20:30:30:30:30:30:20:30:31:30:20:30:20:30:31:20:30:30:30:30:44:E3:0D 17:59:05 [VV ][scheduler:226] Running interval 'update' with interval=1000 last_execution=5664057 (now=5665057) 17:59:06 [VV ][scheduler:226] Running interval 'update' with interval=1000 last_execution=5665057 (now=5666061) 17:59:07 [VV ][scheduler:226] Running interval 'update' with interval=1000 last_execution=5666057 (now=5667057) 17:59:08 [VV ][scheduler:226] Running interval 'update' with interval=1000 last_execution=5667057 (now=5668062) 17:59:09 [VV ][scheduler:226] Running interval '' with interval=10000 last_execution=5658901 (now=5668901) 17:59:09 [VV ][scheduler:226] Running interval 'update' with interval=1000 last_execution=5668057 (now=5669057) 17:59:09 [D] [pipsolar:759] timeout command to poll: QPIGS 17:59:09 [D] [pipsolar:842]
przekroczony czas raczej wynika z przekroczeniem czasu biblioteki pipsolar a nie odczytem z portu który wygląda poprawnie.
Analiza QPIGS
Podział na pola (przykład):
- Grid voltage:
217.1 - Grid frequency:
50.0 - AC output voltage:
217.1 - AC output frequency:
50.0 - AC output apparent power:
0195 - AC output active power:
0181 - Output load percent:
003 - Bus voltage:
299 - Battery voltage:
00.40 - Battery charging current:
000 - Battery capacity:
000 - Inverter heat sink temperature:
0020 - PV input current:
00.0 - PV input voltage:
000.0 - SCC battery voltage:
00.00 - Battery discharge current:
00000 - Flags (
b7b6b5b4b3b2b1b0):01 0 01 - Extra:
0000D
Miał ktoś podobny problem? O co to może chodzić?
Prawdopodobnie problem w tym że dane są rozdzielone są spacją nie przecinkiem. Ale nie wiem jak to sprawdzić ;(
Poddaje się
prawdopodobnie popełniłem głupotę ale nie wiem gdzie wiec znalazłem wyjście na ten moment
# ==========================
# KONFIGURACJA OGÓLNA
# ==========================
substitutions:
name: easun_falownik_pv
tx_pin: GPIO16
rx_pin: GPIO17
esphome:
name: ${name}
platform: ESP32
board: esp32dev
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
manual_ip:
static_ip: 192.168.86.78
gateway: 192.168.86.1
subnet: 255.255.255.0
dns1: 8.8.8.8
dns2: 8.8.4.4
logger:
level: DEBUG
api:
encryption:
key: !secret key
ota:
password: !secret ota_password
platform: esphome
web_server:
port: 80
# ==========================
# KONFIGURACJA UART
# ==========================
uart:
id: uart_0
baud_rate: 2400
tx_pin: GPIO16
rx_pin: GPIO17
debug:
direction: BOTH
after:
delimiter: "\r" # Koniec wiadomości
# Wysyłanie poleceń QPIGS
interval:
- interval: 10s
then:
- logger.log:
level: INFO
format: "Wysyłanie QPIGS..."
- uart.write: [0x51, 0x50, 0x49, 0x47, 0x53, 0xB7, 0xA9, 0x0D]
- delay: 3s
- script.execute: parse_qpigs
# Wysyłanie poleceń QPIRI
- interval: 11s
then:
- logger.log:
level: INFO
format: "Wysyłanie QPIRI..."
- uart.write: [0x51, 0x50, 0x49, 0x52, 0x49, 0xD7, 0xA9, 0x0D]
- delay: 3s
- script.execute: parse_qpiri
# Wysyłanie poleceń QFLAG
- interval: 12s
then:
- logger.log:
level: INFO
format: "Wysyłanie polecenia UART QFLAG..."
- uart.write: [0x51, 0x46, 0x4C, 0x41, 0x47, 0xA9, 0x0D] # Polecenie QFLAG
- delay: 2s
- script.execute: parse_qflag # Uruchom skrypt przetwarzający dane QFLAG
# QMOD
- interval: 15s
then:
- logger.log:
level: INFO
format: "Wysyłanie polecenia UART QMOD..."
- uart.write: [0x51, 0x4D, 0x4F, 0x44, 0x49, 0x0D] # Polecenie QMOD
- delay: 2s
- script.execute: parse_qmod # Uruchom skrypt przetwarzający dane QMOD
# ==========================
# SKRYPTY DO PARSOWANIA
# ==========================
# Skrypt przetwarzający dane QPIGS
script:
- id: parse_qpigs
then:
- lambda: |-
static std::string buffer;
uint8_t byte;
while (id(uart_0).read_byte(&byte)) {
char c = static_cast<char>(byte);
buffer += c;
if (c == '\r') {
ESP_LOGI("UART", "Odebrano QPIGS: %s", buffer.c_str());
if (buffer[0] == '(' && buffer.length() > 70) {
id(grid_voltage).publish_state(atof(buffer.substr(1, 5).c_str()));
id(grid_frequency).publish_state(atof(buffer.substr(7, 4).c_str()));
id(output_voltage).publish_state(atof(buffer.substr(12, 5).c_str()));
id(output_frequency).publish_state(atof(buffer.substr(18, 4).c_str()));
id(output_power).publish_state(atof(buffer.substr(20, 4).c_str()));
id(load_percent).publish_state(atof(buffer.substr(25, 4).c_str()));
id(battery_voltage_qpigs).publish_state(atof(buffer.substr(39, 5).c_str()));
id(charge_current).publish_state(atof(buffer.substr(30, 3).c_str()));
id(discharge_current).publish_state(atof(buffer.substr(34, 4).c_str()));
id(system_status).publish_state(atoi(buffer.substr(68, 2).c_str()));
id(pv_voltage).publish_state(atof(buffer.substr(58, 4).c_str()));
id(pv_power).publish_state(atof(buffer.substr(63, 4).c_str()));
}
buffer.clear();
break;
}
}
# Skrypt przetwarzający dane QPIRI
- id: parse_qpiri
then:
- lambda: |-
static std::string buffer;
uint8_t byte;
while (id(uart_0).read_byte(&byte)) {
char c = static_cast<char>(byte);
buffer += c;
if (c == '\r') {
ESP_LOGI("UART", "Odebrano QPIRI: %s", buffer.c_str());
if (buffer[0] == '(' && buffer.length() > 100) {
id(ac_output_voltage).publish_state(atof(buffer.substr(1, 5).c_str()));
id(battery_voltage_qpiri).publish_state(atof(buffer.substr(7, 5).c_str()));
id(ac_input_voltage).publish_state(atof(buffer.substr(13, 5).c_str()));
id(ac_output_frequency).publish_state(atof(buffer.substr(19, 4).c_str()));
id(battery_charging_voltage).publish_state(atof(buffer.substr(24, 5).c_str()));
id(ac_output_max_apparent_power).publish_state(atof(buffer.substr(30, 5).c_str()));
id(ac_output_max_active_power).publish_state(atof(buffer.substr(36, 5).c_str()));
id(battery_max_voltage).publish_state(atof(buffer.substr(42, 5).c_str()));
id(battery_min_voltage).publish_state(atof(buffer.substr(48, 5).c_str()));
id(battery_cutoff_voltage).publish_state(atof(buffer.substr(54, 5).c_str()));
id(battery_recovery_voltage).publish_state(atof(buffer.substr(60, 5).c_str()));
id(battery_float_charge_voltage).publish_state(atof(buffer.substr(66, 5).c_str()));
id(battery_number).publish_state(atoi(buffer.substr(72, 2).c_str()));
id(max_battery_charging_current).publish_state(atof(buffer.substr(75, 3).c_str()));
id(inverter_temperature).publish_state(atof(buffer.substr(92, 4).c_str()));
id(fan_mode).publish_state(atoi(buffer.substr(97, 1).c_str()));
id(end_code).publish_state(atoi(buffer.substr(101, 3).c_str()));
}
buffer.clear();
break;
}
}
# QFLAG
- id: parse_qflag
then:
- lambda: |-
static std::string buffer;
uint8_t byte;
while (id(uart_0).read_byte(&byte)) {
char c = static_cast<char>(byte);
buffer += c;
if (c == '\r') {
ESP_LOGI("UART", "Odebrano QFLAG: %s", buffer.c_str());
if (buffer[0] == '(' && buffer.length() > 15) {
id(grid_bypass_flag).publish_state(atoi(buffer.substr(1, 1).c_str())); // Flaga bypassu sieci
id(output_short_circuit_flag).publish_state(atoi(buffer.substr(2, 1).c_str())); // Flaga zwarcia wyjścia
id(power_saving_mode_flag).publish_state(atoi(buffer.substr(3, 1).c_str())); // Flaga trybu oszczędzania energii
id(battery_weak_flag).publish_state(atoi(buffer.substr(4, 1).c_str())); // Flaga słabej baterii
id(load_on_flag).publish_state(atoi(buffer.substr(5, 1).c_str())); // Flaga włączenia obciążenia
id(battery_overcharge_flag).publish_state(atoi(buffer.substr(6, 1).c_str())); // Flaga przeładowania baterii
id(system_overheat_flag).publish_state(atoi(buffer.substr(7, 1).c_str())); // Flaga przegrzania systemu
id(system_shutdown_flag).publish_state(atoi(buffer.substr(8, 1).c_str())); // Flaga wyłączenia systemu
id(inverter_fault_flag).publish_state(atoi(buffer.substr(9, 1).c_str())); // Flaga awarii falownika
id(charger_fault_flag).publish_state(atoi(buffer.substr(10, 1).c_str())); // Flaga awarii ładowarki
id(pv_power_saving_flag).publish_state(atoi(buffer.substr(11, 1).c_str())); // Flaga oszczędzania PV
id(internal_com_error_flag).publish_state(atoi(buffer.substr(12, 1).c_str())); // Flaga błędu komunikacji wewnętrznej
id(emergency_shutdown_flag).publish_state(atoi(buffer.substr(13, 1).c_str())); // Flaga awaryjnego wyłączenia
id(low_frequency_flag).publish_state(atoi(buffer.substr(14, 1).c_str())); // Flaga niskiej częstotliwości
}
buffer.clear();
break;
}
}
# QMOD
- id: parse_qmod
then:
- lambda: |-
static std::string buffer;
uint8_t byte;
while (id(uart_0).read_byte(&byte)) {
char c = static_cast<char>(byte);
buffer += c;
if (c == '\r') {
ESP_LOGI("UART", "Odebrano QMOD: %s", buffer.c_str());
// Sprawdź poprawność odpowiedzi
if (buffer[0] == '(' && buffer.length() == 3) { // Oczekiwany format QMOD: np. "(S)"
char mode = buffer[1]; // Drugi znak to tryb pracy
std::string mode_str;
switch (mode) {
case 'S': mode_str = "Standby"; break;
case 'L': mode_str = "Line"; break;
case 'B': mode_str = "Battery"; break;
case 'F': mode_str = "Fault"; break;
case 'P': mode_str = "Power Saving"; break;
case 'H': mode_str = "Standby Heating"; break;
default: mode_str = "Unknown"; break;
}
id(inverter_mode).publish_state(mode_str);
} else {
ESP_LOGW("QMOD", "Nieprawidłowa odpowiedź: %s", buffer.c_str());
id(inverter_mode).publish_state("Invalid Data");
}
buffer.clear();
break;
}
}
# ==========================
# SENSORY
# ==========================
sensor:
# Sensory dla QPIGS
- platform: template
name: "Napięcie Sieci (AC)"
id: grid_voltage
unit_of_measurement: "V"
- platform: template
name: "Częstotliwość Sieci (AC)"
id: grid_frequency
unit_of_measurement: "Hz"
- platform: template
name: "Napięcie Wyjściowe (AC)"
id: output_voltage
unit_of_measurement: "V"
- platform: template
name: "Częstotliwość Wyjściowa (AC)"
id: output_frequency
unit_of_measurement: "Hz"
- platform: template
name: "Moc Wyjściowa (W)"
id: output_power
unit_of_measurement: "W"
- platform: template
name: "Obciążenie (%)"
id: load_percent
unit_of_measurement: "%"
- platform: template
name: "Napięcie Baterii (QPIGS)"
id: battery_voltage_qpigs
unit_of_measurement: "V"
- platform: template
name: "Prąd Ładowania (A)"
id: charge_current
unit_of_measurement: "A"
- platform: template
name: "Prąd Rozładowania (A)"
id: discharge_current
unit_of_measurement: "A"
- platform: template
name: "Napięcie PV (V)"
id: pv_voltage
unit_of_measurement: "V"
- platform: template
name: "Moc PV (W)"
id: pv_power
unit_of_measurement: "W"
- platform: template
name: "Stan Systemu"
id: system_status
unit_of_measurement: ""
# Sensory QPIRI
- platform: template
name: "Napięcie Wyjściowe (AC)"
id: ac_output_voltage
unit_of_measurement: "V"
- platform: template
name: "Napięcie Wejściowe (AC)"
id: ac_input_voltage
unit_of_measurement: "V"
- platform: template
name: "Częstotliwość Wyjściowa (AC)"
id: ac_output_frequency
unit_of_measurement: "Hz"
- platform: template
name: "Napięcie Ładowania Baterii (V)"
id: battery_charging_voltage
unit_of_measurement: "V"
- platform: template
name: "Maksymalna Moc Wyjściowa (VA)"
id: ac_output_max_apparent_power
unit_of_measurement: "VA"
- platform: template
name: "Maksymalna Moc Wyjściowa (W)"
id: ac_output_max_active_power
unit_of_measurement: "W"
- platform: template
name: "Maksymalne Napięcie Akumulatora (V)"
id: battery_max_voltage
unit_of_measurement: "V"
- platform: template
name: "Minimalne Napięcie Akumulatora (V)"
id: battery_min_voltage
unit_of_measurement: "V"
- platform: template
name: "Napięcie Odcięcia Akumulatora (V)"
id: battery_cutoff_voltage
unit_of_measurement: "V"
- platform: template
name: "Napięcie Odzysku Zasilania (V)"
id: battery_recovery_voltage
unit_of_measurement: "V"
- platform: template
name: "Napięcie Zakończenia Ładowania (V)"
id: battery_float_charge_voltage
unit_of_measurement: "V"
- platform: template
name: "Liczba Podłączonych Akumulatorów"
id: battery_number
unit_of_measurement: ""
- platform: template
name: "Maksymalny Prąd Ładowania Akumulatorów (A)"
id: max_battery_charging_current
unit_of_measurement: "A"
- platform: template
name: "Temperatura Falownika (°C)"
id: inverter_temperature
unit_of_measurement: "°C"
- platform: template
name: "Tryb Wentylatora"
id: fan_mode
unit_of_measurement: ""
- platform: template
name: "Kod Końcowy"
id: end_code
unit_of_measurement: ""
- platform: template
name: "Napięcie Baterii (QPIGS)"
id: battery_voltage_qpiri
unit_of_measurement: "V"
binary_sensor:
# Flagi QFLAG
- platform: template
name: "Bypass Sieci"
id: grid_bypass_flag
lambda: |-
return id(grid_bypass_flag).state == 1;
device_class: power
- platform: template
name: "Zwarcie Wyjścia"
id: output_short_circuit_flag
lambda: |-
return id(output_short_circuit_flag).state == 1;
device_class: safety
- platform: template
name: "Tryb Oszczędzania Energii"
id: power_saving_mode_flag
lambda: |-
return id(power_saving_mode_flag).state == 1;
device_class: power
- platform: template
name: "Słaba Bateria"
id: battery_weak_flag
lambda: |-
return id(battery_weak_flag).state == 1;
device_class: battery
- platform: template
name: "Obciążenie Włączone"
id: load_on_flag
lambda: |-
return id(load_on_flag).state == 1;
device_class: power
- platform: template
name: "Przeładowanie Baterii"
id: battery_overcharge_flag
lambda: |-
return id(battery_overcharge_flag).state == 1;
device_class: safety
- platform: template
name: "Przegrzanie Systemu"
id: system_overheat_flag
lambda: |-
return id(system_overheat_flag).state == 1;
device_class: problem
- platform: template
name: "Wyłączenie Systemu"
id: system_shutdown_flag
lambda: |-
return id(system_shutdown_flag).state == 1;
device_class: problem
- platform: template
name: "Awaria Falownika"
id: inverter_fault_flag
lambda: |-
return id(inverter_fault_flag).state == 1;
device_class: problem
- platform: template
name: "Awaria Ładowarki"
id: charger_fault_flag
lambda: |-
return id(charger_fault_flag).state == 1;
device_class: problem
- platform: template
name: "Tryb Oszczędzania PV"
id: pv_power_saving_flag
lambda: |-
return id(pv_power_saving_flag).state == 1;
device_class: power
- platform: template
name: "Błąd Komunikacji Wewnętrznej"
id: internal_com_error_flag
lambda: |-
return id(internal_com_error_flag).state == 1;
device_class: problem
- platform: template
name: "Awaryjne Wyłączenie"
id: emergency_shutdown_flag
lambda: |-
return id(emergency_shutdown_flag).state == 1;
device_class: safety
- platform: template
name: "Niska Częstotliwość"
id: low_frequency_flag
lambda: |-
return id(low_frequency_flag).state == 1;
device_class: problem
# ==========================
# TEKSTOWE SENSORY (QMOD)
# ==========================
text_sensor:
- platform: template
name: "Tryb Pracy Falownika"
id: inverter_mode
icon: "mdi:transmission-tower"
QMOD jeszcze nie działa reszta z grubsza poprawnie
Chętni sobie doszlifują.....lub nie 😉
Udało się komuś odczytać dane z falownika te które są na bieżąco modyfikowane np. obciążenie, napięcie na panelach, moc paneli ?
Mam takie błędy. Falownik Qoltec Off Grid 6kw.
Plik wgrywałem powyższy i ten oryginalny pipsolar i cały czas większe lub mniejsze błędy ale nigdy nie podał powyższych danych.
Sending polling command : QPIGS with length 5 [14:08:14][D][pipsolar:776]: checking crc on incoming message [14:08:14][D][pipsolar:785]: CRC NOK expected: E1 9F but got: EE 9B [14:08:14][D][pipsolar:840]: Sending polling command : QMOD with length 4 [14:08:15][D][pipsolar:776]: checking crc on incoming message [14:08:15][D][pipsolar:779]: CRC OK

