Semplice interfaccia elettronica di controllo con la porta parallela pilotata da vb.net

controllo_led_da_porta_parallelaLa porta parallela, così come ormai la seriale, va sempre più scomparendo (purtroppo!) soprattutto dai portatili. Veniva (viene) utilizzata per lo più per il collegamento delle stampanti (ma anche, tanto tempo fa, per scanner, drive iomega zip, chiavette per la protezione del software ecc). Per la sua semplicità di utilizzo, però, viene ancora oggi preferita dagli hobbysti per l’interfacciamento con numerosi dispositivi, primi tra tutti le CNC o  i programmatori di microcontrollori/smartcard, ma anche per tante altre applicazioni.

La porta parallela è facile da utilizzare per il comando di dispositivi, proprio perchè consente l’invio contemporaneo di un byte su 8 distinte linee (trasmissione parallela – a differenza della trasmissione seriale che utilizza un’unica linea e quindi invia gli 8 bit uno dietro l’altro sulla stessa linea) : 8 linee di I/O, impostabili con un’unico invio di dati, che possono comandare altrettanti attuatori. In realtà, sulla porta parallela, di linee di I/O ce ne sono qualcuna in più, il che la rende appunto ideale per il controllo di relè, triac, mosfet ecc (per l’attuazione di motori, lampade ed altro) senza la necessità di dover “impazzire” con il codificare/decodificare una comunicazione seriale su di un’unica linea e quindi senza utilizzare microcontrollori e software “complicato”. In molti la usano per comandare display LCD (in maniera diretta) o motori passo/passo (tramite interfacce a transistor), soprattutto nelle CNC.

Per seguire meglio questa lezione, vi consiglio innanzitutto di scaricare dapprima il documento “Piedinatura e note di utilizzo della porta parallela” che ho appositamente preparato per voi nella sezione risorse: si tratta di un’unica pagina in formato PDF che può risultare molto utile tenerla sempre a portata di mano nel nostro piccolo laboratorio di elettronica.

La porta parallela

La porta parallela si presenta sul pc come un connettore di tipo Dsub a 25 poli:

pinout_porta_parallela

Le linee su cui normalmente vengono inviati i dati alla stampante (o ad altri dispositivi), sono quelle colorate in viola nel disegno (pin da 2 a 9). Per tale motivo vi sono anche 8 pin di massa: generalmente ogni linea dati va intrecciata con una linea di massa in maniera tale da avere una migliore schermatura per la protezione dai disturbi.

Come vedete ho colorato i pin in maniera differente: questo perchè ogni gruppo di linee  (identificato da un colore) appartiene ad un differente registro. Mi spiego meglio: la porta parallela, sul pc, viene controllata via hardware da 3 differenti registri chiamati Data, Status e Control.

Per controllare lo stato delle linee Data (indicate come Dn, e colorate in viola sullo schema), dovremo impostare opportunamente il registro Data ecc. Le linee Dati (data), sui nuovi pc sono bidirezionali: normalmente sono utilizzate come linee di output, ma settando ad 1 il bit 5 del registro Control, possono essere utilizzate come porte di ingresso.

Gli indirizzi esadecimali dei 3 registri delle porte parallele sono riportati nel documento che citavo prima nella sezione risorse: per la LPT1 (acronimo di Line Printer Terminal 1), che è la porta parallela presente di default sui pc (che la hanno), gli indirizzi sono:

0x378 per il registro Data (indicato anche come indirizzo Base)
0x379 per il registro Status (Base + 1)
0x37A per il registro Control (Base + 2)

L’indirizzo base, che è quello del registro Data, può anche essere dedotto dal Pannello di Controllo, Sotto Windows XP  ci si arriva da  Start ->  Impostazioni -> Pannello di Controllo -> Sistema -> Hardware -> Gestione Periferiche -> Porte (Com e LPT) :

sistema_porte_com_e_lpt

Doppio click su “Porta stampante …” -> Scheda Risorse

sistema_impostazione_lpt1

Il primo indirizzo I/O (0378 in questo esempio) è l’indirizzo del registro Data espresso in esadecimale.

I tre registri che comandano la parallela, sono registri ad 8 bit: per la linea dati, tutti e 8 bit li ritroviamo anche sul connettore (D0-D7).

Per la linea Status vediamo che mancano sul connettore i bit S0, S1 e S2: S0 e S1 non sono utilizzati, S2 è un IRQ negato: se su tale bit leggiamo uno stato logico 0, vuol dire che si è verificato un interrupt.

Per la linea Control vediamo invece che mancano sul connettore i bit da C4 a C7: C4 abilita l’interrupt, C5 come detto prima se impostato a 1 rende le porte D come ingressi, C6 e C7 non sono utilizzati.

Ci sono inoltre da fare ulteriori considerazioni: alcuni bit hanno uno stato invertito: ovvero sul corrispondente pin della porta parallela leggeremo 5volt (livello logico alto) quando il corrispondente bit è posto a Zero, di contro leggeremo 0volt (livello logico basso) quando il corrispondente pin è posto a Uno: questi sono i bit Co (pin n°1), S7 (pin n°11), C1 (pin n°14) e C3 (pin n°17), gli altri pin/bit si comportano in maniera normale (1 => 5Volt, 0 => oVolt).

Per inviare quindi un byte sulla linea dati basterà quindi impostare il registro Data in maniera opportuna.

Esempio
Ho una serie di relè collegati alla LPT1 (tramite apposita interfaccia), e voglio attivare unicamente i relè posti sulle linee D0 e D5, disattivando tutti gli altri: mi basterà impostare il registro 0x378 sul valore:

0b00010001 (in binario), oppure 17 in decimale oppure ancora 0x11 in esadecimale

Ovvero ci sarà bisogno di una funzione del tipo: port(0x378,0x11)

Capite quindi come è semplice potersi interfacciare con la seriale e perchè viene ancora così ampiamente utilizzata in campo elettronico.

Allo stesso modo è possibile inviare o ricevere dati sugli altri 2 registri (Control e Status), tenendo sempre conto che alcuni bit si comportano in maniera inversa rispetto allo standard e che alcuni pin sono a collettore aperto per cui non possono fornire i 5V (e ci sarà quindi bisogno di una resistenza di pull-up collegata ad una sorgente di alimentazione esterna) ma soltanto la linea di massa (fate riferimento al documento “piedinatura e note di utilizzo della porta parallela“).

Utilizzo pratico della porta parallela: semplice interfaccia a Led

controllo_led_da_porta_parallela_02

In questo esempio, collegheremo 8 diodi led alla linea dati della porta parallela, e li faremo accendere via software. C’è innanzitutto da fare una premessa importantissima prima di cominciare:

La corrente in uscita dai pin della porta parallela è bassissima (circa 24mA) quindi è inadatta a comandare grossi carichi: a stento si possono pilotare dei Led tramite resistenza. La corrente inviata dagli altri pin di uscita, (a parte quelli della linea Data), è ancora più bassa: si parla di circa 7/8 mA (inutilizzabili per comandare direttamente anche un led), per cui la raccomandazioni sono:

1- Utilizzate una porta parallela aggiuntiva: sui pc fissi si può acquistare una scheda PCI che aggiunge una porta parallela in più. In questo caso se combiniamo guai, guasteremo unicamente la scheda aggiuntiva (il cui costo si aggira nei negozi intorno ai 15euro, in rete si può trovare ad un prezzo ancora più basso) e non tutta la scheda madre! Difatti se mandiamo in corto circuito un pin, o preleviamo più corrente di quella che la porta può fornire, il chip di controllo della parallela può guastarsi (ricordate sempre la legge di Murphy: se qualcosa potrà andare storto, ci andrà!), e questo è un bel guaio se utilizziamo la porta parallela integrata sul pc: dovremo sostituire la scheda madre e nel caso di un pc portatile… dovremo buttare tutto il portatile! Quindi: Attenzione! Soprattutto ai cortocircuiti!

2 – Utilizzate almeno un sistema di interfacciamento a transistor sia per non correre rischi di sovraccarico sia per tenersi isolati in qualche modo dalla porta parallela: collegare un transistor su ogni porta per stare tranquilli e alimentare i led (o i relè o altro) con una sorgente di alimentazione esterna. Potete utilizzare il seguente schema (i segnali di massa sia della porta parallela che dell’alimentazione esterna, andranno collegati insieme):

schema_con_transistorQuesta configurazione va utilizzata per ogni pin di uscita. Al posto del BC237 (o BC337) potete utilizzare tanti altri transistor NPN come indicato nel documento “Pinout ed equivalenza transistor bjt di bassa potenza” presente nell’area risorse. Il transistor NPN va in conduzione quando sulla base giunge un livello logico alto, si trova in interdizione normalmente quando il pin sulla parallela si trova a livello logico basso, per tale motivo non ho inserito la resistenza di pull-down sulla base.

Lo schema con il transistor qui esposto può essere utilizzato per pilotare anche un relè al posto del diodo led. Un buon sistema di interfacciamento di uscite digitali con relè è proposto da Mauro Laurenti nella pagina “Scheda di controllo 4 Relays” che riporta anche il pcb e le istruzioni di funzionamento.

Molto più comodo sarebbe utilizzare gli array di transistor per risparmiare spazio e cablaggi, come  un  integrato tipo ULN2003 (il quale contiene 7 transistor al suo interno).

3 – Noi abbiamo fatto così e funziona, ma non si esclude che a qualcuno possa guastarsi la porta parallela. Se combinate guai, o qualcosa si guasta utilizzando questo circuito, settorezero nelle persone del webmaster e degli autori, non possono essere ritenuti responsabili: noi vi abbiamo avvisato (leggi anche il  disclaimer).

Lo schema da me utilizzato per fare le prove è il seguente:

schema_led_su_porta_parallela

Il connettore disegnato è quello femmina visto frontalmente, oppure quello maschio visto dal lato saldature.

Come vedete ho collegato i led, tramite resistenze, unicamente alle otto porte dati e ho utilizzato un’unica linea di massa. Le resistenze utilizzate sono da 470Ω, che a 5 Volt consentono una corrente di 10,6mA, per cui come margine di sicurezza (rispetto ai 24mA) ci siamo, come led ho utilizzato i classici led rossi da 5mm (non usate quelli ultraluminosi, che richiedono più corrente per funzionare!).

Come gestire la porta parallela da VB.NET (e da altri linguaggi di programmazione)

Il Visual Basic (sia il vecchio 6.0 che il nuovo .NET) ha normalmente incluso il componente per la comunicazione seriale, per la comunicazione parallela invece no. Esistono tantissime librerie (gratuite) in giro che permettono di interfacciarsi con la porta parallela, tra le tante che ho provato ne ho “eletta” una che per me è davvero ottima e fornita con un bel corredo di funzioni, la libreria si chiama IO.DLL e può essere scaricata gratuitamente dal sito del suo sviluppatore: http://www.geekhideout.com/iodll.shtml

La cosa bella di tale libreria, a parte il fatto che sia gratuita e ben documentata, è che può accedere anche ad altre porte di I/O oltre alla parallela (fate riferimento alla pagina ufficiale per vedere a quali altre porte può accedere).

Per poterla utilizzare, non ho fatto altro che copiare la dll nella cartella “debug” (non è necessario copiarla in System32) e dichiarare ad inizio programma i prototipi di funzione così come indicato sulla pagina ufficiale della libreria:

Private Declare Sub PortOut Lib "IO.DLL" (ByVal Port As Integer, ByVal Data As Byte)
Private Declare Sub PortWordOut Lib "IO.DLL" (ByVal Port As Integer, ByVal Data As Integer)
Private Declare Sub PortDWordOut Lib "IO.DLL" (ByVal Port As Integer, ByVal Data As Long)
Private Declare Function PortIn Lib "IO.DLL" (ByVal Port As Integer) As Byte
Private Declare Function PortWordIn Lib "IO.DLL" (ByVal Port As Integer) As Integer
Private Declare Function PortDWordIn Lib "IO.DLL" (ByVal Port As Integer) As Long
Private Declare Sub SetPortBit Lib "IO.DLL" (ByVal Port As Integer, ByVal Bit As Byte)
Private Declare Sub ClrPortBit Lib "IO.DLL" (ByVal Port As Integer, ByVal Bit As Byte)
Private Declare Sub NotPortBit Lib "IO.DLL" (ByVal Port As Integer, ByVal Bit As Byte)
Private Declare Function GetPortBit Lib "IO.DLL" (ByVal Port As Integer, ByVal Bit As Byte) As Boolean
Private Declare Function RightPortShift Lib "IO.DLL" (ByVal Port As Integer, ByVal Val As Boolean) As Boolean
Private Declare Function LeftPortShift Lib "IO.DLL" (ByVal Port As Integer, ByVal Val As Boolean) As Boolean
Private Declare Function IsDriverInstalled Lib "IO.DLL"  As Boolean

L’utilizzo delle funzioni è semplicissimo, indicando con Port l’indirizzo esadecimale della porta (ricordo: 0x378 per la LPT1, che però in Visual Basic.NET andrà scritto come &H0378) e con Data il dato da inviare, le funzioni andranno utilizzate così:

PortOut : invia un byte (8 bit: valori da 0 a 255) alla porta.

Esempio
Per accendere tutti i led col circuito mostrato prima, sulla porta LPT1, scriveremo in Visual Basic:

PortOut(&H378,255)

PortWordOut : stessa cosa di WordOut ma invia un valore di 16Bit

PortDWordOut : stessa cosa di WordOut ma invia un valore di 32bit

PortIn, PortWordIn e PortDWordIn : leggono un valore (rispettivamente di 8,16 e 32 bit) dalla porta

Esempio
Vogliamo leggere il valore del registro Status della porta parallela:

Dim StatusValue As Integer
StatusValue = PortIn(&H379)

SetPortBit : setta (ovvero imposta a 1) il bit della porta specificata:

Esempio
Vogliamo accendere il led sulla porta D0, lasciando invariati gli altri bit:

SetPortBit(&H378,0)

SetPortBit : Resetta (ovvero imposta a 0) il bit della porta specificata.

NotPortBit : Inverte lo stato del bit della porta specificata.

GetPortBit : Ottiene il valore del bit della porta specificata

Esempio
Vogliamo ricavare lo stato del led sulla porta D0:

Dim D0Status As Boolean
D0Status = GetPortBit(&H378,0)

Nota: In realtà questo metodo a me non funziona, per ricavare lo stato di una singola porta utilizzo la funzione PortIn, converto il risultato ottenuto in binario e infine prelevo il bit che mi interessa.

RightPortShift : Effettua la rotazione a destra dei bit della porta specificata, restituisce il valore del bit meno significativo (il quale “esce” dalla porta), e il valore passato alla funzione diviene il bit più significativo (il bit 7)

Esempio
Abbiamo che il valore attuale della porta è 10010011

Effettuando questa operazione:

RightPortShift(&H378,1)

Il valore della porta diventerà 11001001 (i valori sono stati spostati verso destra, il bit meno significativo è stato perso, e il valore da noi passato (1) diventa il bit più significativo)

LeftPortShift : Effettua la rotazione a sinistra dei bit della porta specificata, restituisce il valore del bit più significativo, e il valore passato alla funzione diviene il bit meno significativo (il bit 0)

IsDriverInstalled : Restituisce un valore diverso da zero se la libreria io.dll è installata e funzionante

Software di esempio

Ho realizzato un piccolo software di esempio che utilizza tale libreria, per accendere/spegnere le uscite sulla porta dati:

parallel_port_control

Lo stato delle linee viene portato alto o basso cliccando con il mouse sui relativi “led” disegnati sull’interfaccia. Le etichette associate ai led (nominate come D0, D1 ecc nell’immagine), possono anche essere cambiate per dargli dei nomi più significativi (questo se ad esempio facciamo un’interfaccia a transistor/relè/triac per comandare vari utilizzatori in casa):

parallel_port_control_02

Lo stato dei led non si aggiorna in maniera “stupida” alla pressione, ma verifica lo stato effettivo della porta. Le etichette, così come la porta parallela alla quale è collegata l’interfaccia, possono essere cambiate dal menù impostazioni. Nella barra di stato sono indicati: la porta LPT in uso e lo stato della linea dati in formato binario, esadecimale e decimale.

Potrebbe verificarsi un errore se è attivo lo spooler di stampa, in questo caso basta terminare il processo “spoolsv.exe” dal task manager (CTRL + ALT + CANC).

Il software per funzionare ha bisogno almeno del .NET Framework 2.0.

Il programma attualmente supporta unicamente la porta dati e il codice sorgente è disponibile previa donazione di supporto a piacere. Nel codice sorgente sono presenti delle semplici funzioni per la conversione nelle varie basi numeriche e dei buoni esempi di spunto su come aggiornare una serie di controlli a runtime.

Ringrazio ancora Fred Bulbak (www.geekhideout.com) per la disponibilità e per aver messo a disposizione questa semplice ed efficace libreria.

Aggiornamento:

Dato che i pc si evolvono, non accetto più commenti del tipo “non funziona”. Il codice sorgente di inpout32.dll si trova qui: http://logix4u.net/parallel-port/16-inpout32dll-for-windows-982000ntxp per cui se qualcuno di voi di buona volontà è in grado di modificare il sorgente e farlo funzionare sui nuovi sistemi, allora in quel caso può lasciare un commento ma solo se è disposto a condividere le modifiche. Altra pagina con sorgenti ed un porting per sistemi a 64 bit si trova qui: http://www.highrez.co.uk/Downloads/InpOut32/default.htm.

Grazie.

Download

[download#56]

Se questo articolo ti è piaciuto, condividilo su un social:
Se l'articolo ti è piaciuto o ti è stato utile, potresti dedicare un minuto a leggere questa pagina, dove ho elencato alcune cose che potrebbero farmi contento? Grazie :)