Dolly Keypad LCD – prima parte

Ti avevo promesso altri articoli dedicati alla Keypad LCD ed al Dolly ed ho deciso di unire i due progetti iniziando una serie di articoli dedicati ad un nuovo Dolly e chiamarli Keypad LCD Dolly.

DollyPhoto

In pratica sto realizzando delle evoluzioni del progetto Dolly II già presentato.

Il perché del Keypad LCD Dolly

Ma siccome non è mai divertente ricalcare un progetto senza inserirci qualcosa di nuovo ho deciso di reinventare il Kit Dolly dividendolo innanzitutto in due versioni:

  • Dolly per macchina fotografica ( DollyPhoto )
  • Dolly per telecamera o videocamera, anche definito Slider ( DollyCamera )

Le differenze principali tra i due progetti sono costituite innanzitutto dal peso dello strumento che ha portato tanti appassionati a scrivermi suggerendomi le due distinte versioni.

Infatti una telecamera professionale pesa decisamente di più di una macchina fotografica e questo comporta che il motore deve essere più potente.

Inoltre i due dolly hanno esigenze differenti, il DollyPhoto ha necessità di spostamenti precisi, piccoli e controllati, avrai bisogno di conoscere:

  • il numero di passi tra uno scatto ed il successivo
  • il tempo tra un passo ed il successivo
  • il tempo di stop prima di scattare
  • controllare lo scatto mediante foto accoppiatore optoisolato
  • controllare il numero di scatti da eseguire
è ideale per gestire questo tipo di progetto un motore stepper o passo-passo in cui puoi definire tutte queste variabili.
Il DollyCamera o Slider ha esigenze differenti in primo luogo il peso della videocamera da spostare e poi:
  • un movimento fluido
  • regolare la velocità del motore
  • nessun tempo di stop tra una ripresa e la successiva

è logico pensare che un motore stepper in questo caso possa essere inutile e sottodimensionato, per cui è meglio usare un motoriduttore e se proprio vuoi conoscere anche quanti giri hai fatto puoi utilizzare un motoriduttore con encoder ad effetto Hall.

Keypad LCD Dolly – prima parte

In questa prima parte dedicata all’evoluzione del Dolly parleremo del DollyPhoto, quello per time-lapse, ed in particolare il primo sketch che puoi provare è dedicato all’uso della Keypad LCD Dolly per visualizzare e gestire i menu.

Come funzione il Keypad LCD Dolly

Quando avrai caricato lo sketch sul tuo Arduino Uno R3 vedrai sul display comparire la schermata:

Keypad LCD Dolly Photo

di presentazione, dopo 2 secondi ( definiti tra le costanti dello sketch ) la schermata diventa:

Keypad LCD DollyPhoto

questo significa che il DollyPhoto è pronto per accettare comandi, premendo il pulsante SELECT per due secondi entri in modalità IMPOSTAZIONI:

Keypad LCD DollyPhoto - impostazioni

i cui primi due menu riguardano l’impostazione dei parametri di funzionamento e la verifica di quanto impostato, premendo il pulsante DOWN l’indicatore a freccia a sinistra si sposta per indicarti che stai selezionando la voce VERIFICA continuando a premenere DOWN la schermata del Keypad LCD Dolly cambia:

Keypad LCD DollyPhoto

mostrandoti gli altri due menu di impostazione, RESET CARRELLO ed AVVIO, a cosa servano sono certo che già lo sai o lo hai intuito.

Dopo 4 secondi durante i quali non premi alcun pulsante il Keypad LCD Dolly esce dalla modalità di impostazione tornando alla schermata di attesa comandi.

Lo sketch

ecco lo sketch che puoi utilizzare per gestire i menu del Keypad LCD Dolly Photo:

/***********************************************************
Progetto DollyPhoto ver 1.0
Autore Mauro Alfieri
Web    mauroalfieri.it
Tw:    @mauroalfieri

Licenza Common Creative
***********************************************************/

#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"};

/**********************************************************/

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) {
    digitalWrite( BACKLIGHT,HIGH );
    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() {
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print( "Menu " );
  lcd.setCursor(0,1);
  lcd.print( "Impostazioni" );    

  delay( SETMODETIME );
}

/**********************************************************/

void verifica() {
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print( "Menu " );
  lcd.setCursor(0,1);
  lcd.print( "Verifica" );    

  delay( SETMODETIME );
}

/**********************************************************/

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 );
}

/**********************************************************/

lo scketch si limita a definire alcuni punti fermi del progetto DollyPhoto, come il menu principale e le funzioni che andrai a richiamare per ciascun menu.

Alcune parti di codice presenti in questo sketch le avrai riconosciute, provengono dal primo articolo dedicato alla Keypad LCD ed altre le ho modificate rispetto a quel primo sketch o aggiunte per far fronte alle esigenze del progetto Keypad LCD Dolly.

I punti fondamentali dello sketch loi ho spostati nelle funzioni aggiunte in modo da analizzarle singolarmente, prima però guarda le linee 49-51 in queste linee disegni 4 simboli che utilizzerai poi nel progetto per renderlo graficamente più bello accattivante:

  • select: freccia con la punta rivolta a sinistra
  • play:    freccia con la punta rivolta a destra
  • stop:    un quadrato
  • pause:  due linee vericali parallele

alle linee 78-81: crei i 4 simboli utilizzando il metodo createChar( n,sibolo ) messo a disposizione dalla classe LiquidCrystal;

linee 85-91: accendi il display e scrivi sulla prima e sulla seconda linea la frase di apertura, poi attendi il tempo definito in MOTDTIME e spegni la retro illuminazione per risparmiare alimentazione;

linea 108: richiami la funzione ctrlButton( valore letto su A0 ) chiedendole di verificare quale pulsante è stato premuto, la logica di questa funzione è identica a quella vista nel precedente articolo, ho fatto solo qualche correzione che ti mostrerò leggendo la funzione. Se il valore restituito da ctrlButton() è 0 o maggiore di 1 vuol dire che hai premuto un qualsisasi pulsante tranne SELECT e quindi non è necessario che lo sketch inizi a contare per quanto tempo il pulsante è stato premuto, alla pressione del pulsante SELECT la ctrlButton() restituisce infatti 1 ed è da quel momento che devi contare quanto tempo lo hai tenuto premuto;

linea 109: verifica che il tempo trascorso dalla pressione del pulsante 1, linea 108, sia maggiore di quello impostato nella variabile SETMODETIME in tal caso entra in modalità di configurazione chiamando la menuMode();

line136-152: la funzione ctrlButton() è la stessa dell’articolo precedente a parte la modifica per cui ad ogni controllo se la condizione è verificata non retituisce subito il valore ma lo imposta nella variabile buttonPress e solo alla fine ( linea 151 ) restituisce questo valore. La modifica ti permette di semplificare il codice in modo che qualunque operazione comune alla pressione di tutti i pulsanti tu voglia eseguire potrai inserirla una sola volta prima del comando return come in questo caso in cui l’accensione della retro illuminazione avviene sempre prima del return;

linea 165: definisci la funzione menuMode() in cui entra se premi per 2 secondi il pulsante SELECT quando il Keypad LCD Dolly è in attesa di comandi;

linee 175-178: imposti alcune variabili utili al funzionamento delo sketch come setMode con cui regoli se sei in modalità di settaggio o meno;

linea 186: fino a quando il valore di setMode non cambia da true a false resti nel ciclo di settaggio;

linea 190: se non premi alcun pulsante, la ctrlButton restituisce 0, il contatore parte; se invece premi un qualsiasi pulsante il valore di timeSetting è reimpostato a millis() ossia il conteggio ricomincia;

linee 192-193: controlli la pressione dei pulsanti UP e DOWN ed in funzione del pulsante premuto incrementi o decrementi il valore della variabile setModeLevel;

linea 195: verifica che il modulo per 2 di setModeLevel sia 0, essendo il modulo il resto della divisione del valore setModeLevel per il dividendo 2 se questo valore è 0 vuol dire che setModeLevel è pari, altrimenti è dispari;

linee 196-199: stai mostrando un menu pari, vedi linea precedente, per cui scriverai sulla prima linea il valore corrente della voce di menu e su quella successiva la voce di menu successiva ( setModeLevel+1 );

linee 201-204: disegna il simbolo 1 definito alla linea 78 in fondo alla prima riga, partendo dall’idea che se il setModeLevel è pari sei sicuramente sulla prima linea del display, puoi quindi pulire il 15° carattere della seconda linea;

linee 206-214: esegui le medesime operazioni viste per le linne 196-204 solo impostando il cursore freccia di selezione sulla seconda linea del display;

linea 217: verifica la pressione del pulsante e confrontala con 1, ossia che hai premuto SELECT sulla Keypad LCD ed in caso di pressione del pulsante atteso esegui le linee successive;

linee 218-221: valuta al momento in cui hai premuto il pulsante quale è il valore di setModeLevel ed in funzione di tale valore richiama la funzione corrispondente;

linea 223: imposta a false il valore di setMode in modo che al prossimo ciclo while non sia verificata la condizione della linea 186 ed esci dalla modalità di settaggio;

linea 224: imposta a 0 il valore di timeSetting in modo da uscire subito dalla menuMode;

linea 227: è il controllo sul tempo trascorso dalla pressione dell’ultimo pulsante, in pratica serve ad uscire dal ciclo while se non premi alcun pulsante per un tempo superiore al doppio di SETMODETIME;

linea 233: pulisci il display dai menu che hai visualizzato prima di tornare alla funzione loop();

linee 238-246: definisci una funzione impostazioni() richiamata dalla funzione menuMode() ( linea 218 ). Lo scopo di questa funzione in questo sketch è scrivere sul monitor il testo contenuto alle linee: 241 e 243 e di attendere il tempo SETMODETIME prima di uscire. Nelle prossime fasi del progetto useremo questa funzione per impostare dei parametri per il Keypad LCD Dolly o DollyPhoto;

linee 250-282: definisci alre 3 funzioni, richiamate dalle linee 219-220-221, identiche alla impostazioni() che utilizzerai per far funzionare il Dolly Photo.

Il video del Keypad LCD Dolly

Per mostrarti come funziona ho realizzato un video:

Buon lavoro !!!

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

Permanent link to this article: https://www.mauroalfieri.it/elettronica/dolly-keypad-lcd-prima-parte.html

21 pings

Skip to comment form

  1. […] prima e nella seconda parte del progetto hai visto che la linea 57 dello sketch relativo al Dolly Photo […]

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.