Files
modborno3/CONFIG.html

612 lines
19 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<title>CONFIG.md</title>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<style>
/* https://github.com/microsoft/vscode/blob/master/extensions/markdown-language-features/media/markdown.css */
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
body {
font-family: var(--vscode-markdown-font-family, -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif);
font-size: var(--vscode-markdown-font-size, 14px);
padding: 0 26px;
line-height: var(--vscode-markdown-line-height, 22px);
word-wrap: break-word;
}
#code-csp-warning {
position: fixed;
top: 0;
right: 0;
color: white;
margin: 16px;
text-align: center;
font-size: 12px;
font-family: sans-serif;
background-color:#444444;
cursor: pointer;
padding: 6px;
box-shadow: 1px 1px 1px rgba(0,0,0,.25);
}
#code-csp-warning:hover {
text-decoration: none;
background-color:#007acc;
box-shadow: 2px 2px 2px rgba(0,0,0,.25);
}
body.scrollBeyondLastLine {
margin-bottom: calc(100vh - 22px);
}
body.showEditorSelection .code-line {
position: relative;
}
body.showEditorSelection .code-active-line:before,
body.showEditorSelection .code-line:hover:before {
content: "";
display: block;
position: absolute;
top: 0;
left: -12px;
height: 100%;
}
body.showEditorSelection li.code-active-line:before,
body.showEditorSelection li.code-line:hover:before {
left: -30px;
}
.vscode-light.showEditorSelection .code-active-line:before {
border-left: 3px solid rgba(0, 0, 0, 0.15);
}
.vscode-light.showEditorSelection .code-line:hover:before {
border-left: 3px solid rgba(0, 0, 0, 0.40);
}
.vscode-light.showEditorSelection .code-line .code-line:hover:before {
border-left: none;
}
.vscode-dark.showEditorSelection .code-active-line:before {
border-left: 3px solid rgba(255, 255, 255, 0.4);
}
.vscode-dark.showEditorSelection .code-line:hover:before {
border-left: 3px solid rgba(255, 255, 255, 0.60);
}
.vscode-dark.showEditorSelection .code-line .code-line:hover:before {
border-left: none;
}
.vscode-high-contrast.showEditorSelection .code-active-line:before {
border-left: 3px solid rgba(255, 160, 0, 0.7);
}
.vscode-high-contrast.showEditorSelection .code-line:hover:before {
border-left: 3px solid rgba(255, 160, 0, 1);
}
.vscode-high-contrast.showEditorSelection .code-line .code-line:hover:before {
border-left: none;
}
img {
max-width: 100%;
max-height: 100%;
}
a {
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
a:focus,
input:focus,
select:focus,
textarea:focus {
outline: 1px solid -webkit-focus-ring-color;
outline-offset: -1px;
}
hr {
border: 0;
height: 2px;
border-bottom: 2px solid;
}
h1 {
padding-bottom: 0.3em;
line-height: 1.2;
border-bottom-width: 1px;
border-bottom-style: solid;
}
h1, h2, h3 {
font-weight: normal;
}
table {
border-collapse: collapse;
}
table > thead > tr > th {
text-align: left;
border-bottom: 1px solid;
}
table > thead > tr > th,
table > thead > tr > td,
table > tbody > tr > th,
table > tbody > tr > td {
padding: 5px 10px;
}
table > tbody > tr + tr > td {
border-top: 1px solid;
}
blockquote {
margin: 0 7px 0 5px;
padding: 0 16px 0 10px;
border-left-width: 5px;
border-left-style: solid;
}
code {
font-family: Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback";
font-size: 1em;
line-height: 1.357em;
}
body.wordWrap pre {
white-space: pre-wrap;
}
pre:not(.hljs),
pre.hljs code > div {
padding: 16px;
border-radius: 3px;
overflow: auto;
}
pre code {
color: var(--vscode-editor-foreground);
tab-size: 4;
}
/** Theming */
.vscode-light pre {
background-color: rgba(220, 220, 220, 0.4);
}
.vscode-dark pre {
background-color: rgba(10, 10, 10, 0.4);
}
.vscode-high-contrast pre {
background-color: rgb(0, 0, 0);
}
.vscode-high-contrast h1 {
border-color: rgb(0, 0, 0);
}
.vscode-light table > thead > tr > th {
border-color: rgba(0, 0, 0, 0.69);
}
.vscode-dark table > thead > tr > th {
border-color: rgba(255, 255, 255, 0.69);
}
.vscode-light h1,
.vscode-light hr,
.vscode-light table > tbody > tr + tr > td {
border-color: rgba(0, 0, 0, 0.18);
}
.vscode-dark h1,
.vscode-dark hr,
.vscode-dark table > tbody > tr + tr > td {
border-color: rgba(255, 255, 255, 0.18);
}
</style>
<style>
/* Tomorrow Theme */
/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */
/* Original theme - https://github.com/chriskempson/tomorrow-theme */
/* Tomorrow Comment */
.hljs-comment,
.hljs-quote {
color: #8e908c;
}
/* Tomorrow Red */
.hljs-variable,
.hljs-template-variable,
.hljs-tag,
.hljs-name,
.hljs-selector-id,
.hljs-selector-class,
.hljs-regexp,
.hljs-deletion {
color: #c82829;
}
/* Tomorrow Orange */
.hljs-number,
.hljs-built_in,
.hljs-builtin-name,
.hljs-literal,
.hljs-type,
.hljs-params,
.hljs-meta,
.hljs-link {
color: #f5871f;
}
/* Tomorrow Yellow */
.hljs-attribute {
color: #eab700;
}
/* Tomorrow Green */
.hljs-string,
.hljs-symbol,
.hljs-bullet,
.hljs-addition {
color: #718c00;
}
/* Tomorrow Blue */
.hljs-title,
.hljs-section {
color: #4271ae;
}
/* Tomorrow Purple */
.hljs-keyword,
.hljs-selector-tag {
color: #8959a8;
}
.hljs {
display: block;
overflow-x: auto;
color: #4d4d4c;
padding: 0.5em;
}
.hljs-emphasis {
font-style: italic;
}
.hljs-strong {
font-weight: bold;
}
</style>
<style>
/*
* Markdown PDF CSS
*/
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif, "Meiryo";
padding: 0 12px;
}
pre {
background-color: #f8f8f8;
border: 1px solid #cccccc;
border-radius: 3px;
overflow-x: auto;
white-space: pre-wrap;
overflow-wrap: break-word;
}
pre:not(.hljs) {
padding: 23px;
line-height: 19px;
}
blockquote {
background: rgba(127, 127, 127, 0.1);
border-color: rgba(0, 122, 204, 0.5);
}
.emoji {
height: 1.4em;
}
code {
font-size: 14px;
line-height: 19px;
}
/* for inline code */
:not(pre):not(.hljs) > code {
color: #C9AE75; /* Change the old color so it seems less like an error */
font-size: inherit;
}
/* Page Break : use <div class="page"/> to insert page break
-------------------------------------------------------- */
.page {
page-break-after: always;
}
</style>
<script src="https://unpkg.com/mermaid/dist/mermaid.min.js"></script>
</head>
<body>
<script>
mermaid.initialize({
startOnLoad: true,
theme: document.body.classList.contains('vscode-dark') || document.body.classList.contains('vscode-high-contrast')
? 'dark'
: 'default'
});
</script>
<h1 id="konfiguracja-programu-modborno3">Konfiguracja programu modb_orno3</h1>
<h2 id="parametry-konfiguracyjne">Parametry konfiguracyjne</h2>
<p>Wszystkie parametry są zdefiniowane na początku pliku <code>modb_orno3.c</code> (linie 11-40):</p>
<pre class="hljs"><code><div><span class="hljs-comment">/* KONFIGURACJA PROGRAMU - EDYTUJ TU */</span>
<span class="hljs-comment">/* Port szeregowy */</span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> USB_DEV_DEFAULT <span class="hljs-meta-string">"/dev/ttyUSB0"</span></span>
<span class="hljs-comment">/* Adresy urządzeń Modbus RTU */</span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> ORNO_SLAVE_ADR 2</span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> SUN2000_SLAVE_ADR 3</span>
<span class="hljs-comment">/* Parametry timing dla ORNO (mikrosekund) */</span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> ORNO_RTS_DELAY 5000 <span class="hljs-comment">/* RTS delay: 5ms */</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> ORNO_BYTE_TIMEOUT 2500 <span class="hljs-comment">/* Byte timeout: 2.5ms */</span></span>
<span class="hljs-comment">/* Parametry timing dla SUN2K (mikrosekund) */</span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> SUN2K_RTS_DELAY 5000 <span class="hljs-comment">/* RTS delay: 5ms */</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> SUN2K_BYTE_TIMEOUT 2500 <span class="hljs-comment">/* Byte timeout: 2.5ms */</span></span>
<span class="hljs-comment">/* Przerwa między ORNO a SUN2K (mikrosekund) */</span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> DELAY_BETWEEN_DEVICES 100000 <span class="hljs-comment">/* 100ms */</span></span>
<span class="hljs-comment">/* MQTT - ustaw 1 aby wyłączyć MQTT */</span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> DISABLE_MQTT 0 <span class="hljs-comment">/* 0 = MQTT włączony, 1 = wyłączony */</span></span>
<span class="hljs-comment">/* Broker MQTT */</span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> MQTT_BROKER <span class="hljs-meta-string">"10.1.1.1"</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> MQTT_PORT 1883</span>
<span class="hljs-comment">/* Tryb pracy */</span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> READ_LOOP false <span class="hljs-comment">/* false = jeden odczyt, true = pętla co 5s */</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> READ_ORNO true <span class="hljs-comment">/* Czy odczytywać ORNO */</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> READ_SUN2K true <span class="hljs-comment">/* Czy odczytywać SUN2K */</span></span>
</div></code></pre>
<h2 id="uruchomienie">Uruchomienie</h2>
<h3 id="kompilacja">Kompilacja:</h3>
<pre class="hljs"><code><div>bash cc-modb_orno3.sh
</div></code></pre>
<h3 id="uruchomienie">Uruchomienie:</h3>
<pre class="hljs"><code><div>./modborno3
</div></code></pre>
<p>Program uruchamia się <strong>bez parametrów</strong> i używa konfiguracji z #define.</p>
<h2 id="sekwencja-dzia%C5%82ania">Sekwencja działania</h2>
<ol>
<li>
<p><strong>Odczyt ORNO</strong> (adres Modbus: 2)</p>
<ul>
<li>Napięcia L1, L2, L3</li>
<li>Prądy L1, L2, L3</li>
<li>Moc Total, L1, L2, L3</li>
<li>Energia Total, L1, L2, L3</li>
<li>Częstotliwość</li>
</ul>
</li>
<li>
<p><strong>Przerwa 100ms</strong></p>
</li>
<li>
<p><strong>Odczyt SUN2K</strong> (adres Modbus: 3)</p>
<ul>
<li>Wszystkie rejestry falownika</li>
<li>Czasy start/shutdown</li>
<li>Statusy</li>
<li>Moce</li>
<li>Energia dzienna i całkowita</li>
</ul>
</li>
</ol>
<h2 id="tematy-mqtt">Tematy MQTT</h2>
<h3 id="orno">ORNO:</h3>
<ul>
<li><code>/energy/orno/U</code> - napięcia (JSON: U1, U2, U3)</li>
<li><code>/energy/orno/I</code> - prądy (JSON: I1, I2, I3)</li>
<li><code>/energy/orno/P</code> - moc (JSON: P_Tot, P1, P2, P3)</li>
<li><code>/energy/orno/W</code> - energia (JSON: W_Tot, W1, W2, W3)</li>
<li><code>/energy/orno/Hz</code> - częstotliwość (wartość)</li>
</ul>
<h3 id="sun2k">SUN2K:</h3>
<ul>
<li><code>/energy/SUN2K</code> - wszystkie parametry (JSON dla każdego rejestru)</li>
</ul>
<h2 id="modyfikacja-konfiguracji">Modyfikacja konfiguracji</h2>
<ol>
<li>Edytuj plik <code>modb_orno3.c</code></li>
<li>Zmień wartości #define</li>
<li>Przekompiluj: <code>bash cc-modb_orno3.sh</code></li>
<li>Uruchom: <code>./modborno3</code></li>
</ol>
<h2 id="przyk%C5%82ady-modyfikacji">Przykłady modyfikacji</h2>
<h3 id="wy%C5%82%C4%85czenie-mqtt">Wyłączenie MQTT:</h3>
<pre class="hljs"><code><div><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> DISABLE_MQTT 1</span>
</div></code></pre>
<h3 id="zmiana-adresu-brokera">Zmiana adresu brokera:</h3>
<pre class="hljs"><code><div><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> MQTT_BROKER <span class="hljs-meta-string">"192.168.1.100"</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> MQTT_PORT 1883</span>
</div></code></pre>
<h3 id="tryb-ci%C4%85g%C5%82y-p%C4%99tla-co-5s">Tryb ciągły (pętla co 5s):</h3>
<pre class="hljs"><code><div><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> READ_LOOP true</span>
</div></code></pre>
<h3 id="tylko-orno-bez-sun2k">Tylko ORNO (bez SUN2K):</h3>
<pre class="hljs"><code><div><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> READ_SUN2K false</span>
</div></code></pre>
<h3 id="zmiana-przerwy-mi%C4%99dzy-odczytami-200ms">Zmiana przerwy między odczytami (200ms):</h3>
<pre class="hljs"><code><div><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> DELAY_BETWEEN_DEVICES 200000</span>
</div></code></pre>
<h2 id="walidacja-danych-i-zabezpieczenia-mqtt">Walidacja danych i zabezpieczenia MQTT</h2>
<h3 id="automatyczna-walidacja-warto%C5%9Bci">Automatyczna walidacja wartości</h3>
<p>Program <strong>automatycznie waliduje</strong> wszystkie odczytane wartości przed wysłaniem do MQTT.
Dane są wysyłane do MQTT <strong>tylko</strong> gdy:</p>
<ol>
<li>✅ Odczyt Modbus zakończył się sukcesem (prawidłowa liczba rejestrów)</li>
<li>✅ Wartość nie jest <strong>NaN</strong> (Not a Number)</li>
<li>✅ Wartość nie jest <strong>Inf</strong> (Infinity)</li>
<li>✅ Wartość mieści się w <strong>rozsądnym zakresie</strong></li>
</ol>
<h3 id="zakresy-walidacji-dla-orno">Zakresy walidacji dla ORNO</h3>
<table>
<thead>
<tr>
<th>Parametr</th>
<th>Zakres</th>
<th>Jednostka</th>
<th>Powód</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Napięcia L1/L2/L3</strong></td>
<td>150 - 280</td>
<td>V</td>
<td>Typowy zakres sieci UE (230V ±20%)</td>
</tr>
<tr>
<td><strong>Prądy L1/L2/L3</strong></td>
<td>0 - 100</td>
<td>A</td>
<td>Zabezpieczenie instalacji domowej</td>
</tr>
<tr>
<td><strong>Moc Total/L1/L2/L3</strong></td>
<td>-25000 - +25000</td>
<td>W</td>
<td>Pozwala na generację (wartości ujemne)</td>
</tr>
<tr>
<td><strong>Energia Total/L1/L2/L3</strong></td>
<td>0 - 1000000</td>
<td>kWh</td>
<td>Licznik nie może mieć ujemnej energii</td>
</tr>
<tr>
<td><strong>Częstotliwość</strong></td>
<td>47 - 53</td>
<td>Hz</td>
<td>Typowy zakres sieci UE (50Hz) / US (60Hz)</td>
</tr>
</tbody>
</table>
<h3 id="logi-walidacji">Logi walidacji</h3>
<p>Program wyświetla szczegółowe informacje o walidacji:</p>
<p><strong>Gdy dane są prawidłowe:</strong></p>
<pre class="hljs"><code><div>Voltages: L1=225.8 V, L2=221.3 V, L3=229.8 V
MQTT: Published voltages
</div></code></pre>
<p><strong>Gdy odczyt się nie powiódł:</strong></p>
<pre class="hljs"><code><div>Failed to read currents: Resource temporarily unavailable
(brak komunikatu MQTT - dane nie są wysyłane)
</div></code></pre>
<p><strong>Gdy wartość jest poza zakresem:</strong></p>
<pre class="hljs"><code><div>WARNING: Value 350.5 out of range [150.0, 280.0]
MQTT: Skipping voltages - invalid values
</div></code></pre>
<p><strong>Gdy wartość jest NaN lub Inf:</strong></p>
<pre class="hljs"><code><div>WARNING: Value is NaN
MQTT: Skipping power - invalid values
</div></code></pre>
<h3 id="zabezpieczenia-dla-sun2k">Zabezpieczenia dla SUN2K</h3>
<p>Dla urządzenia SUN2K program:</p>
<ul>
<li><strong>NIE wysyła</strong> danych gdy odczyt się nie powiódł</li>
<li><strong>NIE używa</strong> starych wartości (<code>buf_last_val</code>) po błędzie</li>
<li><strong>Tylko</strong> aktualne, poprawnie odczytane wartości są publikowane</li>
</ul>
<p><strong>Przykład:</strong></p>
<pre class="hljs"><code><div>modbus_read_registers addr=0x7D55 nb=1 -&gt; ERR (Connection timed out)
Frequency: Failed to 11 read: Connection timed out
MQTT: Skipping Frequency - no valid data
</div></code></pre>
<h3 id="dlaczego-to-wa%C5%BCne">Dlaczego to ważne?</h3>
<p><strong>Bez walidacji:</strong></p>
<ul>
<li>Błędne odczyty (CRC errors) mogły wysyłać śmieciowe dane do MQTT</li>
<li>Wartości NaN/Inf mogły powodować błędy w systemach monitoringu</li>
<li>Niemożliwe wartości (np. 10000V) mogły wywoływać fałszywe alarmy</li>
</ul>
<p><strong>Z walidacją:</strong></p>
<ul>
<li>✅ Tylko <strong>poprawne</strong> wartości trafiają do MQTT</li>
<li>✅ System monitoringu dostaje <strong>wiarygodne</strong> dane</li>
<li>✅ Brak <strong>fałszywych alarmów</strong> z powodu błędnych odczytów</li>
<li><strong>Logi</strong> pokazują dokładnie co poszło nie tak</li>
</ul>
<h3 id="kod-walidacji">Kod walidacji</h3>
<p>Funkcja walidacji znajduje się w <a href="modb_orno3.c#L237-L250">modb_orno3.c:237-250</a>:</p>
<pre class="hljs"><code><div><span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">is_valid_float</span><span class="hljs-params">(<span class="hljs-keyword">float</span> value, <span class="hljs-keyword">float</span> min_val, <span class="hljs-keyword">float</span> max_val)</span>
</span>{
<span class="hljs-keyword">if</span> (isnan(value)) {
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"WARNING: Value is NaN\n"</span>);
<span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
<span class="hljs-keyword">if</span> (isinf(value)) {
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"WARNING: Value is Inf\n"</span>);
<span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
<span class="hljs-keyword">if</span> (value &lt; min_val || value &gt; max_val) {
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"WARNING: Value %.2f out of range [%.2f, %.2f]\n"</span>,
value, min_val, max_val);
<span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
<span class="hljs-keyword">return</span> <span class="hljs-number">1</span>;
}
</div></code></pre>
<p>Walidacja jest wywoływana dla każdego pomiaru przed wysłaniem do MQTT.</p>
<h3 id="modyfikacja-zakres%C3%B3w-walidacji">Modyfikacja zakresów walidacji</h3>
<p>Jeśli chcesz zmienić zakresy walidacji (np. dla instalacji przemysłowej):</p>
<ol>
<li>Otwórz plik <code>modb_orno3.c</code></li>
<li>Znajdź sekcję z walidacją (np. dla napięć około linii 370)</li>
<li>Zmień wartości w <code>is_valid_float()</code>:</li>
</ol>
<p><strong>Przykład - zwiększenie zakresu prądów do 200A:</strong></p>
<pre class="hljs"><code><div><span class="hljs-comment">/* Przed: */</span>
<span class="hljs-keyword">if</span> (is_valid_float(I1, <span class="hljs-number">0.0</span>, <span class="hljs-number">100.0</span>) &amp;&amp; ...
<span class="hljs-comment">/* Po: */</span>
<span class="hljs-keyword">if</span> (is_valid_float(I1, <span class="hljs-number">0.0</span>, <span class="hljs-number">200.0</span>) &amp;&amp; ...
</div></code></pre>
<ol start="4">
<li>Przekompiluj: <code>bash cc-modb_orno3.sh</code></li>
</ol>
</body>
</html>