Lampada intelligente

Materiali: Lampada da tavolo Lampan, prototyping shield Cytron Technologies, alimentatore 5V 2A, quattro NeoPixel, pulsante, sensore di temperatura TMP36, fotoresistenza, due resistenze da 10k ohm, cavi rigidi a filo unico per cablaggi, PLA (ø 3mm).

Strumenti: Arduino, Ultimaker 2 (ugello ø 0,4mm).

concept

Progettazione: I microcontrollori sono piccoli calcolatori autosufficienti contenuti all’interno di singoli chip e sono parte integrante di moltissimi dispositivi elettronici ai quali aggiungono funzionalità evolute, basate sull’interazione con l’uomo e l’ambiente attraverso l’impiego di sensori e attuatori. Arduino è una piattaforma di prototipazione open-source e rappresenta la soluzione più semplice per sviluppare progetti con i microcontrollori.
Lo scopo di questo lavoro era rendere “intelligente” una semplice lampada di plastica venduta da Ikea, sostituendo la lampadina a incandescenza con una striscia di LED NeoPixel che risponde ai segnali ambientali ricevuti da una fotoresistenza e da un sensore di temperatura. Un pulsante permette di passare dalla lettura della luminosità a quella della temperatura, alle quali corrisponde un diverso comportamento dei LED.
Le interazioni fra i diversi componenti del circuito sono mediate da Arduino attraverso uno script. La prima fase della programmazione consiste nella realizzazione di un diagramma di flusso, che permette di rappresentare graficamente le operazioni eseguite dallo script. All’inizio del programma viene definito un contatore per memorizzare il numero di volte che il pulsante viene premuto: ad un numero pari di pressioni corrisponde la lettura dei valori della fotoresistenza, mentre ad un numero dispari corrisponde la lettura dei valori del sensore di temperatura. Nel primo caso la luminosità ambientale viene associata all’intensità della luce prodotta dai LED, in modo che questa risulti massima al buio e minima alla luce del giorno. Nel secondo caso, invece, si presentano tre diverse situazioni: i LED emettono luce rossa, verde o blu per indicare a quale range di temperatura appartiene il valore registrato.

circuito

Circuito: Per testare il circuito è stato realizzato un prototipo collegando i vari componenti sulla breadboard. Il pulsante chiude il circuito quando è applicata una pressione. I piedini che sporgono dallo stesso lato non sono connessi tra loro, interrompendo così il circuito. La resistenza che unisce GND al piedino collegato all’ingresso digitale è detta di pull-down e attira verso GND la tensione quando il circuito è aperto. In questa situazione, infatti, il ponticello funge da antenna e capta rumore ambientale che induce l’ingresso digitale a fluttuare tra gli stati HIGH e LOW. La resistenza di pull-down consente di mantenere lo stato LOW. Inoltre il resistore impedisce che VCC e GND entrino in contatto, creando un cortocircuito. Il sensore di temperatura produce una differenza di potenziale che varia in base alla temperatura percepita. La differenza di potenziale prodotta dal sensore TMP36 è direttamente proporzionale alla temperatura in gradi Celsius. La fotoresistenza è un sensore la cui resistenza è inversamente proporzionale alla quantità di luce che lo colpisce. Per misurare la variazione della resistenza è necessario realizzare un partitore di tensione, perché i piedini analogici di Arduino rilevano solo la differenza di potenziale. Il partitore di tensione è formato dalla fotoresistenza e da un resistore, collegati in serie: la differenza di potenziale misurata nel punto in cui si incontrano è descritta dall’equazione
Vout = Vin*[R2/(R1+R2)], ricavata dalla Legge di Ohm. Dall’equazione risulta che la differenza di potenziale è direttamente proporzionale al rapporto tra le resistenze e di conseguenza varia in funzione della luminosità. I LED vengono pilotati tramite un’uscita analogica utilizzando la tecnica PWM (Pulse Width Modulation) per modulare l’intensità della luce emessa. L’uscita analogica passa rapidamente dallo stato HIGH a LOW, generando un’onda quadra caratterizzata da duty cicle variabile, che permette di simulare una variazione di tensione. Il duty cicle è il rapporto tra il tempo in cui il segnale assume valore HIGH e il periodo dell’onda: un duty cicle del 50%, ad esempio, corrisponde ad una tensione di 2,5V, che genera un’intensità luminosa pari alla metà della luminosità massima.

#include <Adafruit_NeoPixel.h>
Adafruit_NeoPixel strip = Adafruit_NeoPixel(4, 3, NEO_GRB + NEO_KHZ800);

byte FotoR = 5;
byte SensTmp = 1;
int FotoValue = 0;
int MinVal = 1023;
int MaxVal = 0;
byte Bright = 0;
int TmpValue = 0;
float Volt = 0;
float Temp = 0;
byte Button = 0;
byte PushCounter = 0;
byte PrevButton = 0;
unsigned long previousMillis = 0;
long interval = 2000;

void setup() {
  Serial.begin(9600);
  pinMode(13, INPUT);
  strip.begin();
}

void loop() {
  FotoValue = analogRead(FotoR);
  Button = digitalRead(13);
  if (Button != PrevButton) {
    if (Button == HIGH) {
      PushCounter++;
    }
  }
  PrevButton = Button;
  if (PushCounter % 2 == 0) {
    AutoTune();
    strip.setPixelColor(0, Bright, Bright, Bright);
    strip.setPixelColor(1, Bright, Bright, Bright);
    strip.setPixelColor(2, Bright, Bright, Bright);
    strip.setPixelColor(3, Bright, Bright, Bright);
    strip.show();
  }
  else {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis > interval) {
      previousMillis = currentMillis;
      TmpValue = analogRead(SensTmp);
      Volt = (TmpValue / 1024.0) * 5.0;
      Temp = (Volt - 0.5) * 100;
      Serial.println(Temp);
      if (Temp > 25) {
        strip.setPixelColor(0, 255, 0, 0);
        strip.setPixelColor(1, 255, 0, 0);
        strip.setPixelColor(2, 255, 0, 0);
        strip.setPixelColor(3, 255, 0, 0);
        strip.show();
      }
      else if (Temp <= 25 && Temp > 20) {
        strip.setPixelColor(0, 0, 255, 0);
        strip.setPixelColor(1, 0, 255, 0);
        strip.setPixelColor(2, 0, 255, 0);
        strip.setPixelColor(3, 0, 255, 0);
        strip.show();
      }
      else if (Temp <= 20) {
        strip.setPixelColor(0, 0, 0, 255);
        strip.setPixelColor(1, 0, 0, 255);
        strip.setPixelColor(2, 0, 0, 255);
        strip.setPixelColor(3, 0, 0, 255);
        strip.show();
      }
    }
  }
}
void AutoTune() {
  if (FotoValue > MaxVal) {
    MaxVal = FotoValue;
  }
  if (FotoValue < MinVal) {
    MinVal = FotoValue;
  }
  Bright = map(FotoValue, MaxVal, MinVal, 0, 255);
}

Programmazione:
1. Include la libreria utilizzata per pilotare la striscia di LED.
2. Crea un’istanza della classe Adafruit_NeoPixel a cui vengono passati come argomenti il numero di NeoPixel che compongono la striscia, il numero del pin al quale è collegata e il tipo di Neopixel utilizzati.
4 – 17. Dichiarazione delle variabili.
20. Configura la porta seriale utilizzata durante la fase di debugging dello script. L’argomento passato è la velocità espressa in bit al secondo (baud).
21. Il pin al quale è collegato il pulsante viene impostato come ingresso.
22. Configura la striscia di LED per l’uso.
27. Legge lo stato in cui si trova il pulsante.
28 – 30. La variabile PushCounter memorizza il numero di volte che il pulsante viene premuto, aggiungendo al suo valore una unità se lo stato del pulsante è HIGH ed è diverso dallo stato nel ciclo precedente. Quest’ultima condizione impedisce che il valore di PushCounter aumenti quando la pressione sul pulsante viene prolungata, altrimenti PushCounter risulterebbe pari o dispari in base alla durata della pressione e non del numero di volte che il pulsante viene premuto.
33. Nel ciclo successivo, lo stato del pulsante nel ciclo precedente assumerà il valore dello stato nel ciclo in corso.
34 – 39. Se il resto della divisione tra PushCounter e due è uguale a zero (cioè se PushCounter è pari), legge il valore della fotoresistenza, esegue la funzione AutoTune() e imposta i NeoPixel con i valori di luminosità ottenuti dalla funzione. Gli argomenti passati a setPixelColor sono: il numero del NeoPixel che si vuole impostare e i livelli di luminosità, rispettivamente, dei colori rosso, verde e blu.
40. Aggiorna le impostazioni della striscia di LED.
42 – 44. Se invece PushCounter è dispari, conta il numero di millisecondi trascorsi dall’esecuzione dello script e se la differenza tra il tempo totale trascorso e l’ultima volta che è stata misurata la temperatura è maggiore di due secondi…
45. Salva il tempo in cui è stata misurata la temperatura l’ultima volta.
46. Legge il dato misurato dal sensore di temperatura attraverso un ingresso analogico, che restituisce un valore compreso tra 0 e 1023.
47. Il valore letto viene convertito in tensione tramite una proporzione.
48. La formula utilizzata per calcolare la temperatura si basa sulle caratteristiche del sensore TMP36. Alla temperatura di 0°C il sensore produce una tensione di 0,5V, perciò valori inferiori corrispondono a temperature sotto lo zero. 0,5V rappresenta un offset, al quale viene sottratta la tensione misurata per determinare di quanto la temperatura è maggiore o minore rispetto a 0°C. Inoltre una variazione di 0,01V corrisponde ad una variazione di 1°C, quindi per calcolare la temperatura si deve moltiplicare per cento la differenza tra la tensione misurata e l’offset. Ad esempio, se l’ingresso analogico rileva una tensione di 0,51V, la temperatura sarà: (0,51-0,50)= 0,01*100= 1°C.
49. Stampa il valore della temperatura sul monitor seriale per verificare la correttezza del risultato.
50 – 55. Se la temperatura è maggiore di 25°C, i Neopixel emettono luce rossa, impostando i livelli di luminosità del rosso a 255 mentre quelli di verde e blu a 0. 0 – 255 è il range di valori prodotti dall’uscita analogica tramite PWM. La striscia di LED viene quindi aggiornata con le nuove impostazioni.
57 – 62. Se invece la temperatura è minore o uguale di 25°C e maggiore di 20°C, i Neopixel emettono luce verde.
64 – 69. Se invece la temperatura è minore o uguale di 20°C, i Neopixel emettono luce blu.
75 – 76. Ad ogni ciclo, il valore della luminosità ambientale misurato viene confrontato con il valore massimo registrato fino a quel momento: se il nuovo valore è maggiore, MaxVal viene sovrascritto fino a che non raggiunge il valore massimo registrabile in quelle condizioni luminose.
78 – 79. Per MinVal, il cui valore di partenza è il massimo valore misurabile dall’ingresso analogico, vale la situazione opposta e il suo valore diminuisce fino a raggiungere il valore minimo registrabile.
81. Il comando MAP fa una proporzione tra due range di valori. Il valore misurato dalla fotoresistenza, che appartiene al range di valori della luminosità ambientale, i cui estremi sono stati calcolati nei due passaggi precedenti, viene rimappato sul range di valori dell’intensità luminosa prodotta dai LED. Il valore massimo di un range corrisponde al valore minimo dell’altro e viceversa, in modo che al diminuire della luce ambientale aumenti l’intensità della luce dei LED.

Realizzazione: Per realizzare il circuito precedentemente testato sulla breadboard è stata utilizzata una proto shield, alla quale sono stati saldati a stagno i componenti e i fili elettrici. L’operazione di saldatura richiede particolare attenzione affinché il risultato sia pulito e preciso, in modo da evitare che lo stagno debordi sui contatti vicini creando cortocircuiti. Per la stessa ragione, le saldature realizzate sulla fotoresistenza e sul sensore di temperatura sono state isolate utilizzando una guaina termorestringente che impedisse ai fili scoperti di entrare in contatto. Per implementare il circuito sulla lampada è stata rimossa la lampadina, il suo supporto e il cavo elettrico, per creare un foro centrale che permettesse il passaggio dei fili dalla proto shield, collocata nella base, fino al paralume, che contiene i sensori e i LED. Per realizzare una sede in cui posizionare Arduino e la proto shield è stata stampata una base di appoggio ma lo spazio ricavato all’interno della lampada è risultato insufficiente, per cui è stato necessario tagliare una parte dei pin della proto shield rimasti inutilizzati. Per fissare e disporre ordinatamente i LED è stato stampato un secondo supporto. Per inserire il pulsante nella base della lampada è stato realizzato un foro e stampato un supporto ad incastro, poi adattato perché risultato troppo rigido per incastrarsi. Per fissare il supporto al foro è stata quindi utilizzata la colla a caldo invece dell’incastro. Infine sono stati realizzati dei fori per fare in modo che i sensori potessero sporgere all’esterno per registrare i dati ambientali.

Possibili modifiche: L’Internet of Things è l’insieme di tecnologie e soluzioni che permettono agli oggetti di connettersi alla rete: grazie ad uno shield ethernet e un’interfaccia programmata con Processing, ad esempio, sarebbe possibile controllare la lampada attraverso il computer o lo smartphone, compiendo così un primo passo nel campo della domotica.