L'avventura nel mondo degli MSP430 continua, vedremo come arricchire il nostro set di shield aggiuntive assemblando un semplicissimo alimentatore dedicato, inoltre, inizieremo a farle lavorare con i nostri primi codici scritti apposta per l'occasione. Vedremo anche come ottimizzare il semplice codice per ridurre notevolmente le eccessive linee di programma. Mettetevi comodi, l'avventura inizia.

In pratica mi ritrovo un'alimentatore senza troppe pretese ma che mi permetterà di effettuare tutte le prove che mi necessitano con le shield da me assemblate (vedi la prima parte) e con quelle future che mi verranno in mente. Per chi vuole montarsi un'alimentatore più "serio" con le stesse tensioni d'uscita ma con correnti di 3A, può assemblare in base allo schematico in basso.

Penso che, ben presto, monterò il secondo aggiungendoci anche i 9V. Osservando il primo schema si evince che non è stata inserita nessuna protezione sugli eventuali cortocircuiti in uscita, è una cosa che farò in futuro quindi andrà ad allungare la già lunga lista di "cose da fare", mentre il secondo schema non necessita protezione in quanto si trova già all'interno degli LM 2576 (Thermal Shutdown and Current Limit Protection).
Forse sembrerà superfluo farlo presente ma vorrei evitare che qualcuno imiti il mio "errore di distrazione": utilizzando un'alimentatore esterno dobbiamo ricordarci di collegare la massa del LaunchPad alla massa dell'alimentatore o a quella della shield in uso.
Entriamo direttamente nel vivo della programmazione e come prima prova collego la shield degli 8 led e provo a scrivere il mio primo codice, giusto per verificare se effettivamente ho capito come funziona il tutto. Visto che in questo periodo ho iniziato a studiare anche Arduino, per non fare confusione con i due metodi, utilizzo Energia per la programmazione (quindi lo stesso codice potrò utilizzarlo sia con l'MSP430 e sia con Arduino modificando solo il nome dei pin), in seguito farò delle prove anche con CCS (Code Composer Studio).
//LED IN SEQUENZA (versione semplificata)
//
#define led1 P1_0//Nomino i led1-led8 in relazione ai pin del LaunchPad
#define led2 P1_1
#define led3 P1_2
#define led4 P1_3
#define led5 P1_4
#define led6 P1_5
#define led7 P1_6
#define led8 P1_7
//
void setup()
{
pinMode(led1,OUTPUT);//Configuro modalità output per I/O led1-8
pinMode(led2,OUTPUT);
pinMode(led3,OUTPUT);
pinMode(led4,OUTPUT);
pinMode(led5,OUTPUT);
pinMode(led6,OUTPUT);
pinMode(led7,OUTPUT);
pinMode(led8,OUTPUT);
//
digitalWrite(led1,LOW);//Spengo i led
digitalWrite(led2,LOW);
digitalWrite(led3,LOW);
digitalWrite(led4,LOW);
digitalWrite(led5,LOW);
digitalWrite(led6,LOW);
digitalWrite(led7,LOW);
digitalWrite(led8,LOW);
}
//
void loop()
{
digitalWrite(led1,HIGH);//alterno accensione led
delay(500);//attendo 500ms
digitalWrite(led1,LOW);
digitalWrite(led2,HIGH);
delay(500);//attendo 500ms
digitalWrite(led2,LOW);
digitalWrite(led3,HIGH);
delay(500);//attendo 500ms
digitalWrite(led3,LOW);
digitalWrite(led4,HIGH);
delay(500);//attendo 500ms
digitalWrite(led4,LOW);
digitalWrite(led5,HIGH);
delay(500);//attendo 500ms
digitalWrite(led5,LOW);
digitalWrite(led6,HIGH);
delay(500);//attendo 500ms
digitalWrite(led6,LOW);
digitalWrite(led7,HIGH);
delay(500);//attendo 500ms
digitalWrite(led7,LOW);
digitalWrite(led8,HIGH);
delay(500);//attendo 500ms
digitalWrite(led8,LOW);
}
Bene sembra che il funzionamento sia corretto, sono contento del risultato, anche se mi ha fatto impazzire per mezza giornata (avevo dimenticato che alla fine di alcune righe c'e da inserire il ";"). Ero abituato a ben altri metodi di programmazione e trovo questo sistema di una semplicità mostruosa. L'unico neo che trovo in questo codice è che per una operazione così semplice ci sono troppe linee di programma, vedremo in seguito di rimediare modificandolo.
Colleghiamo la shield dei pulsanti e proviamo a scrivere il programma che provvederà a controllare quando un dato pulsante verrà premuto e contemporaneamente accenderà il relativo led.
Questo è il secondo codice:
//LETTURA PULSANTI (versione semplificata)
//
#define led1 P1_0//Nomino i led1-6 in relazione ai pin del LaunchPad
#define led2 P1_1
#define led3 P1_2
#define led4 P1_3
#define led5 P1_4
#define led6 P1_5
//
#define Button1 P2_0//assegno un pulsante ad ogni pin del 2553
#define Button2 P2_1
#define Button3 P2_2
#define Button4 P2_3
#define Button5 P2_4
#define Button6 P2_5
//
int buttonState = 0;//inizializzo la variabile di lettura stato pulsante
//
void setup()
{
pinMode(led1,OUTPUT);//configuro modalità output per I/O led1-6
pinMode(led2,OUTPUT);
pinMode(led3,OUTPUT);
pinMode(led4,OUTPUT);
pinMode(led5,OUTPUT);
pinMode(led6,OUTPUT);
//
digitalWrite(led1,LOW);//mi assicuro che i led siano spenti
digitalWrite(led1,LOW);
digitalWrite(led3,LOW);
digitalWrite(led4,LOW);
digitalWrite(led5,LOW);
digitalWrite(led6,LOW);
//
pinMode(Button1, INPUT);//configuro modalità input per I/O Button1-6
pinMode(Button2, INPUT);
pinMode(Button3, INPUT);
pinMode(Button4, INPUT);
pinMode(Button5, INPUT);
pinMode(Button6, INPUT);
}
//
void loop()
{
//accendo i led in relazione al pulsante pigiato
buttonState = digitalRead(Button1);
if (buttonState == LOW) {
digitalWrite(led1,HIGH);
}
digitalWrite(led1,LOW);
buttonState = digitalRead(Button2);
if (buttonState == LOW) {
digitalWrite(led2,HIGH);
}
digitalWrite(led2,LOW);
buttonState = digitalRead(Button3);
if (digitalRead(Button3) == LOW) {
digitalWrite(led3,HIGH);
}
digitalWrite(led3,LOW);
buttonState = digitalRead(Button4);
if (digitalRead(Button4) == LOW) {
digitalWrite(led4,HIGH);
}
digitalWrite(led4,LOW);
buttonState = digitalRead(Button5);
if (digitalRead(Button5) == LOW) {
digitalWrite(led5,HIGH);
}
digitalWrite(led5,LOW);
buttonState = digitalRead(Button6);
if (digitalRead(Button6) == LOW) {
digitalWrite(led6,HIGH);
}
digitalWrite(led6,LOW);
}
Ottimo! anche questo funziona, appena si pigia uno qualsiasi dei sei pulsanti automaticamente si accende il led ad esso correlato e, nell'istante in cui si rilascia il pulsante il led si spegne. Anche in questo caso il codice è ben leggibile ma troppo lungo per una operazione così semplice, quindi anche questo andrà ottimizzato per avere meno righe di programma. Prima di fare ciò, vorrei provare anche la shield display alfanumerico, sono curioso di vedere se funziona e se riesco a scrivere un codice anche per questa.
Colleghiamo la shield display e scriviamo il seguente programma:
//CONTASECONDI
//
#include <LiquidCrystal.h>
// inizializzo la libreria
LiquidCrystal lcd(P2_0, P2_1, P2_2, P2_3, P2_4, P2_5);
#define Button1 P1_0
#define Button2 P1_1
int buttonState = 0;
//
void setup()
{
pinMode(Button1, INPUT);
pinMode(Button2, INPUT);
lcd.begin(16, 2);//configuro numero caratteri e righe
lcd.print("S1 per Start");//visualizzo il messaggio su LCD
}
//
void loop()
{
buttonState = digitalRead(Button1);
if (buttonState == LOW)
{
lcd.setCursor(0, 0);//setto il cursore sul primo carattere della riga uno
lcd.print("S2 per Stop-");//visualizzo il secondo messaggio
buttonState = digitalRead(Button2);
while (buttonState == HIGH)
{
lcd.setCursor(0, 1);//setto il cursore sul primo carattere della riga due
lcd.print(millis()/1000);//visualizzo il conteggio dei secondi
buttonState = digitalRead(Button2);
if (buttonState == LOW) break;//fermo il conteggio alla pressione di S2
}
}
}
Per scrivere questo codice ho modificato l'esempio di "Hello World" presente all'interno di Energia e a quanto pare funziona anche questo. In pratica il display visualizza che per far partire il conteggio dobbiamo pressare il pulsante S1, e per bloccarlo il pulsante S2, è chiaro che può essere notevolmente migliorato, per ora mi interessa solo provare le varie possibilità.
Vediamo in che modo possiamo ottimizzare per non avere dei listati così lunghi, come primo esempio modifichiamo "Led In Sequenza" come riportato qui:
//LED IN SEQUENZA (versione ottimizzata)
//
//creo un array di 8 elementi e assegno in sequenza i pin
//della porta 1 ad ogni elemento
int led[] = {2,3,4,5,6,7,14,15};
int fineConta = 8;//inizializzo variabile per i cicli "for"
int tempo = 500;//inizializzo variabile per il "delay"
//
void setup()
{
for (int conta = 0; conta < fineConta; conta++)
{
pinMode(led [conta],OUTPUT);//configuro i pin come output
}
//
for (int conta = 0; conta < fineConta; conta++)
{
digitalWrite(led [conta],LOW);//mi assicuro che i led siano spenti
}
}
//
void loop()
{
for (int conta = 0; conta < fineConta; conta++)
{
//alterno accensione led in sequenza
digitalWrite(led [conta],HIGH);
delay(tempo);
digitalWrite(led [conta],LOW);
digitalWrite(led [conta + 1],HIGH);
}
}
Come possiamo notare il listato risulta leggermente meno leggibile ma estremamente più corto. E' interessante notare che più ci "gioco" e più mi sembra di una semplicità unica, basta fare attenzione alla sintassi (che è la mia dannazione). Passiamo ad ottimizzare "Lettura Pulsanti":
//LETTURA PULSANTI (versione ottimizzata)
//
//creo un array di 6 elementi e assegno in sequenza i pin della
//porta 1 ad ogni elemento
int led[] = {2,3,4,5,6,7};
//creo un array di 6 elementi e assegno in sequenza i pin della
//porta 2 ad ogni elemento
int Button[] = {8,9,10,11,12,13};
int fineConta = 6;//inizializzo variabile per i cicli "for"
//
int buttonState = 0;//inizializzo la variabile di lettura stato pulsante
//
void setup()
{
for (int conta = 0; conta < fineConta; conta++)
{
pinMode(led [conta],OUTPUT);//configuro i pin come output
}
//
for (int conta = 0; conta < fineConta; conta++)
{
digitalWrite(led [conta],LOW);//mi assicuro che i led siano spenti
}
//
for (int conta = 0; conta < fineConta; conta++)
{
pinMode(Button [conta],INPUT);//configuro i pin come input
}
}
//
void loop()
{
//accendo i led in relazione al pulsante pigiato
for (int conta = 0; conta < fineConta; conta++)
{
buttonState = digitalRead(Button [conta]);
if (buttonState == HIGH)
{
digitalWrite(led [conta],HIGH);
}
digitalWrite(led [conta],LOW);
}
}
Perfetto, anche questa ottimizzazione funziona, qualsiasi pulsante viene pigiato il sistema accende il relativo led, spegnendolo al suo rilascio. Sono contento di questo risultato, mi aspettavo qualcosa di complicato invece è di una semplicità unica. Adesso abbiamo le basi per poter procedere con il nostro studio. Nel prossimo appuntamento vedremo come montare qualche shield con sensori a bordo e relativa programmazione oppure una shield controllo motori, per quest'ultima non sono sicuro perchè non ho mai fatto esperienze con i motori passo-passo.

E bravo Marven
Ottimo articolo, come avevi promesso sei passato dagli schemi alla programmazione.
Come hai riportato la scrittura e l’adattamento di programmi derivati da Arduino è molto semplice.
Anche l’interfacciamento del display a questo punto è stato un gioco da ragazzi, potendo utilizzare le librerie.
A tal proposito, avendo dato solo una rapida scorsa all’articolo, ma queste librerie solo proprio le stesse di Arduino, pensi sia possibile utilizzarne anche altre per esempio per la lettura di sensori di temperatura seriali?
Penso che il prossimo articolo potrebbe essere un breve tutorial per l’utilizzo del programma ENERGIA che a quanto ho visto, è simile all’IDE di Arduino, magari evidenziando eventuali differenze.
Credo a questo punto sia giunto il momento di acquistare questa piccola/grande scheda.
Ancora bravo, e congratulazione…mi hai raggiunto in classifica!
Saluti
Adriano
Ciao Adriano
Grazie, gentilissimo 🙂
Si, le librerie sono le stesse solo che (dove utilizzata) vi è la nomenclatura dei pin modificata per l’MSP430.
Purtroppo non ho una shield sensori temperatura e non posso provare ma, credo che si possano utilizzare quasi tutte le librerie, compatibilmente con il numero di pin che in Arduino sono molti di più (vedi Arduino Mega), ho notato anche che alcune librerie dei PIC si possono utilizzare semplicemente cambiando il nome dei pin (come sai sto tentando di studiare anche i pic ma il tempo è tiranno).
Credo che non ci siano differenze tra Energia e l’Ide di Arduino oltre alle board utilizzabili, quindi un tutorial sarebbe solo un duplicato.
Se decidi di acquistarla non fare il mio errore: ordinati anche qualche integrato MSP430 per sviluppare shield standalone (acquistandoli in Europa costano un botto).
Controlla bene la classifica, sono sempre terzo 😉 e aspetto di leggere il tuo prossimo progetto.
Ciao
Mario
Ciao Marven,
di nuovo una piacevole lettura di esperienze vissute (riguardo al non pretendere di avvicinarti ad un tutorial, in linea di massima i tutorial sullo sviluppo in ambito embedded partono quasi sempre con una spiegazione su come accendere un led – è “l’Hello World” del mondo embedded – per poi vedere gli ingressi digitali tramite pulsanti e l’output a video tramite display, dunque penso che il tuo lavoro potrebbe essere definito un “experienced tutorial”…).
Ho una domanda ed un’osservazione.
La domanda: se li hai già provati entrambi, che differenze hai notato tra Energia e CCS? Lo chiedo perchè mi sembra che a differenza del primo il secondo abbia limitazioni sulla licenza d’uso e sarei curioso di sapere se Energia, credo libero, sia all’altezza di CCS come IDE.
L’osservazione: nel loop del codice ottimizzato del led in sequenza, credo che potresti ottimizzare ulteriormente togliendo l’istruzione “digitalWrite(led [conta + 1],HIGH);” dal momento che la stessa operazione dovrebbe essere eseguita al successivo ingreso nel ciclo for. Se provi, fammi sapere se ho detto una cavolata 😉
Comunque, bel lavoro. Meglio sempre fissare per bene i concetti di base (sia per chi opera direttamente, sia per il pubblico che legge) prima di passare a cose più complesse.
Un saluto
Ciao delfino_curioso
intanto grazie per gli apprezzamenti che sono sempre graditi 🙂 mentre per quanto riguarda le differenze tra Energia e CCS, non ho avuto modo di approfondire ma, da quel poco che ho notato posso affermare che l’approccio con Energia è più immediato, quindi anche una persona inesperta riesce tranquillamente a scrivere fin da subito del codice valido, ma è ben lontano dall’essere completo, a differenza, CCS è di (relativamente) difficile interpretazione ma molto più completo e professionale, cioè si ha bisogno di maggiore studio per riuscire ad usarlo in tutte le sue possibilità. Direi (forse sbaglio) che per scrivere semplici codici Energia è l’ideale ma per programmi di una certa complessità è d’obbligo CCS. Per quanto riguarda la limitazione della versione light di CCS non è un problema perchè il limite massimo di codice scrivibile corrisponde al limite massimo memorizzabile sugli MSP430.
Appena riesco a studiarlo meglio condividerò i risultati.
Per quanto riguarda l’istruzione “digitalWrite” mi hai incuriosito, 🙂 oggi controllo e ti faccio sapere (così su due piedi non ricordo com’era scritto il codice, tra l’altro scritto anche in fretta).
Ciao
Mario
Ciao Marvin,
ho eseguito il codice per scrivere sul display lcd 16×2 ma purtroppo non mi spunta fuori niente rimane tutto fermo. Da premettere che uso una display lcd 16×2 della Hitachi HD44780. C'è qualche problema con questo tipo di display???
Ciao Armando
ho provato 3 display basati sul 44780 e non ho avuto nessun problema tranne uno, ma era colpa mia non del display, avevo dimenticato di mandare a massa il pin 5 e nella visualizzazione c’erano solo dei quadratini accesi al posto dei caratteri. Il tuo non si accende? o visualizza quadratini?
Mi viene un dubbio: la tua scheda che revisione ha? fino alla revisione 4 c’è da impostare i ponticelli in un certo modo dalla rev 5 vanno messi diversamente…
Mi viene in mente ancora una cosa: se i collegamenti al display sono più lunghi di 20 centimetri c’è da inserire un elettrolitico ed utilizzare solo piattina multifili per evitare che si attorciglino tra loro creando interferenze.
Hai modo di provare se il display è sicuramente funzionante?
Facci sapere
ciao
Mario