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

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

Permanent link to this article: https://www.mauroalfieri.it/elettronica/dolly-slider-per-matteo.html

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.