Due programmi che condividono uModbusRTU e uGauge: - Console/PlanciaConsole: plancia nautica descritta da file XML, con modalita' plancia e modalita' configurazione. Comandi, spie, selettori, strumenti e allarmi sonori; il bus gira in un thread suo perche' la finestra non si fermi mai. - ProjectPlancia: il programma di prova piu' vecchio, usato per collaudare i canali. Le plance sono in Console/*.xml, la documentazione in Console/LEGGIMI.md. Esclusi dal versionamento i compilati (.exe, .dcu), i file dell'IDE e un audio da 17 MB. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
38 KiB
PlanciaConsole
Plancia configurabile su Modbus RTU / RS485. Due modalità, decise dalla riga di comando; la configurazione vive in un file XML letto all'avvio.
Riusa ..\uModbusRTU.pas e ..\uGauge.pas del programma di test
(ProjectPlancia): i due progetti condividono quei due file, non ne esistono
copie. Il bus gira in un thread a parte (uModbusWorker.pas), così la finestra
non si ferma mai; vedi "Il bus in un thread a parte".
Avvio
PlanciaConsole.exe aboard, legge plancia.xml
PlanciaConsole.exe aboard
PlanciaConsole.exe config configurazione
PlanciaConsole.exe config -f rotta.xml configurazione su un altro file
PlanciaConsole.exe rotta.xml aboard su un altro file
Senza indicazioni viene riaperta l'ultima plancia usata, e in mancanza di
quella plancia.xml accanto all'eseguibile. -f <percorso>,
-file=<percorso> o un parametro libero indicano un file diverso.
Modalità aboard
Legge l'XML, apre la porta seriale indicata nel file, si connette da sola e opera. A vista c'è solo la plancia più una barra di stato con porta, baud, LED verde/rosso e ultimo messaggio. Nessun comando di configurazione.
La finestra si dimensiona sulla plancia. Se il pannello è più grande dello schermo lo zoom si riduce automaticamente per farcelo stare: a bordo è meglio una plancia rimpicciolita che una da raggiungere scorrendo.
Cambiare plancia a bordo
In fondo a destra, nella barra di stato, una casella elenca le plance della stessa cartella del file caricato: tutti gli XML che sono configurazioni di plancia, mostrati con il loro titolo. Scegliendone una:
- la porta seriale viene chiusa e riaperta con porta e baud del nuovo file;
- la finestra si ridimensiona sul nuovo pannello;
- le bobine non vengono toccate: i relè restano come sono e la nuova plancia ne rilegge lo stato al primo ciclo di polling.
Il file viene letto per prova prima di lasciare quello in servizio: se è rotto resta la plancia di prima e l'errore compare nella barra di stato.
La casella compare solo in aboard e solo se nella cartella ci sono almeno due plance. In configurazione si usa "Apri", che chiede anche delle modifiche non salvate. Dopo la scelta il fuoco viene tolto alla casella, così le frecce della tastiera non cambiano plancia per sbaglio.
Modalità configuration
Palette a sinistra, pannello a destra con le proprietà dell'elemento selezionato, barra in alto con Nuovo / Apri / Salva / Salva con nome, griglia e zoom.
- Inserire: trascina una voce della palette sul pannello. L'elemento nasce centrato sul punto di rilascio; se lì c'è già qualcosa scala in diagonale finché trova posto libero, così non si impilano tutti nello stesso punto.
- Spostare: trascina l'elemento. Un click senza trascinare non lo sposta: il movimento parte solo oltre la soglia di trascinamento di Windows (pochi pixel), e un asse su cui il mouse non si è mosso non viene riagganciato alla griglia.
- Ridimensionare: trascina una delle otto maniglie dell'elemento selezionato, oppure scrivi larghezza e altezza nel pannello proprietà.
- Ritocchi da tastiera, sull'elemento selezionato: Ctrl+freccia lo sposta di un pixel, Maiusc+freccia cambia le misure di un pixel (destra e giù ingrandiscono, sinistra e su rimpiccioliscono). Un pixel esatto anche con la griglia attiva. Non funzionano mentre si scrive in una casella, dove le frecce restano del testo: cliccare l'elemento riporta i tasti sul pannello.
- Annulla / Ripeti: pulsanti nella barra, oppure Ctrl+Z e Ctrl+Y (o Ctrl+Maiusc+Z). Coprono spostamenti, misure, proprietà, tipo, elementi aggiunti e cancellati e le impostazioni generali, fino a 100 passi. Le modifiche in fila sulla stessa cosa, entro un secondo e mezzo l'una dall'altra, contano come un passo solo: le cifre di una larghezza digitata, o Ctrl+freccia tenuto premuto. Lo storico si azzera con Nuovo e Apri. Un'immagine rimossa dalla libreria non torna con Annulla: tornano i riferimenti degli elementi, ma il file va riaggiunto.
- Griglia: con "Griglia 10 px" attiva posizioni e bordi si agganciano a multipli di 10.
- Zoom: da 50% a 200%. È solo una lente di lavoro: le coordinate salvate nell'XML restano sempre quelle reali al 100%.
- Configurare: seleziona l'elemento e compila i campi. Le modifiche si vedono subito.
- Eliminare: pulsante "Elimina elemento" o tasto Canc.
- Chiusura: chiudendo la finestra la plancia viene salvata da sola nel file su cui si stava lavorando, senza chiedere niente. Solo se il salvataggio non riesce (disco pieno, file di sola lettura) viene chiesto se chiudere comunque. Nuovo, Apri e il passaggio in plancia invece continuano a chiedere cosa fare delle modifiche: lì si può volerle buttare.
Come viene scritto il file. Il salvataggio non scrive mai sopra il file
buono: scrive un .tmp accanto e poi scambia i nomi, tenendo la versione
precedente come .bak. Così un programma chiuso male, un disco pieno o due
copie del programma che salvano insieme non possono lasciare un XML troncato,
che alla riapertura non si leggerebbe più. Se un file non si apre, accanto c'è
il .bak della volta prima: si rinomina e si riparte da lì.
Se il file non si è aperto, chiudendo non ci si salva sopra: il programma avverte e propone "Salva con nome", perché salvare il pannello vuoto cancellerebbe quello che il file contiene.
All'avvio senza indicazioni viene riaperta l'ultima plancia usata: il
percorso è ricordato in plancia-ultima.txt accanto all'eseguibile, e si
aggiorna a ogni apertura, salvataggio e cambio di plancia a bordo. Se quel file
non c'è, o la plancia è stata spostata, si riparte da plancia.xml. Un file
indicato sulla riga di comando ha comunque la precedenza.
In configurazione la porta seriale non viene aperta: si disegna la plancia
senza rischiare di comandare relè per sbaglio. Per provare i canali si usa il
programma di test ProjectPlancia.
Passare da una modalità all'altra
Chi è partito con config trova in fondo a destra, nella barra di stato, un
pulsante "Vai in plancia": la palette e le proprietà spariscono, la finestra
si veste sulla plancia e la porta seriale si apre. Da lì il pulsante diventa
"Torna a configurare" e riporta indietro, chiudendo la porta.
Serve a provare quello che si è appena disegnato senza chiudere e riaprire il programma con un'altra riga di comando.
Tre cose da sapere:
- Se ci sono modifiche non salvate viene chiesto cosa farne prima di passare in plancia, altrimenti si perderebbero in silenzio.
- Tornando a configurare la porta seriale viene chiusa, e le spie tornano a "dato non disponibile": una plancia che non sta leggendo non deve sembrare in servizio.
- Posizione della finestra e zoom di lavoro vengono ritrovati come li si era lasciati, perché in plancia la finestra si ridimensiona sul pannello.
Chi è partito in aboard non vede il pulsante. Una plancia avviata in
servizio non deve offrire la strada per essere modificata per sbaglio; per
configurarla si riavvia con config.
Modalità notturna
Accanto c'è il pulsante "Notte", questo disponibile in entrambe le modalità. Scurisce l'intera plancia: fondo quasi nero, immagine di sfondo ricalcolata scura, e ogni colore abbassato alla stessa frazione, così i rapporti fra i colori restano quelli del giorno e il quadro resta leggibile. Serve in navigazione notturna, dove un pannello chiaro a tutto schermo brucia l'adattamento al buio e per qualche minuto non si vede più fuori.
Le scritte non vengono abbassate ma sostituite con un ambra: una serigrafia nera abbassata resterebbe nera, cioè invisibile sul fondo scuro. L'ambra è anche il colore che disturba meno la visione notturna. Vale per etichette, legende dei selettori, marchi e scale dei gauge.
Si torna al giorno con lo stesso pulsante, che nel frattempo dice "Giorno". La scelta non viene salvata nell'XML: è una condizione del momento, non una proprietà della plancia.
Tipi di elemento
| Tipo | Funzione Modbus | Comportamento |
|---|---|---|
| Pulsante | WriteSingleCoil (05) |
Chiude alla pressione, riapre al rilascio (es. horn) |
| Interruttore | WriteSingleCoil (05) + ReadCoils (01) |
Commuta alla pressione del mouse e resta premuto |
| Selettore | WriteSingleCoil (05) + ReadCoils (01) |
Manopola rotativa a 2 o 3 posizioni, anche a ritorno di molla |
| Spia | ReadDiscreteInputs (02) |
Sola lettura, LED di colore configurabile |
| Gauge | ReadHoldingRegisters (03) |
Colonna con scala, soglie e valore |
| Display | ReadHoldingRegisters (03) |
Numero a sette segmenti rossi su fondo nero |
| Immagine | nessuna | Grafica decorativa: loghi, sagome, cornici |
| Testo | nessuna | Scritta serigrafata sul pannello |
Il campo channel è l'indirizzo Modbus della bobina o del registro, slave
l'indirizzo del nodo sul bus. Immagine e Testo non hanno né slave né canale.
Gli interruttori e i selettori rileggono le bobine ad ogni ciclo: se un relè cambia stato per altra via, o una scrittura non va a segno, il comando a video si riallinea. I pulsanti momentanei non vengono riallineati, perché il loro stato dipende dal mouse.
All'ingresso in plancia la plancia si allinea al campo
Entrando in modalità plancia (all'avvio, tornando dalla configurazione o cambiando plancia) la prima lettura serve a mettere tutto nella posizione in cui è il campo, non solo a controllare:
- interruttori e selettori dalle bobine (funzione 01);
- pulsanti dalle bobine, ma solo in questa prima lettura: se un canale momentaneo è rimasto eccitato va mostrato chiuso, mentre dopo lo stato del pulsante lo decide il mouse e rileggerlo lo farebbe lampeggiare;
- spie dagli ingressi digitali (funzione 02), come sempre.
In questa prima lettura le bobine si chiedono una per una, non a blocco. Un blocco che arriva oltre l'ultimo canale del modulo fallisce tutto, e con lui fallirebbe l'allineamento anche dei comandi su canali che esistono: chiedendo un canale per volta fallisce solo la richiesta del canale che non c'è. Costa un giro più lento, una volta sola. Finito l'allineamento si torna alle richieste raggruppate, che sono quelle che tengono leggero il polling.
Chiudendo il programma non viene scritto niente sul bus: i relè restano come sono, ed è la plancia che alla ripartenza si adatta a loro. Quando l'allineamento è fatto la barra di stato dice quanti canali sono stati letti, quanti comandi risultano chiusi e quanti canali non hanno risposto; se non risponde nessuna bobina si riprova al ciclo dopo, invece di dare per aperto quello che non si sa. Una spia già in allarme all'avvio fa suonare il suo cicalino.
Più comandi sulla stessa bobina
Lo stesso slave e channel si possono mettere su più elementi: lo stesso relè
comandato da due punti della plancia, o un pulsante e un interruttore sullo
stesso circuito. Premendone uno gli altri si muovono subito, senza aspettare
la rilettura: mezzo secondo di disaccordo fra due comandi che sono la stessa cosa
si nota. Vale in tutte le combinazioni, compresi i selettori (per quelli a 3
posizioni conta la bobina del lato).
Le spie no: leggono gli ingressi digitali, che sono un altro spazio di indirizzi, quindi una spia sullo stesso numero di canale di una bobina non è la stessa cosa e non viene toccata.
Una risposta più vecchia del comando appena dato viene scartata. Le letture partono a giri regolari e la risposta può arrivare dopo un click: crederle farebbe tornare indietro il comando per un giro, e si vedrebbe il comando spegnersi, riaccendersi e rispegnersi. Ogni comando segna l'istante in cui ha scritto la sua bobina, e le risposte partite prima di quel momento non vengono applicate a quella bobina.
Attenzione: questo riallineamento è anche il motivo per cui un interruttore può sembrare un pulsante. Se la rilettura della bobina risponde 0 — relè assente, indirizzo sbagliato, scrittura non andata a segno — l'interruttore torna su da solo entro un ciclo di polling, e a occhio sembra che non resti premuto. Il tipo dell'elemento non c'entra: si guarda la barra di stato.
Cambiare tipo dopo il disegno
Pulsante, interruttore e spia si scambiano fra loro in qualsiasi momento, dalla casella Tipo in cima al pannello proprietà, come si fa con la forma o il canale. Condividono tutti i campi — canale, colori, forma, immagini, etichetta — quindi il passaggio non perde niente. Cambia solo il funzionamento: il pulsante chiude il contatto finché lo tieni premuto, l'interruttore commuta e resta, la spia non si preme e si accende quando l'ingresso è chiuso.
Serve soprattutto per le lenti colorate che sulla foto di un quadro sembrano pulsanti ma sono allarmi, come FIRE ALARM e OIL STEERING di ZEBRA.
Attenzione al canale passando da comando a spia o viceversa: il numero resta lo stesso ma cambia significato. Per pulsanti e interruttori è una bobina da comandare, per la spia un ingresso digitale da leggere (funzione 02), che di solito sta su un altro modulo. La barra di stato lo ricorda al momento del cambio.
Cambiando tipo l'elemento riparte da spento, perché un pulsante non viene più riletto dal campo e resterebbe illuminato per sempre. Se l'etichetta era ancora quella predefinita segue il nuovo tipo, altrimenti resta la tua.
Selettore rotativo
La leva ruota: passando da una posizione all'altra si vede girare, sempre passando per l'alto, in 130 millisecondi con partenza e arrivo morbidi. È solo quello che si vede: il comando sul bus parte subito, all'inizio del movimento. In configurazione la leva sta ferma dove dice la definizione.
Si "gira" premendo dal lato verso cui lo si vuole portare: pressione a sinistra
della manopola per scendere di una posizione, a destra per salire. La legenda
sopra la manopola è testo libero (OFF ◄ 0 ► ON, STOP ◄ 0 ► START, …).
Il cablaggio dipende dal numero di posizioni:
- 2 posizioni: una bobina, quella di
channel. Chiusa = posizione destra. - 3 posizioni: due bobine,
channele (salvo indicazione)channel+1. La prima chiusa = posizione sinistra, la seconda chiusa = destra, entrambe aperte = centro (0).
Quindi un selettore a 3 posizioni occupa due canali: nel numerare i canali va lasciato il buco.
Per configurarlo: tipo Selettore, Posizioni = 3, e in Canale la bobina
del lato sinistro. La bobina di destra si imposta nel riquadro "Selettore", in
Canale lato destro: lasciandolo vuoto è il canale successivo (l'etichetta
ricorda quale sarebbe), e si compila solo quando sul modulo le due bobine non
sono contigue. Nell'XML è l'attributo channel2, scritto solo se indicato.
Il suggerimento a comparsa dell'elemento mostra entrambe le bobine.
Ritorno a molla
Con Ritorno a molla spuntato (nell'XML momentary="true") il selettore non
resta dove lo porti: tiene la posizione finché lo tieni premuto e torna al
centro appena lasci il mouse, aprendo entrambe le bobine. È il comando di
avviamento dei quadri veri, STOP ◄ 0 ► START: si tiene su START finché il
motore parte, e si molla.
- Si preme direttamente dal lato voluto, senza passare per lo zero.
- Al rilascio torna al centro sempre, anche se il mouse è finito fuori dall'elemento e anche se la scrittura di andata era fallita: un comando di avviamento non deve mai restare eccitato.
- Finché è premuto il polling non lo sposta, altrimenti una lettura arrivata in quell'istante lo farebbe scattare al centro sotto il dito.
- Vale anche a 2 posizioni: premuto = chiusa, lasciato = aperta.
In antago.xml e in plancia-mfd.xml è così il selettore GENERATOR.
Le due bobine non vengono mai chiuse insieme: a ogni cambio di posizione si apre prima quella del lato opposto e solo dopo si chiude l'altra. Se la seconda scrittura fallisce il selettore resta al centro, con tutte e due aperte. Questa però è una protezione del programma: se i due lati comandano qualcosa che non deve mai partire insieme (due sensi di marcia, due alimentazioni), serve comunque l'interblocco elettrico fra i due relè.
Gauge a quadrante
Con style="dial" il gauge non è una colonna ma uno strumento a lancetta, come
quelli dei display di plancia: scala su 270 gradi con tacche e numeri, lancetta,
e sotto il perno la lettura in cifre con le unità (decimals ne fissa i
decimali). Se l'elemento è più alto che largo il titolo va sotto al quadrante,
altrimenti dentro.
La fascia della scala è grigia. Con warnBelow / warnAbove impostati diventa
verde nell'intervallo buono e rossa fuori: senza soglie resta grigia, perché un
quadrante tutto verde direbbe "tutto a posto" senza saperlo. Senza dato valido
la lancetta non c'è e la lettura mostra ---.
Stile e decimali del quadrante per ora si impostano solo nell'XML; il pannello proprietà non li mostra ma il salvataggio li conserva.
Display
Mostra il registro scalato in unità reali, allineato a destra sul numero di
cifre richiesto, con zeri davanti come i display veri. digits è il numero di
cifre, decimals quante dopo la virgola. Senza dato valido i segmenti restano
tutti spenti.
Spia
Il colore da accesa si imposta con l'attributo color (#RRGGBB): rosso per
gli allarmi, verde per i consensi, giallo e arancio per i livelli. Se
l'etichetta è vuota il LED — o l'immagine PNG che lo sostituisce — occupa tutto
l'elemento, così si possono appoggiare spie piccole sopra una grafica. Vale per
qualunque elemento con l'etichetta fuori dal disegno: senza etichetta non viene
riservata nessuna fascia.
Allarme sonoro
Ogni spia può far suonare qualcosa quando si accende. Nel pannello proprietà, riquadro Allarme sonoro:
- Suona quando si accende: la casella che accende o spegne l'allarme.
- File: si sceglie fra i suoni presenti nella cartella
suoni\accanto al file XML della plancia (MP3 e WAV). Come per le immagini, i suoni viaggiano con la plancia quando si copia la cartella. - Aggiorna: rilegge la cartella. Serve quando si aggiunge un file mentre il programma è già aperto, senza doverlo riavviare.
Nell'XML sono gli attributi alarm="true" e sound="cicalino.mp3" sulla spia.
Il nome del file resta salvato anche con l'allarme spento, così si può
riaccendere senza riscegliere il suono.
Come suona:
- Parte sul fronte, quando la spia passa da spenta ad accesa, e poi va in ciclo: finito il file ricomincia, e continua finché l'allarme c'è. Un cicalino che suona una volta sola lo si perde se in quel momento si sta guardando altrove. Si ferma quando l'allarme rientra, quando lo si zittisce premendo la spia, o lasciando la plancia.
- Se l'allarme è già attivo all'avvio suona appena arriva la prima lettura: una plancia che parte con una sentina piena deve dirlo.
- Non blocca niente: il suono va per conto suo, la plancia resta comandabile.
- Due allarmi diversi si sovrappongono; lo stesso allarme che si ripete riparte da capo.
- Quando l'allarme rientra il suono si ferma subito, senza aspettare la fine del file: serve per i suoni lunghi, una sirena che continua a suonare su un allarme già passato è peggio del silenzio. Se lo stesso file è assegnato a più spie, tace solo quando si è spenta l'ultima ancora accesa.
- Se il file manca o non si può suonare, la barra di stato lo dice: un cicalino muto senza avviso è peggio di nessun cicalino.
- Uscendo dalla plancia (torna a configurare, chiusura) i suoni si fermano.
Zittire un allarme
Si preme la spia che sta suonando: è il gesto che viene naturale, si preme quello che dà fastidio. Ogni pressione allunga il silenzio:
| Pressioni | Silenzio |
|---|---|
| 1 | un minuto |
| 2 | dieci minuti |
| 3 | un'ora |
| 4 | allarme di nuovo attivo |
Le pressioni contano finché il silenzio dura: dopo che è scaduto si ricomincia da un minuto. Il suono in corso si ferma subito alla prima pressione.
Il silenzio non spegne la spia: il LED resta acceso, con una sbarra sopra, perché guardando il quadro si deve capire che quell'allarme c'è ancora e sta suonando a vuoto. Premere una spia spenta, o una senza allarme, non fa niente.
Quando il silenzio scade, se la condizione è ancora presente l'allarme torna a suonare: è il senso di zittire "per un minuto" invece che per sempre.
In basso a destra, nella barra di stato, compare il tasto "N allarmi zittiti (tempo) — riattiva", che dice quanti sono e quanto manca al primo che torna a suonare. Premendolo si riattivano tutti subito, e quelli ancora presenti suonano di nuovo. Il tasto si vede solo finché c'è almeno un allarme zittito.
Se l'allarme rientra da solo, il silenzio si azzera con lui: la volta dopo si riparte da un minuto. Tornando a configurare, o cambiando plancia, i silenzi si azzerano tutti.
In suoni\ c'è cicalino.wav, due bip generati per provare subito; va
sostituito con il suono vero.
La spia accetta anche la forma (shape) dei pulsanti, per somigliare alle
lenti di allarme dei quadri:
round— ghiera metallica e lente tonda. Spenta la lente resta del suo colore ma scura (colorOff, ocolorscurito se manca), accesa prendecolorpieno con un riflesso. La ghiera non cambia: è una spia, non un comando premuto.screen— tasto a video che si riempie dicolorquando l'ingresso è chiuso.- le altre forme — il LED tondo di sempre.
In ogni forma cliccare una spia non fa nulla e non manda niente sul bus.
Aspetto di pulsanti, interruttori e spie
La lente di un pulsante o di un interruttore non cambia mai colore. Lo stato si legge solo dal bordo, come su un quadro vero, dove il vetro è sempre dello stesso colore e quello che cambia è la luce dietro.
- Forma tonda: la ghiera attorno alla lente è grigia a riposo e diventa azzurra luminosa quando il comando è acceso, o mentre un pulsante è tenuto premuto — più chiara contro la lente e più carica all'orlo, come se la luce venisse da dentro.
- Forma squadrata o a pillola: non c'è ghiera, quindi è il bordo stesso che si ingrossa e prende lo stesso azzurro.
Il colore della lente è colorOff. Su pulsanti e interruttori color non
tocca più il vetro: resta usato dalle spie, dove il cambio di colore è tutto
quello che c'è da vedere. Anche l'etichetta scritta dentro al comando resta
uguale: prima diventava bianca e in grassetto da acceso, ed era un secondo modo
di dire la stessa cosa che ora dice il bordo.
Tre attributi permettono di far somigliare i comandi a quelli del quadro vero, e si impostano anche dal riquadro "Aspetto" del pannello proprietà:
shape—auto(pillola per i pulsanti, squadrato per gli interruttori),round,rect,pill,screen. I quadri di bordo hanno quasi sempre pulsanti tondi: conroundl'elemento viene disegnato con ghiera metallica e lente, come un pulsante illuminato da incasso.screen("a video") è il tasto di un display multifunzione ed è l'eccezione alla regola della lente: spento è un riquadro scuro con il filo chiaro (colorOffper tingerlo), acceso si riempie del colorecolor. La scritta sopra passa da chiara a nera quando il fondo diventa chiaro.captionPos—center(etichetta scritta sul comando),below,above. Sui quadri veri l'etichetta è serigrafata sotto al pulsante: conbelowil disegno si restringe per farle posto e il testo resta nero sulla lamiera invece di stare sopra la lente. Le etichette lunghe vanno a capo e la fascia si allarga da sola.colorecolorOff— colore della lente accesa e a riposo. Serve perché un pulsante STOP è rosso anche da spento e si limita a illuminarsi: senzacolorOffla lente a riposo è grigio-azzurra neutra.
Testo e marchi
L'elemento Testo non serve solo alle scritte: con una cornice diventa un marchio serigrafato, disegnato con il font e non con un'immagine, quindi nitido a qualsiasi zoom invece di sgranare come farebbe un PNG ingrandito.
fontName— nome del font, per esempioTimes New RomanoArial Black. Vuoto = quello del pannello. Funziona su qualsiasi elemento, non solo sul Testo.spacing— pixel in più fra una lettera e l'altra. I marchi hanno quasi sempre le lettere larghe e senza questo non somigliano.frame—none,oval,rect,round(rettangolo stondato, cioè a pastiglia). Disegnata con GDI+ in antialiasing, altrimenti un ovale grande verrebbe scalettato.frameWidth— spessore del tratto della cornice.color— colore di inchiostro e cornice.
Un marchio su più righe si compone sovrapponendo più elementi: uno con la sola cornice (etichetta vuota), uno con il nome in grande, uno con il sottotitolo piccolo. È così che sono fatti i loghi ZEBRA e ANTAGO negli esempi.
Per andare a capo dentro un'etichetta si usa , per esempio
caption="PORT ENGINE".
Immagini
La libreria immagini è nel pannello di sinistra: "Aggiungi..." accetta PNG, JPG e BMP (selezione multipla), "Rimuovi" toglie l'immagine e la sgancia dagli elementi che la usavano, chiedendo conferma.
Non è una TImageList: quella imporrebbe a tutte le immagini la stessa
dimensione, mentre qui un LED da 32 px e un logo da 600 px devono convivere.
Nell'XML si salvano nome e percorso, non i pixel. I file restano sul disco e si possono sostituire senza toccare la configurazione. I percorsi sono relativi alla cartella del file XML quando possibile, così l'intera plancia si trasporta copiando una cartella; "Salva con nome" in un'altra cartella ricalcola i percorsi da solo.
Dove si usano:
- Pulsante, interruttore, spia: due immagini, a riposo e attiva. Se il campo "immagine a riposo" è vuoto si torna al disegno vettoriale predefinito. Se è valorizzata solo quella a riposo, l'elemento non cambia aspetto quando si attiva.
- Immagine: una sola, decorativa.
- Sfondo del pannello: si sceglie in "Generale → Immagine di sfondo", ed è stirata su tutto il pannello.
Le PNG con trasparenza funzionano: gli elementi non riempiono il proprio sfondo, quindi un logo con alpha si fonde con lo sfondo della plancia.
L'etichetta continua a essere scritta sopra l'immagine, in bianco con contorno nero perché resti leggibile su fondo chiaro e scuro; sulle spie va in basso per non coprire il LED. Se l'immagine contiene già la scritta, basta svuotare il campo Etichetta.
Se un file manca o non si apre, nella libreria il nome compare seguito da [!]
e l'elemento mostra un riquadro tratteggiato in configurazione.
Il file XML
<?xml version="1.0" encoding="UTF-8"?>
<plancia version="1">
<connection port="COM1" baud="9600" timeoutMs="500" pollMs="500"/>
<panel title="Plancia ZEBRA" width="980" height="560" background="sfondo"/>
<images>
<image name="sfondo" file="immagini\sfondo.png"/>
<image name="btn-off" file="immagini\btn-off.png"/>
<image name="btn-on" file="immagini\btn-on.png"/>
</images>
<elements>
<element kind="button" caption="HORN" slave="1" channel="5"
left="40" top="60" width="180" height="70"
imageOff="btn-off" imageOn="btn-on"/>
<element kind="image" caption="" image="logo-zebra"
left="620" top="440" width="320" height="90"/>
<element kind="gauge" caption="Serbatoio" slave="5" channel="1"
left="640" top="200" width="130" height="200"
rawMin="0" rawMax="4095" engMin="0" engMax="100"
units="%" warnBelow="15" warnAbove="1E30"/>
</elements>
</plancia>
kind vale button, switch, rotary, lamp, gauge, display, image
o label.
fontSize: altezza del testo in pixel logici; assente = font del pannello.imageOff/imageOn: nomi presi da<images>; solo per pulsanti, interruttori e spie.image: l'immagine dell'elemento decorativo.backgroundsu<panel>: immagine di sfondo.inksu<panel>: colore della serigrafia,#RRGGBB, nero se assente. Vale per etichette sotto/sopra i comandi, legende e titoli di selettori, display e quadranti, e per ilabelsenzacolor. Le plance a fondo scuro lo mettono chiaro. Si imposta solo nell'XML.style(barodial) edecimals: aspetto delgauge, vedi sopra.color/colorOff: colore acceso e a riposo di spie, pulsanti e interruttori,#RRGGBB. Sulabelè il colore di inchiostro e cornice.shapeecaptionPos: forma del comando e posizione dell'etichetta.fontNameespacing: font e spaziatura fra le lettere.frameeframeWidth: cornice attorno a unlabel.alarmesound: solo perlamp, allarme sonoro all'accensione; il file sta nella cartellasuoni\accanto all'XML.positions(2 o 3),legend,channel2emomentary: solo perrotary.channel2è la bobina del lato destro di un selettore a 3 posizioni; assente =channel+1.momentary="true"è il ritorno a molla.digitsedecimals: solo perdisplay.raw*,eng*eunitsvalgono pergaugeedisplay:rawMin/rawMaxsono il fondo scala del modulo (4095 = ADC a 12 bit),engMin/engMaxi valori reali corrispondenti.warnBelow/warnAbove: solo pergauge, sono le soglie oltre le quali la colonna diventa rossa (-1E30e1E30significano "soglia non impostata").
I numeri decimali si scrivono con il punto. Il file si può modificare a mano:
un attributo mancante prende il valore di default. Per i caratteri speciali
nelle legende si usano le entità XML, per esempio ◀ e ▶ per le
frecce ◄ ►.
File di esempio
-
esempio-plancia.xml— solo elementi vettoriali, nessuna immagine. -
esempio-immagini.xml— usa la cartellaimmagini\: sfondo, logo con trasparenza, pulsante e LED con grafica. Le immagini sono segnaposto generate per la prova, da sostituire con quelle vere. -
antago.xml— riproduzione del quadro elettrico ANTAGO, ricavata dalla foto del quadro reale. Il pannello è 1270×950 come la foto, così ogni elemento sta dove sta sul quadro vero. -
zebra.xml— riproduzione della pulsantiera ZEBRA: 7 colonne × 6 righe di pulsanti tondi illuminati, i due selettori delle ventole, i comandi motore con gli ovali PORT/STBD ENGINE e il selettore PARALLEL a tre posizioni. La foto è in prospettiva, quindi la griglia è stata ridisegnata dritta (passo 120 in orizzontale, 145 in verticale); etichette, forme e colori delle lenti vengono dalla foto. -
plancia-mfd.xml— tutti i comandi, le spie e le misure di ZEBRA e ANTAGO su una sola plancia, nello stile della fotoimmagini\Esempio plancia.jpg: cornice scura con tasti a video ai lati, schermo nero con quattro quadranti, i due display dei caricabatterie, il sinottico della barca con le spie e i tasti illuminati di motori e servizi; sotto, due file di selettori. Pannello 1900×1080. Gli indirizzi di ZEBRA sono quelli dizebra.xml; le bobine di ANTAGO sono spostate da slave 1 a slave 4, perché sullo slave 1 si sovrapponevano a quelle di ZEBRA, e i due comandi di prova "Luce" e "Horn" diantago.xml(che stavano sul canale 0, lo stesso del selettore VOLTMETER) sono sui canali 26 e 27 dello slave 4.
In tutti slave e canali sono inventati e vanno rimappati sui moduli reali prima di collegare il bus.
Strumenti
strumenti\ contiene gli script PowerShell usati per preparare la grafica dei
due quadri:
| Script | Cosa fa |
|---|---|
ruota.ps1 |
Raddrizza una foto scattata in verticale |
ritaglia-grafica.ps1 |
Ritaglia un pezzo di serigrafia dalla foto e rende trasparente il fondo chiaro, lasciando solo il tratto |
genera-sfondo.ps1 |
Disegna la lamiera del pannello con cornice e viti, di qualsiasi misura |
genera-mfd.ps1 |
Disegna cornice e schermo di plancia-mfd.xml e la sagoma della barca ANTAGO in chiaro per il fondo nero |
Il ritaglio dalla foto conviene solo per i disegni che non si possono ricostruire, come la sagoma della barca del quadro ANTAGO. Le scritte no: i marchi ZEBRA e ANTAGO e gli ovali PORT/STBD ENGINE sono elementi Testo con font e cornice, non immagini, così restano nitidi a ogni ingrandimento.
Diagnostica del bus
Due programmi a riga di comando servono quando un modulo non si legge. Vanno
lanciati con PlanciaConsole chiusa, perché la porta si apre una volta sola.
Si ricompilano con i build-*.bat accanto ai sorgenti.
| Programma | Cosa fa |
|---|---|
scanbus.exe [porta] [baud] [ultimoIndirizzo] |
Interroga gli indirizzi uno per uno e dice chi risponde, con quali funzioni e che dati |
dumpframe.exe [porta] [baud] [slave] [funzione] [start] [quantità] |
Manda una sola richiesta e stampa i byte grezzi della risposta con la verifica della CRC |
monitorio.exe [porta] [baud] [slave] [canali] [cicli] |
Mostra gli ingressi digitali in tempo reale, una riga ad ogni cambiamento |
ringtest.exe [file.bmp] |
Disegna i comandi tondi spenti e accesi a tre misure e salva l'immagine: serve a giudicare una modifica ai colori guardandola |
scanbus serve a trovare l'indirizzo di un modulo appena montato. dumpframe
serve quando scanbus dà risultati incoerenti: mostrando il frame byte per byte
distingue un modulo che non risponde da due moduli che rispondono insieme.
Due nodi con lo stesso indirizzo è il guasto più frequente quando si aggiunge un modulo: i moduli escono quasi tutti con indirizzo 1, e sul bus le due risposte si sovrappongono. Il sintomo è una risposta di lunghezza variabile, spesso con byte a zero in testa, e la CRC che non torna.
Il bus in un thread a parte
Il thread principale non parla mai con la porta seriale. Tutto il Modbus vive
in un thread suo (uModbusWorker.pas), che apre la COM, fa le letture e le
scritture, e lascia i risultati in una cassetta condivisa. La finestra li
ritira con il suo timer. Così un timeout — mezzo secondo per richiesta — costa
tempo al thread del bus e non alla plancia, che resta trascinabile, ridisegnabile
e cliccabile anche con tutti i moduli staccati.
Un thread solo, non uno per le letture e uno per le scritture. Su RS485 il filo è uno: due richieste insieme si sovrappongono e le risposte arrivano mescolate. Chi comanda deve comunque aspettare la fine della richiesta in corso, quindi un secondo thread aggiungerebbe solo un lucchetto attorno alla porta. La reattività dei comandi si ottiene con la precedenza: la coda delle scritture viene svuotata prima di ogni lettura, non solo a ogni giro, quindi un pulsante premuto parte al massimo dopo la richiesta in corso.
Come si comporta:
- Cliccare un comando torna subito. La scrittura va in coda; l'elemento si accende fidandosi. Se la scrittura non va a segno lo dice la barra di stato, e la rilettura delle bobine rimette l'elemento a posto entro un ciclo.
- L'ordine è garantito: le due bobine di un selettore a 3 posizioni, o la pressione e il rilascio di un pulsante, partono nella sequenza in cui sono state messe in coda.
- La porta si riapre da sola. Se non c'è, o se cade (adattatore USB staccato), il thread riprova ogni due secondi: non serve più riavviare il programma.
- Chiudendo, l'attesa del thread dura al massimo quanto la richiesta in corso.
Aggiungere slave e canali
Niente nel programma è legato ai moduli montati adesso: una plancia si può disegnare prima, e i moduli si aggiungono quando arrivano.
- Slave: qualsiasi indirizzo da 1 a 247, quanti se ne vuole sullo stesso bus. Ogni slave nuovo aggiunge solo le sue richieste al giro di polling.
- Canali: qualsiasi numero da 0 a 65535, senza doverli tenere contigui. Canali molto distanti sullo stesso slave allargano però l'intervallo letto (vedi Polling), quindi conviene raggrupparli.
- Limiti di una singola richiesta, imposti dal protocollo: 2000 bit per bobine e ingressi, 125 registri. Oltre, la richiesta viene saltata e la barra di stato lo dice: si spezza l'intervallo o si sposta l'elemento su un altro slave.
- Nuove porte: la porta è una per plancia (
<connection port=...>). Due bus separati si fanno con due plance, e si passa dall'una all'altra con la casella in basso a destra.
Una richiesta che non riesce si divide da sola. Se la lettura di un blocco di bobine fallisce, il programma la spezza a metà e riprova con le due metà, e così via: un modulo da 32 canali interrogato fino al 38 finisce per farsi leggere i suoi 32 in poche richieste, invece di non dare più niente. Ogni divisione compare nella barra di stato. Le divisioni imparate valgono finché non si cambia plancia o non si riapre la porta.
Le richieste che non rispondono non danno fastidio. Dopo tre errori di
fila una richiesta muta viene messa in pausa e riprovata ogni cinque secondi,
invece di costarne il timeout a ogni giro: così una plancia disegnata in
anticipo resta scorrevole e i moduli che rispondono vengono letti alla velocità
giusta. Appena il modulo viene collegato riparte da solo, entro quei cinque
secondi. La barra di stato distingue i due casi: Timeout: nessuna risposta è
una richiesta che si sta ancora provando, non risponde, riprovo fra 4 s è una
messa in pausa. La pausa si azzera da sola quando si cambia plancia, quando si
modificano i canali in configurazione e quando la porta viene riaperta.
La pausa vale per singola richiesta, non per modulo: sullo stesso nodo le bobine possono rispondere benissimo mentre gli ingressi, che quel modulo non ha, danno errore. Mettere in pausa tutto il nodo per colpa degli ingressi lascerebbe la plancia cieca proprio su quello che si legge.
Polling
Ad ogni ciclo (pollMs) gli elementi vengono raggruppati per slave e tipo, e
per ogni gruppo parte una sola richiesta che copre i canali da quello più
basso a quello più alto. Aggiungere elementi contigui non aumenta il traffico
sul bus; canali molto distanti sullo stesso slave sì, perché allargano
l'intervallo letto.
Ogni richiesta va per conto suo: se un modulo non risponde, gli altri gruppi vengono letti comunque. Solo le spie e i gauge di quella richiesta passano a "dato non disponibile"; il resto della plancia continua a leggere. Interruttori e selettori invece non si azzerano, perché la loro posizione è un comando dato, non una misura.
L'errore finisce nella barra di stato dicendo cosa non si è potuto leggere: slave, funzione e intervallo di canali, per esempio
Lettura fallita su 4 richieste, la prima: slave 3, ingressi 0-14 (FC02): timeout
Così si capisce subito se manca un modulo, se l'indirizzo è sbagliato o se si sta leggendo oltre i canali che il modulo ha (tipico: un modulo da 8 bobine interrogato per 37, perché un elemento ha un canale alto). Il polling continua e si riallinea da solo appena il bus risponde.