Dolly Project II con arduino

Il Dolly Project II nasce per soddisfare la voglia di fare di tutti gli appassionati di fotografia e time-lapse che hanno acquistato il kit dolly proposto da robotics-3d

dolly-II

Ho acquistato i componenti che compongono il kit e modificato il mio sketch per adattarlo al display 16×2 e al motore passo passo bipolare fornito.

In ordine: lista della spesa, assemblaggio, sketch e demo della programmazione.

Lista della spesa

Il Kit proposto ha già al suo interno:

  • 1 starter kit 2 con arduino rev 3
  • l’arduino motor shield fe
  • 1 stepper motor
Per realizzare il tuo Dolly è sufficente ed in taluni casi anche abbondante, nel senso che puoi anche aggiungere altre particolarità al robot sfruttando i componenti aggiuntivi presenti nello starter kit 2.

Assembla il tutto

L’assemblaggio potrebbe spaventarti visto il numero di componenti coinvolti ecco perchè ho realizzato qualche foto di esempio.

I pulsanti devono essere collegati come in figura:

pulsanti e resistenze sul dolly

Un contatto del pulsante lo colleghi al polo positivo e l’altro al polo negativo attraverso una resistenza da 330Ω di quelle fornite nel kit, allo stesso pin del pulsante colleghi una delle uscite arduino A0, A1 e A2 come descritto nel progetto Dolly I.

Il motore puoi collegarlo seguendo i colori:

connessione motore dolly

i terminali giallo e bleu alla fase A e i terminali rosso e verde alla fase B sulla motor shield FE. I jumper della shield  puoi lasciarli invariati rispetto al primo progetto.

Il collegamneto dell’LCD è descritto in questo articolo.

Lo Sketch

Il vero cuore di tutto è lo sketch:

/*
* 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 <LiquidCrystal.h>

// 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 pinLed = 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() {
  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 );

  pinMode(motorPinDirA, OUTPUT);
  pinMode(motorPinDirB, OUTPUT);
  pinMode(motorPinPwmA, OUTPUT);
  pinMode(motorPinPwmB, OUTPUT);

  pinMode(pinLed, 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 < 0 )  posizione = 3;

    lcd.print( menu_principale[posizione] );
    //lcd.print(millis()/1000);
    delay(200);

    if ( pconf > 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 < 3 )
  {
    int pnext = analogRead( next );
    int pprev = analogRead( prev );
    int pconf = analogRead( conf );

    if ( message )
    {
      lcd.setCursor(0, 0);
      lcd.print( submenu[i] );
      lcd.setCursor(0, 1);
      message = false;
    }

    if ( pnext > 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 < 1 )
  {
    int pnext = analogRead( next );
    int pprev = analogRead( prev );
    int pconf = analogRead( conf );

    if ( pnext > 1000 )
    {
      nFase++;
      if ( nFase > 4 ) nFase = 1;
      gira( nFase );
    }
    if ( pprev > 1000 )
    {
      nFase--;
      if ( nFase < 1 ) nFase = 4;
      gira( nFase );
    }
    if ( pconf > 1000 )
    {
      lcd.clear();
      i++;
    }
    delay ( 200 );
  }
}

void Go()
{
  lcd.print( "Avvio del dolly" );
  lcd.clear();

  for ( int sc=0; sc <= scatti; sc++ )
  {
    lcd.setCursor(0, 0);
    lcd.print( "scatto: " );
    lcd.setCursor(8, 0);
    lcd.print( sc );    

    for ( int ng=1; ng <= ngiri; ng++ )
    {
      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 );

  }

}

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;

  }
}

Molte linee le avrai trovate identiche a quelle del Dolly Project – prima versione – quindi ti mostro solo le differenze con questa versione.

Le linee di impostazione sono identiche e ti consentono di modificare i pin a cui è collegato l’LCD, il motore, i pulsanti ed il led che simula lo scatto.

le prima modifiche riguardano le linee 19 e 20:

char* menu_principale[4]  =  {"Settaggio","Controllo","Reset Carrello","Avvio"};
char* submenu[3]          =  {"N. passi x scatto","Intervallo passi","Numero scatti"};

in cui devi adattare i messaggi dei menu ai 16 caratteri del display (16×2) ma in compenso hai 2 righe su cui scrivere vedrai come ho pensato di fartele sfruttare nello sketch.

Nella funzione setup() linee 45-49 ti mostro il primo utilizzo:

lcd.begin(16, 2);
lcd.print("Dolly Project II");
lcd.setCursor(0, 1);
lcd.print("mauroalfieri.it");

ho ridotto e diviso il messaggio di benvenuto su due righe.

linea 46: definisci il display come 16 colonne e 2 righe;

linea 47: scrivi sulla prima riga “Dolly Project II”;

linea 48: sposta il cursore alla seconda riga del display, utilizza il metodo setCursor( carattere, riga ) in questo esempio posiziona il cursore al primo carattere della seconda riga. RICORDA: tutti i riferimenti dell’LCD partono da 0, la prima riga è 0 la seconda è 1, il primo carattere è 0, il secondo è 1 ed il sedicesimo è 15;

linea 49: scrivi “mauroalfieri.it” sulla seconda riga, puoi metterci il tuo nome o un tuo sito, se lasci il mio ogni volta che utilizzi il Dolly ti ricorderai di farmi visita 🙂

La modifica appena vista sebbene semplice ha conseguenze su tutto lo sketch, nel senso che ogni volta che scriverai un messaggio sul display dovrai considerare su quale riga e carattere sei, questo per non sovrascrivere quello che ti interessa mantenere, una caratteristica interessante è che il display non viene ripulito fino a che non decidi di utilizzare il metodo clear() o ti riposizioni in un punto e sovrascrivi il messaggio presente, questo ti permette di non doverti curare delle linee che non ti interessa utilizzare lasciando il messaggio invariato.

Tornando allo sketch altre linee modificate si trovano nelle funzioni Setting(),View(),ResetCarretto() e Go() in particolare alla linee 130-132

lcd.setCursor(0, 0);
lcd.print( submenu[i] );
lcd.setCursor(0, 1);

in cui puoi osservare che la linea 130 imposta il cursore sulla prima riga al primo carattere;

linea 131: scrive la voce di menu corrispondente al secondo menu in cui ti trovi;

linea 132: sposta il cursore al primo carattere della seconda riga, che accoglierà l’impostazione che darai con i pulsanti + e -;

anche all’interno delle linee con cui imposti i parametri del Dolly II c’è una piccola modifica che devi eseguire, le linee 140-142 e 146-148 presentano tutte l’istruzione lcd.setCursor(0,1) prima di scrivere il valore, questa modifica ti garantisce che il cursore sia sempre nella posizione corretta quando andrai a scrivere.

modifoche identiche a quelle appena viste le ritrovi anche nella funzione View() ed in particolare alle linee 165-167 e 169-171:

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

e di nuovo nella funzione di ResetCarrello() alle linee 179-182;

In ultimo la funzione Go() la più importante in quanto è quella che muove fisicamente il carrello facendo eseguire al motore i passi impostati nei tempi desiderati e lo scatto.

In questa funzione ho fatto un po di modifiche, alcune identiche alle precedenti altre per migliorare la visualizzazione infatti utilizzando le due righe puoi avere sempre sotto sontrollo lo scatto a cui sei arrivato e il passo che sta eseguendo, nella precedente versione del Dolly avevi solo una di queste informazioni in un dato momento del lavoro.

Per farlo ho deciso di utilizzare la prima riga per tener traccia degli scatti e la seconda dei passi, a tal proposito potrai vedere che le linee 219-222:

lcd.setCursor(0, 0);
lcd.print( "scatto: " );
lcd.setCursor(8, 0);
lcd.print( sc );

scrivono sulla prima riga del display (0,0) la dicitura “sactto: ” e alla posizione riga (8,0) il numero di scatto a cui il Dolly è arrivato, mentre li linee 226-229:

lcd.setCursor(0, 1);
lcd.print( "passo: ");
lcd.setCursor(8, 1);
lcd.print( ng );

ti permettono di gestire la seconda riga con le informazioni relative al passo in cui ti trovi; alla linea 226 posizioni il cursore al primo carattere della seconda riga (0,1);

linea 227: scrivi il messaggio “passo: “;

linea 228: posizioni il cursore alla posizione (8,1);

linea 229: scrivi a video il valore del passo a cui sei arrivato;

tutto il resto dello sketch resta invariato in quanto la funzione di controllo del motore come le altre coinvolte sono identiche a quelle presentate per il primo Dolly.

Il Dolly II a lavoro finito

Ecco il video su come puoi programmare il tuo dolly project II:

Buona realizzazione.

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

Permanent link to this article: https://www.mauroalfieri.it/elettronica/dolly-project-ii-con-arduino.html

39 pings

Skip to comment form

  1. […] Devi modificare la sola funzione go() presentata nel progetto: […]

  2. […] E’ una soluzione un po’ casereccia per evitare di utilizzare 2 optoisolatori, tuttavia posso consigliarti, se vuoi fare un lavoro professionale di acquistare un altro tipo di fotoaccoppiatore il: CNZ3182 della Panasonic, trovi il datasheet quì. Sostituendo l’optoisolatore con uno doppio dovrai cambiare lo sketch in modo che prima di scattare il dolly dovrà mettere a fuoco, con la soluzione iniziale non devi apportare alcuna modifica allo sketch presentato in questo articolo. […]

  3. […] Oggi ti racconto di un progetto realizzato dall’amico Alessandro, @Travis9011 su Tw: TriggerT. Il progetto si rivolge agli appassionati di fotografia come seguito del filone Dolly Project. […]

  4. […] che mi ha segnalato un appassionato di fotografia poiché già in passato ho dedicato realizzato il progetto dolly per gli appassionati di […]

  5. […] 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 […]

  6. […] che Matteo avrebbe voluto realizzare era differente dal progetto Dolly Photo originale, il suo scopo era poter montare sullo slider una telecamera e poterla spostare in modo automatico […]

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.