Un utente del blog, fotografo professionista, mi ha suggerito di aggiungere una funzionalità in più al dolly: lo stop motion.
E’ una funzione che interrompa tutto il ciclo qualora lo hai avviato per errore o tu vogli a interrompere il programma per riprogrammarlo.
Ho trovato interessante il suggerimento e ho lavorato qualche ora per realizzarlo e provarlo.
Nulla di impossibile la soluzione finale è molto più semplice di quello che inizialmente avevo immaginato.
Devi modificare solo la funzione go() presentata nel progetto:
void Go() { lcd.print( "Avvio del dolly" ); lcd.clear(); for ( int sc=0; sc <= scatti; sc++ ) { if ( analogRead( conf ) > 1000) { lcd.clear(); lcd.print( "Stop Motion" ); delay( 1000 ); return; } lcd.setCursor(0, 0); lcd.print( "scatto: " ); lcd.setCursor(8, 0); lcd.print( sc ); for ( int ng=1; ng <= ngiri; ng++ ) { if ( analogRead( conf ) > 1000) { lcd.clear(); lcd.print( "Stop Motion" ); delay( 1000 ); return; } lcd.setCursor(0, 1); lcd.print( "passo: "); lcd.setCursor(8, 1); lcd.print( ng ); gira( nFase ); nFase++; if ( nFase > 4 ) nFase = 1; delay( interv * 1000 ); } digitalWrite( pinLed, HIGH ); delay( 1000 ); digitalWrite( pinLed, LOW ); } }
a voler essere pignolo la modifica riguarda l’inserimento delle linee:
linea 08 ( in questo sketch ): in cui verifichi che il pulsante di conferma sia stato premuto, in tal caso il valore letto sul pin analogico corrispondente passa da 0 a 1023 e la condizione di if è verificata;
linea 09: pulisci ogni scritta sul display;
linea 10: scrivi la frase “Stop Motion” per indicare anche a video che l’interruzione è dovuta alla pressione del pulsante di comando;
linea 11: attendi 1 secondo prima di proseguire, è una sorta di tempo di annullamento della pressione del pulsante conferma, in quanto la pressione dello stesso per eseguire lo “Stop Motion” se non rilasciato in tempo si trasforma in conferma, poiché la funzione Go() di fatto si ritorna al menu “Avvio” la pressione del pulsante conferma causa la ripartenza del ciclo di avvio.
linea 12: l’uso del comando return assicura che la funzione Go() sia interrotta e il controllo ritorni alla funzione loop();
linee 22-26: sono identiche alle linea 08-12.
Perché basta inserire queste linee identiche in questi punti? l’origine di questa scelta risiede nell’osservazione dell’intera funzione, i due cicli di for, l’uno annidato nell’altro, interrompono l’azione del microcontrollore, ossia trattengono l’esecuzione del codice fino al loro completamento, quindi qualsiasi azione di stop va eseguita al loro inetrno.
Spero che questa funzionalità sia utile anche a te che hai letto il mio tutorial fino alla fine, se non per il progetto Dolly almeno imparando qualche trucco di programmazione su Arduino.
Buon divertimento.
10 commenti
Vai al modulo dei commenti
Complimenti per il lavoro fin qui svolto per il dolly II. Sono un fotografo non professionista ma appassionato di elettronica e se può interessare ho apportato una piccola modifica al codice per far funzionare il dolly con l’ interfaccia ir della nikon d3000, e da prove fatte funziona. se a qualcuno interessa allego lo sketch modificato:
/*
* Dolly Project II
*
* Usa un LCD la motor shield FE, un motore bipolare
* tre pulsanti per la programmazione, 3 resistenze
*
* Autore: Alfieri Mauro
* Twitter: @mauroalfieri
*
* Tutorial su: https://www.mauroalfieri.it
*
*/
#include
#include
// Input Digitali
int prev = A0;
int next = A1;
int conf = A2;
// Stepper
int motorPinDirA = 2;
int motorPinDirB = 8;
int motorPinPwmA = 3;
int motorPinPwmB = 9;
int nFase=1;
// Led
int CameraIrPin = 13;
// Menu Level
char* menu_principale[4] = {“Settaggio”,”Controllo”,”Reset Carrello”,”Avvio”};
char* submenu[3] = {“N. passi x scatto”,”Intervallo passi”,”Numero scatti”};
// Init level
int ngiri=0;
float interv=0;
int scatti=0;
int posizione=0;
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 7, 6, 5, 4);
void setup() {
pinMode(CameraIrPin, OUTPUT);
lcd.begin(16, 2);
lcd.print(“Dolly Project II”);
lcd.setCursor(0, 1);
lcd.print(“mauroalfieri.it”);
delay( 1000 );
lcd.clear();
lcd.print( menu_principale[posizione] );
pinMode(motorPinDirA, OUTPUT);
pinMode(motorPinDirB, OUTPUT);
pinMode(motorPinPwmA, OUTPUT);
pinMode(motorPinPwmB, OUTPUT);
}
void loop() {
lcd.setCursor(0, 1);
int pnext = analogRead( next );
int pprev = analogRead( prev );
int pconf = analogRead( conf );
if ( pnext > 1000 || pprev > 1000 || pconf > 1000)
{
if ( pnext > 1000 ) { posizione++; lcd.clear(); }
if ( pprev > 1000 ) { posizione–; lcd.clear(); }
if ( posizione > 3 ) posizione = 0;
if ( posizione 1000 ) {
lcd.clear();
switch ( posizione )
{
case 0:
ngiri=0;
interv=0;
scatti=0;
Setting();
lcd.clear();
lcd.print( menu_principale[0] );
break;
case 1:
View();
lcd.clear();
lcd.print( menu_principale[1] );
break;
case 2:
ResetCarrello();
lcd.clear();
lcd.print( menu_principale[2] );
break;
case 3:
Go();
lcd.clear();
lcd.print( menu_principale[3] );
break;
}
}
}
}
void Setting()
{
int i = 0;
boolean message = true;
while ( i 1000 || pprev > 1000 || pconf > 1000)
{
if ( pnext > 1000 )
{
if ( i == 0 ) { ngiri++; lcd.setCursor(0, 1); lcd.print( ngiri ); }
if ( i == 1 ) { interv += 0.5; lcd.setCursor(0, 1); lcd.print( interv ); lcd.setCursor(6, 1); lcd.print( “sec” ); }
if ( i == 2 ) { scatti++; lcd.setCursor(0, 1); lcd.print( scatti ); }
}
if ( pprev > 1000 )
{
if ( i == 0 ) { ngiri–; lcd.setCursor(0, 1); lcd.print( ngiri ); }
if ( i == 1 ) { interv -= 0.5; lcd.setCursor(0, 1); lcd.print( interv ); lcd.setCursor(6, 1); lcd.print( “sec” ); }
if ( i == 2 ) { scatti–; lcd.setCursor(0, 1); lcd.print( scatti ); }
}
if ( pconf > 1000 )
{
lcd.clear();
i++;
message = true;
}
}
delay( 200 );
}
}
void View()
{
for (int i=0; i<3; i++)
{
lcd.clear();
lcd.print( submenu[i] );
lcd.setCursor(0, 1);
if ( i == 0 ) { lcd.print( ngiri ); }
if ( i == 1 ) { lcd.print( interv ); lcd.setCursor(6, 1); lcd.print( "sec" ); }
if ( i == 2 ) { lcd.print( scatti ); }
delay( 1000 );
}
}
void ResetCarrello()
{
lcd.clear();
lcd.print( "+/- sposta carr" );
lcd.setCursor(0, 1);
lcd.print( "C esce" );
int i = 0;
while ( i 1000 )
{
nFase++;
if ( nFase > 4 ) nFase = 1;
gira( nFase );
}
if ( pprev > 1000 )
{
nFase–;
if ( nFase 1000 )
{
lcd.clear();
i++;
}
delay ( 200 );
}
}
void Go()
{
lcd.print( “Avvio del dolly” );
lcd.clear();
for ( int sc=0; sc 1000) { return; }
lcd.setCursor(0, 0);
lcd.print( “scatto: ” );
lcd.setCursor(8, 0);
lcd.print( sc );
for ( int ng=1; ng 1000) { return; }
lcd.setCursor(0, 1);
lcd.print( “passo: “);
lcd.setCursor(8, 1);
lcd.print( ng );
gira( nFase );
nFase++;
if ( nFase > 4 ) nFase = 1;
delay( interv * 1000 );
}
cameraSnap(CameraIrPin);
}
}
void gira( int nFase ) {
switch( nFase )
{
case 1:
digitalWrite(motorPinDirA, HIGH);
digitalWrite(motorPinDirB, LOW);
digitalWrite(motorPinPwmA, HIGH);
digitalWrite(motorPinPwmB, LOW);
break;
case 2:
digitalWrite(motorPinDirA, LOW);
digitalWrite(motorPinDirB, HIGH);
digitalWrite(motorPinPwmA, LOW);
digitalWrite(motorPinPwmB, HIGH);
break;
case 3:
digitalWrite(motorPinDirA, LOW);
digitalWrite(motorPinDirB, LOW);
digitalWrite(motorPinPwmA, HIGH);
digitalWrite(motorPinPwmB, LOW);
break;
case 4:
digitalWrite(motorPinDirA, LOW);
digitalWrite(motorPinDirB, LOW);
digitalWrite(motorPinPwmA, LOW);
digitalWrite(motorPinPwmB, HIGH);
break;
}
}
va aggiunta la libreria nikonircontrol.h e forse inserito un delay dopo il comando di scatto infrarosso.Saluti e buon lavoro.
Autore
Grazie Alessio, mi scrivi il dettaglio della modifica? Così lo includo nei prossimi sketch come appendice per chi ha la tua stessa Nikon 🙂
ecco le modifiche:
// Led
int CameraIrPin = 13 al posto di int pinLed = 13;
void setup() {
pinMode(CameraIrPin, OUTPUT); aggiunto riga
lcd.begin(16, 2);
lcd.print(“Dolly Project II”);
lcd.setCursor(0, 1);
lcd.print(“mauroalfieri.it”);
delay( 1000 );
lcd.clear();
lcd.print( menu_principale[posizione] );
digitalWrite( pinLed, LOW ); rimossa
pinMode(motorPinDirA, OUTPUT);
pinMode(motorPinDirB, OUTPUT);
pinMode(motorPinPwmA, OUTPUT);
pinMode(motorPinPwmB, OUTPUT);
pinMode(pinLed, OUTPUT); rimossa
digitalWrite( pinLed, HIGH ); I
delay( 1000 ); I in void go() rimosso quste 3 righe
digitalWrite( pinLed, LOW ); I
cameraSnap(CameraIrPin); in sostituzione delle 3 righe precedenti
}
}
lo sketch utilizza la libreria nikonIrControl.h e dopo svariati tentativi ho capito che è compatibile con arduino
ver. 0022, con la più recente 1.0 ci sono imcompatibilità. Grazie e avanti così!
Autore
Ciao Alessio,
Grazie per la modifica, la lascio in un commento in quanto troppo specifica per Nikon e almeno fino a che non riuscirò a trova appassionati e possessori di macchine fotografiche di altre marche che mi diano dritte simili alle tue vorrei che il progetto principale restasse valido per tutti.
Mauro
Ciao Mauro,
Ho provato lo stop-motion. Con il tasto command interrompo la sequenza del settaggio solo virtualmente. Perchè il motore(sketch) continua ad andare ricominciando da zero lo stesso settaggio . In pratica il motore non si ferma mai, manca lo stop effettivo, è quindi rimane difficile riprogrammare.
Dove ho sbagliato? un aiuto
Saverio
Autore
Ciao Saverio,
non hai sbagliato nulla, a te non funziona per una questione di tempi, quando premi il pulsante di fatto esci dalla funzione Go() e ti ritrovi sul menù Avvio, poichè il pulsante è ancora premuto lo sketch riesegue il ciclo di avvio da capo.
Nei miei test non mi era capitato, dopo la tua segnalazione ho intuito il problema e provato a tener premuto il pulsante più a lungo, ed ecco il comportamento che mi segnali.
Ho modificato lo sketch aggiungendo delle linee ed un ritardo di 1 secondo che dovrebbero risolverti il problema e sul display compare anche la scritta “Stop Motion” per indicarti che l’interruzione è dovuta all’azione da te compiuta.
Mauro
Grazie Mauro, sempre pronto.
Un saluto
Ciao Mauro,
Ho inserito anche io lo stop motion e con questa modifica ulteriore funziona in modo corretto.
Con il comando infrarosso ho un piccolo problema, non riesco ad inserire un ritardo (1 secondo è sufficiente) fra lo step del motore,lo scatto, e il successivo step questo per non introdurre del “mosso” nello scatto effettuato. Hai qualche suggerimento?
Autore
Ciao Alessio,
il tuo è un ottimo suggerimento sto elaborando una versione del progetto con anche questa funzionalità 🙂 presto sará on-line.
Ciao Mauro
Finalmente inizio a produrre dei TL interessanti, grazie al tuo progetto Dolly. Voglio solo aggiungere ancora una considerazione sul programma. Nel momento in cui si realizza il TL di giorno (quindi con tempi più veloci sulla macch.fotog) non c’è problema, tutto va bene. Ma se decido di fare dei TL notturni…qui ho alcune difficoltà di gestione del programma. Voglio ricordarti la nota di Alessio. Per le foto notturne, i tempi di esposizione sono più lunghi ( va da 1sec…a 20/30 sec.. poi dipende anche da altri fattori) quindi durante questa fase si ottengono solo foto mosse proprio perchè non si ha la possibilità di fermare ( gestire i tempi di attesa) il motore.
Non è semplice controllare questo “passo” ma sarebbe un ulteriore miglioramento completo dello sketch.
A te questo arduo compito !!!!
Un saluto, Saverio