Brano e artista su LCD con Arduino

Stampa
( 1 Vote ) 
Valutazione attuale:  / 1
ScarsoOttimo 
Categoria principale: Elettronica Categoria: Microcontrollori
Data pubblicazione
Scritto da MGuruDC Visite: 5731

Brano e artista su LCD con Arduino

Salve a tutti
Ecco l'applicazione pratica che avevo promesso per la funzione "readUsart".
Molto sfiziosa secondo me... decisamente inutile per il senso comune.

Questa volta l'Arduino è programmato con una elementare consolle ed è collegato a un display LCD a caratteri.
Grazie a uno script per la shell Linux Vedremo apparire sul display il titolo della canzone che stiamo ascoltando e l'artista che la esegue.

Le informazioni sulla canzone vengono prese dai tag che in genere ogni file audio si porta dietro. Il riproduttore multimediale che ho usato è Rhythmbox, uno dei più importanti player in ambiente Linux, ufficialmente supportato da Ubuntu e da GNOME.
Questo player mentre esegue i brani mette a disposizione le informazioni su un client che è anche in grado di formattarle.



In pratica:
- chiediamo a Rhythmbox le informazioni sul brano
- le mandiamo all'Arduino che è predisposto a ricevere comandi e dati.
- vediamo le informazioni sull'LCD

Elettronica

Semplicissima:
Un display LCD DEM-16213-SYH è collegato alle uscite digitali dell'Arduino, Ecco lo schema:



Nulla di particolare. visto che non avevo spazio a volontà ho usato il display in configurazione 8bit.
Il display che ho usato si pilota esattamente come i diffusissimi Hitachi, probabilmente cambiano solo i codici per le istruzioni.

Per quanto riguarda la regolazione del contrasto, il dati tecnici suggeriscono di usare un trimmer da 10-22k.
Ho provato con un trimmer da 22k ma la regolazione ha una definizione praticamente nulla, maglio usare 10k.

Software / Arduino

Il codice usato è quello per una elementare console.
Quello della console è un progetto che porto avanti da un po' di tempo, qui sono già presenti un po' di funzioni utili tuttavia non mi pare il caso di approfondire l'argomento visto che non ho ancora implementato con successo un vero e proprio parser.
Alle funzioni per la console sono state aggiunte quelle per il display, diamo un'occhiata

#include <string.h>
#include <EEPROM.h>
//================LCD #define RS 11
#define rsI digitalWrite(RS, LOW);
#define rsD digitalWrite(RS, HIGH);
#define RW 12 #define rwR digitalWrite(RW, HIGH);
#define rwW digitalWrite(RW, LOW);
#define E 13 #define Epulse digitalWrite(E, HIGH);
delayMicroseconds(2); digitalWrite(E, LOW);
//=================LCD

i primi define riguardano il display, con questi ho definito i pin usati e le macro necessarie al funzionamento dell'LCD

// pin utilizzabili

#define MIN_PIN 2

#define MAX_PIN 19

// pin PWM

#define PWM_PIN1 3

#define PWM_PIN2 5

#define PWM_PIN3 6

#define PWM_PIN4 9

#define PWM_PIN5 10

#define PWM_PIN6 11

// impostazioni

#define SERIAL_BR 9600

#define DIM_STR 128

// impostazioni EEPROM

#define MAX_EE_IND 1023

#define MAX_EE_VAL 255

questi define invece tengono sotto controllo le funzionalità stesse dell'Arduino e vengono richiamati nelle successive routine

#define ARG strtok_r(NULL, " \0", &car)
#define STR strtok_r(NULL, "\0", &car)

Queste due macro servono a passare alle funzioni gli argomenti o l'intera stringa data insieme al comando della pseudo-console

char* readUsart() { noInterrupts();
char *np = (char*)malloc(strlen((char*)Serial.buff()) + 1);
strcpy(np, (char*)Serial.buff());
unsigned char *p = Serial.buff();
for(int i = 0; i < 128; i ++, p ++) { *p = 0; } Serial.flush();
interrupts(); return np; }

La funzione "readUsat" di cui ho già parlato nell'articolo precedente

void setup() {
Serial.begin(SERIAL_BR);
delay(1000);
Serial.println("---> MGuruDC Arduino Consolle< ---\n>> pronto");
blankPin(); }

Ecco il setup, inizializza la porta seriale e stampa lo "splash screeen"

void loop() {
char* str = readUsart();
if(*str != 0) { Serial.println(str);
exec(str);
} free(str);
delay(100);
}

Grazie alla funzione "readUsart" il loop è molto semplificato. Le uniche operazioni sono:
- interrogazione del buffer
- verifica dei dati
Se ci sono dati, questi vengono passati "all'eseguitore", il cuore della console, se non ci sono dati viene liberata la memoria e il ciclo ricomincia da capo

void exec(char *input) {
char *car, *comando;
comando = strtok_r(input, " \0", &car);
if(!strcmp(comando, "pinH")) { pinH(ARG);
}
else if(!strcmp(comando, "pinL")) { pinL(ARG);
}
... ... else { Serial.println(">>> Comando non trovato");
}
}


 

Ecco "l'eseguitore". Come prima operazione analizza la stringa in ingresso, poi cerca il comando richiesto e gli passa i suoi argomenti.
Se il comando non esiste lo segnala sulla seriale.
Gli eventuali comandi implementati vanno aggiunti nella struttura "if-else if-else"

Dopo la funzione exec ho definito come funzioni tutti i comandi implementati. Tutti i codici sono nei file allegati, per comodità ecco una lista delle funzioni:

pinH imposta a 1 il pin selezionato
pinL imposta a 0 il pin selezionato
blankPin azzera tutti i pin
pinPWM scrive un valore PWM sul pin selezionato
usleep, usleep, usleep mettono in pausa l'Arduino per il valore espresso in microsecondi, millisecondi e secondi
EEwr scrive un valore sulla EEPROM all'indirizzo selezionato
EErd Legge la EEPROM all'indirizzo selezionato
sReset, coma software reset e halt... disabilitati perché inutili a questo stadio di sviluppo della console

Queste sono le funzioni per il display
 

rsI imposta il registro delle funzioni
rsD imposta il registro dei dati
rwR
rwW imposta il display in scrittura
Epulse invia l'impulso di lettura del comando
wData scrive un dato (0-255) sul bus a 8 bit
wDataP scrive un dato sul bus e manda l'impulso E
initLCD inizializza il display
echo scrive una stringa sul display
clear pulisce il display
echo1 scrive solo sulla prima riga dell'LCD
echo2 scrive solo sulla seconda riga dell'LCD

Questa funzione non è richiamabile dalla console perchè prende come argomento un intero e non una stringa, viene usata dalle altre funzioni
 

wDataR scrive un dato (0-255) sul bus a 8 bit

I comandi usati questa volta sono soltanto initLCD, clear, echo1 ed echo2

Sofware / Computer

è uno script bash per Linux che ogni 5 secondi interroga rhythmbox-client e invia i dati all'Arduino, il metodo è lo stesso usato nei
precedenti articoli

if [ -e /dev/ttyUSB0 ] then tt=0 elif [ -e /dev/ttyUSB1 ] then tt=1 elif [ -e /dev/ttyUSB2 ] then tt=2 elif [ -e /dev/ttyUSB3 ] then tt=3 elif [ -e /dev/ttyUSB4 ] then tt=4 elif [ -e /dev/ttyUSB5 ] then tt=5 else exit fi

Una elementare ricerca della porta seriale da utilizzare. Se dopo 6 tentativi non viene trovata lo script non viene eseguito

stty -F /dev/ttyUSB$tt cs8 9600 ignbrk -brkint -icrnl -imaxbel -opost -onlcr -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke noflsh -ixon -crtscts sleep 1

inizializzazione del terminale a 9600baud/s

tail -f /dev/ttyUSB$tt & sleep 2

Apertura della porta in ascolto(senza fare ciò l'Arduino non inizia la comunicazione). la "&" aprirà il processo in background, quindi alla chiusura dello scprit il processo va chiuso separatamente con killall

echo -n "initLCD" > /dev/ttyUSB$tt sleep 2 echo -n "clear" > /dev/ttyUSB$tt

invio dei comandi per l'inizializzazione del display

while true do echo -n "clear" > /dev/ttyUSB$tt sleep 1 titolo=`rhythmbox-client --print-playing-format "%tt"` artista=`rhythmbox-client --print-playing-format "%aa"` echo -n "echo1 $titolo" > /dev/ttyUSB$tt sleep 1 echo -n "echo2 $artista" > /dev/ttyUSB$tt sleep 5 done

ed ecco il ciclo infinito che
    1) pulisce il display
    2) interroga rhythmbox client
    3) invia i dati all'Arduino
    4)si mette in pausa per 5 secondi

è tutto

Stavolta sono stato più parsimonioso con le spiegazioni , specialmente perchè si tratta di un progetto non ben definito e fatto un po' alla buona (basta guardare le temporizzazioni XD). A ogni modo per chi fosse interessato sono disponibile per commenti, chiarimenti, insulti e critiche.
Ciliegina sulla torta, un orribile video del funzionamento. Visto che montare video non è esattamente il mio mestiere questo è il massimo che sono riuscito a fare... cercate di guardarlo a schermo intero.
Video (9.2MB, AVI)


Ciao
Guru