Arduino – Uso di LED RGB – approfondimento

Scrivo questa lezione come approfondimento della guida realizzata tempo fa: Arduino – lezione 09: uso di LED RGB in cui mostravo come funzionano e come si gestiscono i LED RGB con Arduino. Negli esercizi proposti utilizzavo un LED ad ANODO comune. In questa nuova lezione utilizzerò un diodo a CATODO comune e mostrerò tre esempi, nel primo ripropongo in una modalità diversa l’esercizio della prima lezione in cui faccio alcuni approfondimenti sull’uso della direttiva #define, mentre nel secondo e terzo esercizio viene mostrato come impostare il colore emesso dal LED RGB mediante input da tastiera su Serial Monitor richiamando con questi esempi l’uso del qualificatore const per una variabile e l’utilizzo della funzione parseInt(). Come sempre nei commenti, all’interno del codice, trovate la spiegazione del funzionamento di ogni parte dello sketch.

Esempio 01

Variazione colore continuo di un LED RGB secondo lo schema:

ROSSO > VERDE, VERDE > BLU, BLU > ROSSO

Scema di collegamento

/*  Prof. Maffucci Michele
    06.01.2021

    Esempio 01
    Variazione colore continuo
    di un LED RGB secondo lo schema:

    ROSSO > VERDE, VERDE > BLU, BLU > ROSSO

*/

/* Utilizzo della direttiva #define per definire una costante
   La direttiva viene utilizzata per definire una MACRO ovvero
   un simbolo.

   La sintassi per la definizione di una macro è:
   #define nome-MACRO  valore_MACRO

   Per convenzione il nome della macro viene scritta in maiuscolo.

   Il preprocessore legge la definizione di ogni MACRO e ogni volta che
   ne incontra il nome all'interno del programma (file sorgente) sostituisce
   al simbolo il valore corrispondente, senza che venga effettuata la verifica
   della correttezza sintattica dell'espressione risultante.
*/

#define VERDE 9
#define BLU 10
#define ROSSO 11

// tempo di dissolvenza tra i colori
#define tempoRitardo 10

void setup()
{
  // impostazione ad OUTPUT dei pin
  pinMode(ROSSO, OUTPUT);
  pinMode(VERDE, OUTPUT);
  pinMode(BLU, OUTPUT);

  // all'avvio viene emesso il colorore ROSSO
  digitalWrite(BLU, LOW);
  digitalWrite(VERDE, LOW);
  digitalWrite(ROSSO, HIGH);
}

// definizione di variabili
int valoreRosso;
int valoreVerde;
int valoreBlu;

void loop()
{
  // Impostazioni variabili per avere partire con LED:
  // ROSSO accesso, VERDE spento, BLU spento.
  valoreRosso = 255;
  valoreVerde = 0;
  valoreBlu = 0;

  // partendo dal ROSSO si sfuma al VERDE pieno quando i = 255
  for (int i = 0; i < 255; i += 1)
  {
    valoreRosso -= 1;
    valoreVerde += 1;

    // L'intensità del ROSSO viene diminuita ad ogni ciclo, mentre
    // l'intensità del VERDE viene aumentata ad ogni ciclo
    analogWrite(ROSSO, valoreRosso);
    analogWrite(VERDE, valoreVerde);
    delay(tempoRitardo);
  }

  // Impostazioni variabili per avere partire con LED:
  // ROSSO spento, VERDE acceso, BLU spento.
  valoreRosso = 0;
  valoreVerde = 255;
  valoreBlu = 0;

  // partendo dal VERDE si sfuma al BLU pieno quando i = 255
  for (int i = 0; i < 255; i += 1)
  {
    valoreVerde -= 1;
    valoreBlu += 1;

    // L'intensità del VERDE viene diminuita ad ogni ciclo, mentre
    // l'intensità del BLU viene aumentata ad ogni ciclo
    analogWrite(VERDE, valoreVerde);
    analogWrite(BLU, valoreBlu);
    delay(tempoRitardo);
  }

  // Impostazioni variabili per avere partire con LED:
  // ROSSO spento, VERDE spento, BLU acceso.
  valoreRosso = 0;
  valoreVerde = 0;
  valoreBlu = 255;

  // partendo dal BLU si sfuma al ROSSO pieno quando i = 255
  for (int i = 0; i < 255; i += 1)
  {
    valoreBlu -= 1;
    valoreRosso += 1;

    // L'intensità del BLU viene diminuita ad ogni ciclo, mentre
    // l'intensità del ROSSO viene aumentata ad ogni ciclo
    analogWrite(BLU, valoreBlu);
    analogWrite(ROSSO, valoreRosso);
    delay(tempoRitardo);
  }
}

Esempio 02

Inserimento da Serial Monitor dei valori di intensità del colore. La stringa di richiesta inserimento dei valori RGB viene ripetuta una sola volta e ad ogni nuovo inserimento non viene stampato sulla serial monitor il valore inserito.

Lo schema di collegamento è il medesimo dell’esempio 01.

/*  Prof. Maffucci Michele
    06.01.2021

    Esempio 02
    Inserimento da Serial Monitor dei valori
    di intensità del colore.
    La stringa di richiesta inserimento viene ripetuta una sola volta.
    Ad ogni nuovo inserimento non viene stampato sulla serial monitor
    il valore inserito.

    L'inserimento dei tre valori potrà essere effettuato
    in una delle due modalità:
    1. separando i tre numeri con spazio
    2. separando i tre numeri con la virgola
*/

/*
   Una variabile const indica al compilatore che il valore della
   variabile non può essere modificato durante l'esecuzione del programma.
   Una variabile const viene inizializzata nel momento della dichiarazione,
   se ciò viene fatto in un momento successivo il compilatore rileverà un
   errore che segnalerà anche errore in ogni operazione che comportano la
   modifica del valore dell avariabile definita come const
*/

const byte pinRosso = 11;
const byte pinBlu = 10;
const byte pinVerde = 9;

void setup() {
  // Inizializzazione della comunicazione seriale
  Serial.begin(9600);

  // Impostazione dei pin come OUTPUT
  pinMode(pinRosso, OUTPUT);
  pinMode(pinBlu, OUTPUT);
  pinMode(pinVerde, OUTPUT);

  // Messaggio sulla serial monitor
  Serial.println("Inserisci i valori R G B (es. 125, 50, 255)");
  Serial.println("-------------------------------------------");
  delay(1000);
}

void loop() {

  // Controlla se è disponibile almeno un carattere sulla seriale
  // La Serial.available() restituisce
  // 1 se presente un cattere,
  // 0 se non è presente un carattere

  // per maggior informazioni sull'uso di parseInt() consultare il link:
  // https://wp.me/p4kwmk-4Ah

  if (Serial.available()) {
    // memorizzazione dei colori nelle variabili
    int rosso = Serial.parseInt();
    int verde = Serial.parseInt();
    int blu = Serial.parseInt();

    // impostazione del PWM
    analogWrite(pinRosso, rosso);
    analogWrite(pinVerde, verde);
    analogWrite(pinBlu, blu);
  }
}

Esempio 3

Inserimento da Serial Monitor dei valori di intensità del colore.
Il valore inserito verrà stampato sulla Serial Monitor e ad ogni invio verrà richiesto di inserire un nuovo valore.

Lo schema di collegamento è il medesimo dell’esempio 01.

/*  Prof. Maffucci Michele
    06.01.2021

    Esempio 03
    Inserimento da Serial Monitor dei valori
    di intensità del colore.
    Il valore inserito verrà stampato sulla Serial Monitor e ad ogni
    invio verrà richiesto di inserire un nuovo valore.

    L'inserimento dei tre valori potrà essere effettuato
    in una delle due modalità:
    1. separando i tre numeri con spazio
    2. separando i tre numeri con la virgola
*/

/*
   Una variabile const indica al compilatore che il valore della
   variabile non può essere modificato durante l'esecuzione del programma.
   Una variabile const viene inizializzata nel momento della dichiarazione,
   se ciò viene fatto in un momento successivo il compilatore rileverà un
   errore che segnalerà anche errore in ogni operazione che comportano la
   modifica del valore dell avariabile definita come const
*/

const byte pinRosso = 11;
const byte pinBlu = 10;
const byte pinVerde = 9;

// per stampare una sola volta il messaggio sulla Serial Monitor
bool abilitaMessaggio = 0;

void setup() {
  // Inizializzazione della comunicazione seriale
  Serial.begin(9600);

  // Impostazione dei pin come OUTPUT
  pinMode(pinRosso, OUTPUT);
  pinMode(pinBlu, OUTPUT);
  pinMode(pinVerde, OUTPUT);
}

void loop() {
  // consente di visualizzare sulla Serial Monitor
  // una sola stampa delle stringa
  if (abilitaMessaggio == 0) {
    // ritardo che evita la doppia stampa del messaggio
    delay(200);
    Serial.print("Inserisci i valori R G B (es. 125, 50, 255): ");
    abilitaMessaggio = 1;
  }

  // Controlla se è disponibile almeno un carattere sulla seriale
  // La Serial.available() restituisce
  // 1 se presente un cattere,
  // 0 se non è presente un carattere

  // per maggior informazioni sull'uso di parseInt() consultare il link:
  // https://wp.me/p4kwmk-4Ah


  if (Serial.available()) {
    // memorizzazione dei colori nelle variabili
    int rosso = Serial.parseInt();
    int verde = Serial.parseInt();
    int blu = Serial.parseInt();
    Serial.print(rosso);
    Serial.print(", ");
    Serial.print(verde);
    Serial.print(", ");
    Serial.println(blu);
    Serial.println("-------------------------------------------");

    // impostazione del PWM
    analogWrite(pinRosso, rosso);
    analogWrite(pinVerde, verde);
    analogWrite(pinBlu, blu);

    // abilita alla stampa di una nuova stringa:
    // "Inserisci il ritardo in millisecondi: "
    abilitaMessaggio = 0;
  }
}

Esercizi per i miei studenti

Esercizio 1

Utilizzare tre pulsanti che funzionino come interruttori che permettono di accendere e spegnere un solo LED alla volta:

  • pulsante 1: LED ROSSO
  • pulsante 2: LED VERDE
  • pulsante 3: LED BLU

Ogni cambiamento di stato deve essere segnalato sulla Serial Monitor.

Esercizio 2

Utilizzare due pulsanti in gredo di realizzare la seguente automazione:

  • pulsante 1: attivare/disattivare la modalità di variazione continua del colore, così come esposta nell’esempio 01
  • pulsante 2: attivare/disattivare la generazione casuale di un colore

Ogni cambiamento di stato deve essere segnalato sulla Serial Monitor.

Esercizio 3

Utilizzando la Serial Monitor come unico strumento per inviare comandi ad Arduino, realizzare un menù di selezione che permette di impostare le funzionalità dell’esercizio 01 e dell’esercizio 03.

Arduino: utilizzo di buzzer attivi e passivi – lezione 1

Nella progettazione di un sistema di automazione sono molto spesso previsti apparati di interazione e di allarme che potranno essere visivi o sonori. Per quanto riguarda gli apparati sonori spesso vengono utilizzati dei buzzer, chiamati anche cicalini. Con questo dispositivo potremo quindi segnalare lo stato di un sistema.

I buzzer possono essere di due tipi:

  • attivi
  • passivi

I buzzer possono essere di tipo magnetico o piezoelettrici la scelta del tipo dipende sostanzialmente da tre fattori:

  1. segnale di pilotaggio
  2. potenza di uscita richiesta
  3. spazio fisico disponibile

Buzzer attivo

Un buzzer attivo usa un oscillatore interno che permette di emettere un tono a frequenza fissa se viene alimentato con una tensione continua.

L’oscillatore interno è in grado di modificare il campo magnetico di una bobina a cui è connesso meccanicamente una membrana che oscillerà alla frequenza fissata dall’oscillatore.

Con Arduino si potrà realizzare un sistema di automazione in grado di comandare l’emissione del suono abilitando o disabilitando l’alimentazione del buzzer.

Caratteristiche tecniche di un buzzer attivo

  • Tensione nominale: 6V DC
  • Tensione di esercizio: 4-8V DC
  • Corrente nominale: < 30mA
  • Tipo di suono: segnale acustico continuo
  • Frequenza di risonanza: ~2300 Hz

Buzzer passivo

Un buzzer passivo non possiede un oscillatore interno e quindi è indispensabile un circuito esterno in grado di generare un’onda quadra che mettere in oscillazione la membrana interna del buzzer, questi attuatori potranno così emettere toni a diversa frequenza.

Con Arduino si potrà realizzare un sistema di automazione in grado di comandare l’emissione del suono per un certo tempo ad una determinata frequenza utilizzando il la modulazione digitale PWM.

Caratteristiche tecniche di un buzzer attivo

  • Tensione nominale: 5V DC
  • Tensione di esercizio: 4-8V DC
  • Corrente nominale massima: ≤ 32 mA
  • Min. Uscita audio a 10 cm: 85 dB
  • Temperatura di esercizio: da 20°C a 45°C

Pilotare un buzzer con Arduino

Per produrre un suono con Arduino si utilizza la funzione tone, il link vi rimanda al references di Arduino in cui troverete tutti i dettagli di utilizzo della funzione.

L’istruzione che verrà utilizzata è:

tone(pin, frequenza)
tone(pin,frequenza,durata)
  • pin: sarà il pin (PWM) su cui sarà presente il segnale modulato a cui verrà connesso il buzzer.
  • frequenza: frequenza del suono emesso. (unsigned int)
  • durata: la durata del tono espressa in millisecondi. (unsigned long)

Come indicato nel references:

Genera un’onda quadra alla frequenza specificata ( e duty cycle al 50% ) su un pin. Una durata puà essere specificata, altrimenti l’onda continua fino alla chiamata di noTone(). Il pin può essere connesso ad un buzzer piezoelettrico o altro speaker per riprodurre toni.

Solo un tono alla volta può essere generato. Se un tono è gia in riproduzione su un pin differente, la chiamata a tone() non avrà alcun effetto. Se il tono è in riproduzione sullo stesso pin, la chiamata ne imposterà la frequenza.

L’uso della funzione tone() interferirà con l’output PWM sui pin 3 e 11 (sulle schede diverse dalla Mega ).

Non è possibile generare toni inferioni a 31Hz. Per i dettagli tecnici, vedi le note di Brett Hagman.

NOTA: Se vuoi riprodurre toni differenti su pin multipli, hai bisogno di chiamare noTone() su un pin prima di chiamare tone() sul pin successivo.

La funzione noTone() interrompe la generazione dell’onda quadra causata da tone(). L’uso di noTone() non ha alcun effetto se non si sta generando alcun tono.

Sintassi:

noTone(pin);

Con Arduino è possibile riprodurre un solo tono alla volta in quanto l’utilizzo della funzione tone è legato ad un timer specifico del microcontrollore, il timer2 e se questo è richiesto da altre funzioni, come ad esempio un analogRead su pin PWM la funzione tone non potrà essere utilizzata. Per aggirare questo limite è possibile utilizzare la libreria Tone.h che vedremo nella prossime lezioni.

Il suono che può essere riprodotto mediante un altoparlante o un buzzer passivo collegato ad Arduino sarà un suono “metallico”, non sarà simile a quello di uno strumento musicale, e questo verrà ottenuto utilizzando un’onda quadra alla frequenza specificata.

Per riprodurre suoni simili a quelli di uno strumento musicale bisognerà utilizzare una scheda elettronica esterna che verrà controllata da Arduino, ma vedremo questa possibilità in una lezione successiva.

Per questa lezione utilizzerò prima un buzzer attivo e successivamente un buzzer passivo.

Esempio 1 – utilizzo buzzer attivo

 

/* Prof. Michele Maffucci
   data: 04.01.2021

   Esempio 01
   Utilizzo di un buzzer attivo
*/

// pin a cui è collegato il buzzer
byte buzzerPin = 2;
int buzzerRitardo = 1000;      

void setup() {
  // inizializzazione pin a cui è collegto il buzzer
  pinMode(buzzerPin, OUTPUT);
}

void loop() {
  
  // buzzer ON
  digitalWrite(buzzerPin,HIGH);
  delay(buzzerRitardo);

  // buzzer OFF
  digitalWrite(buzzerPin,LOW);
  delay(buzzerRitardo);
}

Esempio 02 – utilizzo buzzer attivo

Per richiamare l’uso di valori interi dalla Serial Monitor di seguito uno sketch che permette di inserire da computer il valore del delay che regola l’ON e l’OFF del buzzer attivo.

Lo schema di collegamento è il medesimo dell’esempio precedente.

/* Prof. Michele Maffucci
   data: 04.01.2021

   Esempio 02
   Utilizzo di un buzzer attivo
   Inserimento delay da Serial Monitor
*/

// pin a cui è collegato il buzzer
byte buzzerPin = 2;
int  buzzerRitardo = 0;      

// per stampare una sola volta il messaggio sulla Serial Monitor  
bool abilitaMessaggio = 0;

void setup() {
   
  // inizializzazione della serial monitor
  Serial.begin(9600);

  // inizializzazione pin a cui è collegto il buzzer
  pinMode(buzzerPin, OUTPUT);
}

void loop() {

  // consente di visualizzare sulla Serial Monitor
  // una sola stampa delle stringa
  if (abilitaMessaggio == 0) {
    // ritardo che evita la doppia stampa del messaggio 
    delay(200);
    Serial.print("Inserisci il ritardo in millisecondi: ");
    abilitaMessaggio = 1;
  }

  // Controlla se è disponibile almeno un carattere sulla seriale
  // La Serial.available() restituisce
  // 1 se presente un cattere,
  // 0 se non è presente un carattere

  // per maggior informazioni sull'uso di parseInt() consultare il link:
  // https://wp.me/p4kwmk-4Ah

  if (Serial.available())
  {
    // in r viene memorizzato il valore inserito
    // attraverso la Serial Monitor
    int r = Serial.parseInt();
    if (r != 0) {
      buzzerRitardo = r;
      Serial.println(buzzerRitardo);

      // abilita alla stampa di una nuova stringa:
      // "Inserisci il ritardo in millisecondi: "
      abilitaMessaggio = 0;
    }
  }
  
  // funzione permette di fare suonare il Buzzer
  suona();
}

void suona() {
  // buzzer ON
  digitalWrite(buzzerPin,HIGH);
  delay(buzzerRitardo);

  // buzzer OFF
  digitalWrite(buzzerPin,LOW);
  delay(buzzerRitardo);
}

Esempio 03 – utilizzo buzzer attivo

Utilizziamo ora un trimmer per modificare il delay che varia tra 100 e 1000 millisecondi, per fare questa operazione utilizzeremo la funzione map che rimapperà i valori presenti su A0 nell’intervallo 100, 1000.

 

/* Prof. Michele Maffucci
   data: 01.01.2021

   Esempio 03
   Utilizzo di un buzzer attivo
   Inserimento delay da Trimmer per impostare
   un ritardo tra 100 e 1000 millisecondi
*/

// pin a cui è collegato il buzzer
byte buzzerPin = 2;
int  buzzerRitardo = 0;      

// per stampare una sola volta il messaggio sulla Serial Monitor  
bool abilitaMessaggio = 0;

// variabile in cui memorizzare il valore restituito dall'analogRead
int val = 0;

void setup() {
   
  // inizializzazione della serial monitor
  Serial.begin(9600);

  // inizializzazione pin a cui è collegto il buzzer
  pinMode(buzzerPin, OUTPUT);
}

void loop() {

  // valore analogico letto su A0 inserito con il trimmer
  val = analogRead(A0);

// Togliere il commento per valutare
// valore massimo/minimo del valore restituito
// dall'analogRead in questo modo si potranno
// inserire nella map i valori massimi e minimi
// dell'intervallo di partenza

// Serial.println(val);
// delay(1000);

  // ValMax = 285, ValMin = 719
  // riconvertiti nell'intervallo 100, 1000
  
  buzzerRitardo = map(val, 285, 719, 100, 1000);

  // funzione permette di fare suonare il Buzzer
  suona();
}

void suona() {
  // buzzer ON
  digitalWrite(buzzerPin,HIGH);
  delay(buzzerRitardo);

  // buzzer OFF
  digitalWrite(buzzerPin,LOW);
  delay(buzzerRitardo);
}

Esempio 4 – utilizzo buzzer passivo

Utilizziamo ora un buzzer passivo per riprodurre un tono in base alla frequenza impostata da un trimmer collegato al pin A0. Si faccia attenzione che ora il buzzer è collegato al pin 5 di tipo PWM

/* Prof. Michele Maffucci
   data: 04.01.2021

   Esempio 04
   Utilizzo di un buzzer passivo per riprodurre
   un tono in base alla frequenza impostata
   da un trimmer collegato al pin A0
*/

// pin (PWM) a cui è collegato il buzzer
byte buzzerPin = 5;

// variabile in cui memorizzare la frequenza del tono
int  intonazionePin = 0;

 // variabile in cui memorizzare il valore restituito dall'analogRead
int val = 0;

// frequenza del tono
unsigned int frequenza;

// durata del tono
unsigned long durata = 10;

void setup()
{
  // inizializzazione pin a cui è collegto il buzzer
  pinMode(buzzerPin, OUTPUT);
}

void loop()
{
   // valore analogico letto su A0 inserito con il trimmer
   val = analogRead(A0);

 // Togliere il commento per valutare
// valore massimo/minimo del valore restituito
// dall'analogRead in questo modo si potranno
// inserire nella map i valori massimi e minimi
// dell'intervallo di partenza

// Serial.println(val);
// delay(1000);

  // ValMax = 285, ValMin = 719
  // riconvertiti nell'intervallo 1000, 5000

  // frequenza assunerà un valore tra 1000 Hz e 5000 Hz
  frequenza = map(val, 285, 719, 1000, 5000);

  // emissione del tono
  tone(buzzerPin, frequenza, durata);

  // pausa di 1 millisecondo
  delay(1);
}

Nella prossime lezioni, utilizzando un buzzer passivo, realizzeremo dei brevi brani musicali e successivamente sostituiremo il buzzer con un altoparlante da 8 Ohm.

Buon Making a tutti 🙂

Arduino: controllo sequenziale uscite digitali

Durante la progettazione di un sistema di automazione accade frequentemente di avere la necessità di ripetere, sequenzialmente e in modo continuo, l’attivazione di apparati (ad es. motori) oppure la lettura continua dei dati provenienti da più sensori. Come attività di ripasso per i miei studenti ho deciso di riprendere alcuni argomenti affrontati nelle scorse settimane con specifiche esperienze di laboratorio:

  • automi a stati finiti;
  • utilizzo degli array;
  • input valori interi da serial monitor;
  • marcia, arresto, pausa di sequenze;
  • controllo uscite digitali mediante ingressi analogici;
  • realizzazione di commutatori con pulsanti con uno o più pulsanti;
  • utilizzo corretto dei tipi di dati per risparmiare memoria;
  • e molto altro

Di seguito 9 sketch in cui vengono ripresi gli argomenti sopra elencati e che potranno essere utilizzati nei prossimi mesi per sviluppare ulteriori sperimentazioni.
Come sempre all’interno degli sketch proposti trovate le spiegazioni di ogni parte del codice ed in alcuni casi trovate link di approfondimento che rimandano a questo sito.

Per ripercorrere gli argomenti svolti partirò dal classico sketch che permette di realizza l’accensione sequenziale di LED, come quello che potete trovare nelle mie slice: Alfabeto Arduino – Lezione 2 a pagina 66.
I LED nel circuito identificano gli apparati da attivare sequenzialmente, realizzando così il classico effetto “super car” (i diversamente giovani 🙂 sanno perché si chiama così).
Circuito e sketch verranno poi modificati per rispondere alle specifiche indicate ad inizio di ogni esempio.

Sketch 01

Sequenza di accensione e spegnimento da destra e sinistra e viceversa di 8 LED con tempo di accensione di 100 millisecondi.

 

/* Prof. Michele Maffucci
   30.12.2020
   Lezione di riferimento: https://wp.me/p4kwmk-4D3

   Versione 01
   Sequenza di accensione e spegnimento alternato
   da destra e sinistra e viceversa di 8 LED con
   tempo di accensione di 100 millisecondi.
   
   Questo codice è di dominio pubblico 
 */

// creazione di un array di 8 pin a cui vanno collegati i LED
// per ulteriori informazioni sull'uso degli array si consulti il seguente link:
// http://wp.me/p4kwmk-26e

byte ledPin[] = {3, 4, 5, 6, 7, 8, 9, 10};

// per approfondimenti sull'uso dei tipi di dati
// si consultino i link:
// https://wp.me/p4kwmk-4As
// https://wp.me/p4kwmk-1zF

// intervallo di accensione/spegnimento
byte ritardoLed = 100;

// indicatore di direzione di accensione
byte direzione = 1;

// indice dell'array per l'accensione del LED
byte ledCorrente = 0;

// variabile in cui memorizzare il tempo di accensione di Arduino
// per ulteriori informazioni sui tipi unsigned long si consulti il seguente link:
// http://wp.me/p4kwmk-1zF

unsigned long tempoTrascorso;

void setup() {                
  // impostiamo tutti i pin ad output
  for (byte x=0; x<8; x++) {
    pinMode(ledPin[x], OUTPUT);
  }
    
  // Memorizzazione del tempo trascorso
  // dal momento in cui avviamo Arduino
  // Per ulteriori informazioni sull'uso di millis() si consulti il seguente link:
  // http://wp.me/p4kwmk-1QG
  
  tempoTrascorso = millis();
}

void loop() {
  // Se sono passati "ritardoLed" millisecondi dall'ultimo cambiamento
  if ((millis() - tempoTrascorso) > ritardoLed) {
    cambiaStatoLed();
    tempoTrascorso = millis();
  }
}

// la funzione cambiaStatoLed() permette di controllare
// la sequenza di accensione dei LED

void cambiaStatoLed() {
  // spegne tutti i LED
  for (byte x=0; x<8; x++) {
    digitalWrite(ledPin[x], LOW);
  }
  // accende il LED corrente
  digitalWrite(ledPin[ledCorrente], HIGH);
  // incrementa la variabile direzione
  ledCorrente += direzione;
  // cambia la direzione se si arriva alla fine
  if (ledCorrente == 7) {
    direzione = -1;
  }
  if (ledCorrente == 0) {
    direzione = 1;
  }
}

Sketch 02

Sequenza di accensione e spegnimento da destra e sinistra e viceversa di 8 LED. Con un trimmer è possibile variare il tempo di accensione nell’intervallo da 50 millisecondi a 1000 millisecondi (1 secondo).

/* Prof. Michele Maffucci
   30.12.2020
   Lezione di riferimento: https://wp.me/p4kwmk-4D3

   Versione 02
   Sequenza di accensione e spegnimento alternato
   da destra e sinistra e viceversa di 8 LED controllato
   da un trimmer che permetterà di variare il tempo di accensione
   da 50 millisecondi a 1000 millisecondi (1 secondo).
   
   Questo codice è di dominio pubblico 
 */

// creazione di un array di 8 pin a cui vanno collegati i LED
// per ulteriori informazioni sull'uso degli array si consulti il seguente link:
// http://wp.me/p4kwmk-26e

byte ledPin[] = {3, 4, 5, 6, 7, 8, 9, 10};

// per approfondimenti sull'uso dei tipi di dati
// si consultino i link:
// https://wp.me/p4kwmk-4As
// https://wp.me/p4kwmk-1zF

// intervallo di accensione/spegnimento
int ritardoLed;

// variabile in cui memorizzare il valore restituito dall'analogRead
int val = 0;

// indicatore di direzione di accensione
byte direzione = 1;

// indice dell'array per l'accensione del LED
byte ledCorrente = 0;

// variabile in cui memorizzare il tempo di accensione di Arduino
// per ulteriori informazioni sui tipi unsigned long si consulti il seguente link:
// http://wp.me/p4kwmk-1zF

unsigned long tempoTrascorso;

void setup() {
  Serial.begin(9600);            
  // impostiamo tutti i pin ad output
  for (byte x=0; x<8; x++) {
    pinMode(ledPin[x], OUTPUT);
  }
    
  // Memorizzazione del tempo trascorso
  // dal momento in cui avviamo Arduino
  // Per ulteriori informazioni sull'uso di millis() si consulti il seguente link:
  // http://wp.me/p4kwmk-1QG
  
  tempoTrascorso = millis();
}

void loop() {

  // valore analogico letto su A0 inserito con il trimmer
  val = analogRead(A0);

// Togliere il commento per valutare
// valore massimo/minimo del valore restituito
// dall'analogRead in questo modo si potranno
// inserire nella map i valori massimi e minimi
// dell'intervallo di partenza

// Serial.println(val);
// delay(1000);

  // ValMax = 285, ValMin = 719
  // riconvertiti nell'intervallo 50, 1000
  
  ritardoLed = map(val, 285, 719, 50, 1000);
  
  // Se sono passati "ritardoLed" millisecondi dall'ultimo cambiamento
  if ((millis() - tempoTrascorso) > ritardoLed) {
    cambiaStatoLed();
    tempoTrascorso = millis();
  }
}

// la funzione cambiaStatoLed() permette di controllare
// la sequenza di accensione dei LED

void cambiaStatoLed() {
  // spegne tutti i LED
  for (byte x=0; x<8; x++) {
    digitalWrite(ledPin[x], LOW);
  }
  // accende il LED corrente
  digitalWrite(ledPin[ledCorrente], HIGH);
  // incrementa la variabile direzione
  ledCorrente += direzione;
  // cambia la direzione se si arriva alla fine
  if (ledCorrente == 7) {
    direzione = -1;
  }
  if (ledCorrente == 0) {
    direzione = 1;
  }
}

Sketch 03

Sequenza di accensione e spegnimento alternato da destra e sinistra e viceversa di 8 LED. L’accensione di ogni LED è fissato in partenza a 100 millisecondi. Con un messaggio sulle Serial Monitor viene richiesto di inserire un nuovo tempo di accensione e spegnimento di ogni LED (delay), tempo che può essere scelto a piacimento.

Lo schema di collegamento è analogo a quello utilizzato per lo sketch 01.

/* Prof. Michele Maffucci
   30.12.2020
   Lezione di riferimento: https://wp.me/p4kwmk-4D3

   Versione 03
   Sequenza di accensione e spegnimento alternato
   da destra e sinistra e viceversa di 8 LED.

   Partenza sequenza con 100 millisecondi e messaggio sulla
   Serial Monitor per modificare il tempo di
   accensione e spegnimento del singolo LED (delay)
   
   Questo codice è di dominio pubblico 
 */

// creazione di un array di 8 pin a cui vanno collegati i LED
// per ulteriori informazioni sull'uso degli array si consulti il seguente link:
// http://wp.me/p4kwmk-26e

byte ledPin[] = {3, 4, 5, 6, 7, 8, 9, 10};

// per approfondimenti sull'uso dei tipi di dati
// si consultino i link:
// https://wp.me/p4kwmk-4As
// https://wp.me/p4kwmk-1zF

// intervallo di accensione/spegnimento
int ritardoLed = 100;

// indicatore di direzione di accensione
byte direzione = 1;

// indice dell'array per l'accensione del LED
byte ledCorrente = 0;

// variabile in cui memorizzare il tempo di accensione di Arduino
// per ulteriori informazioni sui tipi unsigned long si consulti il seguente link:
// http://wp.me/p4kwmk-1zF

unsigned long tempoTrascorso;

// per stampare una sola volta il messaggio sulla Serial Monitor  
bool abilitaMessaggio = 0;

void setup() {
  // inizializzazione della serial monitor
  Serial.begin(9600);
               
  // impostiamo tutti i pin ad output
  for (byte x=0; x<8; x++) {
    pinMode(ledPin[x], OUTPUT);
  }

  // Memorizzazione del tempo trascorso
  // dal momento in cui avviamo Arduino
  // Per ulteriori informazioni sull'uso di millis() si consulti il seguente link:
  // http://wp.me/p4kwmk-1QG
  tempoTrascorso = millis();
}

void loop() {
  // consente di visualizzare sulla Serial Monitor
  // una sola stampa delle stringa
  if (abilitaMessaggio == 0) {
    // ritardo che evita la doppia stampa del messaggio 
    delay(200);
    Serial.print("Inserisci il ritardo in millisecondi: ");
    abilitaMessaggio = 1;
  }

  // Controlla se è disponibile almeno un carattere sulla seriale
  // La Serial.available() restituisce
  // 1 se presente un cattere,
  // 0 se non è presente un carattere

  // per maggior informazioni sull'uso di parseInt() consultare il link:
  // https://wp.me/p4kwmk-4Ah

  if (Serial.available())
  {
    // in r viene memorizzato il valore inserito
    // attraverso la Serial Monitor
    int r = Serial.parseInt();
    if (r != 0) {
      ritardoLed = r;
      Serial.println(ritardoLed);

      // abilita alla stampa di una nuova stringa:
      // "Inserisci il ritardo in millisecondi: "
      abilitaMessaggio = 0;
    }
  }
  
  // funzione che fa lampeggiare il LED su Arduino
  lampeggio();
}

void lampeggio() {
  // Se sono passati "ritardoLed" millisecondi dall'ultimo cambiamento
  if ((millis() - tempoTrascorso) > ritardoLed) {
    cambiaStatoLed();
    tempoTrascorso = millis();
  }
}

// la funzione cambiaStatoLed() permette di controllare
// la sequenza di accensione dei LED

void cambiaStatoLed() {
  // spegne tutti i LED
  for (byte x = 0; x < 8; x++) {
    digitalWrite(ledPin[x], LOW);
  }
  // accende il LED corrente
  digitalWrite(ledPin[ledCorrente], HIGH);
  // incrementa la variabile direzione
  ledCorrente += direzione;
  // cambia la direzione se si arriva alla fine
  if (ledCorrente == 7) {
    direzione = -1;
  }
  if (ledCorrente == 0) {
    direzione = 1;
  }
}

Continua a leggere

BBC micro:bit – Esercizio: Realizzare un timer per il lavaggio delle mani

In una situazione di didattica a distanza fare laboratorio può essere complicato, ma con un po’ di fantasia e l’aiuto degli studenti si può fare molto. Alcuni mesi fa avevo proposto ai miei allievi questa stessa esercitazione però realizzata con Arduino: Arduino – Esercizio: Realizzare un timer per il lavaggio delle mani.

Ho realizzato la medesima esercitazione questa volta con BBC micro:bit in tre modalità diverse che vi condivido, nel codice trovate anche i commenti che spiegano sommariamente il codice. Ovviamente al sistema potrebbe essere aggiunto:

  • allarme sonoro
  • servomotore su cui inserire indice rotante, così come fatto per la sperimentazione con Arduino.

Spero che questa proposta possa essere utile anche ad altri.

Versione 1 (link al codice sorgente)

Versione 2 (link al codice sorgente)

Versione 3 (link al codice sorgente)

Buon making a tutti.

Didattica laboratoriale a distanza: controllare la postura con BBC micro:bit quando siamo seduti al computer


Durante il recente incontro online con il FabLab di Belluno abbiamo parlato di didattica laboratoriale a distanza realizzata con diversi dispositivi elettronici e kit di sperimentazioni che ho realizzato. Siamo entrati anche nello specifico dell’utilizzo di alcune tecnologie come BBC micro:bit ed ho mostrato alcune esercitazioni realizzabili online in didattica a distanza.

Come spesso accade mi piace realizzare con gli studenti sperimentazioni che hanno attinenza con il loro vivere quotidiano in modo da fornire un senso fisico al loro studio teorico. Lavorare continuamente per molte ore davanti al computer è un’azione che molte persone stanno vivendo e gli effetti negativi di questo continuo lavorare online si riflettono sulla nostra salute, occhi e schiena doloranti sono ormai la norma. Ovviamente ginnastica e tempi precisi di lavoro aiutano tantissimo, ma occupandomi di didattica analizzare questo aspetto può rendere la lezione online interessante.

Una semplicissima esercitazione che si può condurre a distanza è quella che consente di controllare l’esatta postura di una persona seduta alla scrivania, viene controllato se si inarca in avanti la schiena.

Per poter realizzare questo sistema si utilizza il sensore di luce del micro:bit, sensore realizzato con la matrice di LED disposti sulla scheda.

Ponendo il micro:bit sullo schienale della sedia, quando siamo seduti correttamente, copriremo con la schiena il micro:bit, non permettendo di rilevare fonti di luce, non appena ci si flette in avanti il sensore rileverà la luce e quindi verrà emesso un un segnale di allarme.

Questo stessa sperimentazione è stata realizzata anche con Arduino ed una fotoresistenza, in un prossimo post pubblicherà l’esercitazione.

Di seguito due esempi, il primo semplice, visualizza un messaggio che indica l’avvio del sistema, ed emette un segnale sonoro nel caso in cui si inarchi la schiena. Il secondo esempio aggiunge un pulsante di avvio sistema, l’impostazione della sensibilità del sistema (da realizzare manualmente) ed ed aggiunge l’utilizzo di funzioni esterne, motivo che mi aiuta a spiegare la chiamata di funzioni.

Ovviamente in questa situazione si utilizza il suono emesso dal computer, ma con alcune piccole modifiche è possibile aggiungere un buzzer esterno.

Versione 1 (link al codice sorgente)

Versione 2 (link al codice sorgente)

Buon Making a tutti 🙂