Continua la serie di articoli dedicati al progetto Dolly Photo che sto rivisitando utilizzando la motor shield arduino e la keypad LCD per la parte di interazione display LCD e pulsanti.
In questo articolo ti mostro la funzione verifica: il cui scopo è consentirti di visualizzare le impostazioni del Dolly Photo prima di eseguire tutta la sequenza di comandi impostata.
Il menu verifica del Dolly Photo
Trattandosi di fotografia time lapse lungo un asse, la sequenza di scatti si sussegue nel tempo e nello spazio.
E’ necesario che tu possa impostare sia i parametri relativi agli scatti che vuoi eseguire:
- Tempo di ALT prima dello scetto;
- Tempo di ALT dopo lo scatto;
- Numero scatti totali;
sia i parametri relativi allo spostamento:
- Numero passi per ciascuno scatto da eseguire;
- Intervallo tra un passo ed il successivo;
la combinazione di questi parametri permette al Dolly Photo di fare le sue operazioni e a te di ottenere il risultato fotografico desiderato.
Lo sketch del Dolly Photo con funzione verifica
Nella prima e nella seconda parte del progetto hai visto che la linea 57 dello sketch relativo al Dolly Photo la seconda voce del menu principale è “Verifica”, lo scopo di questa funzione è permetterti di verificare i parametri impostati nel Dolly Photo prima di lanciare la funzione di Avvio.
Ecco come funzionalo sketch:
/**********************************************************
* Dolly Photo Arduino
*
* Data creazione 22 febbraio 2013
*
* autore: Mauro Alfieri
* web: mauroalfieri.it
* tw: @mauroalfieri
*
*
/**********************************************************/
#include <LiquidCrystal.h>
/**********************************************************/
#define BUTTON A0
#define BACKLIGHT 10
#define MOTDTIME 2000
#define LCDTIME 3000
#define SETMODETIME 2000
#define DEBUG
/**********************************************************/
char line0[16] = "Dolly Foto ver1";
char line1[16] = "mauroalfieri.it";
/**********************************************************/
int SELECT[] = {720,760};
int LEFT[] = {480,520};
int RIGTH[] = {0,20};
int UP[] = {120,160};
int DOWN[] = {300,350};
int buttonPress = 0;
/**********************************************************/
unsigned long timeToBlacklight = 0;
unsigned long timeToSetMode = 0;
unsigned long timeSetting = 0;
/**********************************************************/
boolean blacklightStatus = false;
/**********************************************************/
byte symbolselect[8] = {B00001,B00011,B00111,B01111,B00111,B00011,B00001};
byte symbolplay[8] = {B10000,B11000,B11100,B11110,B11100,B11000,B10000};
byte symbolstop[8] = {B00000,B11111,B11111,B11111,B11111,B11111,B00000};
byte symbolpause[8] = {B00000,B10001,B10001,B10001,B10001,B10001,B00000};
/**********************************************************/
char* principale[4] = {"Impostazioni","Verifica","Reset Carrello","Avvio"};
char* secondario[10] = {"Numero passi","per scatto","Intervallo tra","i passi","Tempo di ALT","prima","Tempo di ALT","dopo","Numero scatti","totali"};
char buffer[16];
/**********************************************************/
int passiXscatto = 0;
int intervaloScatto = 0;
int tempoAltPrima = 0;
int tempoAltDopo = 0;
int numeroScatti = 0;
/**********************************************************/
LiquidCrystal lcd(8,9,4,5,6,7);
/**********************************************************/
void setup() {
#ifdef DEBUG
Serial.begin( 9600 );
Serial.println("Avvio");
#endif
/**********************************************************/
pinMode( BACKLIGHT,OUTPUT );
digitalWrite( BACKLIGHT,LOW );
/**********************************************************/
lcd.begin(16, 2);
lcd.createChar(1, symbolselect);
lcd.createChar(2, symbolplay);
lcd.createChar(3, symbolstop);
lcd.createChar(4, symbolpause);
/**********************************************************/
digitalWrite( BACKLIGHT,HIGH );
lcd.setCursor(0,0);
lcd.print(line0);
lcd.setCursor(0,1);
lcd.print(line1);
delay( MOTDTIME );
lcdBlacklightOff();
}
/**********************************************************/
void loop() {
/**********************************************************/
#ifdef DEBUG
Serial.print( " Button: " ); Serial.print( analogRead( BUTTON ) );
Serial.print( " TimeToBlecklight " ); Serial.print( timeToBlacklight );
Serial.print( " TimeToSetHour " ); Serial.println( timeToSetMode );
#endif
/**********************************************************/
if ( ctrlButton( analogRead( BUTTON ) ) == 0 || ctrlButton( analogRead( BUTTON ) ) > 1 ) { timeToSetMode = millis(); }
if (timeToSetMode > 0 && SETMODETIME < (millis() - timeToSetMode) ) { menuMode(); timeToSetMode = 0; }
/**********************************************************/
buttonPress = ctrlButton( analogRead( BUTTON ) );
/**********************************************************/
if ( (blacklightStatus) && LCDTIME < (millis() - timeToBlacklight) ) { lcdBlacklightOff(); }
/**********************************************************/
char line0[16] = " in attesa di ";
char line1[16] = " comandi ...";
/**********************************************************/
lcd.setCursor(0,0);
lcd.print(line0);
lcd.setCursor(0,1);
lcd.print(line1);
/**********************************************************/
}
/**********************************************************/
int ctrlButton( int button ) {
buttonPress = 0;
if ( SELECT[0] <= button && button <= SELECT[1] ) { buttonPress = 1; }
if ( LEFT[0] <= button && button <= LEFT[1] ) { buttonPress = 2; }
if ( RIGTH[0] <= button && button <= RIGTH[1] ) { buttonPress = 3; }
if ( UP[0] <= button && button <= UP[1] ) { buttonPress = 4; }
if ( DOWN[0] <= button && button <= DOWN[1] ) { buttonPress = 5; }
if (buttonPress > 0) {
analogWrite( BACKLIGHT,128 );
blacklightStatus = true;
timeToBlacklight = millis();
}
return buttonPress;
}
/**********************************************************/
void lcdBlacklightOff() {
digitalWrite( BACKLIGHT,LOW );
blacklightStatus = false;
timeToBlacklight = 0;
lcd.clear();
}
/**********************************************************/
void menuMode() {
/**********************************************************/
#ifdef DEBUG
Serial.println( "Menu Mode" );
#endif
/**********************************************************/
boolean setMode = true;
int setModeLevel = 0;
timeSetting = 0;
lcd.clear();
/**********************************************************/
delay( 1000 );
/**********************************************************/
while ( setMode ) {
/**********************************************************/
if ( ctrlButton( analogRead( BUTTON ) ) != 0 ) { timeSetting = millis(); }
if ( (ctrlButton( analogRead( BUTTON )) == 5 ) && setModeLevel < 3 ) { lcd.clear(); setModeLevel++; }
if ( (ctrlButton( analogRead( BUTTON )) == 4 ) && setModeLevel > 0 ) { lcd.clear(); setModeLevel--; }
if ( (setModeLevel % 2) == 0 ) {
lcd.setCursor(0,0);
lcd.print( principale[setModeLevel] );
lcd.setCursor(0,1);
lcd.print( principale[(setModeLevel+1)] );
lcd.setCursor(15,0);
lcd.write(1);
lcd.setCursor(15,1);
lcd.print(" ");
} else {
lcd.setCursor(0,0);
lcd.print( principale[(setModeLevel-1)] );
lcd.setCursor(0,1);
lcd.print( principale[setModeLevel] );
lcd.setCursor(15,0);
lcd.print(" ");
lcd.setCursor(15,1);
lcd.write(1);
}
if ( ctrlButton( analogRead( BUTTON )) == 1 ) {
if ( setModeLevel == 0 ) { impostazioni(); }
if ( setModeLevel == 1 ) { verifica(); }
if ( setModeLevel == 2 ) { reset(); }
if ( setModeLevel == 3 ) { avvio(); }
setMode = false;
timeSetting = 0;
}
if (timeSetting > 0 && (SETMODETIME*2) < (millis() - timeSetting) ) { setMode = false; }
delay(200);
}
/**********************************************************/
lcd.clear();
}
/**********************************************************/
void impostazioni() {
/**********************************************************/
#ifdef DEBUG
Serial.println( "Menu Impostazioni" );
#endif
/**********************************************************/
lcd.clear();
lcd.setCursor(0,0);
lcd.print( "Menu " );
lcd.setCursor(0,1);
lcd.print( "Impostazioni" );
/**********************************************************/
delay( SETMODETIME );
/**********************************************************/
boolean impostazioniMode = true;
int setModeLevel = 0;
lcd.clear();
/**********************************************************/
while ( impostazioniMode ) {
/**********************************************************/
if ( (ctrlButton( analogRead( BUTTON )) == 5 ) && setModeLevel < 8 ) { lcd.clear(); setModeLevel = (setModeLevel+2); }
if ( (ctrlButton( analogRead( BUTTON )) == 4 ) && setModeLevel > 0 ) { lcd.clear(); setModeLevel = (setModeLevel-2); }
if ( ctrlButton( analogRead( BUTTON )) == 1 ) { impostazioniMode = false; }
/**********************************************************/
#ifdef DEBUG
Serial.print( "setMenuLevel: " );
Serial.println( setModeLevel );
#endif
/**********************************************************/
switch ( setModeLevel ) {
case 0:
if ( (ctrlButton( analogRead( BUTTON )) == 3 ) && passiXscatto <= 99999) { passiXscatto++; lcd.clear(); }
if ( (ctrlButton( analogRead( BUTTON )) == 2 ) && passiXscatto >= 1) { passiXscatto--; lcd.clear(); }
sprintf(buffer, "%s %d", secondario[(setModeLevel+1)], passiXscatto);
break;
case 2:
if ( (ctrlButton( analogRead( BUTTON )) == 3 ) && passiXscatto <= 9999999) { intervaloScatto++; lcd.clear(); }
if ( (ctrlButton( analogRead( BUTTON )) == 2 ) && passiXscatto >= 1) { intervaloScatto--; lcd.clear(); }
sprintf(buffer, "%s %ds", secondario[(setModeLevel+1)], intervaloScatto);
break;
case 4:
if ( (ctrlButton( analogRead( BUTTON )) == 3 ) && tempoAltPrima <= 9999999) { tempoAltPrima++; lcd.clear(); }
if ( (ctrlButton( analogRead( BUTTON )) == 2 ) && tempoAltPrima >= 1) { tempoAltPrima--; lcd.clear(); }
sprintf(buffer, "%s %ds", secondario[(setModeLevel+1)], tempoAltPrima);
break;
case 6:
if ( (ctrlButton( analogRead( BUTTON )) == 3 ) && tempoAltDopo <= 9999999) { tempoAltDopo++; lcd.clear(); }
if ( (ctrlButton( analogRead( BUTTON )) == 2 ) && tempoAltDopo >= 1) { tempoAltDopo--; lcd.clear(); }
sprintf(buffer, "%s %ds", secondario[(setModeLevel+1)], tempoAltDopo);
break;
case 8:
if ( (ctrlButton( analogRead( BUTTON )) == 3 ) && numeroScatti <= 9999999) { numeroScatti++; lcd.clear(); }
if ( (ctrlButton( analogRead( BUTTON )) == 2 ) && numeroScatti >= 1) { numeroScatti--; lcd.clear(); }
sprintf(buffer, "%s %d", secondario[(setModeLevel+1)], numeroScatti);
break;
}
/**********************************************************/
lcd.setCursor(0,0);
lcd.print( secondario[setModeLevel] );
lcd.setCursor(0,1);
lcd.print( buffer );
/**********************************************************/
delay( 200 );
}
/**********************************************************/
lcd.clear();
}
/**********************************************************/
void verifica() {
/**********************************************************/
#ifdef DEBUG
Serial.println( "Menu Verifica" );
#endif
/**********************************************************/
lcd.clear();
lcd.setCursor(0,0);
lcd.print( "Menu " );
lcd.setCursor(0,1);
lcd.print( "Verifica" );
/**********************************************************/
delay( SETMODETIME );
/**********************************************************/
boolean verificaMode = true;
int setModeLevel = 0;
lcd.clear();
/**********************************************************/
while ( verificaMode ) {
/**********************************************************/
if ( (ctrlButton( analogRead( BUTTON )) == 5 ) && setModeLevel < 8 ) { lcd.clear(); setModeLevel = (setModeLevel+2); }
if ( (ctrlButton( analogRead( BUTTON )) == 4 ) && setModeLevel > 0 ) { lcd.clear(); setModeLevel = (setModeLevel-2); }
if ( ctrlButton( analogRead( BUTTON )) == 1 ) { verificaMode = false; }
/**********************************************************/
#ifdef DEBUG
Serial.print( "setMenuLevel: " );
Serial.println( setModeLevel );
#endif
/**********************************************************/
switch ( setModeLevel ) {
case 0:
sprintf(buffer, "%s %d", secondario[(setModeLevel+1)], passiXscatto);
break;
case 2:
sprintf(buffer, "%s %ds", secondario[(setModeLevel+1)], intervaloScatto);
break;
case 4:
sprintf(buffer, "%s %ds", secondario[(setModeLevel+1)], tempoAltPrima);
break;
case 6:
sprintf(buffer, "%s %ds", secondario[(setModeLevel+1)], tempoAltDopo);
break;
case 8:
sprintf(buffer, "%s %d", secondario[(setModeLevel+1)], numeroScatti);
break;
}
/**********************************************************/
lcd.setCursor(0,0);
lcd.print( secondario[setModeLevel] );
lcd.setCursor(0,1);
lcd.print( buffer );
/**********************************************************/
delay( 200 );
}
/**********************************************************/
lcd.clear();
}
/**********************************************************/
void reset() {
lcd.clear();
lcd.setCursor(0,0);
lcd.print( "Menu " );
lcd.setCursor(0,1);
lcd.print( "Reset" );
delay( SETMODETIME );
}
/**********************************************************/
void avvio() {
lcd.clear();
lcd.setCursor(0,0);
lcd.print( "Menu " );
lcd.setCursor(0,1);
lcd.print( "Avvio" );
delay( SETMODETIME );
}
/**********************************************************/
le linee che hai già visto nei precedenti articoli restano invariate, per cui puoi concentrarti solo sulle linee nuove, quelle dedicate alla funzione verifica:
linea 356: definisci la funzione verifica();
linee 359-361: imposta l’invio del testo “Menu Verifica” sul monitor seriale in presenza della costante DEBUG;
linee 365-369: invia al display LCD il testo “Menu” e “Verifica” rispettivamente sulla prima e sulla seconda riga;
linea 373: attendi il tempo definito nella costante SETMODETIME in modo che si possa leggere il messaggio appena scritto sul display;
linea 377: definisci una variabiel di tipo booleana verificaMode ( il cui valore può essere solo true o false ) impostandola a true, è la variabile che utilizzerai nel successivo ciclo while per stabilire quando terminare il ciclo e tornare alla funzione principale;
linea 378: definisci la variabile di tipo integer ( intero ) setModeLevel ed impostala a 0;
linea 379: pulisci le righe del display, prima di scriverci sopra le impostazioni;
linea 383: imposta un ciclo while() la cui condizione di verifica è la variabile verificaMode definita alla linea 377 ed attualemnte impostata a true;
linea 387: controlla, attraverso la funzione ctrlButton, che il pulsante premuto sia DOWN e che il valore di setModeLevel non sia superiore a 8. Se la condizione è verificata cancella il testo dall’LCD ed incrementa il valore di setModeLevel di 2 punti. Se il valore di setModeLevel superasse 8 sommando 2, andresti oltre l’indice 9 dell’array di caratteri denominato secondario;
linea 388: esegui un’operazione simile a quella della linea precedente con la differenza che setModeLevel deve essere superiore a 1 e che il pulsante testato è UP;
linea 389: questa linea ti permette di uscire dal menu infatti alla pressione del pulsante SELECT la funzione ctrlButton() restituisce 1 che rende vera la condizione if testata e di conseguenza impostazioniMode lo imposti a false uscendo dal ciclo while iniziato alla linea 383;
linee 393-396: sono linee di debug che scrivono sul monitor seriale il valore della variabile setModeLevel solo se DEBUG è impostato correttamente;
linea 400: il comando switch valuta il valore di setModeLevel per consentirti di decidere quali operazioni eseguire;
linea 402: se la condizione è verificata ( setModeLevel = 0 ) il Dolly Photo ti mostra sul display LCD il valore della variabile passiXscatto;
linea 403: compone la seconda linea del display LCD come: “testo del menu secondario con indice dispari” + “valore di passiXscatto“;
linee 406-420: eseguono le stesse operazioni viste per le linee 400-403 ciascuna per uno dei valori pre-impostati alle linee 64-68;
linee 377-340: scrivi sul display alla prima riga il valore della voce di menu corrispondente e alla seconda riga il valore composto da una delle condizioni viste alle linee 400-420;
linea 344: attendi un tempo di 200 millisecondi tra un ciclo ed il successivo per consentirti di premere il pulsante;
linea 350: azzera il valore scritto su entrambe le righe del display lcd del Dolly Photo.
Il video del menu Verifica del Dolly Photo
La funzione di verifica del Dolly Photo è utile per assicurarti che tutti i parametri inseriti siano stati correttamente memorizzati.
Ho preparato questo video sul Dolly Photo:
Buona verifica !!







2 comments
andrea
22 aprile 2013 a 13:59 (UTC 2) Link to this comment
buon giorno
sarei interessato a repplicare questo progetto ,
purtroppo ho un af motor shild della adfruit e non credo che il lcd keypad sia compatibile.
altrimenti per seguire il progetto passo passo devo acquistare si la parte motroe che la parte lcd del arduino e fare copia ed incolla con il codice giusto ?
purtroppo di elettronica non ne capisco nulla mi dispiace.
la ringrazio
Mauro Alfieri
22 aprile 2013 a 16:47 (UTC 2) Link to this comment
Ciao Andrea,
hai ragione la motor shield della adafruit non è compatibile con questo progetto così com’è.
Puoi comunque usarla adattando lo sketch, ti basta cambiare i pin che controllano le fasi del motore passo-passo.
Certamente non potrai montarla a “panettone” ma per funzionare dovrebbe funzionare, purtroppo non possiedo una motor shield come la tua per provare.
A breve dovrei riuscire a produrre una shield dedicata a questo progetto in cui aggiungere un arduino e avere tutto su un unica board.
Se sei interessato puoi seguire il blog o iscriverti alla newsletter ed appena pronta ne pubblicherò la notizia.
Mauro