«

»

Mag 08

Stampa Articolo

Dolly Slider per Matteo

Qualche settimana fa ho ultimato la realizzazione di un Dolly Slider su commissione di Matteo, non è lo stesso Matteo che sta preparando lo spettacolo teatrale, trattasi di omonimia.

Dolly Slider

Matteo è un appassionato fotografo e videomakers dedito alla realizzazione di filmati per matrimonio davvero unici.

Il progetto commissionato Dolly Slider

Quando Matteo mi ha contattato aveva già acquistato il kit da robot-domestici e si è già dato da fare da solo, seguendo le istruzioni, e le sue conoscenze nell’assemblare il kit dal punto di vistra elettronico. E’ una dote che apprezzo sempre molto in chi si avvicina al mondo Arduino quella di provarci prima di gettare la spugna e chiedere supporto: Dolly Photo Slider Ciò 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 lungo l’asse orizzontale con la precisione di un motore passo-passo. Inoltre avrebbe voluto poter selezionare non il numero di passi e di scatti con le pause per stabilizzare la macchina ma decidere le velocità ed i tempi di percorrenza dell’intera slitta. Matteo mi ha stupito positivamente quando, nonostante mi stesse commissionando un progetto, ha voluto che la sua esperienza ed il suo Dolly Photo Slider fosse messo in condivisione e pubblicato sul blog. Sono casi rari e che meritano tutta la mia più profonda stima.

La soluzione che ho proposto a Matteo

Di soluzioni che avrei potuto realizzare per questo progetto me ne sono passate molte in mente ma una in particolare ha solleticato la mia curiosità: quella di poter utilizzare il driver pololu a4983 o a4988 in grado di lavorare fino al 1/16 di passo con un motore bipolare: pololu a4983 driver per motori passo-passo bipolari Ho realizzato la basetta in grado di ospitare il driver della pololu usando una proto shield e seguendo lo schema fornito dalla pololu per i pin relativi al motore passo passo ed ai jumper di riduzione:

Dolly Pololu a4983

il motore passo passo va collegato secondo questa foto: Slider contatti motore per completare il progetto ho deciso di aggiungere due finecorsa realizzati con pulsanti e che puoi sostituire con degli interruttori a levetta: Dolly Photo Slider finecorsaa ciascun contatto ho saldato già dal lato della basetta una apposita resistenza di pull-down da 330ohm per evitare fase misurazioni sui pin analogici di Arduino quando il contatto è aperto.

Lo sketch del Dolly Slider

Ho realizzato uno sketch modificato in cui il controllo del motore è affidato al driver per motori passo-passo e sono selezionabili dal menu le diverse velocità che ho concordato con Matteo, in funzione della meccanica che ha realizzato e di cui mi ha fornito i calcoli di sviluppo della corsa:

/*
 * Dolly Slider
 *
 * Autore: Alfieri Mauro
 */

#include <LiquidCrystal.h>

// Definizioni
#define DEBUG
#define TIMEFASE 10
#define TARATURA 800

// INPUT
#define prev A0
#define next A1
#define conf A2
#define start A5
#define alt A4

// LCD BLACKLIGHT
#define pinBL 10

// Stepper
#define pinDir 9
#define pinStep 8

// Menu Level
char* menu_principale[5]  =  {"Settaggio","Controllo","Reset Carrello","Reset Auto","Avvio"};
char* submenu[1]          =  {"Velocita"};
char buffer[16];

// Caratteri
byte symbolplay[8]   = {B10000,B11000,B11100,B11110,B11100,B11000,B10000};
byte symbolstop[8]   = {B00000,B11111,B11111,B11111,B11111,B11111,B00000};
byte symbolpause[8]  = {B11011,B11011,B11011,B11011,B11011,B11011,B11011};
byte symbolrplay[8]  = {B00001,B00011,B00111,B01111,B00111,B00011,B00001};

// Init level
int stepTotali = 2300;
int timeStep[14] = {5,15,25,50,100,150,250,400,800,1500,3000,4750,8000,12500};
int velocita[14] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14};
char* labelVel[14] = {"  11,5 sec","  34,5 sec","    57 sec","  1,55 min","  3,50 min","  5,45 min","  9,35 min"," 15,20 min"," 30,40 min","57,30 min"," 1,55 ore"," 3,02 ore"," 5,07 ore"," 7,59 ore"};
int maxVal = 13;
int velImpostata = 0;
int posizione=0;

boolean blacklightStatus = false;

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 4, 5, 6, 7);

void setup() {

  #ifdef DEBUG
    Serial.begin( 9600 );
    Serial.println( "Dolly Project Start" );
  #endif

  lcd.begin(16, 2);
  lcd.createChar(1, symbolplay);
  lcd.createChar(2, symbolpause);
  lcd.createChar(3, symbolstop);
  lcd.createChar(4, symbolrplay);

  lcd.setCursor(0, 0);
  lcd.print("Dolly Matteo :-)");
  lcd.setCursor(0, 1);
  lcd.print("mauroalfieri.it");

  delay( 2000 );

  lcd.clear();
  lcd.print( menu_principale[posizione] );

  pinMode( pinDir,OUTPUT );
  pinMode( pinStep,OUTPUT );
  pinMode( pinBL,OUTPUT );

  pinMode( start,INPUT );
  pinMode( alt,INPUT );

  digitalWrite( pinDir,LOW );
  digitalWrite( pinStep,LOW );
  digitalWrite( pinBL,HIGH );

  analogWrite( start,LOW );
  analogWrite( alt,LOW );
}

void loop() {
  lcd.setCursor(0, 1);
  int pnext = analogRead( next );
  int pprev = analogRead( prev );
  int pconf = analogRead( conf );

  #ifdef DEBUG
    Serial.print( "Loop Next: " ); Serial.print( pnext );
    Serial.print( " Prev: " ); Serial.print( pprev );
    Serial.print( " Conf: " ); Serial.print( pconf );
    Serial.print( "\n" );
  #endif

  if ( pnext > TARATURA || pprev > TARATURA || pconf > TARATURA) {

    if ( pnext > TARATURA ) { posizione++; lcd.clear(); }
    if ( pprev > TARATURA ) { posizione--; lcd.clear(); }

    if ( posizione > 4 ) posizione = 0;
    if ( posizione < 0 ) posizione = 4;

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

    if ( pconf > TARATURA ) {
      lcd.clear();
      switch ( posizione )
      {
        case 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:
          ResetAuto();
          lcd.clear();
          lcd.print( menu_principale[3] );
        break;

        case 4:
          Go();
          lcd.clear();
          lcd.print( menu_principale[4] );
        break;
      }
    }
  }
}

void Setting()
{
  int i = 0;
  boolean message = true;

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

  while ( i < 1 )
  {
    int pnext = analogRead( next );
    int pprev = analogRead( prev );
    int pconf = analogRead( conf );

    #ifdef DEBUG
      Serial.print( "Setting Next: " );  Serial.print( pnext );
      Serial.print( " Prev: " );         Serial.print( pprev );
      Serial.print( " Conf: " );         Serial.print( pconf );
      Serial.print( " Val: " );          Serial.print( velImpostata );
      Serial.print( " MaxVal: " );       Serial.print( maxVal );

      Serial.print( "\n" );
    #endif

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

    if ( pnext > TARATURA ) { velImpostata++; }
    if ( pprev > TARATURA ) { velImpostata--; }
    if ( pconf > TARATURA ) { lcd.clear(); i++; message = true; }

    if ( velImpostata < 0 )     { velImpostata = 0; }
    if ( velImpostata > maxVal) { velImpostata = maxVal; }

    lcd.setCursor(0, 1);
    sprintf(buffer, "%s %d%s%s", "v:", velocita[velImpostata], " " , labelVel[velImpostata] );
    lcd.print( buffer );

    delay( 200 );
  }
}

void View()
{
  lcd.clear();
  lcd.print( submenu[0] );
  lcd.setCursor(0, 1);

  int _velocita = velocita[velImpostata];
  char* _label  = labelVel[velImpostata];

  sprintf(buffer, "%s %d%s%s ", "v:", _velocita, " " , _label );
  lcd.print( buffer );

  delay( 3000 );
}

void ResetCarrello()
{
  lcd.clear();
  lcd.print( "+/- sposta carr" );
  lcd.setCursor(0, 1);
  lcd.print( "C esce" );
  int i = 0;

  while ( analogRead( conf ) < TARATURA )
  {
    int pnext = analogRead( next );
    int pprev = analogRead( prev );

    int cStart = analogRead( start );
    int cAlt   = analogRead( alt );

    if ( pnext > TARATURA && (cAlt < TARATURA) )   { gira( true );  }
    if ( pprev > TARATURA && (cStart < TARATURA) ) { gira( false ); }

    delay ( TIMEFASE );
  }

  lcd.clear();
  delay( 300 );
}

void ResetAuto()
{
  lcd.clear();
  lcd.print( "Reset Auto" );
  lcd.setCursor(11, 0);
  lcd.write(4);
  lcd.setCursor(12, 0);
  lcd.write(4);

  while ( analogRead( start ) < TARATURA ) {
    gira( false );
  }

  lcd.setCursor(11, 0);
  lcd.write(3);
  lcd.setCursor(12, 0);
  lcd.print( " " );
  delay( 2000 );
}

void Go() {
  int _time = timeStep[velImpostata];

  lcd.print( "Go   " );
  lcd.setCursor(4, 0);
  lcd.write(2);
  lcd.setCursor(0, 1);
  lcd.write(1);
  lcd.setCursor(6, 1);
  lcd.write(2);
  lcd.setCursor(14, 1);
  lcd.write(3);

  for ( int s=0; s <= stepTotali; s++ )
  {
    lcd.setCursor(4, 0);
    lcd.write(1);
    lcd.setCursor(6, 0);
    lcd.print( "Step: " );
    lcd.setCursor(12, 0);
    lcd.print( s );

    if ( analogRead( next ) > TARATURA) {
      lcd.setCursor(4, 0);
      lcd.write(2);
      while ( !(analogRead( prev ) > TARATURA) ) {
        if ( analogRead( conf ) > TARATURA) {
          lcd.setCursor(4, 0);
          lcd.write(3);
          stop();
          delay( 1000 );
          return;
        }
        delay( 200 );
      }
    }

    if ( analogRead( conf ) > TARATURA) {
      lcd.setCursor(4, 0);
      lcd.write(3);
      stop();
      delay( 1000 );
      return;
    }

    int cStart = analogRead( start );
    int cAlt   = analogRead( alt );
    if ( cAlt > TARATURA )   { s = stepTotali; }

    gira( true );
    delay( _time );
  }
}

void gira( boolean dir ) {

  #ifdef DEBUG
    Serial.print( "Gira: " );
    Serial.print( pinDir );
    Serial.print( " Step: " );
    Serial.print( pinStep );
    Serial.print( "\n" );
  #endif

  if ( dir ) { digitalWrite(pinDir, HIGH); }
  else       { digitalWrite(pinDir, LOW);  }

  digitalWrite(pinStep, HIGH);
  digitalWrite(pinStep, LOW);
}

void stop() {
  digitalWrite( pinDir,LOW );
  digitalWrite( pinStep,LOW );
}

Lo sketch è alquanto differente dai progetti Dolly che ho realizzato ma è servito a realizzare il Dolly Slider per telecamera utilizzata nelle riprese di matrimonio e non solo che matto realizza per i suoi clienti e per piacere personale.

Ti invito ad approfondire alcune delle caratteristiche del progetto:

linee 15-19: imposta i pin a cui sono collegati i 3 pulsanti e i due sensori di finecorsa che impediscono al Dolly Slider di forzare la guida alla fine della sua corsa;

linea 40: imposta il numero massimo di step che il motore deve eseguire per percorrere l’intero percorso;

linea 41: definisci un array i cui valori corrispondono ai tempi i millisecondi da attendere tra un paso ed il successivo;

linea 42: imposta un array che funziona da indice nella scelta delle velocità;

linea 43: imposta un array i cui valori sono le stringhe di testo da visualizzare sul display per indicarti il tempo si percorrenza che stai impostando.

Queste righe ti da una informazione precisa del tempo di percorrenza calcolabile come:

[numero di passi] x [il tempo impostato tra un passo ed il successivo]

e ti permette di calcolare il tempo di percorrenza dell’intero carrello:

2300 x 5ms = 11500ms da cui 11,5 secondi

L’ultima differenza è costituita dalle linee 314-329 in cui definisci la funzione gira() il cui scopo è far compiere un passo al motore in funzione del solo parametro dir che può assumere valore true o  false ( orario o antiorario ).

Buon lavoro Matteo !!!

Permalink link a questo articolo: http://www.mauroalfieri.it/elettronica/dolly-slider-per-matteo.html

15 comments

Vai al modulo dei commenti

  1. Paolo

    Buongiorno,
    Mi chiamo Paolo e ho qualche difficoltà con Arduino uno .
    Vorrei controllare uno stepper motor bipolare , usando Arduino 1 connesso con il motor shield R3 e il display LCD Keypad shield.
    L’idea sarebbe quella di usare la tastiera per il controllo del motorino ( deve girare nel verso orario.
    A tale scopo volevo usare il programma del Dolly, magari modificandolo con il Suo aiuto, ma non riesco a far funzionare il programma. Infatti appare la scritta in attesa di comandi, ma non riesco ad impartire nessun comando. Credo che il problema sia l’uso di arduino 1 e non del modello 2009.
    Potrebbe aiutarmi?
    Grazie
    Paolo

    1. Mauro Alfieri

      Ciao Paolo,
      puoi trovare nel blog alcuni articoli che ho dedicato al Dolly in cui racconto passo-passo il progetto.
      La funzione che vuoi ottenere è fattibile con la sola funzione di resetCarrello, omettendo le altre funzioni.

      Il problema che riscontri potrebbe essere dovuto ad un differente valore letto sul pin A0 di solito dovuto a due cause:

      1. non hai separato le piste della motor shield R3 in corrispondenza di A0 ed A1;
      2. i valori letti dal pulsante A0 non sono identici a quelli della mia shield e di conseguenza non rileva la pressione del tasto.

      La soluzione al primo è un taglierino con cui separare le piste.
      La soluzione alla seconda è eseguire dei test con la sola keypad ed Arduino e verificare i valori letti alla pressione di ciascun pulsante.

      Mauro

      1. francesco

        Ciao Mauro,
        ho intrapreso l’avventura di costruire un dolly con time-laps per macchina fotografica, e la parte meccanica è già finita, adesso dovrei pilotare il motore che è un Nema 23 di 2,0 A. e credo che solo con Arduino lo posso ottenere vero?. Ma c’è un problema; non ho alcuna esperienza di programmazione di questa scheda, in verità seguendo un po i tutorial ho anche acquistato :
        1) ARDUINO UNO REV3
        2) ARDUINO MOTOR SHIELD FE
        3) DFRobot – LCD Shield
        Ti chiedo se c’è qualche tutorial (molto elementare) che mi potresti consigliare di come viene collegato il motore, con quale batteria e se c’è qualche programmazione già esistente per questo tipo di lavoro.
        In attesa di una tua risposta ti lascio i miei saluti e ringraziamenti

        Francesco

  2. francesco

    Ciao Mauro,
    ho intrapreso l’avventura di costruire un dolly con time-laps per macchina fotografica, e la parte meccanica è già finita, adesso dovrei pilotare il motore che è un Nema 23 di 2,0 A. e credo che solo con Arduino lo posso ottenere vero?. Ma c’è un problema; non ho alcuna esperienza di programmazione di questa scheda, in verità seguendo un po i tutorial ho anche acquistato :
    1) ARDUINO UNO REV3
    2) ARDUINO MOTOR SHIELD FE
    3) DFRobot – LCD Shield
    Ti chiedo se c’è qualche tutorial (molto elementare) che mi potresti consigliare di come viene collegato il motore, con quale batteria e se c’è qualche programmazione già esistente per questo tipo di lavoro.
    In attesa di una tua risposta ti lascio i miei saluti e ringraziamenti

    Francesco

    1. Mauro Alfieri

      Ciao Francesco,
      ho presentato alcuni articoli di Dolly su questo Blog che puoi leggere, cerca “dolly”.
      Il primo modello utilizzava una motor shield fe ma é da saldare e non in modo semplice quindi ho realizzato il progetto Dolly Photo che usa una motor shield arduino originale e la Keypad LCD.

      Dovrai fare un po’ di lavoro elettronico e di programmazione per unire i due progetti, ma penso c’è in linea di massima sia fattibile.

      Attenzione 2A é la corrente massima della motor sheld fe, come di moltissime shield x arduino che usano l’L293 potresti fonderla.

      Mauro

  3. Diego

    Ciao,
    ho acquistato il kit per il dolly video,come posso utilizzare il motoriduttore(presente nel kit ma non nel tuo progetto) con encoder,cioè che collegamenti devo fare sul motor shield ver3?
    Poi sto provando con una shield wifi arduino a comunicare con il tutto tramite osc,per ora con grande sorpresa ho trovato uno sketch devo adattarlo ,ma per ora riesco ad attivare il motore,se ti invio lo sketch magari mi sai dare più notizie su come fare,visto che in realtà mi serve uno slider e due bottoni..

    1. Mauro Alfieri

      Ciao Diego,
      quale kit hai acquistato? Non ricordo di aver realizzato un kit con motore DC ed encoder.
      Di norma non correggo sketch scritti da altri primo perché non lo trovo corretto nei confronti dell’autore e secondo perché non ho il tempo di provarli.

  4. Diego

    Ciao grazie per la risposta
    in tanto ho scritto un mio sketch e funziona,solo che devo capire con uno slider OSC come posso pilotare il motore in questione.
    intanto ti invio il link del kit
    http://www.robotics-3d.com/component/virtuemart/robot-domestici-store-officine-robot-domestici/dolly-camera-project-arduino-kit
    grazie

    1. Mauro Alfieri

      Ciao Diego,
      si è un vecchio kit sul quale non ho sviluppato molto sw.
      Devo chiedere al sito di sostituirlo con uno dotato di motore più potente quello in dotazione si è rivelato poco potente.
      Con uno slider OSC potresti controllare la velocità del motore e usare due tasti: il primo come start ed il secondo come pausa/stop
      Che ne dici?

  5. Diego

    Perfetto direi….un po’ di sarcasmo c’è
    perché pensavo di aver acquistato un valido progetto e invece neanche esiste?!
    magari può maturare una collaborazione temporanea di supporto…,-)
    ti posso inviare il mio sketch!!!…
    giusto per avere dei suggerimenti per questo motore e quale comando,
    in rete non si trova niente per motoriduttori con encoder,
    mi serve giusto il comando fader/slider lo posso poi postare come up grade del tuo progetto;-)
    grazie Diego

    1. Mauro Alfieri

      Ciao Diego,
      purtroppo non riesco a seguire tutti i progetti che in tanti appassionati mi scrivete e posso consigliarti di leggere i miei articoli sul blog in merito ai motori, al dolly ed agli encoder per sviluppare il progetto in autonomia e non rendere vago il tuo acquisto.
      Se ti va di condividere il progetto una volta ultimato sarò lieto di farlo sul blog.

  6. Paolo

    Una domanda Mauro. Ma in questi progetti o nell’altri non vedo parlare di freno motore. Sarebbe fondamentale per tenere la slider inclinata. Io uso la MotorShiled e non ho ancora trovato una soluzione, sia dal punto di vista del codice che hardware. Ho dovuto rimuovere il ponticello del brake sotto la MotorShiled per renderlo compatibile con il KypadLCD. Qualche idea?

    1. Mauro Alfieri

      Ciao Paolo,
      il freno motore dipende molto dal motore che utilizzi in quanto non è semplice implementarlo elettronicamente se la meccanica non lo supporta.

  7. Domenico

    Ciao complimenti per i tutorial, c’è una versione più aggiornata grazie mille

    1. Mauro Alfieri

      Ciao Domenico,
      perdonami, la tua è una domanda o una affermazione ?

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Puoi usare i seguenti tag ed attributi HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>