Stop motion per Dolly II

Un utente del blog, fotografo professionista, mi ha suggerito di aggiungere una funzionalità in più al dolly: lo stop motion.

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.

  • Questo sito ed i suoi contenuti è fornito "così com'è" e Mauro Alfieri non rilascia alcuna dichiarazione o garanzia di alcun tipo, esplicita o implicita, riguardo alla completezza, accuratezza, affidabilità, idoneità o disponibilità del sito o delle informazioni, prodotti, servizi o grafiche correlate contenute sul sito per qualsiasi scopo.
  • Ti chiedo di leggere e rispettare il regolamento del sito prima di utilizzarlo
  • Ti chiedo di leggere i Termini e Condizioni d'uso del sito prima di utilizzarlo
  • In qualità di Affiliato Amazon io ricevo un guadagno dagli acquisti idonei qualora siano presenti link al suddetto sito.

Permalink link a questo articolo: https://www.mauroalfieri.it/elettronica/stop-motion-per-dolly.html

10 commenti

Vai al modulo dei commenti

    • Alessio il 12 Luglio 2012 alle 22:09
    • Rispondi

    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.

    1. Grazie Alessio, mi scrivi il dettaglio della modifica? Così lo includo nei prossimi sketch come appendice per chi ha la tua stessa Nikon 🙂

    • Alessio il 14 Luglio 2012 alle 13:04
    • Rispondi

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

    1. 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

  1. 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

    1. 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

      1. Grazie Mauro, sempre pronto.

        Un saluto

    • Alessio il 25 Luglio 2012 alle 00:25
    • Rispondi

    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?

    1. Ciao Alessio,
      il tuo è un ottimo suggerimento sto elaborando una versione del progetto con anche questa funzionalità 🙂 presto sará on-line.

      1. 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

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.

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