BEM e Istrumenti di blocco

Torna alla pagina CONTROLLO

Introduzione

Nelle ferrovie italiane da sempre vige il regime del consenso: una stazione per liberare il segnale di partenza deve chiedere preventivamente il consenso alla stazione di destinazione. Questo non avviene in altri paesi, come in Germania, dove il regime di giunto impone alla stazione di destinazione solamente di informare del treno pervenuto. Nelle linee recentemente dotate di dco, tecnologicamente più evolute, essendo unico l’operatore, non ha più senso parlare di richiedere e concedere consensi a se stessi, ma la filosofia di fondo rimane quella d’origine volta a garantire la massima sicurezza di marcia possibile.

Il blocco elettrico manuale (BEM) venne progettato per permettere la circolazione dei treni secondo il regime del consenso. Per sapere come funziona il BEM si rimanda all’articolo apparso su iTreni n. 144. In Internet si trova un’ottima spiegazione nel sito:

http://www.miaferrovia.it/bem.asp

Nello stesso sito si trova anche una semplice simulazione dinamica molto chiara ed efficace.

Poichè la nostra ferrovia modello è ispirata agli anni '60, abbiamo voluto installare nel nostro impianto un sistema simulativo il più possibile aderente al BEM, quindi le stazioni sono dotate di istrumenti di blocco (IB). Gli IB sono apparecchi che combinano complesse funzioni meccaniche ad altrettante connessioni elettriche. La realizzazione ha richiesto alcune ovvie semplificazioni riguardanti soprattutto l'aspetto meccanico. Si pensi solo per esempio alla maniglia di concessione che in realtà è bloccata dal treno in linea e non può essere materialmente ruotata. Il nostro istrumento modello è invece composto da pochi componenti: due luci con il solo aspetti di acceso e spento al posto dei dischi, da un pulsante e da un interruttore a levetta al posto delle maniglie. Resta fedele al reale la disposizione sul lato sinistro dei comandi di richiesta consenso e a destra di quelli di concessione. Rispetto al modello reale manca la riproduzione del disco centrale perché nel nostro caso è inutile.


Il regime di consenso

Chiamiamo allora A e B le stazioni da mettere in comunicazione. Lo IB verso est di A si chiama Ae, mentre quello verso ovest di B si chiama Bo.Nello schema che segue gli interruttori su fondo verde rappresentano le leve di segnale di partenza dalla stazione A, chiamato As, e di protezione della stazione B, chiamato Bs. La prima cosa da fare è definire tutto il ciclo di comunicazione tra due stazioni nel dettaglio. Questa definizione rispecchia nel suo processo logico in modo molto fedele quanto avveniva in realtà.

0 - Posizione iniziale o di riposo

Nell’ordine, al primo passo della sequenza ci troviamo nella situazione iniziale o di riposo. Le luci sono spente, gli interruttori in posizione ribassata, il treno è fermo nella stazione A:

1 – Tentativo di licenziare il treno

Provando a muovere la leva di As, essendo in mancanza di consenso, il segnale rimane al rosso:

2 – Richiesta di consenso

Il capostazione di A deve licenziare il treno e chiede pertanto il consenso al capostazione di B premendo il pulsante di Ae. La luce di richiesta da parte della stazione di A si illumina (in  blu) in Bo e contemporaneamente è emesso un suono di avviso. Se, dato un certo tempo, il capostazione di B non risponde, la richiesta decade, la luce blu si spegne e si ritorna al primo passo. In realtà invece la richiesta resta pendente fino alla concessione del consenso da parte del capostazione di B:

3- Concessione consenso

Se invece ci sono le condizioni, il capostazione di B alza la levetta di concessione del consenso posta in Bo. In Ae si accende la luce gialla di conferma concessione avvenuta. A questo punto il capostazione di B può cambiare l’aspetto di Bs dopo aver predisposto l’itinerario di ingresso. Se si stanno verificando manovre in B, Bs deve rimanere sul rosso. Se in orario B è di transito, il capostazione appena concesso il consenso ad A, dovrà a sua volta effettuare la richiesta alla stazione C per comporre l’itinerario di via libera. A questo punto, se ci sono manovre e se sono terminate, il capostazione di B dispone Bs con l’aspetto verde di via libera:

4 - Licenziamento del treno

A questo punto l’operatore di A, muove la leva di As ed esso assume l’aspetto di via libera. Il treno può partire:

5 – Treno in linea

Il treno è in linea. Appena lasciata A, As va al rosso e protegge la linea. Il segnale di partenza As non può tornare al verde fino completamento del ciclo. In questa fase le luci degli IB rimangono accese. Durante il tragitto il capostazione di B può cambiare l’aspetto di Bs:

6 – Treno in approccio alla destinazione

Suona la tipica campanella di attenzione per l’arrivo del treno:

7 – Treno giunto a destinazione

Il treno occupa la prima sezione della stazione B, mette Bs al rosso, la campanella si ferma e si spegne la luce gialla di Ae e quella azzurra di Bo. Il capostazione di A abbassa la leva del segnale di partenza:

8 – Ripristino situazione iniziale

Termine del ciclo. Il capostazione di A vede spegnersi la luce gialla e muove la leva di As in posizione normale. Il capostazione di B abbassa la leva di concessione di Bo e la leva del segnale di protezione Bs: si ritorna alla condizione iniziale:


La realizzazione

Appare chiaro che ci troviamo davanti a un'applicazione adattissima per mettere a frutto le nostre conoscenze di programmazione digitale. Tutto l'impianto che andiamo a descrivere non è altro che una composizione di elementi visti nei capitoli precedenti. Ci sono molte soluzioni possibili. Quella qui proposta comporta, come vedremo, un approccio da programmazione a oggetti. Lo schema che segue illustra la parte hardware della realizzazione; per semplicità è stato inserito un solo dispositivo di riconoscimento d'occupazione della tratta; i vari componenti dovrebbero essere ormai familiari:

 

Il primo passo è definire tutti gli elementi presenti nella comunicazione assegnando a ciascuno una sigla di riferimento comoda che poi riutilizzeremo nello scrivere il codice del programma. La comunicazione da sinistra a destra avviene tra due semi-IB (lato sinistro dell'IB di A e lato destro dell'IB di B). Le sigle sono composte da tre caratteri con il significato seguente:

primo carattere: area di riferimento  
A stazione di partenza
X transito
Y sezione di approccio alla destinazione
B stazione di destinazione

 

secondo carattere: elemento  
S segnale (seguito eventualmente da un numero progressivo)
O occupazione
D deviatoio (seguito eventualmente da un numero progressivo)
C call - richiesta di consenso
L leaving - concessione consenso

 

terzo carattere: canale digitale  
I ingresso (blocco, lato, valore)
O uscita (indirizzo, valore on, valore off)

 

Elenchiamo allora tutti gli elementi necessari nell'ordine partendo dalla stazione A:

ACO luce gialla consenso ricevuto
ACI pulsante richiesta consenso
AOI occupazione stazione di partenza
ASI stato della leva di liberazione del segnale di partenza
ASO luce segnale di partenza
XOI occupazione sezione di transito
XDnO eventuale deviatoio in linea da muove in automatico (n è il progressivo)
YOI occupazione sezione di approccio
BS1O aspetto segnale di protezione luce 1
BS2O aspetto segnale di protezione luce 2
BOI occupazione stazione di destinazione
BLO luce blu richiesta consenso
BLI stato leva concessione consenso

Alcune considerazioni:

  1. gli elementi AOI e BOI non sono indispensabili. E' possibile infatti identificare il passaggio del treno non solo leggendo l'occupazione della sezione di stazione, ma con l'abbandono della sezione precedente; nel caso di Introbio, per esempio, abbiamo tre binari possibili di occupazione, è quindi più semplice controllare l'uscita dalla sezione di approccio che considerare l'occupazione di tre sezioni in alternativa;
  2. i deviatoi che entrano in gioco non sono quelli delle stazioni che sono comandati direttamente dal capostazione, ma si tratta dei deviatoi presenti lungo la linea di transito (vedi sotto il dettaglio del problema);
  3. il segnale di partenza ammette due soli stati (rosso e verde), quindi si può utilizzare un solo indirizzo con commutatore associato; per la protezione invece, gli aspetti possibili sono tre (rosso, verde, giallo) e in questo caso occorrono almeno due indirizzi di interruttori indipendenti (si veda il capitolo dedicato al comando dei segnali digitali).

Essendo la linea logicamente pensata da punto a punto occorre distinguere i deviatoi presenti nel tracciato, che devono essere orientati secondo il percorso predisposto e quelli mossi dai capistazione. Nel caso per esempio della tratta tra Taceno e Introbio ci troviamo una coppia di deviatoi (XD1O e XD2O) che in realtà vanno orientati costituendo un vero incrocio; nel primo giro permettono il collegamento diretto tra Taceno e Introbio, nel secondo al contrario collegano Introbio con Pasturo:


Programmare a oggetti

Non è possibile descrivere in poche righe cosa sia la programmazione a oggetti. Si rimanda ai tanti corsi che si trovano in rete. In questa sede basti sapere per ora che una classe è una composizione di dati e parti di programma. Nel nostro caso, la classe BEM è costituita da:

  1. PROPRIETA': i dati e i loro riferimenti descritti sopra, il valore degli indirizzi di ingresso e uscita da impiegare;
  2. METODI: le procedure che permettono la sequenza del ciclo descritto.

Per prima cosa aggiungiamo al nostro progetto un modulo di classe che conterrà la struttura di BEM. Lo salviamo come file con il nome clsBEM.cls. Quando useremo questa classe genereremo tante istanze quanti sono le comunicazioni tra stazioni che stiamo utilizzando.

La classe BEM, dichiarazioni

La classe contiene la parte dichiarativa composta da tutte le variabili in uso nel modulo. Esse per chiarezza hanno tutte il prefisso m (= modulo):

Option Explicit

Dim mstrName As String
Dim mintStatus As Integer

Dim mFrm As Form

Dim mintACI_Value As Integer
Dim mintACI_Block As Integer
Dim mstrACI_Side As String

Dim mintACO_Address As Integer
Dim mintACO_OffVal As Integer
Dim mintACO_OnVal As Integer

Dim mintBLI_Value As Integer
Dim mintBLI_Block As Integer
Dim mstrBLI_Side As String

Dim mintBLO_Address As Integer
Dim mintBLO_OffVal As Integer
Dim mintBLO_OnVal As Integer

Dim mintASI_Value As Integer
Dim mintASI_Block As Integer
Dim mstrASI_Side As String

Dim mintASO_Address As Integer
Dim mintASO_OffVal As Integer 'red
Dim mintASO_OnVal As Integer 'green

Dim mintBS1O_Address As Integer
Dim mintBS1O_OffVal As Integer 'red
Dim mintBS1O_OnVal As Integer 'green
Dim mintBS2O_Address As Integer
Dim mintBS2O_OffVal As Integer 'red
Dim mintBS2O_OnVal As Integer 'green

Dim mintXD1O_Address As Integer
Dim mintXD1O_OffVal As Integer 'normale
Dim mintXD1O_OnVal As Integer 'rovescia
Dim mintXD2O_Address As Integer
Dim mintXD2O_OffVal As Integer 'normale
Dim mintXD2O_OnVal As Integer 'rovescia

Dim mintXOI_Value As Integer
Dim mintXOI_Block As Integer
Dim mstrXOI_Side As String

Dim mintYOI_Value As Integer
Dim mintYOI_Block As Integer
Dim mstrYOI_Side As String

Dim mlngWait As Long
 

Const mWAIT = 1500 'frequenza = 100 milli
Const mENDCMD = 32

Come si può notare, oltre alle variabili che dipendono dai nomi che ci siamo dati ci sono anche altre variabili impiegate dalla classe e un paio di valori costanti. La più importante di queste variabili è mintStatus. Essa serve per avcere presente lo stato corrente del ciclo del BEM, ma anche per una ragione tecnica: quando il treno passa da una sezione all'altra del tracciato, per qualche istante le due sezioni contigue risultano occupate; per evitare allora problemi di sincronismo tra gli script, il loro contenuto va in esecuzione una sola volta se controllato dal valore della variabile. E' quello che in gergo si chiama automa a stati finiti.

Per gli elementi di ingresso ci troviamo ad avere tre valori distintivi:

  1. blocco (_Block) = blocco di appartenenza dell'ingresso; si tratta dei moduli di retroazione, blocchi di 16 indirizzi ciascuno;
  2. lato (_Side) =  lato destro o sinistro del blocco; ogni modulo, come descritto nel capitolo sul comando completo per deviatoio trasmette due caratteri di otto bit ciascuno, il primo sarà il carattere sinistro e il secondo il destro;
  3. valore (_Value) = il valore del carattere che spacchettato identifica quali sono i bit di ingresso sollevati, quali no.

Anche per gli elementi in uscita ci troviamo ad avere tre valori distintivi:

  1. indirizzo (_Address) = l'indirizzo in output da assegnare;
  2. comando di apertura (_OffVal) = il comando di apertura; poiché il montaggio dei decoder può richiedere materialmente un cablaggio complesso, non è garantito che il comando di apertura sia sempre il 34 e quello di chiusura il 33; questo valore ci dire quale dei due impieghiamo per l'indirizzo relativo;
  3. comando di chiusura (_OnVal) = è il reciproco del precedente, quindi se un indirizzo ha il comando di apertura uguale a 33, quello di chiusura vale 34 e viceversa; inoltre, se usassimo un'altro modello di centralina, questi valori possono essere differenti.

 

Proprietà

Alla parte dichiarativa  fa seguito la sezione delle proprietà della classe. Si tratta di semplici script che ci permettono di assegnare e di leggere i valori effettivi in uso per le istanze. Non tutte le proprietà sono usate sia in lettura che in scrittura. La form frmMain stessa è usata dalla classe, in questo caso ovviamente la proprietà e di sola scrittura (mFrm è una variabile oggetto che contiene i valori della form principale trasmessi alla classe):

Property Let formRif(ByRef frmPar As Form)
    Set mFrm = frmPar
End Property

 

Il ciclo di comunicazione è diviso in fasi sequenziali; la classe tiene conto in quale fase ci troviamo; occorre pertanto in questo una proprietà di assegnamento della fase del ciclo e di lettura per capire a ceh punto siamo del processo:

Property Let Status(ByVal intStatus As Integer)
    mintStatus = intStatus
End Property


Property Get Status() As Integer
    Status = mintStatus
End Property

Identifichiamo ogni istanza di BEM con un nome proprio:

Property Let Name(ByVal strName As String)
    mstrName = strName
End Property

Property Get Name() As String
    Name = mstrName
End Property

 

Le triplette degli indirizzi di ingresso e di uscita valorizzano le variabili della classe e non c'è necessità di leggerle, pertanto in quersti abbiamo la sola proprietà di scrittura; nel caso di indirizzi di ingresso occorrerà definire una prorpeirtà per ognuno di essi sull'esempio che segue:

Property Let ACI_Value(ByVal intValue As Integer)
   
mintACI_Value = intValue
End Property

Property Let ACI_Block(ByVal intBlock As Integer)
    mintACI_Block = intBlock
End Property

Property Let ACI_Side(ByVal strSide As String)
    mstrACI_Side = strSide
End Property

Nel caso invece di un indirizzo in uscita dichiareremo tre proprietà sulll'esempio che segue

Property Let A_CO_Address(ByVal intAddress As Integer)
    mintACO_Address = intAddress
End Property

Property Let A_CO_OnVal(ByVal intVal As Integer)
    mintACO_OnVal = intVal
End Property

Property Let A_CO_OffVal(ByVal intVal As Integer)
    mintACO_OffVal = intVal
End Property
 

Metodi

I metodi adottati eseguono i passi del ciclo descritto. Inoltre abbiamo quattro metodi (quello di inizializzazione, quello di posizionamento al rosso del segnale di partenza e quello di attesa di consenso; il metodo EditBEM richiede un paragrafo a parte) che non sono strettamente legati al ciclo. Il metodo di inizializzazione viene chiamato quando si istanzia per la prima volta un BEM. Dopo aver assegnato i valori (vedi avanti), tutti gli elementi del BEM vanno messi nella posizione iniziale o di riposo:

Sub Init()

'1. ACO OFF:
mFrm.MSComm1.Output = Chr$(mintACO_OffVal)
mFrm.MSComm1.Output = Chr$(mintACO_Address)
mFrm.MSComm1.Output = Chr$(mENDCMD)

mFrm.tmBell.Enabled = False

Call Sleep(200)

'2. XDnO OFF:
If mintXD1O_Address > 0 Then
    mFrm.MSComm1.Output = Chr$(mintXD1O_OffVal)
    mFrm.MSComm1.Output = Chr$(mintXD1O_Address)
    mFrm.MSComm1.Output = Chr$(mENDCMD)

    Call Sleep(200)
End If
If mintXD2O_Address > 0 Then
    mFrm.MSComm1.Output = Chr$(mintXD2O_OffVal)
    mFrm.MSComm1.Output = Chr$(mintXD2O_Address)
    mFrm.MSComm1.Output = Chr$(mENDCMD)

    Call Sleep(200)
End If

'3. ASO OFF:
mFrm.MSComm1.Output = Chr$(mintASO_OffVal)
mFrm.MSComm1.Output = Chr$(mintASO_Address)
mFrm.MSComm1.Output = Chr$(mENDCMD)

Call Sleep(200)

'4. BLO OFF:
mFrm.MSComm1.Output = Chr$(mintBLO_OffVal)
mFrm.MSComm1.Output = Chr$(mintBLO_Address)
mFrm.MSComm1.Output = Chr$(mENDCMD)

Call Sleep(200)

'5. BSnO OFF:
mFrm.MSComm1.Output = Chr$(mintBS1O_OffVal)
mFrm.MSComm1.Output = Chr$(mintBS1O_Address)
mFrm.MSComm1.Output = Chr$(mENDCMD)

Call Sleep(200)

mFrm.MSComm1.Output = Chr$(mintBS2O_OffVal)
mFrm.MSComm1.Output = Chr$(mintBS2O_Address)
mFrm.MSComm1.Output = Chr$(mENDCMD)

Call Sleep(200)

'6. si pone a zero la fase corrente del ciclo (o stato):
mintStatus = 0
End Sub
 

Quando il capostazione di A richiede il consenso preme il pulsante; a fronte di questo evento scatta il metodo di chiamata; si noti che lo script va in esecuzione solo se siamo allo stato 0 e subito manda un segnale sonoro oltre a illuminare la luce di richiesta nell'IB di destinazione:

Sub Calling()

If mintStatus <> 0 Then Exit Sub

Beep 700, 300

'1. BLO ON:
mFrm.MSComm1.Output = Chr$(mintBLO_OnVal)
mFrm.MSComm1.Output = Chr$(mintBLO_Address)
mFrm.MSComm1.Output = Chr$(mENDCMD)

'2. cambio stato:
mintStatus = 1
End Sub

Quando il capostazione di B riceve la richiesta, vede accendersi la luce blu sull'IB di collegamento ad A unitamente a un suono di richiamo; muovendo la leva di concessione del consenso viene evocato il metodo di concessione che va in esecuzione solo se siamo allo stato 1; si eseguono diversi comandi, si accende la luce gialla di conferma nell'IB di A e in particolare si muovono nella posizione corretta eventuali deviatoi lungo il transito:


Sub Leaving()

If mintStatus <> 1 Then Exit Sub

'1. ACO ON:
mFrm.MSComm1.Output = Chr$(mintACO_OnVal)
mFrm.MSComm1.Output = Chr$(mintACO_Address)
mFrm.MSComm1.Output = Chr$(mENDCMD)

Call Sleep(200)

'2. XDnO -
If mintXD1O_Address > 0 Then
    mFrm.MSComm1.Output = Chr$(mintXD1O_OnVal)
    mFrm.MSComm1.Output = Chr$(mintXD1O_Address)
    mFrm.MSComm1.Output = Chr$(mENDCMD)

    Call Sleep(200)
End If
If mintXD2O_Address > 0 Then

    mFrm.MSComm1.Output = Chr$(mintXD2O_OnVal)
    mFrm.MSComm1.Output = Chr$(mintXD2O_Address)
    mFrm.MSComm1.Output = Chr$(mENDCMD)

    Call Sleep(200)
End If
 

mFrm.MSComm1.Output = Chr$(mintBS1O_OnVal)
mFrm.MSComm1.Output = Chr$(mintBS1O_Address)
mFrm.MSComm1.Output = Chr$(mENDCMD)

Call Sleep(200)

If mintBS2O_Address > 0 Then
    mFrm.MSComm1.Output = Chr$(mintBS2O_OnVal)   
    mFrm.MSComm1.Output = Chr$(mintBS2O_Address)
    mFrm.MSComm1.Output = Chr$(mENDCMD)

    Call Sleep(200)
End If

'3.
mintStatus = 2
End Sub
 

Quando il capostazione di A riceve il consenso muove la leva del segnale di partenza; questa informazione attiva il metodo di liberazione:


Sub Clearing()

If mintStatus <> 2 Then Exit Sub

'1. ASO ON:
mFrm.MSComm1.Output = Chr$(mintASO_OnVal)
mFrm.MSComm1.Output = Chr$(mintASO_Address)
mFrm.MSComm1.Output = Chr$(mENDCMD)

Call Sleep(200)

'2.
mintStatus = 3
End Sub
 

Quando il treno parte e lascia la sezione della stazione per entrare in linea, il segnale di partenza torna automaticamente al rosso:

Sub Proofing()

If mintStatus <> 3 Then Exit Sub

'1. ASO OFF:
mFrm.MSComm1.Output = Chr$(mintASO_OffVal)
mFrm.MSComm1.Output = Chr$(mintASO_Address)
mFrm.MSComm1.Output = Chr$(mENDCMD)

Call Sleep(200)

'2.
mintStatus = 4
End Sub
 

Quando il treno entra nella sezione di approccio alla stazione di destinazione suona la campanella di avviso, come nella realtà; la campanella si attiva tramite un controllo timer in modo indipendente dal ciclo in essere:


Sub Approching()

If mintStatus <> 4 Then Exit Sub

'1. bell on:
mFrm.tmBell.Enabled = True

'2.
mintStatus = 5
End Sub
 

Quando il treno entra nella stazione B di destinazione, o lascia la sezione di approccio, la campanella si spegne e si spengono anche le luci degli IB e si mette al rosso il segnale di protezione (il capostazione di A muove al rosso la leva del segnale di partenza il cui aspetto era già al rosso):

Sub Arriving()
 

If mintStatus <> 5 Then Exit Sub
 

'1. ACO OFF:
mFrm.MSComm1.Output = Chr$(mintACO_OffVal)
mFrm.MSComm1.Output = Chr$(mintACO_Address)
mFrm.MSComm1.Output = Chr$(mENDCMD)

Call Sleep(200)

'2. BLO OFF:
mFrm.MSComm1.Output = Chr$(mintBLO_OffVal)
mFrm.MSComm1.Output = Chr$(mintBLO_Address)
mFrm.MSComm1.Output = Chr$(mENDCMD)

Call Sleep(200)

'3. BS1O OFF:
mFrm.MSComm1.Output = Chr$(mintBS1O_OffVal)
mFrm.MSComm1.Output = Chr$(mintBS1O_Address)
mFrm.MSComm1.Output = Chr$(mENDCMD)

Call Sleep(200)


If mintBS2O_Address > 0 Then
    mFrm.MSComm1.Output = Chr$(mintBS2O_OffVal)
    mFrm.MSComm1.Output = Chr$(mintBS2O_Address)
    mFrm.MSComm1.Output = Chr$(mENDCMD)

    Call Sleep(200)
End If


mFrm.tmBell.Enabled = False

'4.
mintStatus = 6
End Sub

A questo punto il capostazione di B abbassa la leva della concessione del consenso ristabilendo le condizioni iniziali:

Sub Reset()

If mintStatus < 6 Then Exit Sub
Call Me.Init

End Sub

Nella presentazione del ciclo si è detto che dopo la richiesta di un consenso se il capostazione di B non può concederlo per ragioni varie, dopo un certo tempo la richiesta decade ripristinando le condizio0ni iniziali. Per fare questo c'è un metodo appropriato con un conteggio empirico di durata di attesa (si potrebbero usare anche altre tecniche):


Sub Waiting()

If mintStatus <> 1 Then Exit Sub

mlngWait = mlngWait + 1

If mlngWait >= mWAIT Then
mlngWait = 0
Call Me.Init
End If

End Sub

Il capostazione di A, in caso di problemi, può muovere la leva al rosso prima dell'arrivo del treno a destinazione; in questo caso scatta un evento indipendente:

Sub Stopping()

If mintStatus < 3 Then Exit Sub

'1. ASO OFF:
mFrm.MSComm1.Output = Chr$(mintASO_OffVal)
mFrm.MSComm1.Output = Chr$(mintASO_Address)
mFrm.MSComm1.Output = Chr$(mENDCMD)

Call Sleep(200)

End Sub
 

Avanzamento del ciclo

Veniamo ora al metodo principale della classe, quello cioè preposto all'aggiornamento progressivo del BEM. Esso scatta a fronte della lettura degli ingressi che avviene nello script del timer della form principale. Da questo script si chiama il metodo indicando l'indirizzo attivo di ingresso, composto dalla tripletta Blocco, Valore, Lato e dallo stato del bit trasmesso, aperto o chiuso. Il confronto con i valori dell'istanza fa scattare i metodi descritti sopra. Si noti in particolare il caso dell'ingresso in stazione, valutato come rilascio della sezione di approccio:


Sub EditBEM(ByVal intBlock As Integer, _
ByVal intValue As Integer, _
ByVal strLato As String, _
ByVal strStato As String)

If mintACI_Block = intBlock And _
    mintACI_Value = intValue And _
    mstrACI_Side = strLato And _
    strStato = "ON" Then

    Call Calling
End If

Call Waiting

If mintBLI_Block = intBlock And _
    mintBLI_Value = intValue And _
    mstrBLI_Side = strLato And _
    strStato = "ON" Then

    Call Leaving
End If

If mintASI_Block = intBlock And _
    mintASI_Value = intValue And _
    mstrASI_Side = strLato And _
    strStato = "ON" Then

    Call Clearing
End If

If mintXOI_Block = intBlock And _
    mintXOI_Value = intValue And _
    mstrXOI_Side = strLato And _
    strStato = "ON" Then

    Call Proofing
End If

If mintYOI_Block = intBlock And _
    mintYOI_Value = intValue And _
    mstrYOI_Side = strLato And _
    strStato = "ON" Then

    Call Approching
End If

If mintYOI_Block = intBlock And _
    mintYOI_Value = intValue And _
    mstrYOI_Side = strLato And _
    strStato = "OFF" Then

    Call Arriving
End If

If mintBLI_Block = intBlock And _
    mintBLI_Value = intValue And _
    mstrBLI_Side = strLato And _
    strStato = "OFF" Then

    Call Reset
End If

If mintASI_Block = intBlock And _
    mintASI_Value = intValue And _
    mstrASI_Side = strLato And _
    strStato = "OFF" Then

    Call Stopping
End If

End Sub
 


Collezione, istanze e assegnamento dei valori

Nella scheda principale avviene la definizione della collezione delle istanze della classe BEM. La collezione è dichiarata a livello di modulo, quindi:

Dim mBEMs As Collection

All'avvio del programma, all'apertura della scheda principale viene chiamata una procedura di inizializzazione di tutti i BEM presenti nell'impianto. Per ognuno di essi si valorizzano le variabili della classe che poi eseguiranno i comandi descritti sopra. Ogni BEM che definiamo è un'istanza della classe BEM:

Sub SetBEMs()

Dim BEM As clsBEM
Set mBEMs = New Collection


'CREAZIONE NUOVA ISTANZA DI CLASSE:

Set BEM = Nothing
Set BEM = New clsBEM
BEM.Name = "TacenoToIntrobio"
BEM.Status = 0
BEM.formRif = Me 'si passa la form frmMain come proprietà della classe stessa

BEM.ACI_Value = 8
BEM.ACI_Block = 3
BEM.ACI_Side = "L"

BEM.ACO_Address = 28
BEM.ACO_OffVal = 33
BEM.ACO_OnVal = 34
...
 

'dopo aver assegnato tutti i valori si aggiunge l'istanza alla collezione e si inizializza l'istanza stessa:

mBEMs.Add BEM, BEM.Name
Call BEM.Init

'SEGUE POI LA CREAZIONE DI UNA SECONDA NUOVA ISTANZA DI CLASSE:

Set BEM = Nothing
Set BEM = New clsBEM

BEM.Name = "IntrobioToTaceno"
BEM.Status = 0
BEM.formRif = Me

BEM.ACI_Value = 4
BEM.ACI_Block = 1
BEM.ACI_Side = "R"
...

' e relativa aggiunta alla collezione e inizializzazione:

mBEMs.Add BEM, BEM.Name
Call BEM.Init

End Sub
 

Lettura degli ingressi e spacchettamento

Come già descritto nelle pagine precedenti, il timer legge gli ingressi, li spacchetta, riconosce a quale BEM gli ingressi ri riferiscono, e a questo punto chiama il metodo di aggiornamento relativo alla istanza corrente:

Private Sub Timer1_Timer()
...

Dim BEM As clsBEM
 

'lettura ingressi e spacchettamento

...

...

'riconoscimento BEM da usare

If <<<condizioni>>> Then pInsance = "TacenoToIntrobio"

...

' ciclo nella collezione dei BEM per eseguire il metodo relativo solo a quello corrente:
For Each BEM In mBEMs
    If BEM.Name = pInstance Then
        Call BEM.EditBEM(pBlock, pValue, pLato, pStato)
    End If
Next

End Sub

 


L’apparecchio

La realizzazione materiale degli IB è molto semplice. Sono state impiegate infatti comuni scatolette di legno su cui abbiamo effettuato i fori per inserire le due lampadine, il pulsante di richiesta e la leva di concessione del consenso. Dopo la foratura si è passati alla colorazione in rosso vivo con l’uso di una comune bomboletta spray. All’interno della scatoletta è alloggiato, come detto, un decoder 67600:

Sul retro della scatoletta sono collocati i mammut per la connessione ai suoi componenti. Segue qualche immagine di alcuni degli IB installati:


 

Torna all'inizio pagina

Torna alla pagina CONTROLLO