Dolly Photo – terza parte

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.

Keypad LCD Dolly Photo - impostazioni

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 !!

Prima di inserire un commento, per favore, leggi il regolamento

Permanent link to this article: https://www.mauroalfieri.it/elettronica/dolly-photo-terza-parte.html

Lascia un commento

Your email address will not be published.

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.