Interfaccia I/O optoisolata - Raspberry PI

Ho sempre ritenuto che comprarsi un Raspberry solo per vantarsene in giro sia qualcosa da spocchioso radical chic: ci sono troppe cose carine da realizzarci intorno, per interfaccia terminatalasciarlo a prendere polvere su qualche scrivania, nell'attesa che arrivino gli amici cui farlo vedere... Così ho finalmente trovato qualche oretta per realizzare un'interfaccia che permetta di usufruire in tutta tranquillità degli input/output che il Raspberry mette a disposizione. Vi sono infatti la bellezza di 17 pin, di cui 8 utilizzabili come I/O digitali generici e 9 utilizzabili anche per comunicare con dispositivi via I2C, SPI e UART. Nel mio caso trovavo 8 I/O generici insufficienti, così ho deciso di utilizzare anche 4 dei 5 pin implementabili con l'SPI. Ho quindi a disposizione in totale, 6 ingressi e 6 uscite digitali. Detto ciò, per proteggere il Raspberry da corti, sovratensioni e altre zozzerie provenienti da circuiti esterni, i 6 input ed i 6 output vanno optoisolati. Lo schema è veramente semplice,schema interfaccia ed impiega 12 fotoaccoppiatori 4n25. I 6 utilizzati per gli output hanno l'anodo del led connesso al pin del Raspberry tramite una resistenza da 1000Ω (si ottiene così un assorbimento di circa 3mA, visto che la tensione di funzionamento è di 3.3V), ed il catodo a massa. I 6 a protezione degli ingressi hanno l'emettitore del fototransistor a massa ed il collettore direttamente connesso al pin del connettore GPIO: la necessaria resistenza di pull-up è infatti interna al Raspberry ed attivabile via software. Da notare i 4 jumper, inseriti in serie ai pin che permettono di utilizzare il protocollo SPI; infatti nel caso ci fosse bisogno di utilizzare tale protocollo, e non servissero questi I/O, basterebbe escludere tali linee togliendo i relativi ponticelli. La realizzazione dell'interfaccia non presenta particolari difficoltà ed il PCB risultante è di dimensioni contenute: solo qualche centimetro più lungo del Raspberry! L'unica vera attenzione PCB interfacciada prestare è in fase di incisione e saldatura del PCB: una pista interrotta non provocherebbe grossi guai, ma due piste in corto per una saldatura imprecisa (rischio probabile soprattutto in prossimità del connettore da 26 poli) potrebbero costringervi a delle esequie forzate del vostro giocattolo. L'assorbimento è di circa 20 mA (abbondantemente sotto la corrente massima erogabile dalla linea a 3.3V, di 50mA), dovuto praticamente solo ai led dei fotoaccoppiatori utilizzati come output.

Configurazione della scheda: qualche riga in python!

Per utilizzare l'interfaccia sarà necessario inserire all'inizio dei listati un blocco di codice che si occupi di inizializzare correttamente gli I/O, assegnando il giusto ruolo ad ognuno di essi. Per chi scrivesse in Phyton il modulo RPi.GPIO fornisce tutto il necessario. Una volta installato la routine di inizializazione è:

#caricamento del modulo RPi.GPIO, se possibile
try:
import RPi.GPIO as GPIO
except RuntimeError:
print("Errore nell'importare RPi.GPIO! Prova a rieseguire il con privilegi di root")

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)

#impostazione funzioni pin: Input o Output;
#19,21,24,26 sono i pin dedicabili anche a SPI#impostazione funzioni pin: Input o Output;
#19,21,24,26 sono i pin dedicabili anche a SPI
GPIO.setup(7, GPIO.OUT)     #OUT 1 = GPIO 4
GPIO.setup(11, GPIO.OUT)    #OUT 2 = GPIO 17
GPIO.setup(13, GPIO.OUT)    #OUT 3 = GPIO 21
GPIO.setup(15, GPIO.OUT)    #OUT 4 = GPIO 22
GPIO.setup(19, GPIO.OUT)    #OUT 5 = GPIO 10
GPIO.setup(21, GPIO.OUT)    #OUT 6 = GPIO 9
GPIO.setup(12, GPIO.IN)     #IN 1 = GPIO 18
GPIO.setup(16, GPIO.IN)     #IN 2 = GPIO 23
GPIO.setup(18, GPIO.IN)     #IN 3 = GPIO 24
GPIO.setup(22, GPIO.IN)     #IN 4 = GPIO 25
GPIO.setup(24, GPIO.IN)     #IN 5 = GPIO 8
GPIO.setup(26, GPIO.IN)     #IN 6 = GPIO 7

#abilitazione delle resistenze di pull-up interne sugli Input
GPIO.setup(12, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(16, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(22, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(26, GPIO.IN, pull_up_down=GPIO.PUD_UP)

Le prime righe si occupano di caricare il modulo RPi.GPIO. Nel caso il caricamento non interfaccia montata sul rackandasse a buon fine, viene restituito un messaggio che esorta a ritentare l'esecuzione con privilegi di root (con sudo per intenderci, nel 99% dei casi il mancato caricamento è dovuto a tale motivo).

Con GPIO.setmode(GPIO.BOARD) si assegnano ai comandi del modulo RPi.GPIO i numeri corrispondenti sul connettore GPIO. Questo comando è preceduto da GPIO.setwarnings(False) che forza il compilatore ad ignorare eventuali warnings (dovuto ad esempio a precedenti impostazioni delle funzioni dei pin).

Infine con gli ultimi due blocchi, prima si assegna ad ogni pin la corretta funzione (input o output) , poi si attivano le resistenze interne di pull-up sui pin di input. Quindi si può procedere con il resto del programma...

E qui i gli schemi per Eagle!

 

  • Matteo

    Ciao,
    ho visto che hai usato il 4n25 per disaccoppiare e proteggere il raspy.
    Volevo fare la stessa cosa e stavo leggendo i datasheet della Vishay, ma le mie conoscenze di elettronica sono troppo arrugginite. http://www.vishay.com/docs/83725/4n25.pdf
    Quali parametri del datasheet sono utili alla progettazione o meglio immagino di dover usare i valori TYP della sezione ELECTRICAL CHARACTERISTIC, dove immagino 'forward voltage' sia la tensione per accendere il led, ma che corrente passa poi? If i sembra troppo alta.
    Configurato quello sopra accendo e spengo il led -> mando in saturazione o meno il transistor, al quale che tensione e corrente posso applicare (Collector emitter breakdown voltage)?
    grazie

    • appena tornato dalle vacanze! 🙂 esatto, i typ (typical) di quella sezione! La corrente non deve necessariamente essere di 50mA (effettivamente alta) anche 5 o 10mA vanno benissimo. Scelta la corrente (è il parametro più vincolante, visto che se vai oltre il rasppy diventa marmellata) trovi la tensione di forward servendoti del primo grafico a pagina 3 (per una temperatura di 25°C). Ora per ottenere effettivamente quella corrente con quella tensione di forward dovrai calcolare la resistenza di limitazione: basta dividere la differenza fra la tensione di livello alto del pin (3.3V) e quella di forward, per la corrente di forward: così trovi la resistenza da inserire in serie al led.
      scusa ancora per i ritardo! 😉

      • Matteo

        Grazie della risposta invece!
        E continuo...
        Il tuo esempio nel mio commento è per usare il foto accoppiatore come uscita. Ok. Nel caso debba invece e usarlo per proteggere gli ingressi dove arrivo con 12VDC (o 24 devo ancora decidere). Dovrei inserire una R = (12-Vf)/If. Giusto?
        Poi non mi resta che collegare l'emettitore all'ingresso del gpio. Ma perché elettricamente posso farlo?

        • esatto, il calcolo della resisteza è esatto! Elettricamente puoi farlo perchè non fai altro che metterli a massa quando il livello è positivo; inoltre le resistenze le attivi via software (hai i pull up e i pull dow interni) quindi esternamente non devi aggiungere praticamente nulla

          • Matteo

            Benissimo quindi la parte di configurazione della parte LED del ns. optoisolatore.
            Adesso sto cercando poi di capire come e perché funzioni l'accoppiamento con il fototransistor e successivamente con il raspi.
            Cioè che corrente Ic si genera in base all'If.
            Alcuni articoli interessanti su come configurare la resistenza di carico (che nel ns. caso è interna di pull-up abilitabile via SW):
            http://forums.adafruit.com/viewtopic.php?f=25&p=150719

            qui un link generale sulla progettazione con gli optoisolatori che tiene conto dell'invecchiamento degli stessi:
            http://www.renesas.eu/products/opto/technology/usage/index.jsp

  • Eugenio

    Ciao,
    premetto che non so nulla di elettronica, ma qualcosa in piu' di programmazione.
    Ho trovato il tuo articolo cercando informazioni su come connettere un misuratore elettrico con uscita optoisolata al raspberry, perche' ho dei consumi anomali a casa e vorrei verificarli.

    Leggendo il tuo articolo mi pare di capire che hai fatto un'interfaccia optoisolata per proteggere il circuito del raspberry dalle sovratensioni dirette di apparati esterni.

    Io vorrei invece collegare 3 uscite gia' optoisolate di 3 contatori elettrici al gpio del raspberry senza rischi di bruciarlo e volevo chiederti se mi puoi aiutare a capire se lo posso fare direttamente o devo ugualmente interporre un'interfaccia di qualche tipo per la lettura o protezione per i segnali inviati dai contatori (ad esempio qualcosa come questo: http://shop.busware.de/product_info.php/manufacturers_id/10/products_id/82)

    I contatori che ho sono questi: contatori con uscita optoisolata S0+/S0- secondo standard DIN43864: http://www.electrex.it/download/category/69-discontinued.html?download=155%3Aistruzioni-installazione-cd1.
    Il raspberry è il rev 2 con 512 MB di ram (penso che le specifiche gpio tra la rev 1 e 2 non siano cambiate).

    Scusa se la domanda ti sembra banale, ma non so veramante nulla di elettronica e se potessi aiutarmi te ne sarei davvero grato.

    Grazie.

    • allora: l'interfaccia che hai postato dovrebbe andare bene, può accettare fino a 4 dispositivi con standard DIN43864 (quindi tutti e 3 i contatori con un'unica scheda. Inoltre su questa pagina ti danno le istruzioni dettagliate in installazione. Altrimenti dovresti realizzarti tu 3 circuiti per condizionare il segnale e mandarlo al raspberry. Diciamo che se sei poco pratico di elettronica e non hai voglia di perdere troppo tempo, ti conviene la prima soluzione

      • Eugenio

        Seguo il tuo consiglio, per le mie conoscenze elettroniche meglio optare per la soluzione 1 🙂
        Grazie mille!!!!

  • Andrea Pagliarani

    Ciao,
    ritengo il tuo post molto interessante.
    Sono esperto in programmazione ma ho poche conoscenze in ambito di elettronica. Vorrei collegare un sensore a tenda presente nel mio impianto d'allarme di casa. Il contatto d'allarme di questo sensore nelle specifiche indica 100mA - 40V. Per la precisione questa è la scheda tecnica: http://www.amcelettronica.com/it/prodotti/download/if16t-if16l/IF16L_IT_EN.pdf

    Ora, quello che vorrei fare è collegare questo contatto ad un pin input della GPIO del Raspberry. È possibile secondo te?
    Cosa mi consigli per proteggere il raspberry?

    Grazie dell'aiuto e complimenti per l'articolo.

    • Ciao, ho avuto qualche problema con il link che hai postato (non me lo apre), quindi non ho modo di verificare se il contato sia normalmente chiuso o aperto. In ogni caso si tratterebbe di alimentare un lato del contatto e leggere l'altro (collegato a massa trimete una resistenza, altrimenti salterebbe tutto alla chiusura del contatto). Per farlo è fattibilissimo; attenzione però ad affidarsi al raspberry; in diverse occasioni personalmente mi si è bloccato; se succedesse prima di un'intrusione la cosa potrebbe essere deleteria. Se invece il sensore attiva comunque un allarme e la lettura con il raspberry è solo un plus, allora il problema non si pone: si tratta solo di leggere lo stato del contatto con un semplice script in python. Se hai un link funzionante con uno schema del contatto di uscita possiamo darci un'occhiata 😉

      • Andrea Pagliarani

        Grazie intanto per la tua disponibilità.

        In realtà il sensore dovrebbe essere collegato solo al raspberry, quindi non esiste un modo per far si che non si blocchi? Di seguito ti invio un altro link, questa volta funzionante 🙂 https://www.dropbox.com/s/xo64z9jrcx9qbtb/IF16L_IT_EN.pdf?dl=0

        Altra domanda, come faccio a calcolare la resistenza che serve?

        Grazie mille!

        • per quanto riguarda la resistenza, la tensione massima ammissibile sull'ingresso del raspberry è di 3.3V (che potresti derivare da uno dei pin del GPIO); ammettendo una corrente massima di 1mA, la resistenza sarebbe sui 3300 ohm; per quanto rigurada il blocco, intendevo che non essendo di eccezionali prestazioni, il raspberry potrebbe bloccarsi (ad esempio se esegui aggiornamenti, altri programmi o cose del genere mentre lui monitora

          • Andrea Pagliarani

            Ok, non mi è chiara una cosa.
            Il sensore ha 3 output:
            1. NC: contatto di allarme (N.C.) / 100mA - 40V - 16ohm
            2. COM: terminale a negativo di riferimento
            3. AP: terminale tamper anti-apertura (N.C.) Max 40mA - 30 Vdc

            Se ho ben capito lo schema sarebbe questo? https://www.dropbox.com/s/2snlklnx1x04mh3/sch.jpg?dl=0

          • Andrea Pagliarani

            Ok, ti chiedo l'ultimo chiarimento da neofita quale sono.

            Il sensore ha 3 output:
            1. Contatto di allarme (N.C.) / 100mA - 40V - 16ohm
            2. Contatto di tamper (N.C.) / Max 40 mA - 30 Vdc
            3. Terminale a negativo di riferimento

            Se ho ben capito lo schema di collegamento con il "Contatto di allarme" sarà cosi:
            https://www.dropbox.com/s/2snlklnx1x04mh3/sch.jpg?dl=0

            E' corretto?
            Invece per il contatto tamper devo avere una resistenza diversa giusto?

            Grazie.

          • Il contatto di allarme dovrebbe essere un semplice contatto contatto che si chiude ed i cui 2 estremi dovrebbero essere uno il morsetto comune e l'altro il contatto di allarme. La tensione indicata dovrebbe essere quella massima a cui è sottoposto il contatto, non una fornita dal sensore (che tra l'altro è alimentato a 12V). Dovresti fare una controprova: misurare se ci sia tensione fra i due morsetti, sia quando l'allarme scatta, sia quando è a riposo. Non dovresti rilevare alcunchè proprio perché di semplice contatto di parla. Altrimenti le cose si complicano; fammi sapere e ne riparliamo

          • Andrea Pagliarani

            Scusami Tobia, forse non mi sono chiare le basi.
            L’interfaccia GPIO del Raspberry è un’interfaccia digitale: può inviare e ricevere soltanto segnali digitali, ovvero alternanze di 0 volt e 3.3 volt.

            Io ho sempre pensato che il contatto di allarme presente nel sensore inviasse un segnale di 0V quando non rileva nessun movimento e di 40V quando rileva un movimento. Non è così?

          • perfetto per quanto riguarda il raspi, è proprio così; il punto è proprio l'uscita del sensore: non sono sicuro che alzi 40 V perché spesso le uscite sono semplici contatti di relè (quindi non forniscono tensione ma chiudono/aprono solo. nel caso sia la prima (40V) il circuito diventa più complesso, proprio per evitare di danneggiare il raspi. Se invece di solo contatto non alimentato si tratta, la cosa è molto più semplice; per questo chiedevo la misura

          • Andrea Pagliarani

            Ok, quindi la prova che devo fare è alimentare il sensore ed attaccare un filo all'uscita di esso. Con il tester al momento che il sensore scatta, devo vedere se c'è tensione. E' corretto? Scusami ma non vorrei fare cavolate...

          • sì, prova sia quando è scattato sia senza; un puntale lo tieni sul morsetto comune (il terminale negativo mi pare sia scritto sul pdf che mi hai mandato) e l'altro puntale sull'uscita

          • Andrea Pagliarani

            Ho fatto qualche test con il sensore. Come avevi pronosticato, è un semplice contatto. A sensore spento la tensione nei morsetti in uscita al sensore è di 0V, a sensore attivo è di 0,5V. Puoi ora spiegarmi come posso rilevare questo cambiamento di tensione dal raspberry? Grazie.

          • A sensore spento a tensione di 0V indica che il contatto è chiuso (situazione ci cortocircuito che annulla la tensione ai capi del contatto), mentre la tensione di 0.5V è sinonimo di contatto aperto. Puoi confermare eseguendo non una misura di tensione ma una prova di continuità 😉

            Comunque... come mi pare già accennato in precedenza, ad un capo del contatto applicherai una tensione positiva di 3.3V (derivata ad esempio da uno dei GPIO del raspberry); all'altro capo una resistenza da 10kohm con il secondo morsetto a massa (anche questa dei GPIO del raspberry). Nel punto di giunzione tra contatto e resistenza deriverai una linea da mandare direttamente ai GPIO del raspberry e configurare come ingresso. Così facendo: a contatto aperto (sensore attivo) il pin di ingresso sarà a massa (quindi 0 logico), mentre a contatto chiuso (sensore spento, 0V che hai misurato), il pin di ingresso sarà attivo (1 logico)

            Occhio a non dare più di 3.3V, o rischi seriamente di bruciare tutto! 😉

          • Andrea Pagliarani

            Grazie! Lo schema sarebbe questo, è corretto? https://www.dropbox.com/s/uuod5dk610h4drq/schema.jpg?dl=0
            E' possibile collegare più sensori al raspberry seguendo questo stesso schema per ognuno?

            Ultimissima domanda, c'è un modo per assicurarmi che non arrivi più di 3,3V al raspberry?

          • Circa: la linea che hai chiamato GPIO input ha l'estremità tra sensore e resistenza, altrimenti com'è ora il segnale rilevato è sempre massa 😉

            Sì, puoi aggiungere quanti sensori vuoi, sempre con questo schema

            Per il discorso 3.3V il problema non si pone se li prelevi dal raspberry, in quanto l'uscita del sensore è un semplice contatto (non influirà quindi sulla tensione)