Obsidean_VM/01-Documentation/Siemens/Peripherics - Schede - IM/SIMATIC ET 200S 2AI I 4WIRE...

21 KiB

#analogIA #sae452 #mixer

Modulo Elettronico Analogico SIMATIC ET 200S 2AI I 4WIRE ST

Preso dalle schede AI su il SAE452: ==6ES7 134-4GB11-0AB0== Manuale: et200s_2ai_i_4wire_st_manual_en-US.pdf

Guida alla Configurazione e Programmazione per Misure 4-20 mA

1. Range di Misurazione per Corrente: 4-20 mA

La seguente tabella contiene i valori analogici digitalizzati per il range di misurazione del modulo di ingresso analogico. Poiché la rappresentazione binaria dei valori analogici è sempre la stessa, questa tabella confronta i range di misurazione con le unità.

Tabella 4-3: Formato SIMATIC S7: Range di misurazione 4-20 mA

Range di misurazione 4-20 mA Unità Range
Decimale Esadecimale
> 22,8142 32767 7FFFH Overflow
22,8142 : 20,0005 32511 : 27649 7EFFH : 6C01H Range di sovraccarico
20,0000 16,0000 : 4,0000 27648 20736 : 0 6C00H 5100H : 0H Range nominale
3,9995 : 1,1852 -1 : -4864 FFFFH : ED00H Range di sottoccarico
< 1,1852 -32768 8000H Underflow
Assegnazione parametri Valori misurati Descrizione
Decimale Esadecimale
• Diagnostica "Rottura cavo" abilitata 32767 7FFFH • Messaggio diagnostico "Circuito aperto"
• Diagnostica "Rottura cavo" disabilitata
• Diagnostica "Overflow/underflow" abilitata
-32767 8000H • Valore misurato dopo aver lasciato il range di sottoccarico
• Messaggio diagnostico "Valore limite inferiore superato verso il basso"
• Diagnostica "Rottura cavo" disabilitata
• Diagnostica "Overflow/underflow" disabilitata
-32767 8000H • Valore misurato dopo aver lasciato il range di sottoccarico

2. Conversione da Brix a Corrente 4-20 mA

Nel tuo caso specifico, desideri convertire valori Brix dove:

  • 60 Brix corrisponde a 20 mA (valore massimo)
  • 0 Brix corrisponde a 4 mA (valore minimo)
Brix = ((Corrente (mA) - 4) / 16) * 60

3. Parametri di Diagnostica

Parametri per il modulo di ingresso analogico 2 AI I 4WIRE ST

Parametro Valori
Diagnostica di gruppo (errore assegnazione parametri, errore interno) Abilitato
Diagnostica: Overflow/underflow Abilitato
Diagnostica: Rottura cavo* Abilitato
Smoothing (Smorzamento) Nessuno
Tipo/range di misurazione WIRE: 4-20 mA
!Pasted image 20250507112955.png

Spiegazione dei Parametri di Diagnostica:

  1. Diagnostica di gruppo: Quando abilitata, il modulo segnala errori generali come errori di parametrizzazione o errori interni del modulo. Attiva il LED SF (errore) e genera un messaggio diagnostico.

  2. Diagnostica Overflow/underflow: Quando abilitata, il modulo genera messaggi diagnostici quando il valore di ingresso supera (overflow) o scende sotto (underflow) i limiti del range di misurazione. Questi sono:

    • Overflow: > 22,8142 mA
    • Underflow: < 1,1852 mA
  3. Diagnostica Rottura cavo: Quando abilitata, il modulo rileva una interruzione del circuito se la corrente scende sotto 1,185 mA. Questa opzione è disponibile solo nel range di misurazione 4-20 mA.

4. Comportamento del Modulo in Caso di Errore

Valori misurati in caso di rottura del cavo in relazione alla diagnostica abilitata:

Limiti del range di misurazione per il rilevamento di rottura del cavo e underflow: A 1,185 mA

5. Programmazione SCL per Gestire i Diversi Stati

Ecco un esempio di come gestire i diversi stati in programmazione SCL per un PLC S7-300:

// FB100 - Gestione Misurazione Brix con diagnostica
// Configurazione hardware richiesta:
// - Group diagnostics: Abilitato
// - Diagnostic overflow/underflow: Abilitato
// - Wire break: Abilitato

FUNCTION_BLOCK "FB_MisurazioneBrix"
TITLE = 'Gestione sensore Brix con diagnostica'
AUTHOR : Sysadmin
FAMILY : Process

VAR_INPUT
    i_IW_Analog : WORD;                 // Indirizzo dell'ingresso analogico (PEW)
    i_EnableDiagnostic : BOOL := TRUE;  // Abilita la lettura dei messaggi diagnostici
    i_Reset : BOOL;                     // Reset allarmi
END_VAR

VAR_OUTPUT
    o_ValoreBrix : REAL;                // Valore Brix convertito (0-60)
    o_CorrienteMa : REAL;               // Valore corrente in mA (per diagnostica)
    o_StatoSensore : INT;               // 0=OK, 1=Overflow, 2=Underflow, 3=Wire Break, 4=Errore ADAM (2mA)
    o_QualitaBuona : BOOL;              // TRUE se la misura è affidabile
    o_DiagInfo : STRING;                // Informazioni diagnostiche in formato testo
END_VAR

VAR
    // Definizione delle costanti
    OVERFLOW_VALUE : INT := 32767;      // 7FFFH - Valore di overflow
    UNDERFLOW_VALUE : INT := -32768;    // 8000H - Valore di underflow
    WIRE_BREAK_VALUE : INT := 32767;    // 7FFFH - Con diagnostica wire break abilitata
    MAX_NORMAL : INT := 27648;          // 6C00H - 20mA (valore massimo nel range nominale)
    MIN_NORMAL : INT := 0;              // 0000H - 4mA (valore minimo nel range nominale)
    
    // Variabili interne
    ValoreAnalogicoInt : INT;           // Valore analogico convertito in INT
    ErroreRilevato : BOOL;              // Flag per errore rilevato
    TimerRitardo : TON;                 // Timer per filtrare falsi allarmi
    RitardoErrore : TIME := T#2S;       // Ritardo di conferma errore (2 secondi)
    MemoriaStato : INT;                 // Memoria dell'ultimo stato valido
    
    // Variabili per la diagnostica di sistema
    DiagRequest : BOOL;                 // Richiesta di lettura diagnostica
    DiagBusy : BOOL;                    // Blocco diagnostica occupato
    DiagDone : BOOL;                    // Lettura diagnostica completata
    DiagError : BOOL;                   // Errore durante la lettura diagnostica
    DiagStatus : WORD;                  // Stato della diagnostica
    DiagBuffer : ARRAY[0..31] OF BYTE;  // Buffer per i dati diagnostici
    
    // Variabili per rilevazione errore ADAM (circa 2mA)
    ADAM_ERROR_LOW : INT := -3600;      // Limite inferiore per rilevare errore ADAM (~1.8mA)
    ADAM_ERROR_HIGH : INT := -3200;     // Limite superiore per rilevare errore ADAM (~2.2mA)
    
    // Dati temporanei
    TempBrix : REAL;                    // Valore Brix temporaneo per calcoli
    FirstScan : BOOL := TRUE;           // Flag per primo ciclo
END_VAR

VAR_TEMP
    TempValue : INT;                    // Valore temporaneo per calcoli
    TempReal : REAL;                    // Valore temporaneo per calcoli in virgola mobile
    StatusTemp : INT;                   // Stato temporaneo per logica degli stati
END_VAR

BEGIN
    // Inizializzazione delle variabili al primo ciclo
    IF FirstScan THEN
        FirstScan := FALSE;
        o_StatoSensore := 0;
        o_DiagInfo := 'Inizializzazione sistema';
        MemoriaStato := 0;
    END_IF;
    
    // Converti il valore WORD in INT per elaborazione
    ValoreAnalogicoInt := WORD_TO_INT(i_IW_Analog);
    
    // Logica di stato iniziale - determina lo stato del sensore
    StatusTemp := 0;  // Stato predefinito: OK
    ErroreRilevato := FALSE;
    
    // Verifica delle diverse condizioni di errore
    CASE ValoreAnalogicoInt OF
        OVERFLOW_VALUE:  // 32767 (7FFFH)
            // Può indicare overflow o wire break se la diagnostica di rottura cavo è abilitata
            IF i_EnableDiagnostic THEN
                // Dobbiamo leggere le informazioni diagnostiche per distinguere tra overflow e wire break
                DiagRequest := TRUE;
                StatusTemp := 1;  // Assumiamo inizialmente Overflow
                o_DiagInfo := 'Overflow rilevato o Wire Break?';
            ELSE
                StatusTemp := 1;  // Overflow (senza diagnostica non possiamo distinguere)
                o_DiagInfo := 'Overflow rilevato';
            END_IF;
            ErroreRilevato := TRUE;
            
        UNDERFLOW_VALUE:  // -32768 (8000H)
            StatusTemp := 2;  // Underflow
            o_DiagInfo := 'Underflow rilevato - Valore troppo basso';
            ErroreRilevato := TRUE;
    ELSE
        // Verifica se il valore è nell'intervallo che indica errore ADAM (circa 2mA)
        IF ValoreAnalogicoInt >= ADAM_ERROR_LOW AND ValoreAnalogicoInt <= ADAM_ERROR_HIGH THEN
            StatusTemp := 4;  // Errore ADAM (2mA)
            o_DiagInfo := 'Errore rilevato dal sensore ADAM (2mA) - Problema misuratore Brix';
            ErroreRilevato := TRUE;
        ELSIF ValoreAnalogicoInt < MIN_NORMAL AND ValoreAnalogicoInt > UNDERFLOW_VALUE THEN
            // Siamo in underrange ma non ancora in underflow completo
            o_DiagInfo := 'Valore in underrange (< 4mA)';
            // Non consideriamo questo necessariamente un errore, solo una nota
        ELSIF ValoreAnalogicoInt > MAX_NORMAL AND ValoreAnalogicoInt < OVERFLOW_VALUE THEN
            // Siamo in overrange ma non ancora in overflow completo
            o_DiagInfo := 'Valore in overrange (> 20mA)';
            // Non consideriamo questo necessariamente un errore, solo una nota
        ELSE
            // Valore nell'intervallo normale
            StatusTemp := 0;  // OK
            o_DiagInfo := 'Misura OK';
        END_IF;
    END_CASE;
    
    // Filtro temporale per gli errori (evita falsi allarmi)
    IF ErroreRilevato THEN
        // Avvia il timer se è stato rilevato un errore
        TimerRitardo(IN := TRUE, PT := RitardoErrore);
        
        // Imposta lo stato di errore solo se il timer è scaduto
        IF TimerRitardo.Q THEN
            o_StatoSensore := StatusTemp;
        END_IF;
    ELSE
        // Resetta il timer se non ci sono errori
        TimerRitardo(IN := FALSE);
        o_StatoSensore := StatusTemp;
    END_IF;
    
    // Reset degli allarmi se richiesto
    IF i_Reset THEN
        o_StatoSensore := 0;
        o_DiagInfo := 'Stato resettato dall operatore';
        TimerRitardo(IN := FALSE);
    END_IF;
    
    // Calcolo del valore in mA indipendentemente dallo stato
    // Formula: mA = 4 + (ValoreAnalogicoInt / 27648) * 16    
    IF ValoreAnalogicoInt <= MAX_NORMAL AND ValoreAnalogicoInt >= UNDERFLOW_VALUE THEN
        // Conversione normale per valori validi o in underrange
        TempReal := INT_TO_REAL(ValoreAnalogicoInt);
        o_CorrienteMa := 4.0 + (TempReal / INT_TO_REAL(MAX_NORMAL)) * 16.0;
        
        // Un valore sotto lo zero corrisponde a meno di 4mA
        IF o_CorrienteMa < 0.0 THEN
            o_CorrienteMa := 0.0;  // Limitato a 0mA minimo (per evitare valori negativi)
        END_IF;
    ELSIF ValoreAnalogicoInt = OVERFLOW_VALUE THEN
        o_CorrienteMa := 22.81;  // Valore di overflow
    ELSIF ValoreAnalogicoInt = UNDERFLOW_VALUE THEN
        o_CorrienteMa := 0.0;    // Valore di underflow
    END_IF;
    
    // Conversione da corrente a Brix
    // Formula: Brix = ((mA - 4) / 16) * 60
    IF o_StatoSensore = 0 THEN
        // Calcolo normale solo se non ci sono errori
        IF o_CorrienteMa >= 4.0 THEN
            TempBrix := ((o_CorrienteMa - 4.0) / 16.0) * 60.0;
            
            // Limitazione del valore Brix tra 0 e 60
            IF TempBrix < 0.0 THEN
                o_ValoreBrix := 0.0;
            ELSIF TempBrix > 60.0 THEN
                o_ValoreBrix := 60.0;
            ELSE
                o_ValoreBrix := TempBrix;
            END_IF;
        ELSE
            // Sotto 4mA, impostiamo Brix a 0
            o_ValoreBrix := 0.0;
        END_IF;
    ELSE
        // In caso di errore, manteniamo l'ultimo valore valido o impostiamo un valore specifico
        CASE o_StatoSensore OF
            1: // Overflow
                o_ValoreBrix := 60.0;  // Impostiamo al valore massimo
            2: // Underflow
                o_ValoreBrix := 0.0;   // Impostiamo al valore minimo
            3: // Wire Break
                o_ValoreBrix := -1.0;  // Valore speciale per Wire Break
            4: // Errore ADAM
                o_ValoreBrix := -2.0;  // Valore speciale per Errore ADAM
        END_CASE;
    END_IF;
    
    // Imposta la qualità della misura
    o_QualitaBuona := (o_StatoSensore = 0);

    // Gestione lettura diagnostica di sistema (se abilitata)
    IF i_EnableDiagnostic AND DiagRequest THEN
        // Strutture dati necessarie per SFC51
        VAR_TEMP
            DiagHeader : STRUCT    // Struttura dell'header SZL
                LENTHDR : WORD;    // Lunghezza dell'header SZL in byte
                N_DR : WORD;       // Numero di record dati
            END_STRUCT;
            DiagResult : INT;      // Risultato della chiamata SFC51
            DiagLen : WORD;        // Lunghezza dei dati ricevuti
            DiagCount : INT;       // Contatore per l'analisi dei dati
            DiagFound : BOOL;      // Flag per errore trovato
            DiagSlot : BYTE;       // Slot del modulo diagnosticato
            DiagType : BYTE;       // Tipo di errore diagnostico
            DiagAddr : WORD;       // Indirizzo del modulo
            TempAddr : WORD;       // Indirizzo temporaneo per calcoli
            DiagModuleStartAddr : WORD; // Indirizzo di inizio del modulo
        END_VAR
        
        // Leggi lo stato diagnostico del sistema utilizzando SFC51
        // Lettura delle informazioni diagnostiche del modulo
        DiagResult := SFC51(
            REQ := TRUE,                // Richiesta di lettura
            SZL_ID := W#16#00B1,        // ID per informazioni diagnostiche (diagnostica slave DP)
            INDEX := W#16#0000,         // Tutti gli slave
            RET_VAL := DiagStatus,      // Codice di ritorno
            BUSY := DiagBusy,           // Operazione in corso
            SZL_HEADER := DiagHeader,   // Header SZL
            DR := DiagBuffer            // Buffer per i dati diagnostici
        );
        
        // Se l'operazione è completata, analizziamo i risultati
        IF NOT DiagBusy THEN
            DiagRequest := FALSE;       // Reset della richiesta
            
            IF DiagStatus = W#16#0000 THEN
                DiagDone := TRUE;       // Lettura completata con successo
                DiagFound := FALSE;     // Reset flag errore trovato
                
                // Calcola l'indirizzo del modulo analogico
                // Nota: questo è un esempio, devi adattarlo al tuo hardware
                // Supponiamo che l'indirizzo dell'ingresso analogico sia PIW256
                DiagModuleStartAddr := W#16#0100;   // 256 in esadecimale
                
                // Analizza i dati diagnostici ricevuti per trovare errori specifici
                FOR DiagCount := 0 TO INT_TO_INT(DiagHeader.N_DR)-1 DO
                    // Ogni record di diagnostica ha un formato specifico
                    // Estrai lo slot e l'indirizzo del modulo per verificare che sia quello giusto
                    DiagSlot := DiagBuffer[DiagCount*4];     // Slot in byte 0 del record
                    TempAddr := WORD_TO_WORD(SHL(IN:=BYTE_TO_WORD(DiagBuffer[DiagCount*4+2]), N:=8));
                    TempAddr := TempAddr OR BYTE_TO_WORD(DiagBuffer[DiagCount*4+3]);
                    DiagAddr := TempAddr;                    // Indirizzo del modulo
                    
                    // Verifica se questo è il nostro modulo analogico
                    IF DiagAddr = DiagModuleStartAddr THEN
                        // Leggi il tipo di errore (byte 1 del record)
                        DiagType := DiagBuffer[DiagCount*4+1];
                        
                        // Analizza il tipo di errore
                        CASE DiagType OF
                            B#16#06:    // 6D = 00110: Wire break
                                o_StatoSensore := 3;    // Wire break
                                o_DiagInfo := 'Wire Break rilevato tramite diagnostica';
                                DiagFound := TRUE;
                                
                            B#16#07:    // 7D = 00111: Upper limit exceeded
                                o_StatoSensore := 1;    // Overflow
                                o_DiagInfo := 'Overflow rilevato tramite diagnostica';
                                DiagFound := TRUE;
                                
                            B#16#08:    // 8D = 01000: Lower limit undershot
                                o_StatoSensore := 2;    // Underflow
                                o_DiagInfo := 'Underflow rilevato tramite diagnostica';
                                DiagFound := TRUE;
                                
                            B#16#09:    // 9D = 01001: Error (modulo interno)
                                o_StatoSensore := 5;    // Errore interno modulo
                                o_DiagInfo := 'Errore interno del modulo rilevato';
                                DiagFound := TRUE;
                                
                            B#16#10:    // 16D = 10000: Errore parametrizzazione
                                o_StatoSensore := 6;    // Errore configurazione
                                o_DiagInfo := 'Errore configurazione modulo';
                                DiagFound := TRUE;
                        END_CASE;
                        
                        // Se abbiamo trovato un errore, usciamo dal ciclo
                        IF DiagFound THEN
                            EXIT;
                        END_IF;
                    END_IF;
                END_FOR;
                
                // Se non troviamo errori diagnostici ma il valore è 32767, è probabilmente un overflow
                IF NOT DiagFound AND ValoreAnalogicoInt = OVERFLOW_VALUE THEN
                    o_StatoSensore := 1;  // Overflow
                    o_DiagInfo := 'Overflow rilevato (nessun messaggio diagnostico specifico)';
                END_IF;
                
            ELSE
                // Errore nella lettura diagnostica
                DiagError := TRUE;
                o_DiagInfo := CONCAT(IN1:='Errore SFC51: ', IN2:=WORD_TO_STRING(DiagStatus));
            END_IF;
        END_IF;
    END_IF;
    END_IF;	
    
END_FUNCTION_BLOCK



    // Chiamata al blocco funzionale di misurazione Brix
    // Sostituire "PIW256" con l'indirizzo effettivo dell'ingresso analogico
    CALL "FB_MisurazioneBrix", "DB_MisurazioneBrix" (
        i_IW_Analog := PIW256,  // Indirizzo ingresso analogico (da adattare)
        i_EnableDiagnostic := TRUE,
        i_Reset := "Reset_Allarmi"  // Connetti a un ingresso digitale o a una variabile HMI
    );
    
    // Qui puoi aggiungere ulteriore logica per gestire i valori e gli stati
    // Ad esempio, trasferire i valori a DB per visualizzazione HMI, attivare allarmi, ecc.
    

6. Caso Specifico: ADAM/Maselli che Genera 0-20mA

Per gestire questa situazione:

  1. Configurazione del modulo: Configura il modulo analogico SIMATIC per il range 4-20mA

  2. Gestione dei valori sotto 4mA: Quando il valore scende sotto 4mA (che in formato S7 sarebbe sotto 0 in decimale), il modulo lo interpreta come underrange.

  3. Rilevamento dell'errore a 2mA: Il valore di 2mA corrisponde approssimativamente a -3456 in formato decimale S7 per il range 4-20mA.

Senza utilizare la SFC51:


// Determinazione dello stato del sensore basata solo sul valore PEW
IF ValoreAnalogicoInt = OVERFLOW_VALUE THEN  // 32767
    o_StatoSensore := 7;  // Codice generico per "Overflow o Wire Break"
    o_DiagInfo := 'Rilevato Overflow o Wire Break';
ELSIF ValoreAnalogicoInt = UNDERFLOW_VALUE THEN  // -32768
    o_StatoSensore := 2;  // Underflow
    o_DiagInfo := 'Underflow rilevato';
ELSIF ValoreAnalogicoInt >= ADAM_ERROR_LOW AND ValoreAnalogicoInt <= ADAM_ERROR_HIGH THEN
    o_StatoSensore := 4;  // Errore ADAM (2mA)
    o_DiagInfo := 'Errore ADAM rilevato (2mA)';
ELSE
    o_StatoSensore := 0;  // OK
    o_DiagInfo := 'Misura OK';
END_IF;