domenica 19 giugno 2022

La classe Relay (High/Low Level Trigger)

Moduli relay optoisolati

Il mercato offre moduli relay (o relè) di vario tipo, i più diffusi sono optoisolati con logica di comando negata.

La logica di comando negata vuole dire che quando il pin di comando è LOW, il relay risulta eccitato e ovviamente quando il comando è HIGH il relay risulta a riposo.

Normalmente siamo abituati a pensare all’inverso, cioè HIGH per eccitare il relay. Questa logica negata ci spiazza ed è un problema in più da gestire ed è bene risolverlo alla radice.

I moduli relay più diffusi ed economici sono a logica negata, nella loro descrizione commerciale dovreste trovare almeno la specifica seguente: Low Level Trigger.

Altri moduli si stanno diffondendo, ciò che li contraddistingue è la possibilità di configurarli tramite jumer per lavorare con High o Low trigger.

Se il nostro modulo relay è configurabile, possiamo selezionare High Level Trigger in modo che basti un semplice digitalWrite(13, HIGH) , per eccitare la sua bobina. Mentre con Low Level Trigger, siamo costretti ad una digitalWrite(13, HIGH) nel setup per averlo non eccitato e ovviamente scriveremo digitalWrite(13, LOW) per eccitarlo.

Ciò può portare a confusione specie se abbiamo diversi relay alcuni Low Level ed altri High Level. La piccola classe Relay mira a risolvere il problema alla radice.

Il costruttore della classe prende due argomenti, l’ultimo è opzionale ma ci permette di configurare il Level Trigger.

    // costruttore di Relay
    Relay(const byte pin, const bool lt = LOW) : m_relayPin(pin)
                                      , m_levelTrigger(lt) 

L’argomento lt di default è Low Level Trigger poiché sono i moduli più diffusi. La chiamata al costruttore avviene in ambito globale, si crea istanza in uno di questi modi:

    Relay relayOnD6(6, HIGH);  // logica non invertita
    Relay relayOnD6(6, LOW);   // logica invertita
    Relay relayOnD6(6);        // logica invertita

Dopo la creazione della istanza, per ognuna è necessario chiamare il metodo begin() all’interno della funzione setup(). Importante non dimenticare di chiamare questo metodo una sola volta per istanza.

    relayOnD6.begin();

Eccitare il relay o diseccitarlo è semplice, il metodo set() prende un bool come argomento. Di seguito vediamo tre modi equivalenti per eccitarlo:

    relayOnD6.set(HIGH);  // HIGH equivale a true.
    relayOnD6.set(ON);    // ON equivale ad HIGH
    relayOnD6.set(1);     // 1 equivale a ON

Per mettere a riposo il relay (non eccitato), scriviamo:

    relayOnD6.set(LOW);     // oppure
    relayOnD6.set(OFF);     // oppure
    relayOnD6.set(0);

Per leggere lo stato del relay, usiamo il metodo state():

    if (relayOnD6.state() == ON) {
        // ...
    }

L’applicazione dimostrativa (demo)

La demo è molto semplice, ci sono due relay, uno High Level Trigger e l’altro Low Level Trigger. Le istanze sono dichiarate così:

    Relay relayOnD6(6, HIGH);   // High Level Trigger on D6 pin
    Relay relayOnD5(5, LOW);    // Low Level Trigger on D5 pin

Il codice è talmente semplice che non serve commentarlo. Potete provarlo al simulatore seguendo questo link.

 

2 commenti:

  1. Non è più semplice usare dei #define?
    Logica negata:
    #define ON LOW
    #define OFF HIGH

    digitalWrite(6, ON); // Porta l'I/O 6 a livello basso, eccitando il relè.

    RispondiElimina
  2. C'è una componente soggettiva che determina ciò che è semplice, di sicuro è più efficiente con le macro. Ma attenzione con le #define ON LOW, cioè questa vale per qualunque cosa presente nello sketch, dovresti avere tutto in logica negata. Ci sono altri motivi che mi hanno portato a scriverla, nella terza puntata sul termostato la classe thermost eredita la classe Relay.

    RispondiElimina