MSP430: chi ben comincia… (parte seconda)

MSP_11 [640x320]

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.

Avendo a disposizione un alimentatore recuperato da un'apparecchiatura industriale, con due tensioni in uscita, una a 5V 1,5A e una a 12V 1A, ho pensato bene di aggiungere in serie ai 5V un regolatore a 3,3V, per chi non ha la possibilità di riclicare vecchie schede, assemblarlo da zero non è per niente complicato ed è relativamente poco costoso. Lo schematico ce lo indica:

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.

Elenco componenti:
C 1-4-7-10 = 100nF
C 2-5-8 = 100uF 50v
C 3- 6- 9 = 470 uF 25v
D 1-2-3 = PBYR745
IC1 = LM2576-3,3
IC2 = LM2576-5
IC3 = LM2576-12
L1-2-3 = da calcolare in base alla tensione in ingresso (vedi datasheet).

 

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.

Parto in quarta con il mio primo codice.

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).

Avendo a disposizione 8 led al posto dei due on-board del LaunchPad provo ad accenderli in sequenza, è chiaro che vanno tolti i due ponticelli su S5 così escludiamo dal microcontrollore il led1 e il led2 montati a bordo.

//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.

Il mio secondo codice.

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.

 

Il mio terzo codice.

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à.

Ottimizziamo i codici.

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.

Vorrei ribadire ancora una volta che questa mia serie non vuole pretendere di somigliare neanche lontanamente ad un tutorial ma semplicemente vuole essere una condivisione di esperienze (da neofita).
Ho allegato i files zip per chi vuole provare, in "Codici" troveremo sia i due semplificati che i due ottimizzati mentre il "Contasecondi" è a parte.

6 Comments

  1. adrirobot 11 dicembre 2013
  2. Marven 11 dicembre 2013
  3. delfino_curioso 25 dicembre 2013
  4. Armando.Hammouda 19 febbraio 2014
  5. Marven 20 febbraio 2014
  6. Marven 26 dicembre 2013

Leave a Reply