Fotoresistenza

Quando si legge un ingresso analogico usando la funzione analogRead(), si ottiene un numero compreso tra 0 e 1023. Ma quando si vuole generare un segnale PWM usando la funzione analogWrite(), si deve fornire un numero compreso tra 0 e 255. La funzione map() stabilisce una scala tra due intervalli di diversa larghezza.

Level = map(Level, 0, 1023, 0, 255);

Nell'esempio precedente, la funzione map() riceve, come primo parametro, una misura che rientra nell'intervallo tra 0 e 1023 (II e III parametro). Calcola il fattore di scala tra il primo intervallo e il secondo (0, 255) e restituisce il valore che, in proporzione, corrisponde nel secondo intervallo.

Se esiste la possibilità che il numero fornito a map() sia esterno all'intervallo 0-1023, allora la funzione restituirebbe numeri esterni all'intervallo 0-255. Per questa ragione, si usa la funzione constrain() che limita i numeri all'interno dell'intervallo 0-255. Se il numero cade all'esterno dell'intervallo verrà approssimato, altrimenti resta lo stesso valore.

Level = constrain(Level, 0, 255);


Interruttore crepuscolare.

Il programma usa la fotoresistenza per controllare l'intensità luminosa del LED.

Notare che la d.d.p. prelevata sul partitore di tensione, non varia tra 0 e 5V, quindi i numeri letti oscilleranno, ad esempio, tra 300 (ombra) a 800 (luce). Di conseguenza, il LED non sarà mai completamente spento o completamente acceso.

Ci sono due funzioni manualTune() e autoTune()(togliere il commento per provare ciascuna di esse) che consentono di variare i limiti dell'intervallo.

Le due funzioni modificano la variabile lightLevel per coprire correttamente il range da acceso a spento.

Con l'istruzione digitalWrite si illumina il LED in base al valore di lightLevel. Per ottenere il comportamento opposto sostituire lightLevel con 255-lightLevel.


        const int sensorPin = 0;
        const int/ ledPin = 9;
        int lightLevel, high = 0, low = 1023;
        void setup() {
          pinMode(ledPin, OUTPUT);
        }
        void loop() {
          lightLevel = analogRead(sensorPin); // si legge un numero tra 0 e 1023
          manualTune();  // modifica manuale del range da luce a ombra.
          //autoTune();  // modifica automatica
          analogWrite(ledPin, lightLevel); // Ora si regola l'intensità luminosa del LED:
        }
    

La funzione manualTune() consente di tarare l'intervallo. Si dovrebbe trovare, con vari tentativi, il numero corrispondente al livello di ombra tollerato, oltre il quale accendere il LED, e il livello di luce in corrispondenza del quale spegnere il LED. Il numero più piccolo corrisponde all'ombra e il numero più grande corrisponde alla luce.

Per individuare l'ampiezza dell'intervallo, modificare manualmente gli estremi specificati nella funzione map(). Provare a cambiare 0, 1023 in un intervallo più piccolo (da 300 a 800 per esempio). Se il LED non si spegne completamente, ridurre il numero più grande. Se il LED è sempre acceso, aumentare il numero più piccolo.


        void manualTune() {
          lightLevel = map(lightLevel, 0, 1023, 0, 255);
          lightLevel = constrain(lightLevel, 0, 255);
        }
    

La funzione autoTune() regola automaticamente l'intervallo. In questa funzione si utilizzano le due variabili low (che era stata inizializzata a 1023, il valore massimo) e high (che era stata inizializzata a 0, il valore minimo) per memorizzare il valore minimo e il valore massimo letto da analogRead().

I valori calcolati vengono passati alla funzione map(). Ai due valori, però viene aggiunto un offset, per impedire al LED di dare una luce tremolante.


        void autoTune() {
          if (lightLevel < low) {
            low = lightLevel;
          }
          if (lightLevel > high) {
            high = lightLevel;
          }
          lightLevel = map(lightLevel, low+30, high-30, 0, 255);
          lightLevel = constrain(lightLevel, 0, 255);
        }
    

Esercizi

Scegliere un valore al di sotto del quale viene richiamata una funzione che fa lampeggiare il LED per 3 volte.