08 Numerazione capitolo

08 - CLESSIDRA DIGITALE

IN QUESTO PROGETTO, COSTRUIRAI UNA CLESSIDRA DIGITALE CHE ACCENDE UN LED OGNI DIECI MINUTI. SAPRAI PER QUANTO TEMPO STAI LAVORANDO SUI TUOI PROGETTI USANDO IL TIMER INCORPORATO IN ARDUINO

Scopri: il tipo di dati long, creare un timer

Tempo: 30 MINUTI Livello: ■ ■ ■ □ □ Basato sui progetti: 1, 2, 3, 4

Finora con Arduino, quando hai voluto che accadesse qualcosa in uno specifico intervallo di tempo, hai usato la funzione delay(): è pratica, ma un po” limitante. Quando Arduino chiama delay(), blocca il suo stato corrente per la durata del ritardo. Significa che non ci sono altri ingressi o uscite quando è in attesa. I ritardi non sono molto utili per tenere traccia del tempo. Se vuoi fare qualcosa ogni 10 secondi, avere un delay() di 10 secondi è piuttosto scomodo.

Ingredienti

INGREDIENTI

  • Interruttore di inclinazione (Tilt switch)

  • 6 LED

  • Resistenza da 10 Kilo Ohm

  • 6 Resistenze da 220 Ohm

La funzione millis() aiuta a risolvere questi problemi. Tiene traccia del tempo in cui Arduino è funzionante in millesimi di secondo. L’hai usato precedentemente nel Progetto 06 quando hai creato un timer per la calibrazione.

Finora hai dichiarato le variabili come int. Un int (intero) è un numero a 16 bit, che contiene valori tra -32768 e 32767. Possono sembrare numeri grandi, ma Arduino conta 1000 volte al secondo con la funzione millis() e quindi esaurisci i numeri in poco tempo. Il tipo di dato long contiene un numero da 32 bit (tra -2147483648 e 2147483647). Dal momento che non è possibile tornare indietro per ottenere i numeri negativi, la variabile per immagazzinare il tempo millis() è chiamata unsigned long. Quando un tipo di dato è chiamato unsigned, è solo positivo. Questo ti permette di contare ancora di più. Un unsigned long può contare fino a 4294967295. C’è abbastanza spazio per far sì che la funzione millis() tenga traccia del tempo per almeno 50 giorni. Confrontando il valore attuale di millis() a un valore specifico, puoi vedere se è passato un certo periodo di tempo.

Quando capovolgi la clessidra, un interruttore di inclinazione cambierà il suo stato e prenderà il via un nuovo ciclo di accensione dei LED. L’interruttore di inclinazione funziona come un normale interruttore nel senso che è un sensore acceso/spento. Qui lo userai come ingresso digitale.

Ciò che rende unico l’interruttore di inclinazione è che rileva l’orientamento. Normalmente ha una piccola cavità all’interno del corpo che contiene una sfera di metallo. Quando è inclinato in modo corretto, la sfera rotola su un lato della cavità e collega i due terminali che sono sulla breadboard chiudendo l’interruttore.

COSTRUISCI IL CIRCUITO

Schema del circuito e montaggio

  1. Collega alimentazione e massa alla breadboard.

  2. Collega l’anodo (la gamba più lunga) dei sei LED ai piedini digitali 2-7. Collega i LED a massa attraverso una resistenza da 220 ohm.

  3. Collega una estremità dell’interruttore di inclinazione a 5V. Collega l’altra a una resistenza da 10 kilo ohm a massa. Collega il punto dove si incontrano al piedino digitale 8.

Schema elettrico

Forbici e colla

Non c’è bisogno che Arduino sia collegato al computer per funzionare. Prova a costruire un supporto con del cartoncino o del polistirolo e alimentare Arduino con una batteria per creare una clessidra portatile. Puoi creare una copertura con delle cifre a fianco delle luci.

Lente

Gli interruttori di inclinazione sono strumenti ottimi ed economici per determinare l’orientamento di qualcosa. Gli accelerometri sono altri tipi di sensori di inclinazione, ma forniscono molte più informazioni. Sono anche significativamente più costosi. Se ti serve controllare se qualcosa è su o giù, un sensore di inclinazione è più che sufficiente.

IL CODICE

Dichiara una costante

Hai bisogno di alcune variabili globali nel tuo programma. Per iniziare, crea una costante chiamata switchPin. Questo è il nome del piedino al quale è connesso l’interruttore di inclinazione.

const int switchPin = 8;

Crea una variabile per memorizzare il tempo

Crea una variabile di tipo unsigned long. Questa memorizza il momento in cui è stato modificato l’ultimo LED.

unsigned long previousTime = 0;

Variabili per gli ingressi e le uscite

Crea una variabile per lo stato dell’interruttore e un’altra per memorizzare il precedente stato dell’interruttore. Userai queste due variabili per confrontare la posizione dell’interruttore da un ciclo al successivo. Crea una variabile chiamata led, che verrà usata per verificare quale LED è il prossimo ad accendersi. Inizia con il piedino 2.

int switchState = 0;
int prevSwitchState = 0;

int led = 2;

Dichiara una variabile descrivendo l’intervallo tra gli eventi

L’ultima variabile da creare è l’intervallo di accensione di ogni LED. Questo è un tipo di dato long. In 10 minuti (il tempo tra l’accensione di ogni LED) ci sono 600000 millesimi di secondo. Se vuoi che il ritardo tra le luci sia più lungo o corto, questo è il numero da cambiare.

long interval = 600000;

Imposta la direzione dei tuoi piedini digitali

Nel setup(), hai bisogno di dichiarare come output i piedini dei LED 2-7. Un ciclo for() li dichiara tutti e sei come OUTPUT con solo 3 linee di codice. Hai bisogno anche di dichiarare switchPin come INPUT.

void setup() {
  for(int x = 2;x<8;x++){
    pinMode(x, OUTPUT);
  }
  pinMode(switchPin, INPUT);
}

Controlla da quanto tempo è stato avviato il programma

Quando inizia il loop(), misura la quantità di tempo in cui Arduino è stato in funzione con millis() e immagazzinalo in una variabile locale chiamata currentTime.

void loop(){
  unsigned long currentTime = millis();

Valuta la quantità di tempo trascorso dal precedente loop()

Usando un’istruzione if(), controlla se è passato abbastanza tempo per accendere un LED. Sottrai currentTime da previousTime e controlla se è maggiore della variabile interval. Se sono passati 600000 millesimi di secondo (10 minuti), imposta la variabile previousTime al valore di currentTime.

  if(currentTime - previousTime > interval) {
    previousTime = currentTime;

Accendi un LED, prepara il prossimo

Indica l’ultima volta in cui è stato acceso un LED. Quando hai impostato previousTime, accendi il LED e incrementa la variabile led. La prossima volta che passi l’intervallo di tempo, il LED successivo si accende.

    digitalWrite(led, HIGH);
    led++;

Verifica se tutte le luci sono accese

Aggiungi una istruzione if in più nel programma per controllare se il LED sul piedino 7 si è acceso. Non farci ancora nulla. Potrai decidere dopo cosa succede alla fine dell’ora.

    if(led == 7){
    }
  }

Leggi il valore dell’interruttore

Dopo aver controllato il tempo, guarda se l’interruttore ha cambiato il suo stato. Scrivi il valore dell’interruttore nella variabile switchState.

  switchState = digitalRead(switchPin);

Azzera le variabili se necessario

Con una istruzione if(), verifica se l’interruttore si trova in una posizione diversa da quella precedente. Il != controlla se switchState è diverso da prevSwitchState. Se sono diversi, spegni i LED, riporta la variabile led al primo piedino e azzera il timer per i LED impostando previousTime al valore di currentTime.

  if(switchState != prevSwitchState){
    for(int x = 2;x<8;x++){
      digitalWrite(x, LOW);
    }

    led = 2;
    previousTime = currentTime;
  }

Imposta lo stato corrente allo stato precedente

Alla fine del loop(), salva lo stato dell’interruttore in prevSwitchState, così puoi confrontarlo al valore di switchState nel loop() successivo.

  prevSwitchState = switchState;
}

USALO

Una volta che hai programmato la scheda controlla l’ora su un orologio. Dopo che sono passati 10 minuti, il primo LED dovrebbe essersi acceso. Ogni 10 minuti si accenderà un altro LED. Alla fine di un’ora, tutte le 6 luci dovrebbero essere accese. Quando ribalti il circuito e fai cambiare stato all’interruttore di inclinazione, le luci si spegneranno e il timer ripartirà.

Cervello

Quando l’orologio raggiunge un’ora e tutte le 6 luci sono accese, rimangono accese. Puoi pensare a un modo per attirare l’attenzione quando l’ora è passata? Suoni o il lampeggiare di luci sono entrambi buoni indicatori. La variabile led può essere controllata per vedere se tutte le luci sono accese; questo è un buon modo per catturare l’attenzione di qualcuno. Diversamente da una clessidra riempita di sabbia, le luci vanno su o giù a seconda dell’orientamento dell’interruttore. Riesci a capire come utilizzare la variabile switchState per indicare in quale direzione dovrebbero andare le luci?

Per misurare il tempo tra eventi, usa la funzione millis(). Dato che i numeri che genera sono più grandi di quelli che puoi memorizzare in un int, dovresti usare il tipo di dato unsigned long per immagazzinarne i valori.

CODICE COMPLETO

/*
  Arduino Starter Kit example
  Project 8 - Digital Hourglass

  This sketch is written to accompany Project 8 in the Arduino Starter Kit

  Parts required:
  - 10 kilohm resistor
  - six 220 ohm resistors
  - six LEDs
  - tilt switch

  NOTE: This sketch is intentionally incomplete. Make sure to add your own code
  for whatever you want to happen at the end of the hour.

  created 13 Sep 2012
  by Scott Fitzgerald

  https://store.arduino.cc/genuino-starter-kit

  This example code is part of the public domain.
*/

// named constant for the switch pin
const int switchPin = 8;

unsigned long previousTime = 0;  // store the last time an LED was updated
int switchState = 0;             // the current switch state
int prevSwitchState = 0;         // the previous switch state
int led = 2;                     // a variable to refer to the LEDs

// 600000 = 10 minutes in milliseconds
long interval = 600000;  // interval at which to light the next LED

void setup() {
  // set the LED pins as outputs
  for (int x = 2; x < 8; x++) {
    pinMode(x, OUTPUT);
  }
  // set the tilt switch pin as input
  pinMode(switchPin, INPUT);
}

void loop() {
  // store the time since the Arduino started running in a variable
  unsigned long currentTime = millis();

  // compare the current time to the previous time an LED turned on
  // if it is greater than your interval, run the if statement
  if (currentTime - previousTime > interval) {
    // save the current time as the last time you changed an LED
    previousTime = currentTime;
    // Turn the LED on
    digitalWrite(led, HIGH);
    // increment the led variable
    // in 10 minutes the next LED will light up
    led++;

    if (led == 7) {
      // the hour is up
      // add your indicator code here
    }
  }

  // read the switch value
  switchState = digitalRead(switchPin);

  // if the switch has changed
  if (switchState != prevSwitchState) {
    // turn all the LEDs low
    for (int x = 2; x < 8; x++) {
      digitalWrite(x, LOW);
    }

    // reset the LED variable to the first one
    led = 2;

    //reset the timer
    previousTime = currentTime;
  }
  // set the previous switch state to the current state
  prevSwitchState = switchState;
}