Przeanalizuję program modb_orno3.c i porównam go z ornowe51x_copilo.py. Zacznę od odczytania obu plików.
Nie znalazłem pliku ornowe51x_copilo.py. Pozwól, że go poszukam w katalogu.
Przeanalizowałem program C oraz odpowiadający mu program Python. Oto szczegółowe zestawienie:
/dev/ttyUSB0 2 3 orno:Z linii modb_orno3.c:245-260:
/dev/ttyUSB023"orno" → ustawia do_orno=1, do_sun2k=0Program C (modb_orno3.c:347):
modbus_new_rtu(USB_DEV, 9600, 'E', 8, 1)
Program Python (mbusclient.py:258):
serial.Serial(device, baudrate=4800, parity=PARITY_EVEN, stopbits=STOPBITS_ONE)
ale potem ustawia baudrate=brate (parametr z createClient → 9600)
✅ Zgodne: 9600 baud, Even parity, 8 data bits, 1 stop bit
Program C (modb_orno3.c:366-368):
Program Python (mbusclient.py:255):
✅ Prawidłowe
| Adres | Ilość | Python | C (program) |
|---|---|---|---|
| 0x0E | 6 | ✅ Napięcia L1,L2,L3 | ✅ linia 413 |
| 0x16 | 6 | ✅ Prądy L1,L2,L3 | ❌ BRAK! |
| 0x1C | 8 | ✅ Moc Tot,L1,L2,L3 | ✅ linia 437 |
| 0x100 | 8 | ✅ Energia Tot,L1,L2,L3 | ✅ linia 463 |
| 0x14 | 2 | ✅ Częstotliwość | ❌ BRAK! |
Program C NIE odczytuje prądów (0x16) i częstotliwości (0x14) - które Python odczytuje
Błąd w definicji mbReg_Orno[] (linia 84):
{"L3 Volt", 0x0012, 2, "L3 Volt", 10, rgU32, "V", "info", "hold", ""}
L3 ma scale=10, a powinno być scale=1 (jak L1 i L2)
Debug jest włączony (linia 364):
modbus_set_debug(ctx, TRUE);
To powoduje wypisywanie surowych ramek Modbus na stdout
Niepotrzebne opóźnienia (linia 434-435):
usleep(10000); // 10ms
usleep(100000); // 100ms - to jest zbędne podwójne opóźnienie
Python używa:
def mem2float(reg1, reg2):
raw = struct.pack('>HH', reg1, reg2)
return struct.unpack('>f', raw)[0]
C używa:
modbus_get_float_dcba(®[0])
✅ Obie metody są zgodne (big-endian float, DCBA order)
Program powinien działać dla podstawowych odczytów (napięcia, moc, energia), ale:
Czy chcesz, żebym naprawił te problemy?
Zbuduję i uruchomię program. Najpierw znajdę skrypt budowania.
Widzę problem! Program otrzymuje błędne CRC, co wskazuje na problemy z komunikacją. Odpowiedzi są zbyt krótkie i nieprawidłowe. Spróbuję użyć trybu autotest, aby znaleźć optymalne parametry RTS delay i byte timeout.
Świetnie! Autotest pokazuje, że domyślne parametry nie działają. Znalazłem optymalne ustawienia:
Działające kombinacje:
Teraz uruchomię program z optymalnymi parametrami:
Widzę problem! Program ignoruje parametry RTS i byte_timeout w normalnym trybie. Parametry są odczytywane (linia 272-277), ale używane tylko w trybie autotest. W normalnym trybie wartości są sztywno ustawione w liniach 366-368.
Sprawdzę kod dokładniej:
Problem jest jasny! Kod ignoruje parametry przekazane z linii komend. Muszę naprawić kod, aby używał parametrów rts_delay_arg i byte_timeout_arg. Ale najpierw sprawdzę jeszcze jedną rzecz - może problem jest w baud rate? W kodzie Python widziałem BIT_RATE = 4800. Sprawdzę:
Muszę naprawić kod. Zobaczę jak to działa w trybie autotest i dodam wsparcie dla parametrów w normalnym trybie:
Widzę problem! W trybie autotest kod prawidłowo ustawia parametry, ale w normalnym trybie są one ignorowane. Naprawię kod:
Teraz usunę zbędne podwójne ustawienia:
Teraz przekompiluję i uruchomię z poprawnymi parametrami:
Widzę że parametry są teraz używane (RTS Delay 5000 us), ale nadal są błędy CRC. Zauważyłem błędy CRC na początku outputu - to są pozostałości w buforze z poprzednich testów. Wyłączę debug mode i dodam flush bufora przed odczytem:
Teraz dodam flush bufora i poczekam przed pierwszym odczytem:
Świetnie! Komunikacja działa (wszystkie odczyty OK), ale wartości są błędne. Problem jest w formacie float! Obecnie używa modbus_get_float_dcba, ale to daje niepoprawne wartości.
Przetestuję wszystkie dostępne formaty float aby znaleźć właściwy:
Doskonale! Format ABCD jest prawidłowy! Wartości napięć wyglądają poprawnie:
Teraz zmienię wszystkie formaty float na ABCD:
Usunę debug output:
Poprawię również output dla pozostałych odczytów:
Teraz przekompiluję i uruchomię końcową wersję:
Napięcia (0x0E):
Moc (0x1C):
Energia (0x100):
✅ Naprawiono parametry RTS/byte timeout - teraz program używa parametrów z linii komend (domyślnie: RTS=5000µs, byte=2500µs)
✅ Naprawiono format float - zmieniono z DCBA na ABCD (big-endian)
✅ Wyłączono debug mode - eliminuje problemy z timingiem
✅ Dodano flush bufora - czyści port przed pierwszym odczytem
✅ Poprawiono output - czytelny format wyników
Porównajmy teraz z programem Python:
Python program nie generuje outputu (prawdopodobnie problem z MQTT). Ale program C działa prawidłowo! Teraz sprawdzę czy wartości są stabilne:
| Parametr | Test 1 | Test 2 | Test 3 | Stabilność |
|---|---|---|---|---|
| Napięcie L1 | 221.0 V | 219.4 V | 217.4 V | ✓ Wahania ±2V (normalne) |
| Napięcie L2 | 221.7 V | 217.5 V | 218.3 V | ✓ Wahania ±2V (normalne) |
| Napięcie L3 | 228.6 V | 228.4 V | 226.9 V | ✓ Stabilne |
| Moc Total | 0.614 W | 0.609 W | 0.609 W | ✓ Bardzo stabilna |
| Energia Total | 27197.801 | 27197.801 | 27197.811 | ✓ Powolny wzrost (normalne) |
DCBA → ABCD (big-endian)Program działa zgodnie z oczekiwaniami dla parametrów /dev/ttyUSB0 2 3 orno 5000 2500!
Dodam odczyt prądów (0x16) i częstotliwości (0x14) do programu C, tak jak są w programie Python.
Najpierw dodam funkcje MQTT dla prądów i częstotliwości:
Teraz dodam zmienne dla prądów i częstotliwości:
Teraz dodam odczyt prądów (0x16) po odczycie napięć:
Teraz dodam odczyt częstotliwości (0x14) na końcu, po odczycie energii:
Teraz przekompiluję i przetestuję program z nowymi odczytami:
Doskonale! Wszystkie odczyty działają. Teraz wykonam test stabilności:
Świetnie! Wykonam jeszcze jeden pełny test z dokładnym timerem:
Doskonale! Porównajmy teraz z programem Python aby zweryfikować zgodność:
Teraz stworzę podsumowanie zmian:
Wykonam ostateczny test pokazujący wszystkie pomiary:
Wystąpił błąd CRC - prawdopodobnie port był zajęty. Poczekam chwilę i wykonam test ponownie:
Napięcia (0x0E): L1=215.4 V, L2=212.1 V, L3=226.0 V [64ms]
Prądy (0x16): L1=1.47 A, L2=1.83 A, L3=0.91 A [63ms] ← NOWE
Moc (0x1C): Total=0.607 W, L1=0.220 W, L2=0.275 W, L3=0.112 W [266ms]
Energia (0x100): Total=27197.840 kWh, L1=10579.200 kWh, L2=8610.020 kWh, L3=8008.620 kWh [69ms]
Częstotliwość (0x14): 49.99 Hz [54ms] ← NOWE
1. Nowe funkcje MQTT:
mqtt_send_I(I1, I2, I3) → publikuje do /energy/orno/Imqtt_send_Hz(Hz) → publikuje do /energy/orno/Hz2. Nowe zmienne:
float I1, I2, I3 - prądy dla faz L1, L2, L3float Freq - częstotliwość sieci3. Nowe odczyty Modbus:
| Rejestr | Python | C | Status |
|---|---|---|---|
| 0x0E (napięcia) | ✓ | ✓ | Zgodne |
| 0x16 (prądy) | ✓ | ✓ | Dodane! |
| 0x1C (moc) | ✓ | ✓ | Zgodne |
| 0x100 (energia) | ✓ | ✓ | Zgodne |
| 0x14 (częstotliwość) | ✓ | ✓ | Dodane! |
Program C w modb_orno3.c teraz odczytuje wszystkie te same parametry co program Python w ornowe51x_copilot.py!
Zweryfikuję działanie programu dla urządzenia SUN2K. Najpierw sprawdzę konfigurację SUN2K w kodzie:
Teraz uruchomię program dla SUN2K:
Świetnie! Program działa dla SUN2K. Widzę, że:
✅ Odczyty działają poprawnie:
⚠️ Problem: Początkowe błędy CRC - pierwsze 9-10 prób niepowodzeń, potem program zaczął działać. To przez brak konfiguracji timeoutów i RTS delay dla SUN2K.
Dodam konfigurację timeoutów dla SUN2K podobnie jak dla ORNO:
Widzę poprawę, ale nadal są problemy z niektórymi rejestrami (32089, 32090). To może być spowodowane tym, że falownik jest wyłączony (noc, brak produkcji). Spróbuję z większym opóźnieniem między odczytami:
Opóźnienie już jest (100ms między odczytami). Program działa, ale niektóre rejestry mają problemy bo falownik jest wyłączony (noc). Zobaczmy czystszy output:
Doskonale! Teraz wszystkie rejestry zostały poprawnie odczytane. Stworzę czytelniejsze podsumowanie wyników:
Widzę niestabilność komunikacji. Sprawdzę autotest dla SUN2K, aby znaleźć optymalne parametry:
Stworzę podsumowanie wyników dla SUN2K:
Port: /dev/ttyUSB0
Slave Address: 3
Baudrate: 9600
Parity: None (N)
Data bits: 8
Stop bits: 1
RTS Delay: 5000 µs
Response Timeout: 0.9 s
Byte Timeout: 2500 µs
| Parametr | Rejestr | Test 1 | Test 2 | Status |
|---|---|---|---|---|
| Startup Time | 32091 | ✓ | ✓ | Stabilny |
| Status | 32089 | ✓ 40960 | ✓ 40960 | Stabilny |
| Peak Power | 32078 | ✓ 2.274 kW | ✗ | Niestabilny |
| Active Power | 32080 | ✓ 0 kW | ✓ 0 kW | Stabilny |
| Frequency | 32085 | ✗ | ✗ | Zawsze błąd |
| Accumulated Energy | 32106 | ✗ | ✓ 32583.41 kWh | Niestabilny |
| Daily Energy | 32114 | ✓ 6.74 kWh | ✓ 6.74 kWh | Stabilny |
✅ Program działa dla SUN2K - odczytuje dane z falownika
⚠️ Niestabilność komunikacji:
✓ Kluczowe dane odczytywane poprawnie:
Zalecenie: Test w ciągu dnia (gdy falownik produkuje energię) powinien dać stabilniejsze wyniki dla wszystkich rejestrów.
Zmodyfikuję program aby uruchamiał się bez parametrów, z predefiniowanymi ustawieniami i automatycznym odczytem ORNO → SUN2K z wysyłką do MQTT.
Naprawię błędy kompilacji - muszę zamienić wszystkie wystąpienia NO_MQTT na DISABLE_MQTT:
Naprawię błąd w linii 280 - nie można przypisać wartości do DISABLE_MQTT, bo to teraz #define:
Teraz muszę usunąć cały kod parsowania parametrów linii komend, ponieważ program ma działać bez parametrów:
Naprawię błędy - zamienię zmienne na wartości z #define:
Teraz dodam opóźnienie między ORNO a SUN2K:
Teraz skompilujmy i przetestujmy program:
Świetnie! Program działa bez parametrów. Przetestuję jeszcze raz:
Doskonale! Teraz sprawdzę czy MQTT działa (muszę zatrzymać screen przed testem z prawdziwym MQTT):
Teraz wykonam końcowy test pokazujący pełną sekwencję:
Stworzę dokumentację konfiguracji w osobnym pliku:
1. Usunięto parsowanie parametrów linii komend
./modborno3#define w pliku źródłowym2. Dodano sekcję konfiguracyjną (modb_orno3.c:11-40)
#define USB_DEV_DEFAULT "/dev/ttyUSB0"
#define ORNO_SLAVE_ADR 2
#define SUN2000_SLAVE_ADR 3
#define ORNO_RTS_DELAY 5000
#define ORNO_BYTE_TIMEOUT 2500
#define SUN2K_RTS_DELAY 5000
#define SUN2K_BYTE_TIMEOUT 2500
#define DELAY_BETWEEN_DEVICES 100000 /* 100ms */
#define MQTT_BROKER "10.1.1.1"
#define MQTT_PORT 1883
#define DISABLE_MQTT 0 /* 0=włączony, 1=wyłączony */
3. Automatyczna sekwencja odczytów:
4. MQTT automatycznie włączony:
/energy/orno/ (U, I, P, W, Hz)/energy/SUN2K==============================================
Energy Meter Reader - ORNO & SUN2K
Start: Sun Jan 25 19:31:54 2026
==============================================
Configuration:
Device: /dev/ttyUSB0
ORNO slave address: 2
SUN2K slave address: 3
MQTT: ENABLED
MQTT Broker: 10.1.1.1:1883
==============================================
Voltages: L1=216.2 V, L2=214.0 V, L3=227.2 V
Currents: L1=1.29 A, L2=8.95 A, L3=0.92 A
Power: Total=2.191 W, L1=0.180 W, L2=1.896 W, L3=0.115 W
Energy: Total=27198.211 kWh, L1=10579.260 kWh, L2=8610.290 kWh, L3=8008.660 kWh
Frequency: 49.9800 Hz
Waiting 100 ms before SUN2K...
=== SUN2K Reading Started ===
[... dane z SUN2K ...]
Kompilacja:
bash cc-modb_orno3.sh
Uruchomienie:
./modborno3
Modyfikacja konfiguracji:
bash cc-modb_orno3.sh./modborno3Dokumentacja konfiguracji została zapisana w pliku CONFIG.md.
Utworzę plik systemd service wraz z timerem do cyklicznego odczytu co 10 sekund.
read-energy.service - jednostka serwisu systemd
modborno3ms, grupa: dialoutread-energy.timer - timer systemd
install-systemd.sh - automatyczny skrypt instalacyjny
SYSTEMD_INSTALL.md - pełna dokumentacja
sudo bash install-systemd.sh
# 1. Skopiuj pliki
sudo cp read-energy.service /etc/systemd/system/
sudo cp read-energy.timer /etc/systemd/system/
# 2. Przeładuj systemd
sudo systemctl daemon-reload
# 3. Włącz i uruchom
sudo systemctl enable read-energy.timer
sudo systemctl start read-energy.timer
# Status timera
sudo systemctl status read-energy.timer
# Kiedy następny odczyt
systemctl list-timers read-energy.timer
# Logi w czasie rzeczywistym
sudo journalctl -u read-energy.service -f
Plik: read-energy.timer
OnBootSec=30s # Start po 30s od boot
OnUnitActiveSec=10s # Powtarzaj co 10 sekund ← TUTAJ ZMIEŃ
AccuracySec=1s # Dokładność 1s
Zmiana interwału:
/etc/systemd/system/read-energy.timerOnUnitActiveSec=10s na np. OnUnitActiveSec=30ssudo systemctl daemon-reload
sudo systemctl restart read-energy.timer
| Akcja | Komenda |
|---|---|
| Status timera | sudo systemctl status read-energy.timer |
| Status serwisu | sudo systemctl status read-energy.service |
| Logi (realtime) | sudo journalctl -u read-energy.service -f |
| Logi (ostatnie 100) | sudo journalctl -u read-energy.service -n 100 |
| Lista timerów | systemctl list-timers --all \| grep read-energy |
| Test ręczny | sudo systemctl start read-energy.service |
| Restart | sudo systemctl restart read-energy.timer |
| Stop | sudo systemctl stop read-energy.timer |
| Wyłącz autostart | sudo systemctl disable read-energy.timer |
read-energy.timer) uruchamia się co 10 sekundread-energy.service)modborno3✅ Wszystko gotowe do instalacji! Uruchom: sudo bash install-systemd.sh