Archivi tag: C

Errori comuni nell’uso di Arduino – dimenticare il punto e virgola dopo il return

Errore:

if (contatore < 60)
    return    // manca il punto e virgola
contatore = contatore + 1;

Il codice sopra viene compilato come se fosse:

if (contatore < 60)
return contatore = contatore + 1;

Si ricorda che dopo un return incondizionato il codice che segue non verrà mai eseguito.

Ad esempio:

contatore = contatore + 1;
return contatore;
contatore = 10; // questa linea di codice non verrà mai eseguita

Esercizio (semplice semplice 🙂 ) per i miei studenti di terza:

Realizzare due sketch che accettano un input numerico intero da tastiera (sulla Serial Monitor) che dimostrano le due situazioni esposte nella spiegazione precedente.

Appunti di programmazione su Arduino: esercizi di approfondimento su istruzione switch..case, display a 7 segmenti, Serial.read

Durante le scorse settimane ho svolto una serie di esercitazioni di laboratorio che avevano l’obiettivo di insegnare l’uso dell’istruzione switch…case e la modalità di ricezione dati seriali in Arduino.

La prima lezione è introdotta nel post:

Appunti di programmazione su Arduino: controllo di flusso – istruzione switch..case

Nell’articolo trovate due link che fanno riferimento a due guide sul sito Arduino in cui viene mostrato come utilizzando l’istruzione switch…case:

  • per inviare un output specifico sulla Serial monitor in funzione del valore letto dal sensore;
  • usare la Serial input per accendere uno specifico LED.

La seconda lezione è basata sul tutorial:

Arduino – lezione 08: display a 7 segmenti e creazione di librerie

In cui viene mostrato come pilotare un display a 7 segmenti realizzando un contatore da 0 a 9, e cicli di visualizzazione di numeri pari e numeri dispari. Nella parte finale del tutorial viene mostrato come realizzare una libreria dedicata alla gestione del display a 7 segmenti.

La terza lezione mostra come ricevere dati dalla seriale in Arduino.

Per questa parte è indispensabile svolgere le esercitazioni che trovate nelle slide:

Alfabeto di Arduino – Lezione 3 da pagina 53 a pagina 62

Successivamente aggiungo gli esercizi che di seguito condivido, in cui riprendendo la gestione del display a 7 segmenti, però questa volta inviamo dati dal computer mediante la tastiera al display comandato da Arduino.

Per lo svolgimento di questa parte è necessario effettuare una piccola variazione rispetto al circuito mostrato in: Arduino – lezione 08: display a 7 segmenti e creazione di librerie in questa lezione volutamente utilizzo tra tutti i pin il piedino 1 di Arduino che viene utilizzato normalmente come pin TX e ciò provoca un comportamento anomalo di accensione del LED e del display, ciò mi permette di spiegare l’utilizzo dei pin 0 e 1 di Arduino.

Il circuito da realizzare per la terza lezione è il seguente (i pin di controllo di Arduino sono presi in maniera sequenziale dal pin 6 al pin 12)

Esercitazione 1

  • Realizzare un contasecondi da 0 a 9 utilizzando un display 7 segmenti a catodo comune

Soluzione

// Prof. Michele Maffucci
// 14.04.2019

// Conteggio 9 secondi con display 7 segmenti a catodo comune

// definizione delle variabili a cui collegare ogni segmento del display
// la lettera rappresenta il segmento del display il numero il pin
// digitale di Arduino a cui è collegato il corrispondente pin del display

const int a=12;
const int b=11;
const int c=10;
const int d=9;
const int e=8;                           
const int f=7;
const int g=6;

// variabile che definisce la velocità con cui appaiono i numeri
const int pausa = 1000;

void setup()
{
  // inizializzazione dei pin ad OUTPUT
  for (int i=6; i<13; i++) {
    pinMode(i, OUTPUT); 
  }
}

void loop ()
{
  for (int i=0;i<10;i++) 
  {
    LedAcceso(i);
    delay (pausa);
  }
}

void LedAcceso(int n)
{
  switch(n)
  {
  case 0:
    digitalWrite(a, HIGH);
    digitalWrite(b, HIGH);
    digitalWrite(c, HIGH); 
    digitalWrite(d, HIGH); 
    digitalWrite(e, HIGH);
    digitalWrite(f, HIGH);
    digitalWrite(g, LOW);
    break;

  case 1:
    digitalWrite(a, LOW);
    digitalWrite(b, HIGH);
    digitalWrite(c, HIGH); 
    digitalWrite(d, LOW); 
    digitalWrite(e, LOW);
    digitalWrite(f, LOW);
    digitalWrite(g, LOW);
    break;

  case 2:
    digitalWrite(a, HIGH);
    digitalWrite(b, HIGH);
    digitalWrite(c, LOW); 
    digitalWrite(d, HIGH); 
    digitalWrite(e, HIGH);
    digitalWrite(f, LOW);
    digitalWrite(g, HIGH);
    break;
  case 3:
    digitalWrite(a, HIGH);
    digitalWrite(b, HIGH);
    digitalWrite(c, HIGH); 
    digitalWrite(d, HIGH); 
    digitalWrite(e, LOW);
    digitalWrite(f, LOW);
    digitalWrite(g, HIGH);
    break;

  case 4:
    digitalWrite(a, LOW);
    digitalWrite(b, HIGH);
    digitalWrite(c, HIGH); 
    digitalWrite(d, LOW); 
    digitalWrite(e, LOW);
    digitalWrite(f, HIGH);
    digitalWrite(g, HIGH);
    break;

  case 5:
    digitalWrite(a, HIGH);
    digitalWrite(b, LOW);
    digitalWrite(c, HIGH); 
    digitalWrite(d, HIGH); 
    digitalWrite(e, LOW);
    digitalWrite(f, HIGH);
    digitalWrite(g, HIGH);
    break;

  case 6:
    digitalWrite(a, HIGH);
    digitalWrite(b, LOW);
    digitalWrite(c, HIGH); 
    digitalWrite(d, HIGH); 
    digitalWrite(e, HIGH);
    digitalWrite(f, HIGH);
    digitalWrite(g, HIGH);
    break;

  case 7:
    digitalWrite(a, HIGH);
    digitalWrite(b, HIGH);
    digitalWrite(c, HIGH); 
    digitalWrite(d, LOW); 
    digitalWrite(e, LOW);
    digitalWrite(f, LOW);
    digitalWrite(g, LOW);
    break;

  case 8:
    digitalWrite(a, HIGH);
    digitalWrite(b, HIGH);
    digitalWrite(c, HIGH); 
    digitalWrite(d, HIGH); 
    digitalWrite(e, HIGH);
    digitalWrite(f, HIGH);
    digitalWrite(g, HIGH);
    break;

  case 9:
    digitalWrite(a, HIGH);
    digitalWrite(b, HIGH);
    digitalWrite(c, HIGH); 
    digitalWrite(d, HIGH); 
    digitalWrite(e, LOW);
    digitalWrite(f, HIGH);
    digitalWrite(g, HIGH);
    break;
  }
}

Esercitazione 2

  • Scrittura mediante tastiera (su serial monitor) di un numero da 0 a 9.
  • La scrittura avviene quando viene premuto l’invio della tastiera.

Soluzione

// Prof. Michele Maffucci
// 14.04.2019
// Scrittura mediante tastiera (su serial monitor) di un numero da 0 a 9
// La scrittura avviene quando si preme invio.

// definizione delle variabili a cui collegare ogni segmento del display
// la lettera rappresenta il segmento del display il numero il pin
// digitale di Arduino a cui è collegato il corrispondente pin del display

const int a = 12;
const int b = 11;
const int c = 10;
const int d = 9;
const int e = 8;
const int f = 7;
const int g = 6;

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

  // inizializzazione dei pin ad OUTPUT
  for (int i = 6; i < 13; i++) {
    pinMode(i, OUTPUT);
  }
}

void loop()
{
  if (Serial.available()) {
    int selettore = Serial.read();
    LedAcceso(selettore);
  }
}

void LedAcceso(int n)
{
  switch (n)
  {
    case '0':
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, HIGH);
      digitalWrite(f, HIGH);
      digitalWrite(g, LOW);
      break;

    case '1':
      digitalWrite(a, LOW);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, LOW);
      digitalWrite(e, LOW);
      digitalWrite(f, LOW);
      digitalWrite(g, LOW);
      break;

    case '2':
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, LOW);
      digitalWrite(d, HIGH);
      digitalWrite(e, HIGH);
      digitalWrite(f, LOW);
      digitalWrite(g, HIGH);
      break;
      
    case '3':
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, LOW);
      digitalWrite(f, LOW);
      digitalWrite(g, HIGH);
      break;

    case '4':
      digitalWrite(a, LOW);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, LOW);
      digitalWrite(e, LOW);
      digitalWrite(f, HIGH);
      digitalWrite(g, HIGH);
      break;

    case '5':
      digitalWrite(a, HIGH);
      digitalWrite(b, LOW);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, LOW);
      digitalWrite(f, HIGH);
      digitalWrite(g, HIGH);
      break;

    case '6':
      digitalWrite(a, HIGH);
      digitalWrite(b, LOW);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, HIGH);
      digitalWrite(f, HIGH);
      digitalWrite(g, HIGH);
      break;

    case '7':
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, LOW);
      digitalWrite(e, LOW);
      digitalWrite(f, LOW);
      digitalWrite(g, LOW);
      break;

    case '8':
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, HIGH);
      digitalWrite(f, HIGH);
      digitalWrite(g, HIGH);
      break;

    case '9':
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, LOW);
      digitalWrite(f, HIGH);
      digitalWrite(g, HIGH);
      break;
  }
}

Esercitazione 3

  • Scrittura mediante tastiera (su serial monitor) di un numero da 0 a 9.
  • La scrittura avviene quando viene premuto l’invio della tastiera.
  • All’avvio del programma deve essere mostrato un gioco di luci con accensione e spegnimento veloce in sequenza dei led: a, b, c, d, e, f del display

Soluzione

// Prof. Michele Maffucci
// 14.04.2019
// Scrittura mediante tastiera (su serial monitor) di un numero da 0 a 9
// La scrittura avviena quando si preme invio.
// All'avvio del programma gioco di luci con accensione veloce dei led: a, b, c, d, e, f 

// definizione delle variabili a cui collegare ogni segmento del display
// la lettera rappresenta il segmento del display il numero il pin
// digitale di Arduino a cui è collegato il corrispondente pin del display

const int a = 12;
const int b = 11;
const int c = 10;
const int d = 9;
const int e = 8;
const int f = 7;
const int g = 6;

const int intervallo = 10;

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

  // inizializzazione dei pin ad OUTPUT
  for (int i = 6; i < 13; i++) {
    pinMode(i, OUTPUT);
  }
  roll();
}

void loop()
{
  if (Serial.available()) {
    int selettore = Serial.read();
    LedAcceso(selettore);
  }
}

void roll() {
  for (int i = 0; i < 6; i++) {
      digitalWrite(a, HIGH);
      delay(intervallo);
      digitalWrite(a, LOW);
      delay(intervallo);
      digitalWrite(b, HIGH);
      delay(intervallo);
      digitalWrite(b, LOW);
      delay(intervallo);      
      digitalWrite(c, HIGH);
      delay(intervallo);
      digitalWrite(c, LOW);
      delay(intervallo);      
      digitalWrite(d, HIGH);
      delay(intervallo); 
      digitalWrite(d, LOW);
      delay(intervallo);      
      digitalWrite(e, HIGH);
      delay(intervallo);
      digitalWrite(e, LOW);
      delay(intervallo);      
      digitalWrite(f, HIGH);
      delay(intervallo);
      digitalWrite(f, LOW);
      delay(intervallo);
  }
}

void LedAcceso(int n)
{
  switch (n)
  {
    case '0':
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, HIGH);
      digitalWrite(f, HIGH);
      digitalWrite(g, LOW);
      break;

    case '1':
      digitalWrite(a, LOW);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, LOW);
      digitalWrite(e, LOW);
      digitalWrite(f, LOW);
      digitalWrite(g, LOW);
      break;

    case '2':
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, LOW);
      digitalWrite(d, HIGH);
      digitalWrite(e, HIGH);
      digitalWrite(f, LOW);
      digitalWrite(g, HIGH);
      break;

    case '3':
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, LOW);
      digitalWrite(f, LOW);
      digitalWrite(g, HIGH);
      break;

    case '4':
      digitalWrite(a, LOW);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, LOW);
      digitalWrite(e, LOW);
      digitalWrite(f, HIGH);
      digitalWrite(g, HIGH);
      break;

    case '5':
      digitalWrite(a, HIGH);
      digitalWrite(b, LOW);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, LOW);
      digitalWrite(f, HIGH);
      digitalWrite(g, HIGH);
      break;

    case '6':
      digitalWrite(a, HIGH);
      digitalWrite(b, LOW);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, HIGH);
      digitalWrite(f, HIGH);
      digitalWrite(g, HIGH);
      break;

    case '7':
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, LOW);
      digitalWrite(e, LOW);
      digitalWrite(f, LOW);
      digitalWrite(g, LOW);
      break;

    case '8':
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, HIGH);
      digitalWrite(f, HIGH);
      digitalWrite(g, HIGH);
      break;

    case '9':
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, LOW);
      digitalWrite(f, HIGH);
      digitalWrite(g, HIGH);
      break;
  }
}

Esercitazione 4

  • Scrittura mediante tastiera (su serial monitor) di un numero da 0 a 9.
  • La scrittura avviene quando viene premuto l’invio della tastiera.
  • All’avvio del programma deve essere mostrato un gioco di luci con accensione e spegnimento veloce in sequenza dei led: a, b, c, d, e, f del display
  • Alla pressione di un tasto diverso dai numeri da 0 a 9, gioco di luci e spegnimento del display.

Soluzione

// Prof. Michele Maffucci
// 14.04.2019
// Scrittura mediante tastiera (su serial monitor) di un numero da 0 a 9
// La scrittura avviena quando si preme invio.
// All'avvio del programma gioco di luci con accensione veloce dei led: a, b, c, d, e, f
// Alla pressione di un tasto diverso dai numeri da 0 a 9, gioco di luci e spegnimento del display.

// definizione delle variabili a cui collegare ogni segmento del display
// la lettera rappresenta il segmento del display il numero il pin
// digitale di Arduino a cui è collegato il corrispondente pin del display

const int a = 12;
const int b = 11;
const int c = 10;
const int d = 9;
const int e = 8;
const int f = 7;
const int g = 6;

const int intervallo = 10;

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

  // inizializzazione dei pin ad OUTPUT
  for (int i = 6; i < 13; i++) {
    pinMode(i, OUTPUT);
  }
  roll();
}

void loop()
{
  if (Serial.available()) {
    int selettore = Serial.read();
    LedAcceso(selettore);
  }
}

void roll() {
  for (int i = 0; i < 6; i++) {
      digitalWrite(a, HIGH);
      delay(intervallo);
      digitalWrite(a, LOW);
      delay(intervallo);
      digitalWrite(b, HIGH);
      delay(intervallo);
      digitalWrite(b, LOW);
      delay(intervallo);      
      digitalWrite(c, HIGH);
      delay(intervallo);
      digitalWrite(c, LOW);
      delay(intervallo);      
      digitalWrite(d, HIGH);
      delay(intervallo); 
      digitalWrite(d, LOW);
      delay(intervallo);      
      digitalWrite(e, HIGH);
      delay(intervallo);
      digitalWrite(e, LOW);
      delay(intervallo);      
      digitalWrite(f, HIGH);
      delay(intervallo);
      digitalWrite(f, LOW);
      delay(intervallo);
  }
}

void LedAcceso(int n)
{
  switch (n)
  {
    case '0':
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, HIGH);
      digitalWrite(f, HIGH);
      digitalWrite(g, LOW);
      break;

    case '1':
      digitalWrite(a, LOW);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, LOW);
      digitalWrite(e, LOW);
      digitalWrite(f, LOW);
      digitalWrite(g, LOW);
      break;

    case '2':
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, LOW);
      digitalWrite(d, HIGH);
      digitalWrite(e, HIGH);
      digitalWrite(f, LOW);
      digitalWrite(g, HIGH);
      break;

    case '3':
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, LOW);
      digitalWrite(f, LOW);
      digitalWrite(g, HIGH);
      break;

    case '4':
      digitalWrite(a, LOW);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, LOW);
      digitalWrite(e, LOW);
      digitalWrite(f, HIGH);
      digitalWrite(g, HIGH);
      break;

    case '5':
      digitalWrite(a, HIGH);
      digitalWrite(b, LOW);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, LOW);
      digitalWrite(f, HIGH);
      digitalWrite(g, HIGH);
      break;

    case '6':
      digitalWrite(a, HIGH);
      digitalWrite(b, LOW);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, HIGH);
      digitalWrite(f, HIGH);
      digitalWrite(g, HIGH);
      break;

    case '7':
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, LOW);
      digitalWrite(e, LOW);
      digitalWrite(f, LOW);
      digitalWrite(g, LOW);
      break;

    case '8':
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, HIGH);
      digitalWrite(f, HIGH);
      digitalWrite(g, HIGH);
      break;

    case '9':
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, LOW);
      digitalWrite(f, HIGH);
      digitalWrite(g, HIGH);
      break;

    default:
      digitalWrite(a, LOW);
      digitalWrite(b, LOW);
      digitalWrite(c, LOW);
      digitalWrite(d, LOW);
      digitalWrite(e, LOW);
      digitalWrite(f, LOW);
      digitalWrite(g, LOW);
      roll();
  }
}

Esercitazione 5

  • Scrittura mediante tastiera (su serial monitor) di un numero da 0 a 9.
  • La scrittura avviene quando viene premuto l’invio della tastiera.
  • All’avvio del programma deve essere mostrato un gioco di luci con accensione e spegnimento veloce in sequenza dei led: a, b, c, d, e, f del display.
  • Alla pressione di un tasto diverso dai numeri da 0 a 9, gioco di luci e spegnimento del display.
  • Alla pressione di un numero da 0 a 9 prima della comparsa del numero mostrare gioco di luci.

Soluzione

// Prof. Michele Maffucci
// 14.04.2019
// Scrittura mediante tastiera (su serial monitor) di un numero da 0 a 9
// La scrittura avviena quando si preme invio.
// All'avvio del programma gioco di luci con accensione veloce dei led: a, b, c, d, e, f
// Alla pressione di un tasto diverso dai numeri da 0 a 9, gioco di luci e spegnimento del display.
// Alla pressione di un numero da 0 a 9 prima della comparsa del numero mostrare gioco di luci.

// definizione delle variabili a cui collegare ogni segmento del display
// la lettera rappresenta il segmento del display il numero il pin
// digitale di Arduino a cui è collegato il corrispondente pin del display

const int a = 12;
const int b = 11;
const int c = 10;
const int d = 9;
const int e = 8;
const int f = 7;
const int g = 6;

const int intervallo = 10;

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

  // inizializzazione dei pin ad OUTPUT
  for (int i = 6; i < 13; i++) {
    pinMode(i, OUTPUT);
  }
  roll();
}


void loop()
{
  if (Serial.available()) {
    int selettore = Serial.read();
    LedAcceso(selettore);
  }
}

void roll() {
  // spegnimento di tutti i led del display
  digitalWrite(a, LOW);
  digitalWrite(b, LOW);
  digitalWrite(c, LOW);
  digitalWrite(d, LOW);
  digitalWrite(e, LOW);
  digitalWrite(f, LOW);
  digitalWrite(g, LOW);

  // ciclo di sei accensioni e spegnimenti dei led a, b, c, d, e, f
  for (int i = 0; i < 6; i++) {
    digitalWrite(a, HIGH);
    delay(intervallo);
    digitalWrite(a, LOW);
    delay(intervallo);
    digitalWrite(b, HIGH);
    delay(intervallo);
    digitalWrite(b, LOW);
    delay(intervallo);
    digitalWrite(c, HIGH);
    delay(intervallo);
    digitalWrite(c, LOW);
    delay(intervallo);
    digitalWrite(d, HIGH);
    delay(intervallo);
    digitalWrite(d, LOW);
    delay(intervallo);
    digitalWrite(e, HIGH);
    delay(intervallo);
    digitalWrite(e, LOW);
    delay(intervallo);
    digitalWrite(f, HIGH);
    delay(intervallo);
    digitalWrite(f, LOW);
    delay(intervallo);
  }
}

void LedAcceso(int n)
{
  switch (n)
  {
    case '0':
      roll();
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, HIGH);
      digitalWrite(f, HIGH);
      digitalWrite(g, LOW);
      break;

    case '1':
      roll();
      digitalWrite(a, LOW);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, LOW);
      digitalWrite(e, LOW);
      digitalWrite(f, LOW);
      digitalWrite(g, LOW);
      break;

    case '2':
      roll();
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, LOW);
      digitalWrite(d, HIGH);
      digitalWrite(e, HIGH);
      digitalWrite(f, LOW);
      digitalWrite(g, HIGH);
      break;

    case '3':
      roll();
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, LOW);
      digitalWrite(f, LOW);
      digitalWrite(g, HIGH);
      break;

    case '4':
      roll();
      digitalWrite(a, LOW);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, LOW);
      digitalWrite(e, LOW);
      digitalWrite(f, HIGH);
      digitalWrite(g, HIGH);
      break;

    case '5':
      roll();
      digitalWrite(a, HIGH);
      digitalWrite(b, LOW);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, LOW);
      digitalWrite(f, HIGH);
      digitalWrite(g, HIGH);
      break;

    case '6':
      roll();
      digitalWrite(a, HIGH);
      digitalWrite(b, LOW);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, HIGH);
      digitalWrite(f, HIGH);
      digitalWrite(g, HIGH);
      break;

    case '7':
      roll();
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, LOW);
      digitalWrite(e, LOW);
      digitalWrite(f, LOW);
      digitalWrite(g, LOW);
      break;

    case '8':
      roll();
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, HIGH);
      digitalWrite(f, HIGH);
      digitalWrite(g, HIGH);
      break;

    case '9':
      roll();
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, LOW);
      digitalWrite(f, HIGH);
      digitalWrite(g, HIGH);
      break;

    default:
      roll();
  }
}

Esercitazione 6

Realizzare le stesse funzionalità dell’esercizio 5 ma ottimizzare la funzione roll() in modo che lo spegnimento iniziale dei LED sia costituito da un ciclo for e l’accensione e lo spegnimento sequenziale sia realizzato da due cicli for annidati.

Soluzione

// Prof. Michele Maffucci
// 14.04.2019
// Scrittura mediante tastiera (su serial monitor) di un numero da 0 a 9
// La scrittura avviena quando si preme invio.
// All'avvio del programma gioco di luci con accensione veloce dei led: a, b, c, d, e, f
// Alla pressione di un tasto diverso dai numeri da 0 a 9, gioco di luci e spegnimento del display.
// Alla pressione di un numero da 0 a 9 prima della comparsa del numero mostrare gioco di luci

// Versione in cui la funzione roll() è stata ottimizzata
// Lo spegnimento iniziale dei LED è costituito da un ciclo for e l'accensione e lo spegnimento sequenziale
// è realizzato da due cicli for annidati.

// definizione delle variabili a cui collegare ogni segmento del display
// la lettera rappresenta il segmento del display il numero il pin
// digitale di Arduino a cui è collegato il corrispondente pin del display

const int a = 12;
const int b = 11;
const int c = 10;
const int d = 9;
const int e = 8;
const int f = 7;
const int g = 6;

const int intervallo = 10;

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

  // inizializzazione dei pin ad OUTPUT
  for (int i = 6; i < 13; i++) {
    pinMode(i, OUTPUT);
  }
  roll();
}


void loop()
{
  if (Serial.available()) {
    int selettore = Serial.read();
    LedAcceso(selettore);
  }
}

// funzione per gioco di luci
void roll() {

  // spegnimento di tutti i led del display
  for (int i = 6; i < 13; i++) {
    digitalWrite(i, LOW);
  }

  // ciclo di sei accensioni e spegnimenti dei led a, b, c, d, e, f
  for (int m = 0; m < 6; m++) {
    for (int p = 12; p > 6; p--) {
      digitalWrite(p, HIGH);
      delay(intervallo);
      digitalWrite(p, LOW);
      delay(intervallo);
    }
  }
}

// la funzione LedAcceso prende come input il carattere numerico che deve essere mostrato su display
// prima che venga stampato il numero viene eseguita la funzione roll()
void LedAcceso(int n)
{
  switch (n)
  {
    case '0':
      roll();
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, HIGH);
      digitalWrite(f, HIGH);
      digitalWrite(g, LOW);
      break;

    case '1':
      roll();
      digitalWrite(a, LOW);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, LOW);
      digitalWrite(e, LOW);
      digitalWrite(f, LOW);
      digitalWrite(g, LOW);
      break;

    case '2':
      roll();
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, LOW);
      digitalWrite(d, HIGH);
      digitalWrite(e, HIGH);
      digitalWrite(f, LOW);
      digitalWrite(g, HIGH);
      break;

    case '3':
      roll();
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, LOW);
      digitalWrite(f, LOW);
      digitalWrite(g, HIGH);
      break;

    case '4':
      roll();
      digitalWrite(a, LOW);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, LOW);
      digitalWrite(e, LOW);
      digitalWrite(f, HIGH);
      digitalWrite(g, HIGH);
      break;

    case '5':
      roll();
      digitalWrite(a, HIGH);
      digitalWrite(b, LOW);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, LOW);
      digitalWrite(f, HIGH);
      digitalWrite(g, HIGH);
      break;

    case '6':
      roll();
      digitalWrite(a, HIGH);
      digitalWrite(b, LOW);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, HIGH);
      digitalWrite(f, HIGH);
      digitalWrite(g, HIGH);
      break;

    case '7':
      roll();
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, LOW);
      digitalWrite(e, LOW);
      digitalWrite(f, LOW);
      digitalWrite(g, LOW);
      break;

    case '8':
      roll();
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, HIGH);
      digitalWrite(f, HIGH);
      digitalWrite(g, HIGH);
      break;

    case '9':
      roll();
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, LOW);
      digitalWrite(f, HIGH);
      digitalWrite(g, HIGH);
      break;

    default:
      roll();
  }
}

Esercitazione 7

Realizzare le stesse funzionalità dell’esercizio 6 realizzando una libreria di gestione “LedAcceso.h” richiamata dallo sketch principale. Per l’esecuzione di questo esercizio seguire le indicazioni fornite al fondo del tutorial: Arduino – lezione 08: display a 7 segmenti e creazione di librerie

Soluzione

LedAcceso.cpp

/* display_sette_segmenti.cpp
libreria che consente il controllo di un display a 7 segmenti a catodo comune
del tipo HDSP 5503
*/

#include "Arduino.h"

const int a = 12;
const int b = 11;
const int c = 10;
const int d = 9;
const int e = 8;
const int f = 7;
const int g = 6;

const int intervallo = 10;

// funzione per gioco di luci
void roll() {

  // spegnimento di tutti i led del display
  for (int i = 6; i < 13; i++) {
    digitalWrite(i, LOW);
  }

  // ciclo di sei accensioni e spegnimenti dei led a, b, c, d, e, f
  for (int i = 0; i < 6; i++) {
    for (int j = 12; j > 6; j--) {
      digitalWrite(j, HIGH);
      delay(intervallo);
      digitalWrite(j, LOW);
      delay(intervallo);
    }
  }
}

// la funzione LedAcceso prende come input il carattere numerico che deve essere mostrato su display
// prima che venga stampato il numero viene eseguita la funzione roll()
void LedAcceso(int n)
{
  switch (n)
  {
    case '0':
      roll();
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, HIGH);
      digitalWrite(f, HIGH);
      digitalWrite(g, LOW);
      break;

    case '1':
      roll();
      digitalWrite(a, LOW);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, LOW);
      digitalWrite(e, LOW);
      digitalWrite(f, LOW);
      digitalWrite(g, LOW);
      break;

    case '2':
      roll();
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, LOW);
      digitalWrite(d, HIGH);
      digitalWrite(e, HIGH);
      digitalWrite(f, LOW);
      digitalWrite(g, HIGH);
      break;

    case '3':
      roll();
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, LOW);
      digitalWrite(f, LOW);
      digitalWrite(g, HIGH);
      break;

    case '4':
      roll();
      digitalWrite(a, LOW);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, LOW);
      digitalWrite(e, LOW);
      digitalWrite(f, HIGH);
      digitalWrite(g, HIGH);
      break;

    case '5':
      roll();
      digitalWrite(a, HIGH);
      digitalWrite(b, LOW);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, LOW);
      digitalWrite(f, HIGH);
      digitalWrite(g, HIGH);
      break;

    case '6':
      roll();
      digitalWrite(a, HIGH);
      digitalWrite(b, LOW);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, HIGH);
      digitalWrite(f, HIGH);
      digitalWrite(g, HIGH);
      break;

    case '7':
      roll();
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, LOW);
      digitalWrite(e, LOW);
      digitalWrite(f, LOW);
      digitalWrite(g, LOW);
      break;

    case '8':
      roll();
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, HIGH);
      digitalWrite(f, HIGH);
      digitalWrite(g, HIGH);
      break;

    case '9':
      roll();
      digitalWrite(a, HIGH);
      digitalWrite(b, HIGH);
      digitalWrite(c, HIGH);
      digitalWrite(d, HIGH);
      digitalWrite(e, LOW);
      digitalWrite(f, HIGH);
      digitalWrite(g, HIGH);
      break;

    default:
      roll();
  }
}

LedAcceso.h

/* LedAcceso.h
   header file della libreria LedAcceso
*/
 
#include "Arduino.h"
 
void LedAcceso(int n);  // prototipo della funzione
void roll();            // prototipo della funzione

sketch

// Prof. Michele Maffucci
// 14.04.2019
// Scrittura mediante tastiera (su serial monitor) di un numero da 0 a 9
// La scrittura avviena quando si preme invio.
// All'avvio del programma gioco di luci con accensione veloce dei led: a, b, c, d, e, f
// Alla pressione di un tasto diverso dai numeri da 0 a 9, gioco di luci e spegnimento del display.
// Alla pressione di un numero da 0 a 9 prima della comparsa del numero mostrare gioco di luci

// Versione con inclusione della libreria di gestione dell'accensione del display

// definizione delle variabili a cui collegare ogni segmento del display
// la lettera rappresenta il segmento del display il numero il pin
// digitale di Arduino a cui è collegato il corrispondente pin del display

#include "LedAcceso.h"

const int a = 12;
const int b = 11;
const int c = 10;
const int d = 9;
const int e = 8;
const int f = 7;
const int g = 6;

const int intervallo = 10;

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

  // inizializzazione dei pin ad OUTPUT
  for (int i = 6; i < 13; i++) {
    pinMode(i, OUTPUT);
  }
  roll();
}

void loop()
{
  // verifica se sulla serial monitor è presente un carattere,
  // se la condizione è vera viene letto il carattere presente sulla serial monitor
  if (Serial.available()) {
    int selettore = Serial.read();
    LedAcceso(selettore);
  }
}

Buon Coding a tutti 🙂

Errori comuni nell’uso di Arduino – utilizzo scorretto dei tipi float e integer

Continuo la segnalazione degli errori più comuni che riscontro nella correzione delle esercitazioni su Arduino che svolgo con i miei allievi.

Capita molto spesso per errore di effettuare calcoli in cui i valori appartengono a tipi diversi, ad esempio quando dividiamo un numero di tipo float ed un numero di tipo int. L’operazione è permessa dal compilatore in quanto l’operazione può essere sfruttata dal programmatore, ma se non si conosce come funzionano le conversioni di tipo in C si rischia di commettere errori.

L’operazione di conversione di tipo è conosciuta anche come typecasting e converte una variabile da un tipo di dato a un altro e può avvenire nelle due direzioni, ad esempio da float ad int o da int a float

Ricordo che:

Il tipo di dato int viene usato per gestire numeri interi, quindi senza decimali e memorizzano valori a 16 bit (2 byte) nel range da 32.767 a -32.768

Il tipo di dato float è usato per i numeri in virgola mobile per la rappresentazione di numeri piccolissimi o grandissimi con o senza segno e con o senza decimali. I float sono memorizzati utilizzando 32 bit (4 byte) nel range tra 3,4028235E+38 a -3,4028235E+38.

int pippo = 4;
float pluto = 10 / pippo; // verificate se questa operazione è corretta
Serial.println(pluto);

Cosa vi aspettate venga visualizzato sulla Serial Monitor?
Dovreste verificare che la divisione restituisce il valore 2, anche se l’operazione dovrebbe restituire il valore 2,5.

Il compilatore vi mostrerà solamente il valore intero.
Per evitare questo problema potete agire in due modi.

Modo 1

Possiamo convertire gli interi in float, in modo che il compilatore sappia trattarli come float anziché interi:

int pippo = 4;
float pluto = (float)10 / (float)pippo;
Serial.println(pluto);

Modo 2

Potete aggiungere un decimale al valore di tipo float, nel caso del valore 10 il valore decimale che possiamo aggiungere è 0, quindi scriveremo il numero come 10.0

int pippo = 4;
float pluto = 10.0 / pippo; // verificate se questa operazione è corretta
Serial.println(pluto);

Qual è il metodo migliore? Dipende, probabilmente il secondo metodo risulta più chiaro e snello nella scrittura, ma siete liberi di scegliere quello che preferite.

Buona Sperimentazione 🙂

Arduino – algebra booleana e funzioni logiche – dai componenti discreti, agli integrati, alla codifica in C

Nuovo Istituto, nuove avventure didattiche. Con le classi di questo nuovo anno scolastico più elettronica e più automazione. Tra gli argomenti che ho rivisto negli scorsi mesi in virtù delle attività che vorrò svolgere, molte sperimentazioni dedicata all’elettronica digitale e all’algebra di Boole, ho riformulato le esercitazioni con componenti discreti che utilizzano i classici integrati TTL 74XX: 7404, 7432, 7408, 7402, 7400, 7486, 74266 corrispondenti alle porte logiche: NOT, OR, AND, NOR, NAND, XOR, XNOR a queste attività aggiungerò, in una fase successiva, la realizzazione delle porte logiche con Arduino, quindi progettazione di semplici shield per la dimostrazione delle tabelle di verità degli operatori logici fondamentali e derivati.

Per rendere più interessante il laboratorio di elettronica, oltre che usare la breadboard, realizzare pcb e saldare, cercherò se il tempo lo permetterà, di far realizzare la scheda Arduino prima su breadboard e poi realizzare una nostra personalissima scheda Arduino con protezioni specifiche sulle uscite digitali ed altro… sogni nel cassetto… vedremo, un passettino alla volta.

Questo articolo è da intendersi come esercitazione e di supporto alla parte teorica ed è dedicata agli studenti delle classi 3′ e 4′ automazione, per lo svolgimento si richiede che gli allievi abbiano seguito un corso base su Arduino. Di seguito senza dilungarmi riprendo alcuni concetti di base che hanno solo l’obiettivo di comprendere meglio la parte sviluppata su Arduino, al fondo due circuiti e due sketch di esempio che potrete migliorare ed espandere.

Avviso per gli studenti

Quest’anno faremo automazione, non solo con PLC ma anche con microcontrollori (Arduino), quindi incominciare a strutturare in C le funzioni logiche sarà essenziale per iniziare a costruire i mattoncini di base dell’automazione, vedremo come costruire altre funzioni nel corso dell’anno.

Premessa (per ripassare velocemente)

I circuiti digitali sono presenti in moltissimi strumenti che utilizzimo ogni giorno, i più noti sono i computer costituiti principalmente da circuiti digitali che, come già sapete, elaborano segnali logici 0 e 1.

Qualsiasi calcolo all’interno di un computer utilizza l’aritmetica binaria e l’adozione di questa aritmetica è stata fatta perché i bit sono rappresentabili in modo semplice tramite dispositivi elettronici in cui è possibile distinguere i 2 stati del potenziale elettrico: high e low a cui si associano i numeri 1 e 0.

Partendo da questi presupposti è possibile costruire un sistema di calcolo che impiega i soli due simboli 0 e 1 che viene chiamato sistema logico binario.

Fu George Boole (1815-1864) che per primo costruì un modello matematico fondato su una logica di tipo binario, tale modello prende il nome di: algebra di Boole.

Come diffusamente esposto durante le lezioni di teoria, l’algebra booleana utilizza equazioni ed espressioni, ma segue le leggi della logica e non quelle dell’aritmetica, per cui le operazioni seguono regole differenti dall’algebra convenzionale.

Le porte logiche realizzano le operazioni logiche dell’algebra binaria.

Porte logiche fondamentali

Somma logica OR

L’operazione può essere effettuata su due o più variabili di ingresso. La somma logica OR assumerà il valore 1 se almeno una delle variabili di ingresso è al valore 1.

Se chiamiamo con A e B le variabili di ingresso e con Y la variabile di uscita, la somma logica assumerà lo stato logico 1 se almeno una delle due variabili assume lo stato logico 1.


si legge A OR B

Nella figura che segue è mostrata la tabella della verità con le quattro possibili combinazioni delle variabili di ingresso A e B è il simbolo logico corrispondente. Nella colonna Y sono indicati i valori dalla variabile di uscita Y che soddisfa la definizione della porta logica OR.

Prodotto logico AND

L’operazione può essere effettuata su due o più variabili di ingresso. Il prodotto logico AND assumerà il valore 1 se tutte le variabili di ingresso assumeranno il valore 1.

Se chiamiamo con A e B le variabili di ingresso e con Y la variabile di uscita, il prodotto logico assumerà lo stato logico 1 solo se tutte le variabili di ingresso sono allo stato 1.

si legge A AND B

Nella figura che segue è mostrata la tabella della verità con le quattro possibili combinazioni delle variabili di ingresso A e B è il simbolo logico corrispondente. Nella colonna Y sono indicati i valori dalla variabile di uscita Y che soddisfa la definizione della porta logica AND.

Negazione NOT

L’operazione può essere effettuata su una sola variabile di ingresso. Se chiamiamo con A la variabile di ingresso e con Y la variabile di uscita, la negazione farà assumere all’uscita il valore opposto a quello applicato all’ingresso.

si legge A NEGATO oppure A COMPLEMENTATO oppure NOT A

Nella figura che segue è mostrata la tabella della verità con le due possibili combinazioni
di A ed il simbolo logico corrispondente. Nella colonna Y è indicato il valore della variabile di uscita Y che soddisfa la definizione della porta logica NOT.

Porte logiche derivate

Sono le porte logiche ottenute partendo da una o più porte logiche fondamentali però poiché sono estremamente importanti per l’elettronica sono rappresentate con un simbolo unico.

Somma logica negata NOR

L’operazione può essere effettuata su due o più variabili di ingresso. Se chiamiamo con A e B le variabili di ingresso e con Y la variabile di uscita, la somma logica negata assumerà lo stato logico 1 solo se tutte le variabili di ingresso sono allo stato 1, in tutti gli altri casi l’uscita assumerà il valore 1.

La somma logica negata corrrisponde al collegamento di una OR seguita da una porta NOT.

si legge A NOR B

Nella figura che segue è mostrata la tabella della verità con le quattro possibili combinazioni delle variabili di ingresso A e B è il simbolo logico corrispondente. Nella colonna Y sono indicati i valori dalla variabile di uscita Y che soddisfa la definizione della porta logica NOR.

Prodotto logico negato NAND

L’operazione può essere effettuata su due o più variabili di ingresso. Il prodotto logico negato NAND assumerà il valore 1 se tutte le variabili di ingresso assumeranno il valore 0, in tutti gli altri casi l’uscita assumerà il valore 1.

Il prodotto logico negato corrrisponde al collegamento di una AND seguita da una porta NOT.

si legge A NAND B

Nella figura che segue è mostrata la tabella della verità con le quattro possibili combinazioni delle variabili di ingresso A e B è il simbolo logico corrispondente. Nella colonna Y sono indicati i valori dalla variabile di uscita Y che soddisfa la definizione della porta logica NAND.

OR esclusivo – XOR

L’operazione può essere effettuata su due o più variabili di ingresso. l’OR esclusivo assumerà il valore 1 e solo se vi è almeno un ingresso che differisce dagli altri, mentre varrà 0 se tutti gli ingressi assumono lo stesso valore.

Nel caso di due variabili di ingresso A e B, l’OR esclusivo assumerà il valore 1 se gli ingressi assumeranno valori diversi e varrà 0 se gli ingressi assumono lo stesso valore.

si legge A OR ESCLUSIVO B oppure A DIVERSO B

Nella seguente figura si mostra la tabella della verità con le quattro possibili combinazioni tra A e B ed il simbolo logico relativo ad una porta XOR. Nella colonna Y si sono posti i valori assunti dall’uscita Y che soddisfa la definizione della porta XOR.

L’OR ESCLUSIVO può essere espresso anche dalla seguente formula:

formula da ricordare quando dovrete implementare il codice C per Arduino che realizza questa funzione.

NOR esclusivo XNOR

L’operazione può essere effettuata su due o più variabili di ingresso. Il NOR esclusivo assumerà il valore 1 se e solo se tutti gli ingressi hanno il medesimo valore logico, è equivalente alla negazione della porta XOR.

Nel caso di due variabili di ingresso A e B, l’XNOR assumerà il valore 1 se gli ingressi assumeranno valori uguali e varrà 0 se gli ingressi assumono valore diverso.

e si legge A NOR ESCLUSIVO B oppure A COINCIDENTE CON B.

Nella seguente figura si mostra la tabella della verità con le quattro possibili combinazioni tra A e B ed il simbolo logico relativo ad una porta XNOR. Nella colonna Y si sono posti i valori assunti dall’uscita Y che soddisfa la definizione della porta XNOR.

Il NOR ESCLUSIVO può essere espresso anche dalla seguente formula:

formula da ricordare quando dovrete implementare il codice C per Arduino che realizza questa funzione.

Porte logiche con Arduino

Partiamo ora con la realizzazione delle porte logiche descritte sompra utilizzando Arduino.

In un precedente post ho descritto quali sono gli operatori logici disponibili all’interno di Arduino

Se gli ingressi A e B li indichiamo con le varibili:

  • pinInA
  • pinInB

e l’uscita Y la indichiamo con

  • pinOutY

usando la notazione in C che ritrovate nel link indicato sopra si otterrà:

OR

Y = A || B

AND

Y = A && B

NOT

Y = !A

NOR

Y = !(A || B)

NAND

Y = !(A && B)

XOR

Y = A ⊕ B = (A && !B) || (!A && B)

XNOR

Y = !(A ⊕ B) = !((A && !B) || (!A && B))

Premesso ciò la scrittura dello sketch è estremamente semplice.

Realizziamo i due ingressi A e B mediante due pulsanti connessi rispettivamente ai pin 8 e 7, mentre l’uscita sarà connessa al pin 9.

/* Michele Maffucci
   08.09.18

   Versione 1 - sostituzione del codice per verificare
   la tabella di verità degli operatori logici
*/

int pinOutY = 9;
int pinInA = 8;
int pinInB = 7;

void setup()
{
  pinMode(pinOutY, OUTPUT); 
  pinMode(pinInA, INPUT);
  pinMode(pinInB, INPUT);
}
void loop()
{
  boolean statoInA = digitalRead(pinInA);
  boolean statoInB = digitalRead(pinInB);
  boolean statoOut;

  // --- sostituire l'operatore logico indicata nel commento in fondo --- 

  // funzione logica OR
  statoOut = statoInA || statoInB;
  digitalWrite(pinOutY, statoOut);
}

/*
Sostituisci all'interno del loop nella posizione indicata

  // operatore logico OR
  statoOut = statoInA || statoInB;
  
  // operatore logico AND
  statoOut = statoInA && statoInB;

  // operatore logico NOT
  statoOut = !statoInA;
  
  // operatore logico NOR
  statoOut = !(statoInA || statoInB);

  // operatore logico NAND
  statoOut = !(statoInA && statoInB);

  // operatore logico XOR
  statoOut = (statoInA && !statoInB) || (!statoInA && statoInB);
  
  // operatore logico XNOR
  statoOut = !((statoInA && !statoInB) || (!statoInA && statoInB));
*/

Vediamo ora come realizzare uno sketch che permette dalla Serial Monitor di selezionare mediante menù il tipo di porta logica che si intende simulare; quando la selezione viene effettuata da menù la pressione dei pulsanti deve realizzare la tabella di verità della funzione logica selezionata.

Un pulsante aggiuntivo, che chiameremo: “AVVIA MENU'” verrà utilizzato per riavviare il menù di scelta.

Le azioni quindi saranno:

  1. primo avvio – selezione funzione (da 1 a 7) inserendo da tastiera il numero sulla Serial Monitor
  2. verifica della tabella di verità premendo i pulsanti A e B controllando che il LED, che identifica la Y, sarà acceso per un livello logico 1 e sarà spento per un livello logico 0
  3. Cambio funzione logica:
    1. premere il pulsante: “AVVIA MENU'”
    2. seleziono la funzione logica da verificare e ripetere nuovamente dal passo 1

/* Michele Maffucci
   08.09.18

   Versione 2 - scelta dell'operatore logico da menù stampato sulla Serial Monitor.

 All'avvio compare un menù di selezione dell'operatore logico
  1: OR
  2: AND
  3: NOT
  4: NOR
  5: NAND
  6: XOR
  7: XNOR

  Scrivere sulla Serial Monitor il numero corrispondente e con
  i pulsanti A e B verificare la tabella di verità

  La selezione di un altro operatore avviene premendo il pulsante: AVVIA MENU
  che mostrerà nuovamente sulla Serial Monitor il menù di selezione operatore
*/

int pinOutY = 9;
int pinInA = 8;
int pinInB = 7;

int pinChiave = 10;

boolean statoInA;
boolean statoInB;
boolean statoOut;

// array da utilizzare come chiave di stampa
// per le tabelle di verità delle singole funzioni logiche

int chiavi[] = {1, 1, 1, 1, 1, 1, 1};

void setup()
{
  Serial.begin(9600);
  pinMode(pinOutY, OUTPUT);
  pinMode(pinInA, INPUT);
  pinMode(pinInB, INPUT);

  pinMode(pinInB, INPUT);

  // funzione per la stampa sulla Serial Monitor
  // del menù di scelta dell'operatore logico
  stampaMenu();
}

void stampaMenu() {
  Serial.println("---- Seleziona l'operatore logico ----");
  Serial.println("1: OR");
  Serial.println("2: AND");
  Serial.println("3: NOT");
  Serial.println("4: NOR");
  Serial.println("5: NAND");
  Serial.println("6: XOR");
  Serial.println("7: XNOR");
  Serial.println("--------------------------------------");
  Serial.println("");
  Serial.println("");
}

// La funzione di stampa tabella di verità pone a 0 il valore della
// chiave, chiavi[n] = 0, dove n identifica la tabella di verità
// e il valore associato, 1 o 0, indica il fatto di poterla stampare oppure no.
// chiavi[n] = 0 permette di non stampare ciclicamente una stessa tabella
// di verità all'interno dei singoli cicli while presenti nel loop in cui avviene
// il controllo di quale selezione è stata fatta.

void stampaOr() {
  Serial.println("Hai selezionato l'operatore OR");
  Serial.println("La tabella di verità è:");
  Serial.println(" A  |  B  |  Y  ");
  Serial.println("----|-----|-----");
  Serial.println(" 0  |  0  |  0  ");
  Serial.println(" 0  |  1  |  1  ");
  Serial.println(" 1  |  0  |  1  ");
  Serial.println(" 1  |  1  |  1  ");
  Serial.println("");
  Serial.println("----------------------------------------------------------------");
  Serial.println("Per selezionare un altro operatore premi il pulsante AVVIA MENU'");
  Serial.println("----------------------------------------------------------------");
  Serial.println("");

  mettiUnoChiavi();
  chiavi[0] = 0;
}

void stampaAnd() {
  Serial.println("Hai selezionato l'operatore AND");
  Serial.println("La tabella di verità è:");
  Serial.println(" A  |  B  |  Y  ");
  Serial.println("----|-----|-----");
  Serial.println(" 0  |  0  |  0  ");
  Serial.println(" 0  |  1  |  0  ");
  Serial.println(" 1  |  0  |  0  ");
  Serial.println(" 1  |  1  |  1  ");
  Serial.println("");
  Serial.println("----------------------------------------------------------------");
  Serial.println("Per selezionare un altro operatore premi il pulsante AVVIA MENU'");
  Serial.println("----------------------------------------------------------------");
  Serial.println("");

  mettiUnoChiavi();
  chiavi[1] = 0;
}

void stampaNot() {
  Serial.println("Hai selezionato l'operatore NOT");
  Serial.println("La tabella di verità è:");
  Serial.println(" A  |  Y  ");
  Serial.println("----|-----");
  Serial.println(" 0  |  1  ");
  Serial.println(" 1  |  0  ");
  Serial.println("");
  Serial.println("----------------------------------------------------------------");
  Serial.println("Per selezionare un altro operatore premi il pulsante AVVIA MENU'");
  Serial.println("----------------------------------------------------------------");
  Serial.println("");

  mettiUnoChiavi();
  chiavi[2] = 0;
}

void stampaNor() {
  Serial.println("Hai selezionato l'operatore NOR");
  Serial.println("La tabella di verità è:");
  Serial.println(" A  |  B  |  Y  ");
  Serial.println("----|-----|-----");
  Serial.println(" 0  |  0  |  1  ");
  Serial.println(" 0  |  1  |  0  ");
  Serial.println(" 1  |  0  |  0  ");
  Serial.println(" 1  |  1  |  0  ");
  Serial.println("");
  Serial.println("----------------------------------------------------------------");
  Serial.println("Per selezionare un altro operatore premi il pulsante AVVIA MENU'");
  Serial.println("----------------------------------------------------------------");
  Serial.println("");

  mettiUnoChiavi();
  chiavi[3] = 0;
}

void stampaNand() {
  Serial.println("Hai selezionato l'operatore NAND");
  Serial.println("La tabella di verità è:");
  Serial.println(" A  |  B  |  Y  ");
  Serial.println("----|-----|-----");
  Serial.println(" 0  |  0  |  1  ");
  Serial.println(" 0  |  1  |  1  ");
  Serial.println(" 1  |  0  |  1  ");
  Serial.println(" 1  |  1  |  0  ");
  Serial.println("");
  Serial.println("----------------------------------------------------------------");
  Serial.println("Per selezionare un altro operatore premi il pulsante AVVIA MENU'");
  Serial.println("----------------------------------------------------------------");
  Serial.println("");

  mettiUnoChiavi();
  chiavi[4] = 0;
}

void stampaXor() {
  Serial.println("Hai selezionato l'operatore XOR");
  Serial.println("La tabella di verità è:");
  Serial.println(" A  |  B  |  Y  ");
  Serial.println("----|-----|-----");
  Serial.println(" 0  |  0  |  0  ");
  Serial.println(" 0  |  1  |  1  ");
  Serial.println(" 1  |  0  |  1  ");
  Serial.println(" 1  |  1  |  0  ");
  Serial.println("");
  Serial.println("----------------------------------------------------------------");
  Serial.println("Per selezionare un altro operatore premi il pulsante AVVIA MENU'");
  Serial.println("----------------------------------------------------------------");
  Serial.println("");

  mettiUnoChiavi();
  chiavi[5] = 0;
}

void stampaXnor() {
  Serial.println("Hai selezionato l'operatore XNOR");
  Serial.println("La tabella di verità è:");
  Serial.println(" A  |  B  |  Y  ");
  Serial.println("----|-----|-----");
  Serial.println(" 0  |  0  |  1  ");
  Serial.println(" 0  |  1  |  0  ");
  Serial.println(" 1  |  0  |  0  ");
  Serial.println(" 1  |  1  |  1  ");
  Serial.println("");
  Serial.println("----------------------------------------------------------------");
  Serial.println("Per selezionare un altro operatore premi il pulsante AVVIA MENU'");
  Serial.println("----------------------------------------------------------------");
  Serial.println("");

  mettiUnoChiavi();
  chiavi[6] = 0;
}

void mettiUnoChiavi() {
  for (int indice = 0; indice < 7; indice++) {
    chiavi[indice] = 1;
  }
}

void loop()
{

  if (Serial.available())
  {
    byte selezione = Serial.read();

    while (selezione == '1')
    {
      if (chiavi[0] == 1)
      {
        stampaOr();
      }

      statoInA = digitalRead(pinInA);
      statoInB = digitalRead(pinInB);

      // funzione logica OR
      statoOut = statoInA || statoInB;
      digitalWrite(pinOutY, statoOut);

      if (digitalRead(pinChiave) == HIGH) {
        mettiUnoChiavi();
        stampaMenu();
        break;
      }
    }

    while (selezione == '2')
    {
      if (chiavi[1] == 1) {
        stampaAnd();
      }
      statoInA = digitalRead(pinInA);
      statoInB = digitalRead(pinInB);

      // funzione logica AND
      statoOut = statoInA && statoInB;
      digitalWrite(pinOutY, statoOut);
      //selezione = Serial.read();

      if (digitalRead(pinChiave) == HIGH) {
        mettiUnoChiavi();
        stampaMenu();
        break;
      }
    }

    while (selezione == '3')
    {
      if (chiavi[2] == 1) {
        stampaNot();
      }

      statoInA = digitalRead(pinInA);
      statoInB = digitalRead(pinInB);

      // funzione logica NOT
      statoOut = !statoInA;
      digitalWrite(pinOutY, statoOut);

      if (digitalRead(pinChiave) == HIGH) {
        mettiUnoChiavi();
        stampaMenu();
        break;
      }
    }

    while (selezione == '4')
    {
      if (chiavi[3] == 1) {
        stampaNor();
      }

      statoInA = digitalRead(pinInA);
      statoInB = digitalRead(pinInB);

      //funzione logica NOR
      statoOut = !(statoInA || statoInB);
      digitalWrite(pinOutY, statoOut);

      if (digitalRead(pinChiave) == HIGH) {
        mettiUnoChiavi();
        stampaMenu();
        break;
      }
    }

    while (selezione == '5')
    {
      if (chiavi[4] == 1) {
        stampaNand();
      }

      statoInA = digitalRead(pinInA);
      statoInB = digitalRead(pinInB);

      //funzione logica NAND
      statoOut = !(statoInA && statoInB);
      digitalWrite(pinOutY, statoOut);

      if (digitalRead(pinChiave) == HIGH) {
        mettiUnoChiavi();
        stampaMenu();
        break;
      }
    }

    while (selezione == '6')
    {
      if (chiavi[5] == 1) {
        stampaXor();
      }

      statoInA = digitalRead(pinInA);
      statoInB = digitalRead(pinInB);

      // funzione logica XOR
      
      statoOut = (statoInA && !statoInB) || (!statoInA && statoInB);
      digitalWrite(pinOutY, statoOut);

      if (digitalRead(pinChiave) == HIGH) {
        mettiUnoChiavi();
        stampaMenu();
        break;
      }
    }

    while (selezione == '7') {
      if (chiavi[6] == 1) {
        stampaXnor();
      }

      statoInA = digitalRead(pinInA);
      statoInB = digitalRead(pinInB);

      // funzione logica XNOR
      statoOut = !((statoInA && !statoInB) || (!statoInA && statoInB));
      digitalWrite(pinOutY, statoOut);

      if (digitalRead(pinChiave) == HIGH) {
        mettiUnoChiavi();
        stampaMenu();
        break;
      }
    }
  }
}

 

Propongo come esercizio cinque varianti all’esempio precedente:

  1. Gli ingressi selezionati con pulsanti devono essere visualizzati con LED (1 acceso, 0 spento), create inoltre una libreria dedicata per l’implementazione delle funzioni logiche (inserite il codice in un file .h). Per sapere come creare una libreria seguire il link, al fondo del tutorial troverete la spiegazione.
  2. La selezione della funzione logica non avviene più tramite la serial monitor, ma attraverso 7 pulsanti di selezione funzione, la cui selezione deve essere visualizzata con un LED (Acceso = selezionato; Spento= non selezionato). Deve essere presente un pulsante che effettua il reset dell’operazione (non deve essere il reset della scheda Arduino).
  3. Realizzare le stesse funzionalità del punto 2 ma in questo caso non si devono utilizzare LED ma un display 16×2 del tipo Hitachi HD44780, se desiderate potete utilizzare un’interfaccia I2C HD44780 per utilizzare meno pin.
  4. Aggiungere il codice per effettuare il debounce (anti-rimbalzo) sui pulsanti.
  5. Per gli studenti di 4′ superiore realizzare un debounce usando l’elettronica a componenti discreti.

Per chi volesse esplorare nuove frontiere:

  • Realizzate tutto ciò che è stato esposto prima mediante BBC micro:bit e programmate tutto in microPython.
  • Realizzate tutto ciò che è stato esposto prima mediante Raspberry Pi e programmate tutto in Python.

Buon Coding (e studio) a tutti 🙂

Arduino – Concatenare la stampa di stringhe e variabili

In un recente post ho approfondito l’uso di Serial.write() e Serial.print(), proseguo riprendendo gli appunti che di volta in volta aggiungo a quanto sviluppato durante i corsi. Come sapete per inviare sulla seriale un testo molto lungo è necessario scrivere molte linee di codice, una sequenza di Serial.print() che hanno come argomento il testo che si vuole visualizzare, questo un esempio:

Serial.print("Nel mezzo ");
Serial.print("del cammin ");
Serial.print("di nostra vita ");
Serial.print("mi ritrovai ");
Serial.print("per una selva oscura ");
Serial.print("ché la diritta via ");
Serial.print("era smarrita. ");

Tutte queste righe potrebbero essere scritte in una forma più compatta, accodando tutte le Serial.print() :

Serial.print("Nel mezzo ");Serial.print("del cammin ");
Serial.print("di nostra vita ");Serial.print("mi ritrovai ");
Serial.print("per una selva oscura ");
Serial.print("ché la diritta via ");Serial.print("era smarrita. ");

Sarebbe interessante poter avere la possibilità di concatenare il testo da stampare così come è possibile fare con altri linguaggi di programmazione: Java / VB / C # / C ++, ecc…

Questa funzionalità è stata implementata qualche tempo fa da Mikal Hart che ha realizzato la libreria Streaming (file zip). I vantaggi di utilizzo risiedono nella compattezza del codice prodotto e nella velocità di scrittura.

Con l’uso della libreria Streaming il codice precedente che stampa una serie di stringhe utilizzando la Serial.print(), diventa:

Serial << "Nel mezzo " << "del cammin " << "di nostra vita " << "mi ritrovai " << "per una selva oscura " << "ché la diritta via " << "era smarrita."<< endl;

Nel caso si volesse suddividere l’invio sulla seriale su più linee::

Serial << "Nel mezzo " << "del cammin " << "di nostra vita " << endl;
Serial << "mi ritrovai " << "per una selva oscura " << endl;
Serial << "ché la diritta via " << "era smarrita. " << endl;

Prendendo spunto dall’esempio che trovate nella libreria:

#include <Streaming.h>

void setup()
{
  Serial.begin(9600);
  int lettera = 'M';
  int mese = 7, giorno = 6, anno = 1967;
  
  Serial << "Questo è un esempio dell'uso della libreria Streaming," << endl;
  Serial << "che ti permette di stampare variabili" << endl;
  Serial << "senza dover digitare ad ogni riga" << endl;
  Serial << "Serial.print().  Esempio: " << endl;
  
  Serial << "M è " << lettera << "." << endl;
  Serial << "La mia data di nascita è " << giorno << "-" << mese << "-" << anno << "." << endl;
  
  Serial << "Puoi anche usare i modificatori, per esempio:" << endl;
  Serial << _BYTE(lettera) << " e " << _HEX(lettera) << " in esadecimale. " << endl;
}

void loop()
{}

Realizzimo uno sketch che conta il numero di pressioni del pulsante e visualizziamo sulla Serial Monitor una stringa che ne da indicazione, il circuito è costituito da:

  • Arduino UNO R3
  • Resitore da 1KOhm
  • 1 pulsante

Lo sketch di esempio è il seguente:

#include <Streaming.h>

#define PULSANTE 11 // pin di input a cui è collegato il pulsante

// Variabili
int ContatorePulsantePremuto = 1; // conta il numero di volte che il pulsante è premuto buttonPushCounter 
int StatoPulsante = 0;            // stato corrente del pulsante
int StatoPulsantePrecedente = 0;  // stato precedente del pulsante

void setup() {
  pinMode(PULSANTE, INPUT); // imposta il pin digitale come output
  Serial.begin(9600);       // inizzializza la seriale a a 9600 bps
}

void loop() {
  StatoPulsante = digitalRead(PULSANTE);
  // legge il valore dell'input e lo conserva

  if (StatoPulsante != StatoPulsantePrecedente) {   // compara lo stato del pulsante attuale con il precedente
    if (StatoPulsante == HIGH) {                    // se lo stato è cambiato incrementa il contatore
      // se lo stato corrente è alto, il pulsante è passato da off a on
      
      // Stampa sulla seriale il numero di pressioni del pulsante
        Serial << "Il pulsante è stato premuto " << ContatorePulsantePremuto << " volte" << endl;
      
      ContatorePulsantePremuto++;
    }
  }

  // salva lo stato corrente nella variabile che indica lo stato precedente per il loop successivo 
  StatoPulsantePrecedente = StatoPulsante;
}

Ad ogni pressione del pulsante sulla seriale compariranno le stringhe:

Esercizio

L’invio dello dello stream del testo può avvenire non solo sulla seriale ma anche su qualsiasi classe derivata da Print, ad esempio su display.

Sapreste ottenere la stessa cosa con un display a 16 colonne e 2 righe?

Suggerimento:

lcd << "Il pulsante è stato premuto " << contatore << " volte" << endl;

Buon Coding a tutti 🙂