Robotica educativa/Invio di un SOS

Wikibooks, manuali e libri di testo liberi.
Indice del libro

Il primo passo nella programmazione è la creazione di un led lampeggiante. Funziona, si può gridare al mondo «Questo l'ho fatto io!», ma – alla fine dei conti – non è poi così divertente.

Salvaci O Signore[modifica]

Chiamata SOS col codice Morse

L'SOS è la sequenza di tre lettere che normalmente descrive il segnale universale di richiesta di soccorso. Espresso in codice Morse è estremamente semplici: tre punti, tre linee, tre punti (si scrive: · · · — — — · · ·). Si trasmette senza separazione fra le singole lettere, come fosse un'unica parola, ed è così semplice da permettere anche a non esperti di recepire immediatamente il messaggio.

Invece la genesi è un po' incerta: subito occorre soccorso, salvate le nostre anime, dall'inglese save our souls, oppure save our ship, ovvero salvate la nostra nave. Non c'è certezza sul vero significato. Ecco spiegato il motivo del titolo.

Suddivisione del programma[modifica]

Scrivere l'intero programma tutto in una volta non è facile e può dar facilmente luogo a errori. Per questo vengono in soccorso le funzioni. Non solo quelle che ci fornisce l'ambiente di sviluppo, ma – soprattutto – quelle che scriveremo noi:

  • punto
  • linea
  • S
  • O

Le persone più audaci avranno già capito che punto e linea verranno definite per prime. Seguiranno le lettere S e O. Dopodiché, sarà sufficiente richiamare le funzioni S, O, S (in quest'ordine) è il programma funzionerà come per magia.

No, non è magia: è tecnologia.

Cominciamo dalla fine[modifica]

Quest'approccio (chiudere gli occhi, sognare e fingere che tutto sia già stato fatto) è quello che più aiuta, perché consente di concentrarsi sul problema. I programmatori che amano darsi un tono la chiamano tecnologia top-down-botton-up.

Pertanto ora il programma principale diventerà semplicemente la chiamata delle tre lettere dell'SOS, seguite da una pausa: la pausa tra parole.

La funzione che consente di generare una pausa è delay(ms); dove:

  1. delay è il nome della funzione;
  2. ms è il suo argomento che viene racchiuso tra parentesi tonde. Esprime il tempo di pausa in millisecondi (1000 significa un secondo);
  3. il simbolo ; dice alla macchina che l'operazione è terminata. Verrà inserito al termine di ogni funzione e comando.

Ora, il programma assumerà questa forma:

void setup() {
  // inserisci qui il codice di configurazione, verrà eseguito una volta sola:

}

void loop() {
  // Invocazione di un SOS
  S();
  O();
  S();
  
  // Attende un secondo
  delay(1000);
}

Le funzioni vengono richiamate con S(); perché non hanno argomenti. Se si volesse scrivere un programma più complesso (per esempio che può scrivere tutte le parole o frasi) si scriverà una funzione che avrà come argomento la lettera o la frase, esattamente come avviene per delay.

Come è facile intuire, il simbolo // precede un commento a spiegazione del codice. Anche i programmatori esperti li usano per sapere cosa svolge il codice e ricordarselo anche dopo mesi o anni. Il commento termina quando si va a capo.

A questo punto, si devono definire le lettere: in particolare la S e la O. Per farlo verranno inserite altre due funzioni nel codice: punto e linea. Ma niente fretta: come detto prima, cominciamo dalla fine.

void setup() {
  // inserisci qui il codice di configurazione, verrà eseguito una volta sola:

}

void loop() {
  // Invocazione di un SOS
  S();
  O();
  S();
  
  // Attende un secondo
  delay(1000);
}

// Lettera O dell'alfabeto Morse
void O() {
  linea();
  linea();
  linea();
}

// Lettera S dell'alfabeto Morse
void S() {
  punto();
  punto();
  punto();
}

Due parole sulle funzioni[modifica]

Le funzioni devono poter essere richiamate (sennò sarebbe inutile scriverle). Ecco perché hanno un nome. Sin qui tutto bene. Ma non tutti i nomi sono ammessi (e ti pareva!). Niente paura: non si possono usare i nomi delle funzioni già definite nell'ambiente di sviluppo di Arduino. Questo significa che se le funzioni utente (così si chiamano quelle che si creano per il proprio programma) non vengono scritte in inglese è altamente improbabile che ci siano problemi.

Per chi ama la lingua d'oltralpe è buona prassi chiamare le funzioni in un modo personale, tipo myFunction, così da evitare conflitti di interessi.

Dopodiché vengono gli argomenti: uno, nessuno, centomila. Si dichiarano all'interno della parentesi specificandone il tipo, come float divisione(float divisore, float dividendo) dove float significa che divisore e dividendo sono numeri che possono avere la virgola, mentre void (usato già più volte) significa argomento vuoto, o nessun argomento. Ma dal momento che ogni oggetto deve averne uno, quando non ve ne sono si utilizza questo.

Infine, i vari argomenti, si separano con una virgola.

Ora è il momento di scrivere cosa devono fare punto e linea e terminare il codice.

Per organizzare meglio il lavoro iniziamo dalle definizioni: esistono anche qua, si scrivono una per riga e... sono le uniche a non richiedere il ; finale, poiché richiedono che si vada a capo.

Servono a rendere più ordinato e comprensibile il codice, così vengono scritte all'inizio. E sono magiche: non occupano memoria perché al loro posto – nel programma – verranno usati i valori specificati che potranno sempre essere modificati. Quindi, il loro utilizzo presenta solo vantaggi.

Basta scrivere #define IVA 0.22 per fare quello che immaginate (applicare l'IVA a un importo, ma non è questo il caso).

// Definizioni
#define tempoPunto         250
#define tempoLinea         500

#define intervallo         200
#define intervalloLettere  500
#define intervalloParole  1000

#define pinLed              13

void setup() {
  // Specifica che il pin n. 13 e' un'uscita
  pinMode(pinLed, OUTPUT);
}

void loop() {
  // Invocazione di un SOS
  S();
  O();
  S();
  
  // Attende un secondo (intervallo tra parole)
  delay(intervalloParole);
}

// Lettera O dell'alfabeto Morse
void O() {
  linea();
  linea();
  linea();
}

// Lettera S dell'alfabeto Morse
void S() {
  punto();
  punto();
  punto();
}

// Singolo punto
void punto(){
  // Accende il led e aspetta 250 ms
  digitalWrite(pinLed, HIGH);
  delay(tempoPunto);
  // Spegne il led e aspetta 200 ms
  digitalWrite(pinLed, LOW);
  delay(intervallo);
}

// Singola linea
void linea(){
  // Accende il led e aspetta 500 ms
  digitalWrite(pinLed, HIGH);
  delay(tempoLinea);
  // Spegne il led e aspetta 200 ms
  digitalWrite(pinLed, LOW);
  delay(intervallo);
}

Nel setup, una volta per tutte, si specifica che il pin n. 13 (ma, modificando la definizione, cambia anche il circuito) è un'uscita (OUTPUT).

Le funzioni punto e linea sono praticamente identiche: differiscono per il tempo che mantengono acceso il led.

L'uscita viene controllata con la funzione digitalWrite che ha due argomenti: il pin in cui va a lavorare e il livello di tensione, il quale può essere LOW (basso, ) oppure HIGH (alto, ).

Schema di montaggio[modifica]

Oltre alla scheda Arduino, per utilizzare il diodo LED occorre anche una resistenza elettrica come in tabella:

Componenti utilizzati
Componente Valore
Diodo LED Rosso
Resistenza

Questo perché il diodo è un componente che si oppone al passaggio di corrente elettriche in un senso, ma lo consente nell'altro. Il diodo LED è come un diodo, semplicemente si illumina al passaggio della corrente. Però questa va limitata per non distruggerlo e il modo migliore per farlo è l'utilizzo di una resistenza elettrica, l'equivalente di una strozzatura in una tubatura.

Il valore di è indicativo: se più basso il LED farà più luce, ma avrà una vita media più bassa; viceversa, se sarà più alto la luminosità sarà inferiore.

Ma tutti i led sono uguali?[modifica]

Assolutamente nì! Sono uguali nel senso che producono luce. Per collegarli il terminale da mettere a è il corrispondente del terminale più corto. Se recuperate il LED da un vecchio giocattolo, basta guardarlo all'interno e si noteranno due elementi distinti. A ci va quello di dimensioni maggiori.

Di seguito lo schema di montaggio. La resistenza può essere posta sia prima, sia dopo il collegamento ad Arduino.

Led lampeggiante con arduino

Espansioni suggerite[modifica]

E se volessimo inviare un qualsiasi messaggio in codice Morse?

Per prima cosa dovremmo definire tutte le lettere. Probabilmente sarebbe più elegante scrivere una funzione che, data la lettera, esegue punti e linee opportuni. Dopodiché, non rimarrebbe altro che scrivere il testo.