«

»

Dic 18

Corso Arduino – Lezione 6 – Accendere luci con Arduino

L’accensione di una luce con Arduino può essere una cosa non troppo sicura, stiamo collegando un circuito digitale in corrente continua a bassa tensione alla tensione di rete di 220v in corrente alternata. Il rischio di rompere qualcosa è sempre dietro l’angolo. Fortunatamente esistono dei relay che funzionano con la 220v pilotabili in continua da Arduino a 5V. Tuttavia non saremo mai certi della qualità se prendiamo cinesate online, vi consiglio di affidarvi a prodotti affidabili. Io ho acquistato un prodotto che fa il suo dovere ma le piste non sembrano troppo distanti ed è piccolino. Perfetto per entrare in una presa a muro ma chissà se è sicuro! La cosa mi frena molto ma la studierò meglio. Tuttavia ci sono sicuramente prodotti ad elevata affidabilità in commercio! Puntate a quelli!

Come potete vedere il vantaggio di un sistema domotico programmabile è la modularità che consente di scegliere come abbassare i costi (escludere sensori) e di scegliere la qualità in funzione di ciò che si può fare! Sconsiglio di risparmiare quando si lavora con la 220!

L’accensione di una luce con Arduino, tuttavia è una procedura molto semplice! A meno di non avere interruttori multipli connessi alla stessa lampadina o altri relay! Generalmente l’uso di deviatori o relay richiede di variare il circuito che andremo ad affrontare fra poco ma è sempre possibile. Noi useremo questa lezione per accendere una luce con un pulsantino ma al posto dell’interruttore potremmo anche inserire un fotoresistore per rilevare l’abbassamento della luminosità in casa e accenderle automaticamente. Naturalmente il fotoresistore deve essere esposto alla luce per rilevare le variazioni luminose quotidiane. Vedremo in seguito come gestirlo! E anche come associarlo a un rilevatore di presenza per comandare la luce su un balcone soltanto in caso ci sia una persona in movimento sul balcone al crepuscolo!

COSTI

Relay 2,89+iva

Totale circa 3,5 euro.

Come funziona un relay?

Senza addentrarci in tecnicismi, generalmente, un relè, o relay, è un interruttore (o deviatore) magnetico azionato da un impulso elettrico.Il tutto avviene eccitando un circuito che si occupa di chiudere il contatto del neutro e della fase. È generalmente dotato di 3 connessioni:

– Comune: alla quale collegare la fase della 220V

– Normalmente Aperto o NO: dove possiamo collegare il neutro

– Normalmente Chiuso o NC: come sopra!

Naturalmente di questi utlimi due se ne usa soltanto uno! Si sceglie in funzione dei casi. Se inseriamo il filo nell’NC la corrente fluirà normalmente perchè il circuito rimarrà chiuso naturalmente e quando il relay scatterà invece staccherà il circuito. Viceversa usando il connettore NO, il relay manterrà staccati la Fase Comune e il Neutro su NO e per fare fluire la corrente sarà necessario chiudere il circuito eccitando il relay.

Di tutto ciò si occuperà Arduino che con un impulso sulla linea dei 5V farà chiudere o aprire il circuito. Sotto trovate una foto esplicativa del funzionamento di un tipo di relay pilotato tramite un pulsante ! (Immagine non mia – Fonte: http://www.aggiustatutto.it/images/stories/imma-elettricita/). Il funzionamento non è tanto diverso. Il circuito di comando è formato da Arduino e la sua 5V che con il segnale alto preme il pulsante e aziona il relay che a sua volta chiude il circuito fra fase e neutro!

relay funzionamento

Fritzing

ATTENZIONE, STATE MANEGGIANDO LA 220V PERTANTO USATE GUANTI DA LAVORO E STACCATE L’INTERRUTTORE GENERALE ONDE EVITARE DANNI PERSONALI. USATE ANCHE UN CERCA FASE PER VERIFICARE CHE NON VI SIA CORRENTE CIRCOLANTE. IL CERCAFASE E’ UN CACCIAVITE COLLEGATO A UN ELEVATA RESISTENZA E UNA LUCINA, TOCCANDO I FILI CON LA PUNTA DEL CACCIAVITE E LA PIASTRINA POSTA SUL MANICO LA LUCE SI ACCENDE IN PRESENZA DI CORRENTE. SE VERIFICATE CHE NONOSTANTE L’INTERRUTTORE STACCATO IL CERCAFASE SI ILLUMINA NON METTETE MANO AI FILI. TANTI ELETTRICISTI NON STACCANO NEANCHE IL CIRCUITO MA CIO’ NON TOGLIE CHE SI RISCHIA LA VITA O DANNI SERI E CHE SONO PROFESSIONISTI, DOTATI DI GUANTI DA LAVORO PROFESSIONALI E HANNO L’ESPERIENZA CHE MANCA A ME E A VOI PER POTER GESTIRE QUESTE SITUAZIONI. NON MI RITENGO RESPONSABILI DI DANNI PERSONALI, FISICI E QUANTO ALTRO. SIETE STATI AVVISATI!

Tenendo conto degli avvertimenti qui sopra passiamo al circuito e alle connessioni. Non avendo trovato il relay in mio possesso fra i componenti di Fritzing troverete sullo schema un relay con 5 pin il più possibile somigliante. Ho deciso di collegarlo come se fosse il nostro relay! Uno dei pin che va ad Arduino è mancante e ho fatto finta fosse presente, non fate caso al fatto che non è connesso a nulla. Ho anche inserito un LED al posto della lampadina per lo stesso motivo ed è connesso casualmente. Naturalmente, sul relay, il comune andrà connesso a uno dei fili della 220 e sarà al centro e l’altro filo andrà inserita in NO o NC a seconda che vogliate mantenere la luce accesa o spenta. Nel nostro caso preferiamo sia normalmente spenta pertanto inseriremo il filo in NO. Generalmente si preferisce interrompere la fase piuttosto che il neutro pertanto individuate la fase e inseritela nel comune (potrebbe essere benefico con alcune lampadine a risparmio energetico, che se rimangono connesse alla fase lampeggiano a causa di segnali spuri, masse non volute e cose simili). Gli altri pin del relay vanno connessi naturalmente alla 5V e alla GND per alimentarlo e il pin connesso al nulla è il nostro pin di segnalazione che va inserito in uno dei pin di Arduino! Scegliamo il 2.

relay fritzing

Codice Arduino IDE

Il codice è molto semplice, il relay ha un pin per inviare il segnale di chiusura o apertura del circuito e due pin di alimentazione, Vcc (5V) e GND (massa). Come vediamo dall’immagine Fritzing riuseremo lo stesso schema visto in precedenza per gestire il pulsante. Il pin di gestione del relay viene gestito tramite pinMode(pinRelay, OUTPUT) e digitalWrite(pinRelay, HIGH). In caso di segnale HIGH se il relay è collegato con il normalmente chiuso spegne la luce, se collegato con il normalmente aperto accende la luce perché chiude il circuito. Il nostro caso è naturalmente il secondo! Ho inserito anche un delay dopo il rilevamento del pulsante per evitare che in caso di pressione troppo lunga il pulsante venga rilevato nuovamente e venga spenta la luce. Se vi rendete conto che sentite il relay staccare e attaccare o la luce accendersi e spegnersi aumentate questo valore! La variabile backupVal serve a mantenere lo stato precedente. Se la luce è stata accesa in precedenza lo stato di val è stato HIGH e pertanto lo salvo. Se lo stato precedente era alto, la luce è accesa pertanto stacco il relay e riaggiorno il valore a LOW (spento).

int power_pin=9; // il pin del pulsantino
int relayPin=2;
 int val=0;
 int backupVal=LOW;
void setup() {
  Serial.begin(9600);

  pinMode(relayPin, OUTPUT);
  pinMode(power_pin, INPUT);
}

void loop() {
   val = digitalRead(power_pin); // leggo il valore del pulsante (PREMUTO = 1, NON PREMUTO = 0)
   Serial.print("Il valore è ");
   Serial.print(val);
   Serial.print(" Il backval è ");
   Serial.println(backupVal);
   
  // se è stato premuto
  if(val==HIGH && backupVal==LOW){
    backupVal=val;
    digitalWrite(relayPin, HIGH);
    delay(500);
  }else if(val==HIGH && backupVal==HIGH){
    backupVal=LOW;
    digitalWrite(relayPin,LOW);
    delay(500);
  } 
}

Nella prossima Lezione modificheremo il circuito inserendo un fotoresistore e un rilevatore di presenza per la gestione della luce sul balcone al crepuscolo. E in quella seguente useremo un rilevatore vocale per accendere la luce con la voce!

  • Lorenzo Andreani

    scusa,premetto che nn ho molta esperienza… ho provato a scrivere lo sketch ma andando a fare la verifica mi da errore ‘amp’ was not declared in this scope, potresti mica spiegarmi il perchè e/o dove sbaglio?
    Grazie mille !!

    • http://www.mariobonofiglio.it/ Mario Bonofiglio

      Ciao, purtroppo il blog wordpress ha aggiunto in automatico amp come codifica del testo. Per intenderci devi sostituire && con &&. Correggo subito il blog, grazie per la segnalazione. Fammi sapere se ci sono altri ptoblemi, mi fa piacere sapere di essere seguito ed essere stato utile 😉

  • Monica Ansaloni

    Ciao ho scaricato questo programma e devo dire che funziona perfettamente.
    Mi sono appassionata da poco ad Arduino e non ho grosse conoscenze.
    Vorrei chiedervi se qualcuno riesce ad aiutarmi?
    Dovrei comandare un relè che funzioni per un certo tempo e si spenga per un tempo diverso, in un ciclo continuo da fermare con un pulsante nel caso avvengano anomalie.
    Riuscite a dirmi se posso fare ciò con due pulsanti collegati su due pin differenti? e come devo gestire il programma?
    Ringrazio anticipatamente per i suggerimenti che potrete darmi grazie mille

    • http://www.mariobonofiglio.it/ Mario Bonofiglio

      Ciao, non credo di aver capito esattamente di cosa hai bisogno. Provo a risponderti per quel che credo di aver compreso ma correggimi pure e chiedi se hai bisogno di tutt’altro.
      – Tu vuoi realizzare un’accensione programmata uno spegnimento programmato per tempi ben determinati o casuali. Se ho male interpretato dimmelo pure.
      – Il reset in caso di anomalie lo puoi fare sfruttando il pulsante reset di Arduino che si occuperà di riavviare lo sketch che hai caricato.
      – Per quanto concerne l’accensione e lo spegnimento credo tu possa fare uso di un delay(milliseconds) dopo aver usato un digitalWrite(High) sul pin del relay per poterlo accendere. La medesima cosa puoi farla con il valore low di spegnimento. E naturalmente puoi usare anche valori random generati a runtime. Credo funzioni!

      Se posso esserti nuovamente utile chiedi pure.

      • Monica Ansaloni

        Ciao ti ringrazio per i consigli.
        Sono riuscita a fare lo sketch con i tempi di accensione e spegnimento.
        Il ciclo comanda un relè che attiva e disattiva una pompa.
        quello che non riesco a fare è bloccare il ciclo del relè durante il funzionamento.
        Puoi aiutarmi grazie

        • http://www.mariobonofiglio.it/ Mario Bonofiglio

          Figurati. Così a occhio e senza visualizzare il tuo sketch posso intuire che tu voglia disattivare il relay durante un delay. Questo purtroppo potrebbe essere il problema. Posso chiederti di farmi vedere lo sketch? Se non vuoi farlo pubblicamente puoi anche inviarlo tramite email o form contatti ;).

          • Monica Ansaloni

            int Relay = 8;
            int interrCount=0;
            void setup()
            {
            pinMode(Relay, OUTPUT);
            pinMode(Relay, LOW);
            attachInterrupt(0, interruptRelay, RISING);
            }
            void loop(){
            interrCount++;
            digitalWrite(Relay, HIGH); // spegne il relay
            delay(5000);
            digitalWrite(Relay, LOW); // accende il relay
            delay(6500);
            if ( interrCount == 10 )
            {
            interrCount = 0;
            digitalWrite(Relay, LOW);
            }
            }
            void interruptRelay()
            {
            digitalWrite(Relay, HIGH);
            }
            Mi era venuto il dubbio che fosse legato al funzionamento del relè, lo interrompe solo nel ciclo di spegnimento della pompa.

          • http://www.mariobonofiglio.it/ Mario Bonofiglio

            Allora, non c’entra con il tuo problema ma vorrei comunque darti un paio di consigli ti consiglio sullo sketch.
            Premesso che non è scorretto ma ti suggerisco:
            – di cambiare pinMode(Relay, LOW) in digitalWrite(Relay, LOW) se il tuo intento è di inizializzare a LOW il pin :).
            – sarebbe preferibile usare attachInterrupt con attachInterrupt(digitalPinToInterrupt(pin), interruptRelay(), RISING)

            Ma naturalmente dipende anche da quale Arduino stai usando :). Vuole essere giusto un consiglio.

            Passando alla tua richiesta! Non credo di aver capito l’intento ma leggendo come funziona lo sketch in pratica:
            – tu hai il relay già acceso dal setup()
            – successivamente viene spento e viene incrementato il contatore.
            – Trascorsi 5 secondi viene riacceso
            – trascorsi 6,5 secondi viene verificato il contatore e se non è 10 il relay viene rispento dal loop() che ricomincia
            – se invece siamo a interrCount 10 viene resettato il contatore e viene acceso il relay. Ma il relay sarà già acceso e l’operazione successiva sarà quella di spegnimento.

            Il tuo intento se ho capito bene è spegnerlo per 5 secondi e accenderlo per 6,5 e poi di nuovo rispegnere e riaccendere. Se ciò avviene per 10 volte invece di spegnerlo deve continuare a rimanere acceso, giusto? Se non ho capito male devi spostare l’if.

            Se ho inteso bene provo a scriverti la modifica se invece ho frainteso correggimi pure. Il codice dell’interrupt invece è corretto

          • Monica Ansaloni

            mI

          • http://www.mariobonofiglio.it/ Mario Bonofiglio

            Mi spiace. Domani dovrei avere Arduino sotto mano e potrò esserti più utile. In questo momento non riesco a fare di più :)

          • Monica Ansaloni

            Scusa ma ho sbagliato sketch.
            Quello che volevo realizzare era qualcosa di più semplice.
            -Relè acceso per 6,5 secondi
            -Relè spento per 5 secondi
            ( a ciclo continuo)
            Però devo poterlo fermare in qualsiasi momento con un pulsante (come se intervenisse una sicurezza)
            Far ripartire il ciclo da dove era rimasto
            o con un reset sempre con il pulsante.
            Oppure come alternativa un pulsante per il ciclo e uno pe l’arresto.
            Spero di averti spiegato meglio quello che dovrei fare.
            Comunque ho apportato le modifiche al programma come mi hai consigliato, lo proverò al più presto.
            Ti ringrazio per l’aiuto ciao

          • http://www.mariobonofiglio.it/ Mario Bonofiglio

            Allora per interrompere l’esecuzione durante un delay devi per forza usare un interrupt quindi devi collegare un pulsante al pin che userai per l’interrupt. Se non sbaglio su Arduino Uno puoi usare il 2 o il 3. Ma hai anche una seconda possibilità.
            [code]
            int Relay = 8;
            int pinPulsante = 3;
            int trigger;
            int premuto;
            void setup()
            {
            pinMode(Relay, OUTPUT);
            digitalWrite(Relay, HIGH);
            pinMode(pinPulsante, INPUT);
            trigger=0;
            premuto = 0;
            }

            void loop(){
            premuto = digitalRead(pinPulsante);
            if(premuto==1){
            premuto=0;
            if(trigger=0)
            trigger = 1;
            else
            trigger = 0;
            }

            if(interruttore==1){
            digitalWrite(Relay, LOW); // spegne il relay
            delay(6500);
            digitalWrite(Relay, HIGH); // accende il relay
            delay(5000);
            }
            }
            [/code]
            Non l’ho testato ma credo possa andare bene. Quando hai necessità di bloccare tutto devi premere il pulsante di reset di Arduino. Resettando lo sketch tutte le variabili verranno inizializzate nuovamente e solo alla pressione del tuo pulsantino sul pin 3 avvierai lo sketch con il ciclo accensione e spegnimento ogni 5-6,5secondi.

          • Monica Ansaloni

            Ho provato a caricarlo ma non funziona.
            Ho modificato interruttore con pinPulsante perché mi segnalava un errore durante il caricamento.
            Ci riguardo domani a quest’ora non sono molto lucida intanto grazie

          • http://www.mariobonofiglio.it/ Mario Bonofiglio

            Perdonami, lo sketch corretto è questo. Non posso provarlo non avendo Arduino fra le mani in questo momento ma compila correttamente. Interruttore va sostituito con trigger.

            int Relay = 8;
            int pinPulsante = 3;
            int trigger;
            int premuto;
            void setup()
            {
            pinMode(Relay, OUTPUT);
            digitalWrite(Relay, HIGH);
            pinMode(pinPulsante, INPUT);
            trigger=0;
            premuto = 0;
            }

            void loop(){
            premuto = digitalRead(pinPulsante);
            if(premuto==1){
            premuto=0;
            if(trigger=0)
            trigger = 1;
            else
            trigger = 0;
            }

            if(trigger==1){
            digitalWrite(Relay, LOW); // spegne il relay
            delay(6500);
            digitalWrite(Relay, HIGH); // accende il relay
            delay(5000);
            }
            }

          • Monica Ansaloni

            Non mi funziona ancora.

          • http://www.mariobonofiglio.it/ Mario Bonofiglio

            Ciao, scusa il ritardo. La colpa è mia, non funziona per qualche errore nello sketch. Purtroppo scrivendo da smartphone non è così semplice riportare tutto correttamente e avere una visione globale di quel che si sta facendo.

            Il funzionamento dello sketch è semplice, tu vuoi registrare la pressione del tuo pulsante anche durante le pause del relay. In questo modo con la pressione del pulsante puoi effettuare uno spegnimento della pompa. Tuttavia tieni conto del fatto che l’uso del comando delay non ti consente di uscire immediatamente ma piuttosto ti consente di intervenire su una variabile di stato che potrai usare per il controllo del flusso. Ma comunque il delay deve essere portato a termine. Se il tuo intento è l’interruzione immediata puoi usare un timer al posto di delay.
            Usando delay invece puoi usare questo sketch qui sotto che fa uso di una variabile di stato e la verifica prima di ogni comando così da interrompere il flusso subito dopo l’esecuzione del delay in atto. Se vuoi fermare l’esecuzione puoi usare il tasto reset di Arduino che riporterà il microcontrollore nello stato iniziale e cioè quando il relay era spento. È un po’ ridondante ma funziona. Tieni conto del fatto che non è una buona pratica usare delay nella funzione di interrupt ma ho usato delle tempistiche molto brevi per evitare i falsi positivi durante la pressione del pulsante. Non saprei dirti se esiste un altro metodo ma mi informerò perchè credo ci sia sicuramente qualcoa si più corretto e elegante. Senza questo piccolo delay una pressione troppo prolungata del pulsante farebbe cambiare nuovamente lo stato e otterresti un comportamento scorretto. Puoi alzarlo fino a 500ms a mio parere.

            #include

            int Relay = 8;
            int pinPulsante = 3;

            volatile byte state = LOW;

            void setup()
            {
            pinMode(Relay, OUTPUT);
            Serial.begin(9600);
            digitalWrite(Relay, LOW);
            pinMode(pinPulsante, INPUT);
            attachInterrupt(digitalPinToInterrupt(pinPulsante), interrupt, RISING);
            }

            void loop(){

            Serial.print(“Stato “);
            Serial.println(state);

            while(state){

            if(state){
            Serial.println(“Sto per riaccenderlo per 5secondi”);
            digitalWrite(Relay, HIGH); // accende il relay
            delay(5000);
            }else{
            digitalWrite(Relay, LOW); // spegne il relay
            }
            if(state){
            Serial.println(“Sto per spegnerlo per 6,5secondi”);
            digitalWrite(Relay, LOW); // spegne il relay
            delay(6500);
            }else{
            digitalWrite(Relay, LOW); // spegne il relay
            }
            }
            }

            void interrupt()
            {
            delay(200);
            state = !state;
            }

          • Monica Ansaloni

            Sono io a dovermi scusare per il ritardo ma non sono stata bene e mi sono fermata.
            Ora mi sento meglio e ho provato a caricare lo skethc .
            Direi che funziona .
            Ti ringrazio per la pazzienza e l’aiuto che mi hai dato e per tutte le indicazioni utili anche per i prossimi lavori che avremmo intenzione di realizzare grazie ancora continuero a seguirti ciao Monica