Finora abbiamo esaminato le strutture di controllo, variabili e funzioni, etc. nella seconda parte di questo corso, abbiamo visto come comunicare con la porta seriale. Oggi lo approfondiremo. Oltre ad utilizzare la porta seriale per eseguire il debug del programma e acquisire informazioni, invieremo anche comandi alla ZUM BT 328, o a qualsiasi altra scheda Arduino, usando il monitor seriale. Per esempio, questo ci permette di inviare un vettore al nostro robot che gli indichi la direzione e la velocità a cui dovrebbe muoversi. Imparerermo a farlo con un segnale analogico usando i pins PWM di Arduino, che utilizzeremo per cambiare il colore di un LED RGB. La funzione PWM della scheda Arduino ci permette di generare un segnale analogico utilizzando segnali digitali. Per saperne di più puoi visitare la pagina di riferimento del PWM.
Lista dei materiali
- La scheda di controllo ZUM BT-328 o una compatibile con Arduino.
- Breadboard (o scheda di test o protoboard).
- LED RGB , in questo caso a catodo comune.
- Cavi jumper.
Collegamenti elettrici
Usando la breadboard, quando si hanno progetti grandi è meglio utilizzare cavi colorati per riconoscere visivamente le varie parti del circuito. Usando un LED RGB possiamo, per esempio utilizzare un cavo di colore rosso per collegare il pin che controlla il LED RGB di colore rosso. Normalmente usiamo un cavo di colore rosso per i fili che portano tensione nel circuito e il nero o marrone per il cavo di terra o GND (ground). Il LED che usiamo in questo esempio è già dotato di resistenze interne che limitano la corrente nei LED, ma se ne hai uno che non ha resistenze incorporate, dovrai collegare per ogni colore una resistenza che evita di bruciare il LED. Questo schema fornisce un esempio di come collegare un LED che non ha resistenze integrate:
In questo progetto, collegheremo il LED RGB e la scheda ZUM BT-328 come vedi sotto:
ZUM BT-328 | LED RGB |
GND | GND |
6 | R |
5 | G |
3 | B |
Il codice
Come al solito, iniziamo a dichiarare le variabili dei pins:
1 |
int redPin = 6, greenPin = 5, bluePin = 3; |
Dichiariamo anche altre variabili che utilizzeremo nel programma:
1 2 3 |
int delayLed = 10; // Tempo che intercorre per ogni variazione di colore LED (ms) // Variabili che memorizzano l'ultimo colore per ogni LED int red_old = 0, green_old = 0, blue_old = 0; |
Nella variabile delayLed, memorizziamo il tempo che deve intercorrere tra l’accensione di un LED e quello successivo. Ti consigliamo di utilizzare un valore molto basso, in quanto il delay è usato per una transizione morbida. Di conseguenza, occorre tener presente che maggiore è il valore, maggiore sarà il tempo per compiere la transizione, per esempio, per un valore di 10 ms, la transizione dal nero al bianco, o da (0,0,0) a (255,255,255), viene completata in 7.6 secondi. La stessa transizione con 5 ms dura 3.8 seconds. Ora utilizziamo la funzione setup per inizializzare il programma:
1 2 3 4 5 6 7 8 9 10 11 |
void setup() { // Avvia la porta seriale. Serial.begin(9600); // Impostiamo i pins come uscite. pinMode(redPin, OUTPUT); pinMode(greenPin, OUTPUT); pinMode(bluePin, OUTPUT); Serial.println("Pronto!"); } |
Avviamo la porta seriale nel setup e la utilizzeremo per comunicare tra Arduino ed il computer. Impostiamo anche come uscite i differenti pins utilizzati per ogni colore. All’interno del loop, possiamo trovare diversi metodi che non abbiamo visto fino ad ora; parseInt e constrain. Il metodo parseInt è usato insieme alla Seriale con il comando Serial.parseInt();. Cerca una serie di numeri che provengono dalla porta seriale finchè non trova una virgola. Puoi vedere la pagina di riferimento qui. La funzione constrain è utilizzata per “comprimere” un valore in un intervallo compreso tra due altri valori. Questo significa che se il valore risulta compreso nell’intervallo A-B, allora manterrà il suo valore. Se è inferiore, assumerà il valore di A o se è maggiore prenderà il valore di B. Puoi vedere la pagina di riferimento qui. Il codice da scrivere nel loop è come segue:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
void setup() { // Avvia la porta seriale. Serial.begin(9600); // Impostiamo i pins come uscita. pinMode(redPin, OUTPUT); pinMode(greenPin, OUTPUT); pinMode(bluePin, OUTPUT); Serial.println("Pronto!"); } void loop() { // Se ci sono informazioni disponibili nella porta seriale le utilizziamo: while (Serial.available() > 0) { int red = 0, green = 0, blue = 0; // Cerca una nuova serie di soli numeri e // assegna un valore convertito in numero alla variabile corrispondente red = Serial.parseInt(); // cerca ancora. green = Serial.parseInt(); // cerca ancora: blue = Serial.parseInt(); // Cerca un carattere linea terminata. Comunica al programma che i dati da ricevere sono finiti. // Se usi la IDE di Arduino o altra IDE che permette di includere il formato // di nuova linea nell'invio dei dati via monitor seriale, cancella il commento // dalla linea 33 e 34. // if (Serial.read() == 'n'){ if (Serial.read() == '*'){ // Usando constrain, siamo sicuri che il valore rimane all'interno dell'intervallo del PWM // Per LEDs ad anodo comune usa, per esempio, per il rosso: red = 255 - constrain(red, 0, 255); red = constrain(red, 0, 255); green = constrain(green, 0, 255); blue = constrain(blue, 0, 255); // stampa i tre numeri in una stringa come esadecimale: Serial.print(red, HEX); Serial.print(green, HEX); Serial.println(blue, HEX); // Cambia il colore del LED RGB fade(redPin, red, red_old); fade(greenPin, green, green_old); fade(bluePin, blue, blue_old); Serial.println("Colore cambiato"); // Memorizziamo il dato dei colori precedenti. red_old = red; green_old = green; blue_old = blue; } } } |
All’interno del loop, puoi notare che viene chiamata la funzione fade, che abbiamo creato per permetterci di cambiare in modo regolare il colore del LED nel nuovo colore. La funzione fade è definita dopo il loop, come di seguito:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
void fade(int pin, int newValue, int aktValue) { // Questa funzione cambia ogni colore corrente in quello successivo // Distinguiamo tra due casi: // 1 - Il nuovo valore è più elevato del valore corrente, così dobbiamo aumentarlo // 2 - Il nuovo valore è più basso di quello corrente, così dobbiamo ridurlo if (newValue < aktValue) { for (int i = aktValue; i <= newValue; i++) {analogWrite(pin, i); delay(delayLed);} } else if (newValue > aktValue) { for (int i = aktValue; i >= newValue; i--) { analogWrite(pin, i); delay(delayLed); } } } |
- In questa funzione possiamo distinguere due casi:
- Il valore successivo è maggiore di quello corrente, così dobbiamo aumentare il valore del LED.
- Il valore successivo è minore di quello corrente, così dobbiamo diminuire il valore del LED.
Un comando che non conosciamo e che usiamo in questa funzione, analogWrite, permette di utilizzare le possibilità offerte dal PWM (pulse width modulation) della nostra scheda. Il PWM simula un segnale analogico usando impulsi discreti di un segnale digitale. Puoi trovare maggiori informazioni nella pagina di riferimento PWM reference.