← Înapoi la Fulminis.ro
Martie 2026 AI PLC Stație Betoane

Cum am învățat un AI să programeze PLC-uri industriale: Decodificarea formatului XEF Schneider

Cum un folder ascuns din directorul de instalare Control Expert a transformat un model de limbaj într-un instrument de programare PLC.

Daca ai programat vreodata un PLC Schneider M340, cunosti EcoStruxure Control Expert. Si stii ca editorul de text este blocat undeva pe la nivelul Notepad din 2003. Fara multi-cursor. Fara find-and-replace cu regex. Fara editare in masa. Copierea maparii I/O la adrese de memorie — genul de munca care ocupa 60% dintr-un proiect nou — este un efort manual si predispus la erori.

            <p>Ani de zile am procedat asa cum fac majoritatea inginerilor de automatizari: exportam sectiunile relevante, le editam in Sublime Text folosind multi-cursor, le lipeam inapoi. Functiona, dar era totusi anevoios. O sesiune completa de scaffolding &mdash; variabile, mapare I/O, structura de baza a sectiunilor &mdash; putea dura cu usurinta o jumatate de zi pe un proiect de dimensiune medie.</p>

            <p>Apoi, in timp ce lucram la integrarea unui model de limbaj (LLM) in aplicatia noastra SCADA pentru statii de betoane, mi-a venit o idee: fisierele XEF sunt XML. Text simplu. Exact lucrul la care LLM-urile sunt cu adevarat bune.</p>

            <h2>Prima incercare: abordarea evidenta</h2>

            <p>Primul meu instinct a fost automatizarea prin interfetele proprii ale Control Expert. Cu siguranta un instrument atat de matur ar avea vreo interfata COM sau OLE &mdash; ceva ce as putea scripta.</p>

            <p>Nu are. Control Expert nu ofera nicio interfata programatica. Fara obiecte COM, fara compilator in linia de comanda, fara hook-uri de scripting. Singura cale de intrare si iesire este interfata grafica si export/import-ul XML.</p>

            <p>Dar in timp ce cautam prin directorul de instalare al Control Expert dupa orice tip de API, DLL sau mecanism de automatizare, am gasit ceva mai bun.</p>

            <h2>Piatra Rosetta ascunsa</h2>
C:\Program Files (x86)\Schneider Electric\Control Expert 15.3\SrcXmlSchema\
            <p>XSD (XML Schema Definition) este un limbaj formal care descrie structura exacta a unui document XML &mdash; ce elemente sunt permise, ce atribute pot avea, ce valori sunt valide, cum se imbrica elementele unele in altele. Este planul de constructie. Daca fisierul XEF este o cladire, XSD-ul este proiectul de arhitectura.</p>

            <p>Si aceste XSD-uri defineau formatul complet al fisierelor XEF. <code>FefExchangeFile.xsd</code> &mdash; schema radacina &mdash; include 15 sub-scheme care acopera totul: de la <code>commonElements.xsd</code> (variabile, headere, tipuri de baza) la <code>LDSource.xsd</code> (reprezentarea grafica Ladder Diagram), <code>SFCSource.xsd</code> (Sequential Function Charts), <code>IOConf.xsd</code> (configurarea hardware) si <code>program.xsd</code> (sectiunile de program).</p>

            <p>Documentatia oficiala Schneider mentioneaza export/import XML ca functionalitate, dar nu spune nimic despre structura formatului. Pe forumuri existau fragmente imprastiate &mdash; snippet-ul cuiva despre blocul de variabile, descrierea partiala a altcuiva despre formatul SFC. Dar schema completa si autoritativa se afla in directorul de instalare de tot timpul, livrata cu fiecare instalare Control Expert.</p>

            <figure class="blog-image">
                <img src="/blog/img/screenshot_xsd_folder.png" alt="Folderul SrcXmlSchema din directorul de instalare Control Expert" loading="lazy">
                <figcaption>Folderul SrcXmlSchema din directorul de instalare Control Expert &mdash; 87 de fisiere care definesc formatul complet XEF, livrate cu fiecare instalare, practic nedocumentate.</figcaption>
            </figure>

            <p>Cu schema in mana, m-am intors la ideea originala &mdash; dar acum cu o abordare complet diferita. In loc sa cer unui AI sa ghiceasca structura XML, puteam sa-l invat regulile.</p>

            <p>Am incercat cel mai simplu lucru mai intai: export proiect in XEF, il dau lui Claude, il rog sa modifice sectiunile Structured Text. Pentru editari simple de ST &mdash; ca remaparea <code>%I0.3.0</code> pana la <code>%I0.3.31</code> catre <code>%MW100</code> pana la <code>%MW131</code> &mdash; a functionat din prima. Import, compilare, zero erori.</p>

            <p>Acela a fost momentul in care am realizat ca asta poate fi ceva mai mare decat un shortcut de editare text.</p>

            <h2>Problema cu "doar XML"</h2>

            <p>Fisierele XEF sunt XML, dar nu sunt XML simplu. Un fisier de proiect tipic are 500 KB de elemente profund imbricate care cuprind: configurarea hardware, declaratii de variabile, logica de program in patru limbaje diferite (Structured Text, Ladder Diagram, Sequential Function Charts, Instruction List), parametri de comunicatie si setari IDE.</p>

            <p>Cand i-am cerut lui Claude sa genereze o sectiune completa de Ladder Diagram de la zero, a produs XML care arata valid dar pe care Control Expert l-a respins cu erori criptice. Schemele XSD erau necesare dar nu suficiente &mdash; AI-ul trebuia sa invete si regulile practice care nu sunt surprinse in nicio schema.</p>

            <h2>Construirea skill-ului</h2>

            <p>Cu schemele XSD ca baza de adevar, am construit ceea ce Claude Code numeste un "skill" &mdash; un document structurat care invata AI-ul regulile unui domeniu specific. Al nostru acopera:</p>

            <p><strong>Structura completa XEF</strong> &mdash; fiecare element, atribut si relatie de imbricare. Ce intra in <code>&lt;FEFExchangeFile&gt;</code>, cum <code>&lt;dataBlock&gt;</code> contine variabilele, cum sectiunile <code>&lt;program&gt;</code> contin <code>&lt;STSource&gt;</code>, <code>&lt;LDSource&gt;</code> sau <code>&lt;FBDSource&gt;</code>, cum <code>&lt;SFCProgram&gt;</code> inlantuie pasi, tranzitii si actiuni.</p>

            <p><strong>Toate enumerarile din XSD</strong> &mdash; valorile valide pentru fiecare atribut. Tipuri de pasi (<code>initialStep</code>, <code>step</code>, <code>macroStep</code>), tipuri de bobine (<code>coil</code>, <code>setCoil</code>, <code>resetCoil</code>, <code>callCoil</code>), tipuri de contacte, calificatori de actiuni SFC (<code>N</code>, <code>P</code>, <code>S</code>, <code>R</code>, <code>L</code>, <code>D</code>, <code>DS</code>), tipuri de task-uri, niveluri de protectie. Un AI care ghiceste aceste valori produce XML care arata corect dar esueaza la compilare.</p>

            <p><strong>Pattern-uri Python de extractie si generare</strong> &mdash; cod ElementTree pentru citirea variabilelor, sectiunilor, configuratiei hardware, ordinii de executie. Si, critic, regulile de scriere: pastreaza header-ul XML original, nu folosi niciodata tag-uri auto-inchise (<code>&lt;tag /&gt;</code> &mdash; Control Expert le respinge), foloseste intotdeauna <code>&lt;tag&gt;&lt;/tag&gt;</code>.</p>

            <p><strong>Capcanele</strong> &mdash; aici s-a dus cea mai mare parte din timpul de dezvoltare. Fiecare dintre acestea a fost descoperita pe calea grea, printr-un ciclu de compilare-eroare-corectie:</p>

            <ul>
                <li><code>step</code> este cuvant rezervat in Control Expert. Foloseste-l ca nume de variabila intr-un DFB si primesti <code>E1235 invalid identifier</code>. Am invatat sa folosim <code>sm_step</code> sau <code>etapa</code> in schimb.</li>
                <li>Parametrul buffer al <code>WRITE_VAR</code> se numeste <code>EMIS</code>, nu <code>EMESSION</code> cum sugereaza unele documentatii Schneider. <code>E1031 'EMESSION' is not a parameter</code>.</li>
                <li>Variabilele EBOOL in Ladder trebuie sa foloseasca <code>&lt;coil&gt;</code>, nu <code>&lt;operateBlock&gt;</code>. Elementul <code>operateBlock</code> este doar pentru calcule (REAL, INT, TIME). Folosirea cu EBOOL compileaza dar produce comportament incorect la rulare.</li>
                <li><code>posY</code> in elementele FFBBlock este pozitie absoluta pe grid. Insereaza un rung nou si fiecare bloc de sub el trebuie sa aiba coordonata Y incrementata, altfel elementele se suprapun.</li>
                <li>O singura instructiune per <code>operateBlock</code>. Doua asignari in acelasi bloc dau <code>E1002</code>. Ai nevoie de doua? Doua elemente <code>typeLine</code> separate cu continuare <code>VLink</code>.</li>
                <li>Literalii booleeni trebuie sa fie cu majuscule: <code>TRUE</code>, <code>FALSE</code>. <code>true</code> cu minuscule este eroare de sintaxa in IEC 61131-3 ST.</li>
                <li>Array-urile dinamice trebuie activate explicit in setarile proiectului (<code>unity.dynamicArray=1</code>) altfel <code>READ_VAR</code>/<code>WRITE_VAR</code> in DFB-uri esueaza cu <code>E1208</code>.</li>
            </ul>

            <p>Documentul skill are 570 de linii. Fiecare linie castigata printr-o compilare esuata.</p>

            <h2>Un exemplu real: indicatorul de cantarire Laumas W100</h2>

            <p>Ca sa fie concret, iata un DFB (Derived Function Block) generat in intregime de AI &mdash; un driver Modbus TCP pentru un indicator de cantarire industrial Laumas W100 folosit in statii de betoane.</p>

            <p>Sarcina: comunicarea cu W100 prin Modbus, citirea registrelor de greutate (brut, net, tara), decodificarea bitilor de status (stabil, aproape de zero, eroare celula de sarcina), gestionarea comenzilor de calibrare si a erorilor de comunicatie cu timeout si logica de reincercare.</p>

            <p>In Control Expert, scrierea manuala inseamna: crearea DFB-ului, definirea a 4 intrari, 14 iesiri si 16 variabile private, scrierea masinii de stare Modbus cu apeluri <code>READ_VAR</code>/<code>WRITE_VAR</code>, implementarea parsarii registrelor (valori de greutate pe 32 de biti impartite in doua registre de 16 biti), decodificarea tabelului de factori de diviziune din manualul de protocol al instrumentului, adaugarea gestionarii timeout-ului si a recuperarii din erori. O jumatate de zi solida de munca daca cunosti bine protocolul.</p>

            <p>Cu skill-ul, am descris harta de registre Modbus a W100 si AI-ul a generat 128 de linii de Structured Text gata de productie:</p>
(* Masina de stare: CITIRE registre 40006-40050 *)
10:
    READ_VAR(ADR := ADDM(addm_string),
        OBJ := 'MW', NUM := 5, NB := 45,
        GEST := gest_r, RECP => buf_r);
    comm_state := 1; sm_step := 11;

11:
    READ_VAR(ADR := ADDM(addm_string),
        OBJ := 'MW', NUM := 5, NB := 45,
        GEST := gest_r, RECP => buf_r);
    IF (gest_r[1] AND 1) = 0 THEN
        IF gest_r[2] = 0 THEN
            reg_status := buf_r[1];
            reg_gross_h := buf_r[2]; reg_gross_l := buf_r[3];
            reg_net_h := buf_r[4]; reg_net_l := buf_r[5];
            reg_div_units := buf_r[8];
            data_valid := TRUE;
            ok_counter := ok_counter + 1;
            IF ok_counter >= 3 THEN comm_ok := TRUE; END_IF;
            sm_step := 30;
        ELSE sm_step := 90;  (* Eroare Modbus *)
        END_IF;
    ELSIF timer.Q THEN sm_step := 90;  (* Timeout *)
    END_IF;

(* Decodificare factor de diviziune din registrul de configurare *)
30:
    div_index := reg_div_units AND 16#FF;
    CASE div_index OF
        0: divisor:=100.0; 1: divisor:=50.0;  2: divisor:=20.0;
        3: divisor:=10.0;  4: divisor:=5.0;   5: divisor:=2.0;
        6: divisor:=1.0;   7: divisor:=0.5;   8: divisor:=0.2;
        9: divisor:=0.1;  10: divisor:=0.05; 11: divisor:=0.02;
       12: divisor:=0.01; 13: divisor:=0.005;14: divisor:=0.002;
       15: divisor:=0.001;
    ELSE divisor := 1.0;
    END_CASE;

    (* Reconstruire greutate 32-bit din doua registre de 16 biti *)
    raw_32 := SHL(INT_TO_DINT(reg_gross_h), 16)
              OR WORD_TO_DINT(INT_TO_WORD(reg_gross_l));
    gross_weight := DINT_TO_REAL(raw_32) * divisor;
            <figure class="blog-image">
                <img src="/blog/img/screenshot_dfb_laumas_code.png" alt="DFB-ul laumas_w100 generat de AI in Control Expert" loading="lazy">
                <figcaption>DFB-ul laumas_w100 generat de AI, deschis in Control Expert &mdash; 128 de linii de Structured Text, compilat cu succes ca parte a unui proiect complet de automatizare statie de betoane.</figcaption>
            </figure>

            <p>Acest DFB a fost generat pentru o statie specifica care foloseste indicatoare Laumas W100 &mdash; una din multele adaptari specifice instalatiei. Proiectul de baza este un program standard de statie de betoane pe care l-am dezvoltat de-a lungul anilor. AI-ul se ocupa de personalizare: instrumentele specifice, configuratiile I/O si protocoalele de comunicatie care difera de la o statie la alta. Rezultatul: 539 de variabile, 14 sectiuni de program, 6 DFB-uri si o secventa SFC cu 84 de pasi si 95 de tranzitii &mdash; importate si compilate cu zero erori.</p>

            <figure class="blog-image">
                <img src="/blog/img/screenshot_import_progress.png" alt="Import XEF in Control Expert" loading="lazy">
                <figcaption>Importarea fisierului XEF generat de AI in Control Expert &mdash; "Begin IMPORT, File name: Z:\smart-concrete\docs\automat.XEF".</figcaption>
            </figure>

            <figure class="blog-image">
                <img src="/blog/img/screenshot_import_xef.png" alt="Import reusit cu 0 erori" loading="lazy">
                <figcaption>Integrarea importului completa &mdash; "Process succeeded: 0 Error(s), 0 Warning(s)".</figcaption>
            </figure>

            <figure class="blog-image">
                <img src="/blog/img/screenshot_build_success.png" alt="Proiectul complet compilat in Control Expert" loading="lazy">
                <figcaption>Proiectul complet in Control Expert: bus PLC cu configuratia hardware M340, browser de proiect cu toate DFB-urile si variabilele, log de build confirmand "0 Error(s)".</figcaption>
            </figure>

            <h2>Cum arata in practica</h2>

            <p>Astazi, cand trebuie sa creez un program PLC nou pentru o statie de betoane, fluxul de lucru este:</p>

            <ul>
                <li>Pornesc de la proiectul nostru standard de statie de betoane &mdash; programul de baza, secventele SFC si logica de baza comuna tuturor statiilor.</li>
                <li>Descriu lui Claude configuratia specifica a statiei &mdash; ce instrumente sunt conectate (indicatoare de cantarire, senzori de umiditate), ce module I/O sunt in rack, ce adrese Modbus sa foloseasca. Claude genereaza DFB-urile custom, adapteaza maparea I/O, adauga variabilele si sectiunile specifice statiei.</li>
                <li>Import fisierul XEF in Control Expert. Compilez. Corectez eventualele probleme (rare acum &mdash; skill-ul s-a maturizat).</li>
                <li>Din aplicatia noastra SCADA, un script rescrie adresele de memorie Modbus pe PLC, sincronizand HMI-ul cu programul generat.</li>
                <li>Ma concentrez pe ceea ce conteaza cu adevarat: logica de proces. Secventele de dozare, timingul, interblocarile de siguranta &mdash; partile care necesita judecata de inginer, nu rezistenta la copy-paste.</li>
            </ul>

            <p>Ceea ce dura ore &mdash; adaptarea proiectului standard la hardware-ul si instrumentele specifice ale unei noi statii &mdash; acum dureaza minute. Bottleneck-ul s-a mutat de la scrierea codului la pasii manuali care nu pot fi automatizati: importul in interfata grafica a Control Expert, build-ul si transferul pe PLC. Adaptarea este partea la care un LLM exceleaza &mdash; repetitiva, bazata pe tipare, care urmeaza reguli. Reglajul procesului este partea care inca necesita un inginer care a stat langa o statie in functiune.</p>

            <h2>Ce urmeaza</h2>

            <p>Lucram la ceva mai ambitios: un modul LLM integrat direct in aplicatia SCADA. Nu pentru generarea de cod PLC &mdash; ci pentru optimizarea parametrilor instalatiei in timpul functionarii. Producerea betonului are zeci de variabile care interactioneaza in moduri neintuitive: umiditatea agregatelor, temperatura cimentului, timpul de amestecare, factorii de corectie a apei. Un AI care poate observa datele de proces si sugera ajustari ale parametrilor ar putea imbunatati semnificativ calitatea productiei.</p>

            <p>Skill-ul XEF a fost un accident al curiozitatii &mdash; cautam o modalitate de a evita copy-paste si am gasit o modalitate de a face un AI cu adevarat util in automatizarile industriale. Schemele au fost acolo tot timpul, intr-un folder la care nimeni nu s-a gandit sa se uite.</p>

            <hr>

            <p class="blog-endnote">Construim sisteme de automatizare pentru statii de asfalt si betoane &mdash; software de comanda, programare PLC, tablouri electrice si retrofit al sistemelor vechi. Daca aveti de-a face cu sisteme de comanda al caror producator nu mai ofera suport de ani buni, <a href="/#contact">contactati-ne</a>.</p>