#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](https://cache.industry.siemens.com/dl/files/991/25545991/att_70599/v1/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:
```pascal
// 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:
***
```pascal
// 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;
```