Archivi tag: arduino

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 🙂

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

Nella scorsa settimana e in quella che verrà, con gli allievi di 3A e 3B Automazione ho svolto e svolgerò alcune esercitazioni sul controllo di flusso per gestire valori provenienti da sensori e controllare l’attivazione di motori elettrici mediante tastiera del computer e tastierino numerico esterno. Al fine di approfondire l’uso in C del controllo di flusso aggiungo alcune informazioni aggiuntive sull’uso dell’istruzione switch..case, per le altre istruzioni sul controllo di flusso si consulti su questo sito la sezione: Usare Arduino -> Appunti di Programmazione -> controllo di flusso

Come accade per l’istruzione if, l’istruzione switch…case, che viene chiamata anche istruzione di selezione multipla, permette il controllo di flusso dei vostri programmi permettendo di specificare porzioni diverse di codice da eseguire in funzione di una serie di condizioni impostate.

In particolare, l’istruzione switch (interruttore) confronta il valore intero costante con i valori specificati nelle etichetta case (caso). Quando viene trovata un’istruzione case il cui valore corrisponde a quello passato dallo switch, viene eseguito il codice contenuto nel case.

Nel caso in cui non venga riscontrata nessuna occorrenza del valore passato dalla switch, sarà eseguita la sezione default.

L’istruzione break consente l’uscita dall’istruzione switch e viene in genere utilizzata alla fine di ogni case, portando il controllo del programma a continuare con la prima istruzione dopo l’istruzione switch.

Nel caso in cui il break non venga inserita all’interno del case, l’istruzione switch continuerà ad eseguire le istruzioni che seguono, comportamento che viene chiamato “falling-through”, fino all’interruzione o alla fine dell’istruzione switch.

Nel caso in cui il break non fosse inserito in ognuno dei case, ogni volta che fosse incontrata una corrispondenza con uno dei case, verrebbero eseguite anche tutte le istruzioni dei case rimanenti, nel caso in cui non venga riscontrata nessuna occorrenza del valore passato dalla switch, sarà eseguita la sezione default e successivamente visualizzato un messaggio di errore.

Si faccia attenzione che quando si utilizza il comando switch, ogni singolo case può essere utilizzato solamente per controllare una espressione intera costante, cioè ogni combinazione di costanti di carattere e interi che possono essere valutati come valori interi, le costanti intere sono semplicemente dei valori interi ed una variabile di tipo carattere è rappresentata con il carattere specifico posto tra apici singoli, come ‘M’. Si ricordi che i caratteri sono in realtà dei valori interi memorizzati in un byte.

Sintassi

switch (variabile) {
   case label:
   // istruzioni
   break;
case label:
   // istruzioni
   break;
default:
   // istruzioni
   break;
}

Vi rimando al reference on-line sul sito di Arduino per analizzare alcuni esempi che svilupperemo con ulteriori esercitazioni tratte dalle mie slide e che svolgeremo a lezioni:

Buon lavoro 🙂

Utilizzo dell’LCD 16×2 Hitachi HD44780 1602 con modulo I2C PCF8574T

Addendum al progetto EduRobot.

Una settimana è bastata per scatenare la fantasia di giovani studenti alle prese con EduRobot per l’attività di Alternanza Scuola Lavoro. Le relazioni di lavoro mettono in evidenza soluzioni alternative originali, la richiesta è di continuare ad aggiungere funzionalità ad EduRobot, vedremo nelle prossime settimane come proseguire con i lavori, ma sicuramente in questa prima fase mi posso ritenere soddisfatto! 😊

Tra le richieste che mi sono state fatte vi è quella di inserire un display per aggiungere interattività con il robot. Tra le possibilità ho suggerito l’utilizzo di un LCD 16×2 Hitachi HD44780 1602 quelli in dotazione con molti kit Arduino. Per rendere più agevole la gestione e i collegamenti, visto l’elevato numero di connessioni presenti su EduRobot, ho consigliato l’utilizzo di un modulo PCF8574T per il controllo in I2C, poiché gli studenti sono giovani ed ancora non hanno affrontato questo argomento, con questo post voglio dare un piccolo aiuto.

Disponiamo dei moduli della sunfounder su cui è già saldato il modulo i2C:

l’utilizzo è identico ai più comuni expander esterni come quelli indicati nell’immagine che segue:

Il display è costituito da 4 pin di connessione, due dedicati all’alimentazione e due alla comunicazione i2C.

Le connessioni tra LCD1602 i2C ed Arduino sono i seguenti:

LCD1602 —> Arduino
GND -> GND
Vcc -> 5V
SDA -> A4
SCL -> A5

Per poter utilizzare questo display è necessario installare la libreria LiquidCrystal_I2C dal seguente link: https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library

Prelevate il file .zip ed installate la libreria direttamente dall’IDE di Arduino:

in alternativa potete scompattare e copiare il tutto nella cartella libraries di Arduino.

Piccolo avvertimento, sicuramente nelle vostre sperimentazioni prenderete spunto da sketch che troverete on-line, alcune volte questi esempi sono datati e si riferiscono ad una versione dell’ide di qualche anno fa in cui si poteva inizializzare l’LCD nel setup con: lcd.init(), ciò non è più possibile sostituitela con la classe lcd.begin() così come indicato negli esempi che seguono.

Includo a questo post una serie di sketch tutti tratti dal reference di Arduino e riadattati per un uso con il modulo PCF8574T in modo da accelerare le attività di sperimentazione dei miei allievi.

Il funzionamento di ogni esempio è dettagliato con commenti all’interno degli sketch.

/* Prof. Michele Maffucci
 * Utilizzo di un display LCD 16×2 Hitachi HD44780 1602
 * con modulo i2C PCF8574T
 * Esempio 1: scrittura testo su due righe
 */

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// inizializzazione della libreria in cui è descritta la modalità di utilizzo dei pin
LiquidCrystal_I2C lcd(0x27, 16, 2); // impostazione dell'indirizzo dell'LCD 0x27 di 16 caratteri e 2 linee
//-----------------------------
void setup()
{
  lcd.begin();      // inizializzazione dell'LCD
  lcd.backlight();  // attivazione della retroilluminazione
}
//-----------------------------


void loop()
{
  lcd.setCursor(2,0);
  lcd.print("Ciao Ragazzi");
  lcd.setCursor(0,1);
  lcd.print("Io sono EduRobot");
}
/* Prof. Michele Maffucci
 * Utilizzo di un display LCD 16×2 Hitachi HD44780 1602
 * con modulo i2C PCF8574T
 * Esempio 2: noBlink - Blink
 */

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// inizializzazione della libreria in cui è descritta la modalità di utilizzo dei pin
LiquidCrystal_I2C lcd(0x27, 16, 2); // impostazione dell'indirizzo dell'LCD 0x27 di 16 caratteri e 2 linee
//-----------------------------
void setup()
{
  lcd.begin();      // inizializzazione dell'LCD
  lcd.backlight();  // attivazione della retroilluminazione
}
//-----------------------------

void loop() {
  // Turn off the blinking cursor:
  lcd.noBlink();
  delay(3000);
  // Turn on the blinking cursor:
  lcd.blink();
  delay(3000);
}
/* Prof. Michele Maffucci
 * Utilizzo di un display LCD 16×2 Hitachi HD44780 1602
 * con modulo i2C PCF8574T
 * Esempio 3: noDisplay - Display
 */

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// inizializzazione della libreria in cui è descritta la modalità di utilizzo dei pin
LiquidCrystal_I2C lcd(0x27, 16, 2); // impostazione dell'indirizzo dell'LCD 0x27 di 16 caratteri e 2 linee
//-----------------------------
void setup()
{
  lcd.begin();      // inizializzazione dell'LCD
  lcd.backlight();  // attivazione della retroilluminazione
  lcd.print("EduRobot");
}
//-----------------------------

void loop() {
  // disattiva il display
  lcd.noDisplay();
  delay(500);
  // attiva il display
  lcd.display();
  delay(500);
}
/* Prof. Michele Maffucci
 * Utilizzo di un display LCD 16×2 Hitachi HD44780 1602
 * con modulo i2C PCF8574T
 * Esempio 4: scrollDisplayLeft() - scrollDisplayRight()
 */

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// inizializzazione della libreria in cui è descritta la modalità di utilizzo dei pin
LiquidCrystal_I2C lcd(0x27, 16, 2); // impostazione dell'indirizzo dell'LCD 0x27 di 16 caratteri e 2 linee
//-----------------------------
void setup()
{
  lcd.begin();      // inizializzazione dell'LCD
  lcd.backlight();  // attivazione della retroilluminazione
  lcd.print("EduRobot");
  delay(1000);
}
//-----------------------------

void loop() {
  // sposta di 8 posizioni (lunghezza della tringa: EduRobot) a sinistra
  for (int positionCounter = 0; positionCounter < 8; positionCounter++) {
    // per far percepire la variazione di posizione del testo mettiamo in pausa per un breve istante
    lcd.scrollDisplayLeft();
    // aspetta un momento:
    delay(150);
  }

  // sposta di 24 posizioni (lunghezza della tringa + lunghezza del siplay(n. colonne)) a destra
  for (int positionCounter = 0; positionCounter < 24; positionCounter++) {
    // sposta di una posizione a destra
    lcd.scrollDisplayRight();
    // per far percepire la variazione di posizione del testo mettiamo in pausa per un breve istante
    delay(150);
  }

  // sposta di 24 posizioni (lunghezza della tringa + lunghezza del siplay(n. colonne)) a sinistra
  // to move it back to center:
  for (int positionCounter = 0; positionCounter < 24; positionCounter++) {
    // sposta di una posizione a sinistra
    lcd.scrollDisplayLeft();
    // per far percepire la variazione di posizione del testo mettiamo in pausa per un breve istante
    delay(150);
  }

  // al termine di un ciclo di uno spostamento destra e sinistra
  // attesa di 1 secondo
  delay(1000);
}
/* Prof. Michele Maffucci
 * Utilizzo di un display LCD 16×2 Hitachi HD44780 1602
 * con modulo i2C PCF8574T
 * Esempio 5: Serial Input
 */

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// inizializzazione della libreria in cui è descritta la modalità di utilizzo dei pin
LiquidCrystal_I2C lcd(0x27, 16, 2); // impostazione dell'indirizzo dell'LCD 0x27 di 16 caratteri e 2 linee
//-----------------------------
void setup()
{
  lcd.begin();        // inizializzazione dell'LCD
  lcd.backlight();    // attivazione della retroilluminazione
  Serial.begin(9600); // inizializzazione della porta seriale
}
//-----------------------------


void loop() {
  // quando un carattere viene inviato alla serial monitor...
  if (Serial.available()) {
    // attende un momento prima di inviare il testo sulla seril monitor
    delay(100);
    // cancella lo schermo
    lcd.clear();
    // legge tutti i caratteri disponibili sulla seriale
    while (Serial.available() > 0) {
      // visualizza i caratteri sul display
      lcd.write(Serial.read());
    }
  }
}
/* Prof. Michele Maffucci
 * Utilizzo di un display LCD 16×2 Hitachi HD44780 1602
 * con modulo i2C PCF8574T
 * Esempio 6: setCursor()
 */

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// inizializzazione della libreria in cui è descritta la modalità di utilizzo dei pin
LiquidCrystal_I2C lcd(0x27, 16, 2); // impostazione dell'indirizzo dell'LCD 0x27 di 16 caratteri e 2 linee
//-----------------------------

const int numRows = 2;
const int numColonne = 16;

void setup()
{
  lcd.begin();        // inizializzazione dell'LCD
  lcd.backlight();    // attivazione della retroilluminazione
}
//-----------------------------


void loop() {
  // stampa in loop i caratteri ASCII da 'a' a 'z':
  for (int lettera = 'a'; lettera <= 'z'; lettera++) {
    // ciclo per le colonne
    for (int  riga = 0; riga < numRows; riga++) {
      // ciclo per le righe
      for (int colonna = 0; colonna < numColonne; colonna++) {
        // imposta la posizione del cursore
        lcd.setCursor(colonna, riga);
        // stama il carattere
        lcd.write(lettera);
        delay(200);
      }
    }
  }
}
/* Prof. Michele Maffucci
 * Utilizzo di un display LCD 16×2 Hitachi HD44780 1602
 * con modulo i2C PCF8574T
 * Esempio 7: leftToRight() - rightToLeft()
 */

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// inizializzazione della libreria in cui è descritta la modalità di utilizzo dei pin
LiquidCrystal_I2C lcd(0x27, 16, 2); // impostazione dell'indirizzo dell'LCD 0x27 di 16 caratteri e 2 linee
//-----------------------------

int lettera = 'a';

void setup()
{
  lcd.begin();        // inizializzazione dell'LCD
  lcd.backlight();    // attivazione della retroilluminazione
  lcd.cursor();       // attiva il cursore
}
//-----------------------------


void loop() {
  // cambia direzione (da destra a sinistra)
  // quando l'ultima lettera stampata è la 'm':
  if (lettera == 'm') {
    // sposta il cursore a destra per stampare la lettera successiva
    lcd.rightToLeft();
  }
  // cambia direzione (da sinistra a destra)
  // // quando l'ultima lettera stampata è la 's':
  if (lettera == 's') {
    // sposta il cursore a sinistra per stampare la lettera successiva
    lcd.leftToRight();
  }
  // reset quando atriviamo alla 'z':
  if (lettera > 'z') {
    // spostare il cursore a (0,0):
    lcd.home();
    // ricomincia dalla posizione 0
    lettera = 'a';
  }
  // stampa il carattere
  lcd.write(lettera);
  // aspetta un secondo
  delay(1000);
  // incrementa la lettera
  lettera++;
}

Buona sperimentazione 🙂

Errori comuni nell’uso di Arduino – confondere pin analogici con pin digitali

Come sicuramente saprete i pin analogici di Arduino UNO, da A0 a A5 possono essere utilizzati anche in modalità digitale e questa caratteristica alcune volte crea qualche confusione in quanto i pin se vengono utilizzati in modalità analogica non è necessario dichiararne il pinMode all’interno del setup(), ciò ovviamente non accade se bisogna usarli in modalità digitale.
Dopo un po’ questa funzionalità viene memorizzata, un modo per non dimenticare questa caratteristica potrebbe essere quella di inserire una dichiarazione “inutile” che ne rammenta la modalità di utilizzo:

void setup() {
   Serial.begin(9600);
   analogRead(A2); // Sensore di luminosità
   pinMode(13, OUTPUT);
   pinMode(2, INPUT);
}

In ogni caso, per i miei studenti chiedo di ricordare a mente senza aggiungere dichiarazioni inutili, ma se si è all’inizio tale notazione può essere accettata.

Un’altra cosa che noto  confonde è l’uso della notazione Ax per i pin digitali e non del valore decimale.
In Arduino.h viene definito ad esempio A2 come una costante di tipo intero. Su Arduino UNO ad A2 è assegnato il valore numerico 16 e poiché è una costante di tipo intero possiamo trattare a tutti gli effetti A2 come se si trattasse del numero 16.

Per completezza ricordo che:

  • A0 -> 14
  • A1 -> 15
  • A2 -> 16
  • A3 -> 17
  • A4 -> 18
  • A5 -> 19

In generale sconsiglio di indicare i pin analogici con il loro valore numerico per due motivi:

  1. la notazione Ax immediatamente mette in evidenza che si tratta di pin analogico,
  2. se utilizziamo su una scheda con più pin I/O, come un Arduino Mega non andremo in confusione e non rischieremo far andare in collisione un pin digitale con un pin analogico nel caso ad esempio che stessimo mettendo mano ad uno sketch funzionante su Arduino Uno e che vogliamo far funzionare sul Mega, infatti su Arduino UNO l’A0 corrisponde al pin 14 della scheda mentre sull’Arduino Mega corrsiponde al pin 54 della scheda, se usiamo la notazione Ax non ci sbagliamo.

Ricordate inoltre che se all’interno del nostro loop() passiamo ad una digitalRead un valore da 0 a 5 non intendiamo segnalare un pin digitale da 0 a 5, ma uno dei pin da A0 ad A5.

Buon lavoro 🙂

EduRobot – ASL (Alternanza Scuola Lavoro) – Manuale di costruzione – 3/3

Nella guida che segue illustro un schema molto semplice per la realizzazione del controllo di EduRobot effettuata con Arduino. Fornirò passo passo gli sketch di esempio che dovrete migliorare. è può essere considerato la base di partenza per ogni sperimentazione basata appunto su Arduino.
Per il pilotaggio dei motori ho utilizzato e L298N Dual H-Bridge Motor Controller di cui vi ho dato indicazioni nella lezione precedente.

Ovviamente anche la soluzione proposta in questo tutorial potranno essere migliorate da voi, lo scopo è quello di svolgere l’attività di Alternanza Scuola Lavoro di questi giorni, ma nelle settimane che seguiranno potrete migliorare ogni aspetto del robot in quanto il corso su Arduino che state svolgendo nelle mie ore sarà svolto proprio sulla piattaforma EduRobot.

Potrete sostituire alle batterie che io ho utilizzato, batterie ricarrabili, o pacchi batterie con autonomia maggiore che potrete fissare utilizzando gli appositi fori predisposti sullo chassis, durante le lezioni in classe vi fornirò suggerimenti e modalità diverse di utilizzo della scheda L298N.

Nelle parti che seguono costruiamo passo passo il programma che consente la realizzaizone di un robot che si muove in modo autonomo.

Negli esempio che seguono verranno di volta aggiunte nuove funzioni, la lista completa è la seguente:

rotazioneOraria(tempo necessario per effettuare una determinata rotazione, velocità con cui ruota il robot)

Rotazione oraria di EduRobot sul proprio asse

stopEduRobot()

Blocca il movimento del robot

distanzaOstacolo()

restituisce la distanza in cm dell’ostacolo rilevato

paragonaDistanze()

verifica la distanza dell’ostacolo che si trova a distanza maggiore dal robot

scegliDirezione()

sceglie la direzione da prendere in funzione della distanza a cui si trova l’ostacolo

La spiegazione del funzionamento d ogni parte del codice è inclusa all’interno dello sketch come commento.

Nota per lo studio:

i 6 sketch proposti variano solo nel loop per la realizzazione delle funzioni richieste, la variazione tra uno sketch e l’altro consiste nell’aggiunta di poche linee di codice, sarà quindi necessario effettuare uno studio preliminare di tutte le parti dello sketch 1.

Sketch 1

Rotazione di 90° in senso orario del robot sul proprio asse e ritorno alla posizione di partenza con intervallo di stop di 3 secondi.

/*
  Prof. Maffucci Michele
  21.01.19

  EduRobot - Programma test n. 4
  Rotazione di 90° in senso orario del robot sul proprio asse
  e ritorno alla posizione di partenza con intervallo di stop di 3 secondi.

  Collegamenti:

  L298N -->  Arduino

  ENB  -->  Pin 10
  IN4  -->  Pin 5
  IN3  -->  Pin 4
  IN2  -->  Pin 3
  IN1  -->  Pin 2
  ENA  -->  Pin 9
  +12V -->  Vin
  GND  -->  GND
*/

// Impostazione pin motori

// motore 1 (sx)

int direzione1_M1 = 2;
int direzione2_M1 = 3;
int velocita_M1 = 9; // pin di tipo PWM per controllare la velocità del motore

// motore 2 (dx)

int direzione1_M2 = 4;
int direzione2_M2 = 5;
int velocita_M2 = 10; // pin di tipo PWM per controllare la velocità del motore

int velocita = 200;               // velocità di rotazione dei motori. Valore compreso tra 0 e 255
int velocita_scelta_dir = 150;    // velocità di rotazione dei motori per la scelta direzione. Valore compreso tra 0 e 255

int tempo_rotazione = 500;        // quantità di tempo di rotazione o di fermo motore

int tempo_rotazione_angolo = 350; // tempo per far ruotare il motore di 90°. Da variare in funzione della carica della batteria.
int velocita_rotazione = 150;     // velocità di rotazione di EduRobot sul proprio asse

int attesa = 3000; // tempo di attesa prima che il robot si muova

void setup() {

  // modalità di utilizzo dei pin di controllo
  pinMode(direzione1_M1, OUTPUT);
  pinMode(direzione2_M1, OUTPUT);
  pinMode(velocita_M1, OUTPUT);
  pinMode(direzione1_M2, OUTPUT);
  pinMode(direzione2_M2, OUTPUT);
  pinMode(velocita_M2, OUTPUT);

  delay(attesa);
}

// rotazione oraria di EduRobot sul proprio asse
// tempo: tempo per compiere uno specifico angolo di rotazione
// velocita_rotazione: velocità con cui gira il robot

void rotazioneAntioraria(int tempo, int velocita_rotazione) {

  // Motore 1 (Sx) avanti - senso antiorario
  // Motore 2 (Dx) avanti - senso orario

  analogWrite(velocita_M1, velocita_rotazione); // Imposta la velocità del motore M1 a velocità = 200
  analogWrite(velocita_M2, velocita_rotazione); // Imposta la velocità del motore M2 a velocità = 200

  // per far girare il motore M1 (Sx) in senso antiorario
  // per far girare il motore M2 (Dx) in senso orario

  digitalWrite(direzione1_M1, LOW);
  digitalWrite(direzione2_M1, HIGH);
  digitalWrite(direzione1_M2, HIGH);
  digitalWrite(direzione2_M2, LOW);
  delay(tempo);
}

// rotazione antioraria di EduRobot sul proprio asse
// tempo: tempo per compiere uno specifico angolo di rotazione
// velocita_rotazione: velocità con cui gira il robot

void rotazioneOraria(int tempo, int velocita_rotazione) {

  // Motore 1 (Sx) - senso orario
  // Motore 2 (Dx) - senso antiorario

  analogWrite(velocita_M1, velocita_rotazione); // Imposta la velocità del motore M1 a velocità = 200
  analogWrite(velocita_M2, velocita_rotazione); // Imposta la velocità del motore M2 a velocità = 200

  // per far girare il motore M1 (Sx) in senso orario
  // per far girare il motore M2 (Dx) in senso antiorario

  digitalWrite(direzione1_M1, HIGH);
  digitalWrite(direzione2_M1, LOW);
  digitalWrite(direzione1_M2, LOW);
  digitalWrite(direzione2_M2, HIGH);
  delay(tempo);
}

// ferma i motori
void stopEduRobot() {
  // Per fermare il motore impostare a 0 il secondo parametro
  analogWrite(velocita_M1, 0);
  analogWrite(velocita_M2, 0);
}

void loop() {
  rotazioneOraria(tempo_rotazione_angolo, velocita_rotazione);
  stopEduRobot();
  delay(3000);
  rotazioneAntioraria(tempo_rotazione_angolo, velocita_rotazione);
  stopEduRobot();
  delay(3000);
}

Dalla lezione precedente si sono utilizzati le parti di sketch che permettono la rotazione in senso antiorario ed orario dei motori.

La funzione rotazioneOraria e rotazioneAntioraria, di seguito evidenziate, consentono la rotazione di EduRobot sul proprio asse in una delle due direzioni. Le funzioni accettano due parametri:

  • tempo: tempo per compiere uno specifico angolo di rotazione
  • velocita_rotazione: velocità con cui gira il robot

Il tempo per compiere un angolo di 90° deve essere valutato sperimentalmente in quanto funzione della carica della batteria. Per regolare il tempo di rotazione per un angolo di 90° variare il valore della variabile globale: tempo_rotazione_angolo che trovate all’inizio dello sketch.

...
void rotazioneOraria(int tempo, int velocita_rotazione) {

  // Motore 1 (Sx) - senso orario
  // Motore 2 (Dx) - senso antiorario

  analogWrite(velocita_M1, velocita_rotazione); // Imposta la velocità del motore M1 a velocità = 200
  analogWrite(velocita_M2, velocita_rotazione); // Imposta la velocità del motore M2 a velocità = 200

  // per far girare il motore M1 (Sx) in senso orario
  // per far girare il motore M2 (Dx) in senso antiorario

  digitalWrite(direzione1_M1, HIGH);
  digitalWrite(direzione2_M1, LOW);
  digitalWrite(direzione1_M2, LOW);
  digitalWrite(direzione2_M2, HIGH);
  delay(tempo);
}
...
...
void rotazioneOraria(int tempo, int velocita_rotazione) {

  // Motore 1 (Sx) - senso orario
  // Motore 2 (Dx) - senso antiorario

  analogWrite(velocita_M1, velocita_rotazione); // Imposta la velocità del motore M1 a velocità = 200
  analogWrite(velocita_M2, velocita_rotazione); // Imposta la velocità del motore M2 a velocità = 200

  // per far girare il motore M1 (Sx) in senso orario
  // per far girare il motore M2 (Dx) in senso antiorario

  digitalWrite(direzione1_M1, HIGH);
  digitalWrite(direzione2_M1, LOW);
  digitalWrite(direzione1_M2, LOW);
  digitalWrite(direzione2_M2, HIGH);
  delay(tempo);
}
...

Per interrompere la rotazione di EduRobot è sufficiente inviare sui pin 9 e 5 di Arduino di tipo PWM il valore 0

...
void stopEduRobot() {
  // Per fermare il motore impostare a 0 il secondo parametro
  analogWrite(velocita_M1, 0);
  analogWrite(velocita_M2, 0);
}
...

Sketch 2

Rotazione di 180° in senso orario del robot sul proprio asse e ritorno alla posizione di partenza con intervallo di stop di 3 secondi.

Per eseguire questa esercitazione sarà sufficiente aggiungere allo sketch precedente un’ulteriore chiamata alle funzioni rotazioneOraria e rotazioneAntioraria, oppure variare il valore della variabile tempo_rotazione_angolo per un tempo doppio rispetto al tempo necessario per compiere una rotazione di 90°.

/*
  Prof. Maffucci Michele
  21.01.19

  EduRobot - Programma test n. 5
  Rotazione di 180° in senso orario del robot sul proprio asse e
  ritorno alla posizione di partenza con intervallo di stop di 3 secondi.

  Collegamenti:

  L298N -->  Arduino

  ENB  -->  Pin 10
  IN4  -->  Pin 5
  IN3  -->  Pin 4
  IN2  -->  Pin 3
  IN1  -->  Pin 2
  ENA  -->  Pin 9
  +12V -->  Vin
  GND  -->  GND
*/

// Impostazione pin motori

// motore 1 (sx)

int direzione1_M1 = 2;
int direzione2_M1 = 3;
int velocita_M1 = 9; // pin di tipo PWM per controllare la velocità del motore

// motore 2 (dx)

int direzione1_M2 = 4;
int direzione2_M2 = 5;
int velocita_M2 = 10; // pin di tipo PWM per controllare la velocità del motore

int velocita = 200;               // velocità di rotazione dei motori. Valore compreso tra 0 e 255
int velocita_scelta_dir = 150;    // velocità di rotazione dei motori per la scelta direzione. Valore compreso tra 0 e 255

int tempo_rotazione = 500;        // quantità di tempo di rotazione o di fermo motore

int tempo_rotazione_angolo = 350; // tempo per far ruotare il motore di 90°. Da variare in funzione della carica della batteria.
int velocita_rotazione = 150;     // velocità di rotazione di EduRobot sul proprio asse

int attesa = 3000; // tempo di attesa prima che il robot si muova

void setup() {

  // modalità di utilizzo dei pin di controllo
  pinMode(direzione1_M1, OUTPUT);
  pinMode(direzione2_M1, OUTPUT);
  pinMode(velocita_M1, OUTPUT);
  pinMode(direzione1_M2, OUTPUT);
  pinMode(direzione2_M2, OUTPUT);
  pinMode(velocita_M2, OUTPUT);

  delay(attesa);
}

// rotazione oraria di EduRobot sul proprio asse
// tempo: tempo per compiere uno specifico angolo di rotazione
// velocita_rotazione: velocità con cui gira il robot

void rotazioneAntioraria(int tempo, int velocita_rotazione) {

  // Motore 1 (Sx) avanti - senso antiorario
  // Motore 2 (Dx) avanti - senso orario

  analogWrite(velocita_M1, velocita_rotazione); // Imposta la velocità del motore M1 a velocità = 200
  analogWrite(velocita_M2, velocita_rotazione); // Imposta la velocità del motore M2 a velocità = 200

  // per far girare il motore M1 (Sx) in senso antiorario
  // per far girare il motore M2 (Dx) in senso orario

  digitalWrite(direzione1_M1, LOW);
  digitalWrite(direzione2_M1, HIGH);
  digitalWrite(direzione1_M2, HIGH);
  digitalWrite(direzione2_M2, LOW);
  delay(tempo);
}

// rotazione antioraria di EduRobot sul proprio asse
// tempo: tempo per compiere uno specifico angolo di rotazione
// velocita_rotazione: velocità con cui gira il robot

void rotazioneOraria(int tempo, int velocita_rotazione) {

  // Motore 1 (Sx) - senso orario
  // Motore 2 (Dx) - senso antiorario

  analogWrite(velocita_M1, velocita_rotazione); // Imposta la velocità del motore M1 a velocità = 200
  analogWrite(velocita_M2, velocita_rotazione); // Imposta la velocità del motore M2 a velocità = 200

  // per far girare il motore M1 (Sx) in senso orario
  // per far girare il motore M2 (Dx) in senso antiorario

  digitalWrite(direzione1_M1, HIGH);
  digitalWrite(direzione2_M1, LOW);
  digitalWrite(direzione1_M2, LOW);
  digitalWrite(direzione2_M2, HIGH);
  delay(tempo);
}

// ferma i motori
void stopEduRobot() {
  // Per fermare il motore impostare a 0 il secondo parametro
  analogWrite(velocita_M1, 0);
  analogWrite(velocita_M2, 0);
}

void loop() {
  rotazioneOraria(tempo_rotazione_angolo, velocita_rotazione);
  rotazioneOraria(tempo_rotazione_angolo, velocita_rotazione);
  stopEduRobot();
  delay(3000);
  rotazioneAntioraria(tempo_rotazione_angolo, velocita_rotazione);
  rotazioneAntioraria(tempo_rotazione_angolo, velocita_rotazione);
  stopEduRobot();
  delay(3000);
}

Sketch 3

Rotazione di 360° in senso orario del robot sul proprio asse, rotazione di 360° in senso antiorario del robot sul proprio asse con intervallo di stop a 180° di 1 secondo e stop di 3 secondi a 360°.

/*
  Prof. Maffucci Michele
  21.01.19

  EduRobot - Programma test n. 6
  Rotazione di 360° in senso orario del robot sul proprio asse, rotazione di 360°
  in senso antiorario del robot sul proprio asse con intervallo di stop a 180°
  di 1 secondo e stop di 3 secondi a 360°.

  Collegamenti:

  L298N -->  Arduino

  ENB  -->  Pin 10
  IN4  -->  Pin 5
  IN3  -->  Pin 4
  IN2  -->  Pin 3
  IN1  -->  Pin 2
  ENA  -->  Pin 9
  +12V -->  Vin
  GND  -->  GND
*/

// Impostazione pin motori

// motore 1 (sx)

int direzione1_M1 = 2;
int direzione2_M1 = 3;
int velocita_M1 = 9; // pin di tipo PWM per controllare la velocità del motore

// motore 2 (dx)

int direzione1_M2 = 4;
int direzione2_M2 = 5;
int velocita_M2 = 10; // pin di tipo PWM per controllare la velocità del motore

int velocita = 200;               // velocità di rotazione dei motori. Valore compreso tra 0 e 255
int velocita_scelta_dir = 150;    // velocità di rotazione dei motori per la scelta direzione. Valore compreso tra 0 e 255

int tempo_rotazione = 500;        // quantità di tempo di rotazione o di fermo motore

int tempo_rotazione_angolo = 350; // tempo per far ruotare il motore di 90°. Da variare in funzione della carica della batteria.
int velocita_rotazione = 150;     // velocità di rotazione di EduRobot sul proprio asse

int attesa = 3000; // tempo di attesa prima che il robot si muova

void setup() {

  // modalità di utilizzo dei pin di controllo
  pinMode(direzione1_M1, OUTPUT);
  pinMode(direzione2_M1, OUTPUT);
  pinMode(velocita_M1, OUTPUT);
  pinMode(direzione1_M2, OUTPUT);
  pinMode(direzione2_M2, OUTPUT);
  pinMode(velocita_M2, OUTPUT);

  delay(attesa);
}

// rotazione oraria di EduRobot sul proprio asse
// tempo: tempo per compiere uno specifico angolo di rotazione
// velocita_rotazione: velocità con cui gira il robot

void rotazioneAntioraria(int tempo, int velocita_rotazione) {

  // Motore 1 (Sx) avanti - senso antiorario
  // Motore 2 (Dx) avanti - senso orario

  analogWrite(velocita_M1, velocita_rotazione); // Imposta la velocità del motore M1 a velocità = 200
  analogWrite(velocita_M2, velocita_rotazione); // Imposta la velocità del motore M2 a velocità = 200

  // per far girare il motore M1 (Sx) in senso antiorario
  // per far girare il motore M2 (Dx) in senso orario

  digitalWrite(direzione1_M1, LOW);
  digitalWrite(direzione2_M1, HIGH);
  digitalWrite(direzione1_M2, HIGH);
  digitalWrite(direzione2_M2, LOW);
  delay(tempo);
}

// rotazione antioraria di EduRobot sul proprio asse
// tempo: tempo per compiere uno specifico angolo di rotazione
// velocita_rotazione: velocità con cui gira il robot

void rotazioneOraria(int tempo, int velocita_rotazione) {

  // Motore 1 (Sx) - senso orario
  // Motore 2 (Dx) - senso antiorario

  analogWrite(velocita_M1, velocita_rotazione); // Imposta la velocità del motore M1 a velocità = 200
  analogWrite(velocita_M2, velocita_rotazione); // Imposta la velocità del motore M2 a velocità = 200

  // per far girare il motore M1 (Sx) in senso orario
  // per far girare il motore M2 (Dx) in senso antiorario

  digitalWrite(direzione1_M1, HIGH);
  digitalWrite(direzione2_M1, LOW);
  digitalWrite(direzione1_M2, LOW);
  digitalWrite(direzione2_M2, HIGH);
  delay(tempo);
}

// ferma i motori
void stopEduRobot() {
  // Per fermare il motore impostare a 0 il secondo parametro
  analogWrite(velocita_M1, 0);
  analogWrite(velocita_M2, 0);
}

void loop() {

  rotazioneOraria(tempo_rotazione_angolo, velocita_rotazione);
  rotazioneOraria(tempo_rotazione_angolo, velocita_rotazione);
  stopEduRobot();
  delay(1000);

  rotazioneOraria(tempo_rotazione_angolo, velocita_rotazione);
  rotazioneOraria(tempo_rotazione_angolo, velocita_rotazione);
  stopEduRobot();
  delay(3000);

  rotazioneAntioraria(tempo_rotazione_angolo, velocita_rotazione);
  rotazioneAntioraria(tempo_rotazione_angolo, velocita_rotazione);
  stopEduRobot();
  delay(1000);

  rotazioneAntioraria(tempo_rotazione_angolo, velocita_rotazione);
  rotazioneAntioraria(tempo_rotazione_angolo, velocita_rotazione);
  stopEduRobot();
  delay(3000);
}

Facendo eseguire ad EduRobot i medesimi spostamenti, ottimizzare il codice presente nel loop riducendo il numero di istruzioni.

Sketch 4

Ripetere la sequenza: avanti per 500 millisecondi, stop per 3 secondi, rotazione di 180° in senso orario del robot, stop di 1 secondo, avanti per 500 millisecondi, stop di 3 secondi, rotazione di 180° in senso antiorario, stop di 1 secondo, movimento in avanti per 500 millisecondi.

/*
  Prof. Maffucci Michele
  21.01.19

  EduRobot - Programma test n. 7
  Sequenza: avanti per 500 millisecondi, stop per 3 secondi, rotazione di 180° in senso orario del robot,
  stop di 1 secondo, avanti per 500 millisecondi, stop di 3 secondi, rotazione di 180° in senso antiorario,
  stop di 1 secondo, movimento in avanti per 500 millisecondi.

  Collegamenti:

  L298N -->  Arduino

  ENB  -->  Pin 10
  IN4  -->  Pin 5
  IN3  -->  Pin 4
  IN2  -->  Pin 3
  IN1  -->  Pin 2
  ENA  -->  Pin 9
  +12V -->  Vin
  GND  -->  GND
*/

// Impostazione pin motori

// motore 1 (sx)

int direzione1_M1 = 2;
int direzione2_M1 = 3;
int velocita_M1 = 9; // pin di tipo PWM per controllare la velocità del motore

// motore 2 (dx)

int direzione1_M2 = 4;
int direzione2_M2 = 5;
int velocita_M2 = 10; // pin di tipo PWM per controllare la velocità del motore

int velocita = 200;               // velocità di rotazione dei motori. Valore compreso tra 0 e 255
int velocita_scelta_dir = 150;    // velocità di rotazione dei motori per la scelta direzione. Valore compreso tra 0 e 255

int tempo_rotazione = 500;        // quantità di tempo di rotazione o di fermo motore

int tempo_rotazione_angolo = 350; // tempo per far ruotare il motore di 90°. Da variare in funzione della carica della batteria.
int velocita_rotazione = 150;     // velocità di rotazione di EduRobot sul proprio asse
int velocita_avanti = 150;        // velocità di avanzamento in avanti di EduRobot

int attesa = 3000; // tempo di attesa prima che il robot si muova

void setup() {

  // modalità di utilizzo dei pin di controllo
  pinMode(direzione1_M1, OUTPUT);
  pinMode(direzione2_M1, OUTPUT);
  pinMode(velocita_M1, OUTPUT);
  pinMode(direzione1_M2, OUTPUT);
  pinMode(direzione2_M2, OUTPUT);
  pinMode(velocita_M2, OUTPUT);

  delay(attesa);
}

// rotazione oraria di EduRobot sul proprio asse
// tempo: tempo per compiere uno specifico angolo di rotazione
// velocita_rotazione: velocità con cui gira il robot

void rotazioneAntioraria(int tempo, int velocita_rotazione) {

  // Motore 1 (Sx) avanti - senso antiorario
  // Motore 2 (Dx) avanti - senso orario

  analogWrite(velocita_M1, velocita_rotazione); // Imposta la velocità del motore M1 a velocità = 200
  analogWrite(velocita_M2, velocita_rotazione); // Imposta la velocità del motore M2 a velocità = 200

  // per far girare il motore M1 (Sx) in senso antiorario
  // per far girare il motore M2 (Dx) in senso orario

  digitalWrite(direzione1_M1, LOW);
  digitalWrite(direzione2_M1, HIGH);
  digitalWrite(direzione1_M2, HIGH);
  digitalWrite(direzione2_M2, LOW);
  delay(tempo);
}

// rotazione antioraria di EduRobot sul proprio asse
// tempo: tempo per compiere uno specifico angolo di rotazione
// velocita_rotazione: velocità con cui gira il robot

void rotazioneOraria(int tempo, int velocita_rotazione) {

  // Motore 1 (Sx) - senso orario
  // Motore 2 (Dx) - senso antiorario

  analogWrite(velocita_M1, velocita_rotazione); // Imposta la velocità del motore M1 a velocità = 200
  analogWrite(velocita_M2, velocita_rotazione); // Imposta la velocità del motore M2 a velocità = 200

  // per far girare il motore M1 (Sx) in senso orario
  // per far girare il motore M2 (Dx) in senso antiorario

  digitalWrite(direzione1_M1, HIGH);
  digitalWrite(direzione2_M1, LOW);
  digitalWrite(direzione1_M2, LOW);
  digitalWrite(direzione2_M2, HIGH);
  delay(tempo);
}

// ferma i motori
void stopEduRobot() {
  // Per fermare il motore impostare a 0 il secondo parametro
  analogWrite(velocita_M1, 0);
  analogWrite(velocita_M2, 0);
}

// Movimento in Avanti di EduRobot
void avantiPer(int tempo_avanti)
{
  // Motore 1 (Sx) avanti - senso antiorario
  // Motore 2 (Dx) avanti - senso orario

  analogWrite(velocita_M1, velocita_avanti); // Imposta la velocità del motore M1 a velocita_avanti
  analogWrite(velocita_M2, velocita_avanti); // Imposta la velocità del motore M2 a velocita_avanti

  // per far girare il motore M1 (Sx) in senso antiorario
  // per far girare il motore M2 (Dx) in senso orario

  digitalWrite(direzione1_M1, HIGH);
  digitalWrite(direzione2_M1, LOW);
  digitalWrite(direzione1_M2, HIGH);
  digitalWrite(direzione2_M2, LOW);
  delay(tempo_avanti);

}

void loop() {

  // avanti per 500 millisecondi, stop per 3 secondi
  avantiPer(500);
  stopEduRobot();
  delay(3000);

  // rotazione di 180° in senso orario del robot, stop di 1 secondo
  rotazioneOraria(tempo_rotazione_angolo, velocita_rotazione);
  rotazioneOraria(tempo_rotazione_angolo, velocita_rotazione);
  stopEduRobot();
  delay(1000);

  // avanti per 500 millisecondi, stop di 3 secondi
  avantiPer(500);
  stopEduRobot();
  delay(3000);

  // rotazione di 180° in senso antiorario, stop di 1 secondo
  rotazioneAntioraria(tempo_rotazione_angolo, velocita_rotazione);
  rotazioneAntioraria(tempo_rotazione_angolo, velocita_rotazione);
  stopEduRobot();
  delay(1000);

}

Sketch 5

Realizzare uno sketch che permetta di realizzare in sequenza le tre rotazioni:

  1. 45° in senso antiorario del robot
  2. dalla posizione raggiunta rotazione di 90° in senso orario
  3. dalla posizione raggiunta, rotazione di 45° in senso antiorario

Sketch 6

Utilizzando il sensore ad ultrasuoni HC-SR04 per rilevare gli ostacoli ed effettuare la scelta della direzione da intraprendere in funzione dell’ostacolo che si trova a distanza maggiore dal robot.

Funzionamento del sensore HC-SR04

Per l’utilizzo del sensore ad ultrasuoni ne avevo già dato spiegazione in EduRobot UNO – Come costruire il vostro primo Arduino Robot – Lezione 2  ma per permetterne un’agevole studio duplico quanto già scritto nel tutorial in modo che abbiate un punto unico di riferimento.

Per far evitare gli ostacoli al nostro robot utilizzeremo un sensore ad ultrasuoni, in altro modo useremo questo sensore per misurare la distanza dell’ostacolo, ma potremo anche pensare di usare questo sensore, ad esempio, in un sistema anti-intrusione che deve far suonare un allarme. In questa lezione viene utilizzato il sensore HC-SR04, dispositivo economico e con un buon range operativo, ha una sensibilità dichiarata nei datasheet che va da 2 centimetri a 4,5 metri circa, in realtà la massima distanza da esperimenti che ho effettuato arriva a circa 3,5 metri, molto comunque dipende dai materiali colpiti e dalla loro capacità di assorbimento sonoro.

Ma come funziona un sensore di questo tipo?

I sensori ad ultrasuoni non forniscono direttamente la misura della distanza dell’oggetto più vicino, ma misurano il tempo impiegato da un segnale sonoro a raggiungere l’oggetto e ritornare al sensore.

L’impulso ad ultrasuoni inviato all’HC-SR04 è di circa 40KHz il tempo viene misurato in microsecondi, la tensione di funzionamento è di 5V, quindi potremo alimentarlo direttamente utilizzando Arduino.

L’HC-SR04 è dotato di 4 piedini: GND, eco, trigger, +Vcc.

Per convertire l’intervallo di tempo misurato in una lunghezza, bisogna ricordare che la velocità del suono è di 331,5 m/s a 0 °C e di 343,4 m/s a 20 °C ed in generale varia secondo la relazione:

v = 331,4 + 0,62 T

dove la temperatura T è misurata in °C.

Per effettuare una misura di distanza di un ostacolo assumiamo di lavorare ad una temperatura ambiente di 20 °C e quindi la velocità del suono sarà di 343 m/s (approssimiamo) che vuol dire anche 0,0343 cm/microsecondi.

Quindi, ricordando che v=s/t (v: velocità, s: spazio, t: tempo) allora lo spazio percorso sarà:

s = v*t

da cui

s = 0,0343 *t

però, per calcolare lo spazio percorso, bisogna tener conto che il suono percorre due volte la distanza da misurare (giunge sull’oggetto e ritorna indietro al sensore) quindi il valore di t ottenuto deve essere diviso per 2. La formula corretta per la misura dello spazio percorso è:

s = 0,0343 * t/2

eseguendo la divisione di 0,0343/2 possiamo scrivere:

s = 0,01715 * t

oppure:

s = t/58,31

approssimando

s = t/58

formula più semplice da ricordare.

Per calcolare la distanza dell’oggetto dal sensore sarà sufficiente dividere il tempo t (tempo impiegato dal segnale per giungere sull’oggetto e tornare al sensore) per 58.

Per poter effettuare una misurazione viene mantenuto a livello basso il pin Trigger, dopo di che viene fornito un impulso a livello alto della durata minima di 10µs riportandolo poi a livello basso, dopo questo momento la capsula trasmittente emette un burst (sequenza di livelli alti/bassi) a circa 40KHz, l’onda ultrasonica generata (burst) colpisce l’ostacolo, torna indietro venendo rilevata dalla capsula ricevente. L’elettronica del sensore effettua un calcolo del tempo di andata e ritorno del segnale emettendo sul pin Echo, normalmente a livello basso, un segnale a livello alto direttamente proporzionale alla distanza dell’ostacolo:

/*
  Prof. Maffucci Michele
  21.01.19

  EduRobot - Programma test n. 8
  Utilizzando il sensore ad ultrasuoni rilevare gli ostacoli ed effettuare la scelta
  della direzione da intraprendere in funzione dell’ostacolo che si
  trova a distanza maggiore dal robot.

  Collegamenti:

  L298N -->  Arduino

  ENB  -->  Pin 10
  IN4  -->  Pin 5
  IN3  -->  Pin 4
  IN2  -->  Pin 3
  IN1  -->  Pin 2
  ENA  -->  Pin 9
  +12V -->  Vin
  GND  -->  GND
*/

// Impostazione pin motori

// motore 1 (sx)

int direzione1_M1 = 2;
int direzione2_M1 = 3;
int velocita_M1 = 9; // pin di tipo PWM per controllare la velocità del motore

// motore 2 (dx)

int direzione1_M2 = 4;
int direzione2_M2 = 5;
int velocita_M2 = 10; // pin di tipo PWM per controllare la velocità del motore

int velocita = 200;               // velocità di rotazione dei motori. Valore compreso tra 0 e 255
int velocita_scelta_dir = 150;    // velocità di rotazione dei motori per la scelta direzione. Valore compreso tra 0 e 255

int tempo_rotazione = 500;        // quantità di tempo di rotazione o di fermo motore

int tempo_rotazione_angolo = 350; // tempo per far ruotare il motore di 90°. Da variare in funzione della carica della batteria.
int velocita_rotazione = 150;     // velocità di rotazione di EduRobot sul proprio asse
int velocita_avanti = 150;        // velocità di avanzamento in avanti di EduRobot

int attesa = 3000; // tempo di attesa prima che il robot si muova

// Impostazione sensore ultrasuoni
const int distanzaPericolo = 20;      // distanza minima dell'ostacolo (in cm)
int distanzaSinistra, distanzaDestra; // distanza sinistra e destra
int misuraDistanza = 0;

long durata;            // durata dell'impulso
long distanza;          // distanza dell'oggetto
int pin_segnale = 7;    // pin Arduino a cui è collegato il sensore SR04
int pin_trig = 6;       // pin Arduino a cui è collegato il sensore SR04

void setup() {

  // modalità di utilizzo dei pin di controllo
  pinMode(direzione1_M1, OUTPUT);
  pinMode(direzione2_M1, OUTPUT);
  pinMode(velocita_M1, OUTPUT);
  pinMode(direzione1_M2, OUTPUT);
  pinMode(direzione2_M2, OUTPUT);
  pinMode(velocita_M2, OUTPUT);

  // impostazione pin per sensore ultrasuoni SR04
  pinMode(pin_trig, OUTPUT);
  pinMode(pin_segnale, INPUT);

  delay(attesa);
}

// rotazione oraria di EduRobot sul proprio asse
// tempo: tempo per compiere uno specifico angolo di rotazione
// velocita_rotazione: velocità con cui gira il robot

void rotazioneAntioraria(int tempo, int velocita_rotazione) {

  // Motore 1 (Sx) avanti - senso antiorario
  // Motore 2 (Dx) avanti - senso orario

  analogWrite(velocita_M1, velocita_rotazione); // Imposta la velocità del motore M1 a velocità = 200
  analogWrite(velocita_M2, velocita_rotazione); // Imposta la velocità del motore M2 a velocità = 200

  // per far girare il motore M1 (Sx) in senso antiorario
  // per far girare il motore M2 (Dx) in senso orario

  digitalWrite(direzione1_M1, LOW);
  digitalWrite(direzione2_M1, HIGH);
  digitalWrite(direzione1_M2, HIGH);
  digitalWrite(direzione2_M2, LOW);
  delay(tempo);
}

// rotazione antioraria di EduRobot sul proprio asse
// tempo: tempo per compiere uno specifico angolo di rotazione
// velocita_rotazione: velocità con cui gira il robot

void rotazioneOraria(int tempo, int velocita_rotazione) {

  // Motore 1 (Sx) - senso orario
  // Motore 2 (Dx) - senso antiorario

  analogWrite(velocita_M1, velocita_rotazione); // Imposta la velocità del motore M1 a velocità = 200
  analogWrite(velocita_M2, velocita_rotazione); // Imposta la velocità del motore M2 a velocità = 200

  // per far girare il motore M1 (Sx) in senso orario
  // per far girare il motore M2 (Dx) in senso antiorario

  digitalWrite(direzione1_M1, HIGH);
  digitalWrite(direzione2_M1, LOW);
  digitalWrite(direzione1_M2, LOW);
  digitalWrite(direzione2_M2, HIGH);
  delay(tempo);
}

// ferma i motori
void stopEduRobot() {
  // Per fermare il motore impostare a 0 il secondo parametro
  analogWrite(velocita_M1, 0);
  analogWrite(velocita_M2, 0);
}

// Movimento in Avanti di EduRobot
void avantiPer(int tempo_avanti)
{
  // Motore 1 (Sx) avanti - senso antiorario
  // Motore 2 (Dx) avanti - senso orario

  analogWrite(velocita_M1, velocita_avanti); // Imposta la velocità del motore M1 a velocita_avanti
  analogWrite(velocita_M2, velocita_avanti); // Imposta la velocità del motore M2 a velocita_avanti

  // per far girare il motore M1 (Sx) in senso antiorario
  // per far girare il motore M2 (Dx) in senso orario

  digitalWrite(direzione1_M1, HIGH);
  digitalWrite(direzione2_M1, LOW);
  digitalWrite(direzione1_M2, HIGH);
  digitalWrite(direzione2_M2, LOW);
  delay(tempo_avanti);

}

void avantiSempre(int velocita)
{

  // Motore 1 (Sx) - senso antiorario

  analogWrite(velocita_M1, velocita); // Imposta la velocità del motore M1 a velocità = 200

  // per far girare il motore M1 (Sx) in senso antiorario
  digitalWrite(direzione1_M1, HIGH);
  digitalWrite(direzione2_M1, LOW);

  // Motore 2 (Dx) - senso orario

  analogWrite(velocita_M2, velocita); // Imposta la velocità del motore M2 a velocità = 200

  // per far girare il motore M2 (Dx) in senso orario
  digitalWrite(direzione1_M2, HIGH);
  digitalWrite(direzione2_M2, LOW);
}

// Indietro senza stop
void indietroSempre(int velocita)
{

  // Motore 1 (Sx) - in senso orario

  analogWrite(velocita_M1, velocita); // Imposta la velocità del motore M1 a velocità = 200

  // per far girare il motore M1 (Sx) in senso orario
  digitalWrite(direzione1_M1, LOW);
  digitalWrite(direzione2_M1, HIGH);

  // Motore 2 (Dx) - senso antiorario

  analogWrite(velocita_M2, velocita); // Imposta la velocità del motore M2 a velocità = 200

  // per far girare il motore M2 (Dx) in senso antiorario
  digitalWrite(direzione1_M2, LOW);
  digitalWrite(direzione2_M2, HIGH);
}

// restituisce la distanza in cm dell’ostacolo rilevato
long distanzaOstacolo()
{
  digitalWrite(pin_trig, LOW);
  delayMicroseconds(2);
  digitalWrite(pin_trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(pin_trig, LOW);
  durata = pulseIn(pin_segnale, HIGH);
  distanza = (durata / 2) / 29.1;
  delay(100);
  return distanza;
}

// verifica la distanza dell’ostacolo che si trova a distanza maggiore dal robot
void paragonaDistanze()
{
  if (distanzaSinistra > distanzaDestra) // vai a sinistra perchè ostacolo a sx più lontano
  {
    rotazioneAntioraria(tempo_rotazione_angolo, velocita_scelta_dir);
    delay(500);
  }
  else if (distanzaDestra < distanzaSinistra) // vai a destra perchè ostacolo a dx più lontano
  {
    rotazioneOraria(tempo_rotazione_angolo, velocita_scelta_dir);
    delay(500);
  }
  else // se le distanze degli ostacoli a
  { // sx e dx sono uguali gira di 180 gradi (circa)
    rotazioneOraria(tempo_rotazione_angolo, velocita_scelta_dir);
    rotazioneOraria(tempo_rotazione_angolo, velocita_scelta_dir);
    delay(1000);
  }
}

// sceglie la direzione da prendere in funzione della distanza a cui si trova l’ostacolo
void scegliDirezione() {
  rotazioneOraria(tempo_rotazione_angolo, velocita_scelta_dir);
  distanzaDestra = distanzaOstacolo();   // lettura distanza ostacolo di dx
  delay(500);
  rotazioneAntioraria(tempo_rotazione_angolo, velocita_scelta_dir);
  rotazioneAntioraria(tempo_rotazione_angolo, velocita_scelta_dir);
  distanzaSinistra = distanzaOstacolo(); // lettura distanza ostacolo di sx
  delay(500);
  rotazioneOraria(tempo_rotazione_angolo, velocita_scelta_dir);
  delay(100);
  paragonaDistanze();
}

void loop() {
  misuraDistanza = distanzaOstacolo();
  if (misuraDistanza > distanzaPericolo) // vai avanti
  {
    avantiSempre(velocita_avanti);                      // se non ci sono ostacoli vai avanti
  }
  // valutazione dell'ostacolo che si trova a distanza maggiore
  // se l'ostacolo si trova a distanza minore di "distanzaPericolo"
  // bisogna scegliere la direzione
  else
  {
    stopEduRobot();
    scegliDirezione();
  }
}

Descrizione sketch 6

Nota: si descrivono solo le sezioni aggiunte rispetto agli sketch precedenti.

Impostazione del sensore ad ultrasuoni

...
// Impostazione sensore ultrasuoni
const int distanzaPericolo = 20;      // distanza minima dell'ostacolo (in cm)
int distanzaSinistra, distanzaDestra; // distanza sinistra e destra
int misuraDistanza = 0;

long durata;            // durata dell'impulso
long distanza;          // distanza dell'oggetto
int pin_segnale = 7;    // pin Arduino a cui è collegato il sensore SR04
int pin_trig = 6;       // pin Arduino a cui è collegato il sensore SR04
...

Questa sezione è dedicata all’impostazione del sensore ad ultrasuoni.

La variabile “durata” è il tempo impiegato dall’onda ultrasonica per giungere al rilevatore, questo valore verrà utilizzato per il calcolo della distanza dell’oggetto.
Le due variabili: pin_segnale e pin_trig sono quelle associate ai pin signal e trigger del sensore ad ultrasuoni.

Descrizione funzionamento loop()

...
void loop() {
  misuraDistanza = distanzaOstacolo();
  if (misuraDistanza > distanzaPericolo) // vai avanti
  {
    avantiSempre(velocita_avanti);       // se non ci sono ostacoli vai avanti
  }
  // valutazione dell'ostacolo che si trova a distanza maggiore
  // se l'ostacolo si trova a distanza minore di "distanzaPericolo"
  // bisogna scegliere la direzione
  else
  {
    stopEduRobot();
    scegliDirezione();
  }
}
...

Nel loop() come prima azione viene memorizzata nella variabile misuraDistanza il valore restituito dalla funzione che calcola la distanza dell’ostacolo: distanzaOstacolo() che riceve le informazioni dal sensore ad ultrasuoni.
Se la distanza misurata è maggiore della distanzaPericolo, la minima distanza dall’ostacolo, allora vuol dire che EduRobot può continuare ad andare avanti, altrimenti se la misuraDistanza è inferiore alla distanza di pericolo bisogna fermare EduRobot ed effettuare il cambio di direzione.

...
  {
    stopEduRobot();
    scegliDirezione();
  }
...

Scelta della direzione da prendere

...
// sceglie la direzione da prendere in funzione della distanza a cui si trova l’ostacolo
void scegliDirezione() {
  rotazioneOraria(tempo_rotazione_angolo, velocita_scelta_dir);
  distanzaDestra = distanzaOstacolo();   // lettura distanza ostacolo di dx
  delay(500);
  rotazioneAntioraria(tempo_rotazione_angolo, velocita_scelta_dir);
  rotazioneAntioraria(tempo_rotazione_angolo, velocita_scelta_dir);
  distanzaSinistra = distanzaOstacolo(); // lettura distanza ostacolo di sx
  delay(500);
  rotazioneOraria(tempo_rotazione_angolo, velocita_scelta_dir);
  delay(100);
  paragonaDistanze();
}
...

EduRobot effettua una rotazione di 90° a destra, effettua la lettura ed assegna il valore letto alla variabile distanzaDestra, si ferma nella posizione per mezzo secondo.
EduRobot effettua una rotazione di 180° in senso antiorario rispetto alla precedente posizione effettua la lettura della distanza dell’ostacolo che viene memorizzata nella variabile distanzaSinistra, si ferma nella posizione per mezzo secondo.
Si pone nuovamente in posizione frontale ruotando in senso orario di 90°, mantiene la posizione ed invoca la funzione paragonaDistanze() che verifica quale delle due misure risulta maggiore.

Lettura della distanza dell’ostacolo

...
// restituisce la distanza in cm dell’ostacolo rilevato
long distanzaOstacolo()
{
  digitalWrite(pin_trig, LOW);
  delayMicroseconds(2);
  digitalWrite(pin_trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(pin_trig, LOW);
  durata = pulseIn(pin_segnale, HIGH);
  distanza = (durata / 2) / 29.1;
  delay(100);
  return distanza;
}
...

La modalità di funzionamento di questa funzione è stata descritta nella parte iniziale della sezione dedicata allo sketch 6.

Paragonare le distanze per la scelta del percorso

...
// verifica la distanza dell’ostacolo che si trova a distanza maggiore dal robot
void paragonaDistanze()
{
  if (distanzaSinistra > distanzaDestra) // vai a sinistra perchè ostacolo a sx più lontano
  {
    rotazioneAntioraria(tempo_rotazione_angolo, velocita_scelta_dir);
    delay(500);
  }
  else if (distanzaDestra < distanzaSinistra) // vai a destra perchè ostacolo a dx più lontano
  {
    rotazioneOraria(tempo_rotazione_angolo, velocita_scelta_dir);
    delay(500);
  }
  else // se le distanze degli ostacoli a
  { // sx e dx sono uguali gira di 180 gradi (circa)
    rotazioneOraria(tempo_rotazione_angolo, velocita_scelta_dir);
    rotazioneOraria(tempo_rotazione_angolo, velocita_scelta_dir);
    delay(1000);
  }
}
...

Nel caso in cui l’ostacolo che si trova a sinistra è ad una distanza maggiore da quello dell’ostacolo di destra, allora EduRobot ruoterà in senso antiorario di 90° e manterrà la posizione raggiunta per mezzo secondo.

Se invece l’ostacolo che si trova a destra si trova a distanza maggiore di quello di sinistra, allora EduRobot ruoterà in senso orario di 90° e manterrà la posizione raggiunta per mezzo secondo.

Se le distanze degli ostacoli a sinistra e a destra sono identiche, EduRobot ruota di 180° in senso orario e mantiene la posizione per 1 secondo.

Movimento continuo in avanti e indietro alla velocità scelta

...
void avantiSempre(int velocita)
{

  // Motore 1 (Sx) - senso antiorario

  analogWrite(velocita_M1, velocita); // Imposta la velocità del motore M1 a velocità = 200

  // per far girare il motore M1 (Sx) in senso antiorario
  digitalWrite(direzione1_M1, HIGH);
  digitalWrite(direzione2_M1, LOW);

  // Motore 2 (Dx) - senso orario

  analogWrite(velocita_M2, velocita); // Imposta la velocità del motore M2 a velocità = 200

  // per far girare il motore M2 (Dx) in senso orario
  digitalWrite(direzione1_M2, HIGH);
  digitalWrite(direzione2_M2, LOW);
}

// Indietro senza stop
void indietroSempre(int velocita)
{

  // Motore 1 (Sx) - in senso orario

  analogWrite(velocita_M1, velocita); // Imposta la velocità del motore M1 a velocità = 200

  // per far girare il motore M1 (Sx) in senso orario
  digitalWrite(direzione1_M1, LOW);
  digitalWrite(direzione2_M1, HIGH);

  // Motore 2 (Dx) - senso antiorario

  analogWrite(velocita_M2, velocita); // Imposta la velocità del motore M2 a velocità = 200

  // per far girare il motore M2 (Dx) in senso antiorario
  digitalWrite(direzione1_M2, LOW);
  digitalWrite(direzione2_M2, HIGH);
}
...

Nel codice sopra indicato avantiSempre(int velocita) permette di movimentare EduRobot in avanti ad una specifica velocità è necessario far girare la ruota sinistra in senso antiorario e lo destra in senso orario, mentre indietroSempre(int velocita) permette di muovere indietro (in retromarcia) EduRobot alla specifica velociotà è necessario far girare la ruota sinistra in senso orario e lo destra in senso antiorario.

Esercizi

Esercizio 1

Ad ogni stop del robot si accendere un led rosso.

Esercizio 2

Ad ogni stop si accendere un led rosso e durante la scelta della direzione lampeggia un led giallo.

Esercizio 3

Ad ogni stop si accendere un led rosso e durante la scelta della direzione lampeggia un led giallo, mentre il movimento in avanti ed indietro è evidenziato da un led verde acceso che dovrà spegnersi durante la scelta della direzione.

Esercizio 4

Aggiungere al circuito dell’esercizio precedente un buzzer che all’avvio del robot per 2 secondi, vengano suonate alcune note musicali.

Esercizio 5

Aggiungere al circuito dell’esercizio precedente un buzzer che all’avvio del robot per 2 secondi,emetta un jingle musicale ed ogni volta che viene effettuata la rilevazione del percorso da intraprendere vengano suonate alcune note musicali.

Esercizio 6

Aggiungere una funzione di casualità che ad intervalli prestabiliti fa cambiare direzione al robot indipendentemente dalla scelta della direzione verso l’ostacolo più lontano.

Esercizio 7

EduRobot non è dotato di un encoder, ovvero un sistema in grado di regolare la velocità delle due in modo da far andare dritto il robot, avrai notato che un motore gira ad una velocità superiore rispetto ad un’altro.

Saresti in grado di realizzare un semplice programma di calibrazione da eseguire in fase iniziale in grado di migliorare leggermente il movimento rettilineo del robot?

Buona sperimentazione a tutti 🙂