Dolly Photo – quarta parte

Questo articolo riprende e continua il filone del progetto Dolly Photo la nuova versione del Dolly Project che ho realizzato sulla base delle richieste giunte da molti appassionati fotografi e makers come te.

Keypad LCD Dolly Photo

Nella quarta parte del progetto troverai come collegare la motor shield arduino, il motore stepper ed il keypad LCD  e provi il reset del motore.

L’operazione di reset ti consente di verificare che il progetto funzioni e che i collegamenti tra arduino-motor shield-keypad lcd-motore siano corretti.

Il montaggio del Dolly Photo

Questa versione del Dolly Photo è studiata per essere decisamente più semplice da montare rispetto al suo predecessore infatti tutte le shield sono già vendute pre-assemblate.

Puoi semplicemente comporle come in figura:

Dolly Photo shield kit

una sull’altra nell’ordine, partendo dal basso verso l’alto:

  1. Arduino Uno R3
  2. Motor shield Arduino
  3. Keypad LCD

Nella figura sopra vedi anche che l’alimentazione arriva dall’esterno attraverso un trasformatore stabilizzato da 12v che fornisce allo stesso tempo alimentazione a tutto lo stack di schede o panettone ( come alcuni appassionati lo chiamano )

Il motore passo-passo del Dolly Photo

Il motore passo-passo che vedi in figura è quelo che ho utilizzato come dimostrazione e test, quello che trovi nel kit Dolly Photo è lo stesso motore previsto per la versione precedente del Dolly Project:

Motore passo-passo bipolare

in cui puoi riconoscere le fasi osservando questo video:

Il motore passo-passo che ho utilizzato per i test è questo:

DollyPhoto stepper

il modo in cui i due motori sono connessi alla motor shield è lo stesso, cambiano i colori dei fili ma le coppie A e B del motore sono le medesime.

La motor shield arduino per il Dolly Photo

La motor shield arduino hai già avuto modo di vederla all’opera con i motori passo-passo in questo articolo: “Motor Shield R3 Arduino – motore passo-passo” ho deciso di utilizzarla anche per il nuovo Dolly Photo:

Dolly Photo motor shield per dolly

Collega i fili della coppia A sul canale 1 e i fili della coppia B sul canale 2, ricordati di alimentare la shield e tutto arduino con un alimentatore esterno da 12v ed esegui i tuoi test senza la connessione al Pc, ossia con la porta USb scollegata:

DollyPhoto alimentazione

questa situazione ti premette di evitare inconvenienti dovuti a carico eccessivo delle porte USB del tuo computer o peggio di bruciarle se qualche componente non si comporta in modo adeguato.

Lo sketch del DollyPhoto con funzione reset

Ho arricchito lo sketch aggiungendo righe di codice nella funzione reset:

/**********************************************************
 * Dolly Photo Arduino
 *
 * Data creazione 25 febbraio 2013
 *
 * autore: Mauro Alfieri
 * web:    mauroalfieri.it
 * tw:     @mauroalfieri
 *
 *
/**********************************************************/

#include <LiquidCrystal.h>

/**********************************************************/

#define BUTTON A0
#define BACKLIGHT 10
#define MOTDTIME 2000
#define LCDTIME  3000
#define SETMODETIME 2000
#define DEBUG

/**********************************************************/

#define PWMA 3
#define PWMB 11
#define DIRA 12
#define DIRB 13
#define TIMEFASE 35

/**********************************************************/

char line0[16] = "Dolly Foto ver1";
char line1[16] = "mauroalfieri.it";

/**********************************************************/

int SELECT[]     =  {720,760};
int LEFT[]       =  {480,520};
int RIGTH[]      =  {0,20};
int UP[]         =  {120,160};
int DOWN[]       =  {300,350};

int buttonPress  = 0;
int nFase        = 0;

/**********************************************************/

unsigned long timeToBlacklight  =  0;
unsigned long timeToSetMode     =  0;
unsigned long timeSetting       =  0;

/**********************************************************/

boolean blacklightStatus = false;

/**********************************************************/

byte symbolselect[8] = {B00001,B00011,B00111,B01111,B00111,B00011,B00001};
byte symbolplay[8]   = {B10000,B11000,B11100,B11110,B11100,B11000,B10000};
byte symbolstop[8]   = {B00000,B11111,B11111,B11111,B11111,B11111,B00000};
byte symbolpause[8]  = {B00000,B10001,B10001,B10001,B10001,B10001,B00000};

/**********************************************************/
char* principale[4]   =  {"Impostazioni","Verifica","Reset Carrello","Avvio"};
char* secondario[10]  =  {"Numero passi","per scatto","Intervallo tra","i passi","Tempo di ALT","prima","Tempo di ALT","dopo","Numero scatti","totali"};
char buffer[16];

/**********************************************************/

int passiXscatto      = 0;
int intervaloScatto   = 0;
int tempoAltPrima     = 0;
int tempoAltDopo      = 0;
int numeroScatti      = 0;

/**********************************************************/

LiquidCrystal lcd(8,9,4,5,6,7);

/**********************************************************/

void setup() {

  #ifdef DEBUG
    Serial.begin( 9600 );
    Serial.println("Avvio");
  #endif

  /**********************************************************/

  pinMode( BACKLIGHT,OUTPUT );
  digitalWrite( BACKLIGHT,LOW );

  /**********************************************************/

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

  /**********************************************************/

  digitalWrite( BACKLIGHT,HIGH );
  lcd.setCursor(0,0);
  lcd.print(line0);
  lcd.setCursor(0,1);
  lcd.print(line1);
  delay( MOTDTIME );
  lcdBlacklightOff();
}

/**********************************************************/

void loop() {

  /**********************************************************/

  #ifdef DEBUG
    Serial.print( " Button: " );           Serial.print( analogRead( BUTTON ) );
    Serial.print( " TimeToBlecklight " );  Serial.print( timeToBlacklight );
    Serial.print( " TimeToSetHour " );     Serial.println( timeToSetMode );
  #endif

  /**********************************************************/

  if ( ctrlButton( analogRead( BUTTON ) ) == 0 || ctrlButton( analogRead( BUTTON ) ) > 1 ) { timeToSetMode = millis(); }
  if (timeToSetMode > 0 && SETMODETIME < (millis() - timeToSetMode) ) { menuMode(); timeToSetMode = 0; }

  /**********************************************************/

  buttonPress = ctrlButton( analogRead( BUTTON ) );

  /**********************************************************/

  if (  (blacklightStatus) && LCDTIME < (millis() - timeToBlacklight) ) { lcdBlacklightOff(); }

  /**********************************************************/

  char line0[16] = " in attesa di  ";
  char line1[16] = "    comandi ...";

  /**********************************************************/

  lcd.setCursor(0,0);
  lcd.print(line0);
  lcd.setCursor(0,1);
  lcd.print(line1);

  /**********************************************************/
}

/**********************************************************/

int ctrlButton( int button ) {

  buttonPress = 0;
  if ( SELECT[0] <= button && button <= SELECT[1] )  { buttonPress = 1; }
  if ( LEFT[0] <= button && button <= LEFT[1] )      { buttonPress = 2; }
  if ( RIGTH[0] <= button && button <= RIGTH[1] )    { buttonPress = 3; }
  if ( UP[0] <= button && button <= UP[1] )          { buttonPress = 4; }
  if ( DOWN[0] <= button && button <= DOWN[1] )      { buttonPress = 5; }

  if (buttonPress > 0) {
    analogWrite( BACKLIGHT,128 );
    blacklightStatus = true;
    timeToBlacklight = millis();
  }

  return buttonPress;
}

/**********************************************************/

void lcdBlacklightOff() {
  digitalWrite( BACKLIGHT,LOW );
  blacklightStatus = false;
  timeToBlacklight = 0;
  lcd.clear();
}

/**********************************************************/

void menuMode() {

  /**********************************************************/

  #ifdef DEBUG
    Serial.println( "Menu Mode" );
  #endif

  /**********************************************************/

  boolean setMode  = true;
  int setModeLevel = 0;
  timeSetting      = 0;
  lcd.clear();

  /**********************************************************/

  delay( 1000 );

  /**********************************************************/  

  while ( setMode ) {

    /**********************************************************/

    if ( ctrlButton( analogRead( BUTTON ) ) != 0 ) { timeSetting = millis(); }

    if ( (ctrlButton( analogRead( BUTTON )) == 5 ) && setModeLevel < 3 ) { lcd.clear(); setModeLevel++; }
    if ( (ctrlButton( analogRead( BUTTON )) == 4 ) && setModeLevel > 0 ) { lcd.clear(); setModeLevel--; }

    if ( (setModeLevel % 2) == 0 ) {
      lcd.setCursor(0,0);
      lcd.print( principale[setModeLevel] );
      lcd.setCursor(0,1);
      lcd.print( principale[(setModeLevel+1)] );  

      lcd.setCursor(15,0);
      lcd.write(1);
      lcd.setCursor(15,1);
      lcd.print(" ");
    } else {
      lcd.setCursor(0,0);
      lcd.print( principale[(setModeLevel-1)] );
      lcd.setCursor(0,1);
      lcd.print( principale[setModeLevel] );  

      lcd.setCursor(15,0);
      lcd.print(" ");
      lcd.setCursor(15,1);
      lcd.write(1);
    }

    if ( ctrlButton( analogRead( BUTTON )) == 1 ) {
      if ( setModeLevel == 0 ) { impostazioni(); }
      if ( setModeLevel == 1 ) { verifica();     }
      if ( setModeLevel == 2 ) { reset();        }
      if ( setModeLevel == 3 ) { avvio();        }

      setMode = false;
      timeSetting = 0;
    }

    if (timeSetting > 0 && (SETMODETIME*2) < (millis() - timeSetting) ) { setMode = false; }
    delay(200);
  }

  /**********************************************************/

  lcd.clear();
}

/**********************************************************/

void impostazioni() {

  /**********************************************************/

  #ifdef DEBUG
    Serial.println( "Menu Impostazioni" );
  #endif

  /**********************************************************/

  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print( "Menu " );
  lcd.setCursor(0,1);
  lcd.print( "Impostazioni" );    

  /**********************************************************/

  delay( SETMODETIME );

  /**********************************************************/

  boolean impostazioniMode  = true;
  int setModeLevel = 0;
  lcd.clear();

  /**********************************************************/

  while ( impostazioniMode ) {

    /**********************************************************/

    if ( (ctrlButton( analogRead( BUTTON )) == 5 ) && setModeLevel < 8 ) { lcd.clear(); setModeLevel = (setModeLevel+2); }
    if ( (ctrlButton( analogRead( BUTTON )) == 4 ) && setModeLevel > 0 ) { lcd.clear(); setModeLevel = (setModeLevel-2); }
    if (  ctrlButton( analogRead( BUTTON )) == 1 )                       { impostazioniMode = false; }

    /**********************************************************/

    #ifdef DEBUG
      Serial.print( "setMenuLevel: " );
      Serial.println( setModeLevel );
    #endif

    /**********************************************************/

    switch ( setModeLevel ) {

      case 0:
        if ( (ctrlButton( analogRead( BUTTON )) == 3 ) && passiXscatto <= 99999)  { passiXscatto++; lcd.clear(); }
        if ( (ctrlButton( analogRead( BUTTON )) == 2 ) && passiXscatto >= 1)      { passiXscatto--; lcd.clear();  }

        sprintf(buffer, "%s %d", secondario[(setModeLevel+1)], passiXscatto);
      break;

      case 2:
        if ( (ctrlButton( analogRead( BUTTON )) == 3 ) && passiXscatto <= 9999999)  { intervaloScatto++; lcd.clear();  }
        if ( (ctrlButton( analogRead( BUTTON )) == 2 ) && passiXscatto >=     1)    { intervaloScatto--; lcd.clear();  }

        sprintf(buffer, "%s %ds", secondario[(setModeLevel+1)], intervaloScatto);
      break;

      case 4:
        if ( (ctrlButton( analogRead( BUTTON )) == 3 ) && tempoAltPrima <= 9999999)  { tempoAltPrima++; lcd.clear();  }
        if ( (ctrlButton( analogRead( BUTTON )) == 2 ) && tempoAltPrima >=     1)    { tempoAltPrima--; lcd.clear();  }

        sprintf(buffer, "%s %ds", secondario[(setModeLevel+1)], tempoAltPrima);
      break;

      case 6:
        if ( (ctrlButton( analogRead( BUTTON )) == 3 ) && tempoAltDopo <= 9999999)  { tempoAltDopo++; lcd.clear();  }
        if ( (ctrlButton( analogRead( BUTTON )) == 2 ) && tempoAltDopo >=     1)    { tempoAltDopo--; lcd.clear();  }

        sprintf(buffer, "%s %ds", secondario[(setModeLevel+1)], tempoAltDopo);
      break;

      case 8:
        if ( (ctrlButton( analogRead( BUTTON )) == 3 ) && numeroScatti <= 9999999)  { numeroScatti++; lcd.clear();  }
        if ( (ctrlButton( analogRead( BUTTON )) == 2 ) && numeroScatti >=     1)    { numeroScatti--; lcd.clear();  }

        sprintf(buffer, "%s %d", secondario[(setModeLevel+1)], numeroScatti);
      break;

    }

    /**********************************************************/

    lcd.setCursor(0,0);
    lcd.print( secondario[setModeLevel] );
    lcd.setCursor(0,1);
    lcd.print( buffer );        

    /**********************************************************/

    delay( 200 );

  }

  /**********************************************************/

  lcd.clear();

}

/**********************************************************/

void verifica() {
  /**********************************************************/

  #ifdef DEBUG
    Serial.println( "Menu Verifica" );
  #endif

  /**********************************************************/

  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print( "Menu " );
  lcd.setCursor(0,1);
  lcd.print( "Verifica" );    

  /**********************************************************/

  delay( SETMODETIME );

  /**********************************************************/

  boolean verificaMode  = true;
  int setModeLevel = 0;
  lcd.clear();

  /**********************************************************/

  while ( verificaMode ) {

    /**********************************************************/

    if ( (ctrlButton( analogRead( BUTTON )) == 5 ) && setModeLevel < 8 ) { lcd.clear(); setModeLevel = (setModeLevel+2); }
    if ( (ctrlButton( analogRead( BUTTON )) == 4 ) && setModeLevel > 0 ) { lcd.clear(); setModeLevel = (setModeLevel-2); }
    if (  ctrlButton( analogRead( BUTTON )) == 1 )                       { verificaMode = false; }

    /**********************************************************/

    #ifdef DEBUG
      Serial.print( "setMenuLevel: " );
      Serial.println( setModeLevel );
    #endif

    /**********************************************************/

    switch ( setModeLevel ) {

      case 0:
        sprintf(buffer, "%s %d", secondario[(setModeLevel+1)], passiXscatto);
      break;

      case 2:
        sprintf(buffer, "%s %ds", secondario[(setModeLevel+1)], intervaloScatto);
      break;

      case 4:
        sprintf(buffer, "%s %ds", secondario[(setModeLevel+1)], tempoAltPrima);
      break;

      case 6:
        sprintf(buffer, "%s %ds", secondario[(setModeLevel+1)], tempoAltDopo);
      break;

      case 8:
        sprintf(buffer, "%s %d", secondario[(setModeLevel+1)], numeroScatti);
      break;

    }

    /**********************************************************/

    lcd.setCursor(0,0);
    lcd.print( secondario[setModeLevel] );
    lcd.setCursor(0,1);
    lcd.print( buffer );        

    /**********************************************************/

    delay( 200 );

  }

  /**********************************************************/

  lcd.clear();

}

/**********************************************************/

void reset() {

  /**********************************************************/

  #ifdef DEBUG
    Serial.println( "Menu Reset" );
  #endif

  /**********************************************************/

  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print( "Menu " );
  lcd.setCursor(0,1);
  lcd.print( "Reset" );    

  /**********************************************************/

  delay( SETMODETIME );

  /**********************************************************/

  boolean resetMode  = true;
  lcd.clear();

  /**********************************************************/

  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print( "LEFT antiorario" );
  lcd.setCursor(0,1);
  lcd.print( "RIGTH orario" );    

  /**********************************************************/

  while ( resetMode ) {

    /**********************************************************/

    if ( ctrlButton( analogRead( BUTTON )) == 3 )  { nFase++; }
    if ( ctrlButton( analogRead( BUTTON )) == 2 )  { nFase--; }
    if ( ctrlButton( analogRead( BUTTON )) == 1 )  { resetMode = false; }

    /**********************************************************/

    nFase = fase( nFase );

    /**********************************************************/

    delay( 100 );
  }

  /**********************************************************/

  stop();

  /**********************************************************/

  lcd.clear();
}

/**********************************************************/

void avvio() {
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print( "Menu " );
  lcd.setCursor(0,1);
  lcd.print( "Avvio" );    

  delay( SETMODETIME );
}

/**********************************************************/

int fase( int nFase ) {

  if ( nFase > 4 ) { nFase = 1; }
  if ( nFase < 1 ) { nFase = 4; }

  #ifdef DEBUG
      Serial.print( "fase() - nFase: " );
      Serial.println( nFase );
  #endif

  switch( nFase ) {
  case 1:
    digitalWrite(DIRA, HIGH);
    digitalWrite(DIRB, LOW);
    digitalWrite(PWMA, HIGH);
    digitalWrite(PWMB, LOW);
    break;

  case 2:
    digitalWrite(DIRA, LOW);
    digitalWrite(DIRB, HIGH);
    digitalWrite(PWMA, LOW);
    digitalWrite(PWMB, HIGH);
    break;

  case 3:
    digitalWrite(DIRA, LOW);
    digitalWrite(DIRB, LOW);
    digitalWrite(PWMA, HIGH);
    digitalWrite(PWMB, LOW);
    break;

  case 4:
    digitalWrite(DIRA, LOW);
    digitalWrite(DIRB, LOW);
    digitalWrite(PWMA, LOW);
    digitalWrite(PWMB, HIGH);
    break;
  }

  delay(TIMEFASE);

  return nFase;
}

/**********************************************************/

int stop() {
  digitalWrite(DIRA, LOW);
  digitalWrite(DIRB, LOW);
  digitalWrite(PWMA, LOW);
  digitalWrite(PWMB, LOW);
}

/**********************************************************/

ci sono delle nuove funzioni che ho aggiunto e servono per controllare il motore o fermarlo durante la fase di reset e la prossima fase: Avvio.

Le nuove funzioni sono:

reset()

linea 453: definisci la funzione reset() richiamata alla linea 241 dalla menuMode();

linee 457-459: imposta il controllo sulla definizione di DEBUG per scrivere sul monitor seriale il testo “Menu Reset()”;

linee 463-467: scrivi sul display il testo “Menu” sulla prima linea e “Reset” sulla seconda;

linea 471: attendi il tempo definito nella costante SETMODETIME prima di cancellare il testo dall’LCD;

linea 475: inizializza una variabile di tipo boolean ( il cui valore può essere true o false ) denominata resetMode e impostala a true;

linea 476: cancella ogni linea di testo dal Display LCD;

linee 480-484: scrivi sulla prima riga del display del Dolly Photo il testo “LEFT antiorario” e sulla seconda riga il testo “RIGHT orario”;

linea 488: verifica che il valore di restMode sia true e fino a quando non diventa false esegui un ciclo while();

linea 492: controlla quale bottone della keypad LCD viene premuto e se premi RIGHT che la ctrlButton trasforma in 3 allora incrementa la variabile nFase. Utilizzerai tale variabile per far avanzare alla fase successiva il motore;

linea 493: decrementa la variabile nFase se il pulsante che hai premuto è LEFT, tradotto dalla ctrlButton in 2;

linea 494: controlla che il pulsante premuto sia SELECT ( 1 per la ctrlButton ) ed in tal caso imposta la variabile resetMode a false;

linea 498: richiama la funzione fase() passandole il numero di fase da seseguire ed impostando l’output restituito dalla funzione nella medesima variabile nFase. Vedrai in seguito perchè;

linea 502: attendi 200 millisecondi prima di procedere al ciclo while successivo;

linea 507: richiama la funzione stop() che toglie corrente a tutte le fasi del motore fermandolo;

linea 511: cancella dal display LCD tutto il testo per lasciar posto al testo successivo.

fase( nFase )

rispetto alle precedenti versioni di questa funzione troverai alcune differenze che aiutano a rendere il codice esterno più semplice e demandano il controllo della rotazione del motore a questa funzione;

linea 530: verifica che il valore di nFase non sia superiore a 4 in tal caso imposta la variabile a 1 essendo 4 le fasi ( da 1 a 4 );

linea 531: verifica che il valore di nFase non sia inferiore a 1 per evitare che in caso di rotazione inversa il motore finisca in una fase che non  può controllare;

linee 533-536: imposta il DEBUG scrivendo sul monitor seriale il valore di nFase ogni volta che questa funzione viene richiamata;

linee 540-543: per la fase 1 del motore imposta la sequenza: HIGH,LOW,HIGH,LOW sui rispettivi pin della motor shield arduino;

linee 547-564: imposta le altre 3 fasi del motore;

linea 568: attendi per ogni eseguzione di questa funzione un tempo definito nella costante TIMEFASE. Questa attesa serve ad evitare che la velocità con cui Arduino richiama la funzione si rifletta sul motore che non è in grado dieseguirla e resta fermo o peggio oscilla su se stesso. Dovrai variare il valore di TIMEFASE alla linea 30 in funzione del motore che scegli, se ti attieni al motore del kit tale valore è già corretto;

linea 570: ritorna alla funzione chiamante, ossia la reset() in questo caso, il valore di nFase. Avrai quindi capito il perché della ri assegnazione di tale valore alla medesima variabile ( nFase ) alla linea 498. Se nFase è 5 quando avviva alla funzione fase() viene automaticamente corretta in 1, si posiziona il motore in fase 1 e restituisci il nuovo valore.

stop()

è una funzione abbastanza semplice, il cui scopo è evitare che il motore resti alimentato anche nelle fasi di stop, evitando consumo di corrente e sopratutto di surriscaldarlo:

linee 576-579: imposti a LOW tutti i pin relativi alla motor shield arduino;

Il video della funzione reset del Dolly Photo

Come per tutta la serie di articoli dedicati al Dolly Photo ho realizzato anche per questo un video demo:

Buon reset !!!

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

Permanent link to this article: http://www.mauroalfieri.it/elettronica/dolly-photo-quarta-parte.html

29 comments

Skip to comment form

    • michele on 9 Mag 2013 at 22:42
    • Reply

    perdonami l’ignoranza ma i fili della motor shield in alimenentazione intravedo che sono collegati insieme?

    1. Ciao Michele,
      nessuna ignoranza, nelle foto non è sempre chiaro.
      Quello che vedi è del termo retrattile che tiene uniti i due fili, i contatti sono separati 🙂

      Mauro

    • Owen on 15 Mag 2013 at 11:54
    • Reply

    Ciao Mauro, ho assemblato tutto il dolly, per evitare che la keypad shield e la motor shield andassero in conflitto ho “tagliato” il contatto su A0 della motor shield ed anche i 2 brake (8 e 9)
    il problema ora è che il motore se imposto 10step e 5 scatti, ruota un po a sinistra, un po a destra e poi si ferma 🙁
    il motore è stato recuperato da una vecchia stampante, ma è un comune nema 17 bipolare
    le fasi le ho divise con il tuo metodo, ma non sono riuscito a capire come individuare i rispettivi + e – delle 2 fasi
    potrebbe essere quello il problema?

    colgo l’occasione per farti un’altra domanda: se volessi sostituire la motorshield con un pololu, come posso dividere le fasi avendo su quest’ultimo solo STEP e DIR e non i PWMA e PWMB?
    praticamente, questa parte di codice come andrebbe modificata?


    /**********************************************************/

    int fase( int nFase ) {

    if ( nFase > 4 ) { nFase = 1; }
    if ( nFase < 1 ) { nFase = 4; }

    #ifdef DEBUG
    Serial.print( "fase() - nFase: " );
    Serial.println( nFase );
    #endif

    switch( nFase ) {
    case 1:
    digitalWrite(DIRA, HIGH);
    digitalWrite(DIRB, LOW);
    digitalWrite(PWMA, HIGH);
    digitalWrite(PWMB, LOW);
    break;

    case 2:
    digitalWrite(DIRA, LOW);
    digitalWrite(DIRB, HIGH);
    digitalWrite(PWMA, LOW);
    digitalWrite(PWMB, HIGH);
    break;

    case 3:
    digitalWrite(DIRA, LOW);
    digitalWrite(DIRB, LOW);
    digitalWrite(PWMA, HIGH);
    digitalWrite(PWMB, LOW);
    break;

    case 4:
    digitalWrite(DIRA, LOW);
    digitalWrite(DIRB, LOW);
    digitalWrite(PWMA, LOW);
    digitalWrite(PWMB, HIGH);
    break;
    }

    delay(TIMEFASE);

    return nFase;
    }

    /**********************************************************/

    1. Ciao Owen,
      hai fatto un ottimo lavoro 🙂 si vede che ti sei impegnato e non arreso alla prima difficoltà.
      Per individuare + e – delle fasi puoi seguire un altro articolo, che non so se hai già letto:
      http://www.mauroalfieri.it/elettronica/tutorial-motore-bipolare-passo-passo-riconoscere-le-fasi.html

      Se ancora non funziona potrebbe essere dovuto alle correnti delle fasi troppo elevate che mandano in tilt il controllore.

      Per la modifica allo sketch hai individuato perfettamente la funzione, puoi prendere spunto dal Dolly che ho realizzato per Matteo e pubblicato qualche giorno fa.

      Mauro

    • Owen on 15 Mag 2013 at 18:13
    • Reply

    ciao Mauro, sono riuscito ad individuare le fasi corrette, ma il problema persiste, come controprova ho caricato uno sketch base che faccia semplicemente ruotare il motore


    /*************************************************************
    Motor Shield Stepper Demo
    by Randy Sarafan

    For more information see:
    http://www.instructables.com/id/Arduino-Motor-Shield-Tutorial/

    *************************************************************/

    int delaylegnth = 30;

    void setup() {

    //establish motor direction toggle pins
    pinMode(12, OUTPUT); //CH A -- HIGH = forwards and LOW = backwards???
    pinMode(13, OUTPUT); //CH B -- HIGH = forwards and LOW = backwards???

    //establish motor brake pins
    pinMode(9, OUTPUT); //brake (disable) CH A
    pinMode(8, OUTPUT); //brake (disable) CH B

    }

    void loop(){

    digitalWrite(9, LOW); //ENABLE CH A
    digitalWrite(8, HIGH); //DISABLE CH B

    digitalWrite(12, HIGH); //Sets direction of CH A
    analogWrite(3, 255); //Moves CH A

    delay(delaylegnth);

    digitalWrite(9, HIGH); //DISABLE CH A
    digitalWrite(8, LOW); //ENABLE CH B

    digitalWrite(13, LOW); //Sets direction of CH B
    analogWrite(11, 255); //Moves CH B

    delay(delaylegnth);

    digitalWrite(9, LOW); //ENABLE CH A
    digitalWrite(8, HIGH); //DISABLE CH B

    digitalWrite(12, LOW); //Sets direction of CH A
    analogWrite(3, 255); //Moves CH A

    delay(delaylegnth);

    digitalWrite(9, HIGH); //DISABLE CH A
    digitalWrite(8, LOW); //ENABLE CH B

    digitalWrite(13, HIGH); //Sets direction of CH B
    analogWrite(11, 255); //Moves CH B

    delay(delaylegnth);

    }

    e tutto funziona bene, ricarico il tuo sketch e il motore continua a fare un po di step da un lato e un po dall’altro 🙁

    • Owen on 16 Mag 2013 at 23:35
    • Reply

    Ciao Mauro, ti aggiorno… ho fatto l’ultima prova a mia disposizione… ho sostituito l’arduino uno con un leonardo che avevo a disposizione… ed ora funziona tutto!!!
    ora però da bravo maker vorrei migliorarlo… ad esempio un fattore fondamentale secondo me è la rumorosità degli step del motore, purtroppo non so da cosa sia dovuta… uso lo stesso motore che ho su una stampante 3d ma li è molto silenzioso eppure è alimentato sempre a 12v, potrebbe essere la velocità di rotazione? nel caso, come si potrebbe aumentare? non ho notato nello sketch nessun delay tra uno step ed il successivo

    1. Ciao Owen,
      ben fatto !!!
      Mi stupisci sei così bravo e attento e non ti sei accorto del delay nella funzione fasi(), puoi regolarlo dalla costante TIMEFASE che pensavo fosse un nome parlante 🙂

      Continua così che stai facendo un ottimo lavoro.
      Mauro

        • andreA on 6 Mag 2015 at 22:40
        • Reply

        CIAO MAURO io ho provato in tutti i modi a tornare ad utilizzare uno stepper il mio modello è un vecchio vexta pk244-02a-c58
        ti allego il link
        http://store.motadistribution.com/pk244-02a.html#Documents

        ho caricato sulla mia scheda il listato che avevi inserito nei tutorial ,
        a questa pagina
        http://www.mauroalfieri.it/elettronica/motor-shield-r3-arduino.html
        e tutto va alla grande il motore è forte e funziona in ogni sua parte
        ma se inserisco il tuo listato (e modifico la voce TIMEFASE con vari parametri ,, il motore scatta sempre.. gira nel senso giusto (quindi il caso non è come quello di OWEN)

        come posso trovare il TIMEFASE GIUSTO per me? ho visto le specifiche di questo motore, e alla voce TORQUE: 0.26 N-m;
        ho provato ad inserire 26 in time fase ma non ho risolto nulla
        potresti aiutarmi ? come avrai notato sono ritornato a lavorare sullo stepper
        ti ringrazio in anticipo

        1. Ciao Andrea,
          se il TIMEFASE dell’altro articolo funziona bene usa quello, mi sembra sia impostato a delay( 20 ).

            • ANDREA on 7 Mag 2015 at 12:26

            rieccomi, si ho già provato a valori come 1/8/10/12/16/18/20/25/30/35/40/50/55/80/260
            ma niente da fare
            io utilizzo un arduino uno.
            dicui che il problema sia che la scheda non è compatibile?
            ma se cosi fosse non mi spiego perche la stessa scheda accoppiata alla motor shild funzioni perfettamente (e con un ottima coppia del motore) inserento il tuo vecchio sketch
            ..
            perdona la mia ignoiranza ma c’e un altra voce che (oltre a controllare le fasi (

            digitalWrite(DIRA, LOW);

            digitalWrite(DIRB, HIGH);

            digitalWrite(PWMA, LOW);

            digitalWrite(PWMB, HIGH);
            ecc.. ecc. mi permette oltre la timfase di dirli di essere costante ed omogeneo?

            i poli del motore sono corretti (a +/- ed b+/-)
            sembra che qualcosa nel listato non si sincronizzi bene .
            aiuto mauro ..
            sono anni che inizio sto progetto e poi lo abbandono ..

          1. Ciao Andrea,
            perdonami ma proprio non riesco a seguirti e quindi ad aiutarti.
            In questo sketch la funzione avvio non fa nulla, non muove il motore .. come fai a verificare che si muove a scatti ?
            Stai utilizzando un altro sketch o hai eseguito delle modifiche al mio ed io non le conosco ?

            • andrea on 7 Mag 2015 at 17:34

            ciao mauro no ho copiato ed incollato solo delle righe, non è il listato
            in pratica APPARTE la voce timefase CHE HO OPPORTUNEMANTE provato a cambiare con vari vaolri, compreso il valore 20 che mi dici tu ..

            in piu ho provato con :1/8/10/12/16/18/20/25/30/35/40/50/55/80/260

            poi ti chiedevo se nel listato c’e oltre a timefase un altro parametro che permette di gestire o settare la coordinazione o la coppia del motore..

            (ho provato piu di uno stepper con il tuo listato del (dolly quinta parte)
            ed il problema è questo come già descritto..
            il motore funziona ed è collegato correttamente.
            ma va avanti ed indietro a scatti con una coppia debolissima…
            alimento tutto con alimentatore da 12v e 2A il motore assorbe 0.8Aper fase .
            ma.
            se tolgo la keypad lcd ed utilizzo un altro tuo listato ovvero questo
            http://www.mauroalfieri.it/elettronica/motor-shield-r3-arduino.html

            il motore gira alla grande e con un ottima coppia ..
            e qui entra in gioco la mia richiesta di aiuto ho guardato i listati ed inserito lo stesso valore di TIMEFASE
            MA SE torno a inserire il listato del dolly quinta parte torna lo stesso problema.
            ..

          2. Ciao Andrea,
            confronta le due funzioni per verificare quali differenze possano causare la diminuzione di coppia, dai miei test in laboratorio i due sketch non producono effetti differenti sui motori con cui li ho testati.

    • Claudio on 26 Ago 2013 at 11:47
    • Reply

    Sto cercando di utilizzare gli scketch che ha creato per il dolly photo. In particolare sto usando la versione 2 che prevede di impilare una motor shield ed un lcd shield 1602. Ho a disposizione una motor shield arduino rev 3 ed un lcd keypad shield simile al tuo.
    Collegando la sola kcd keypad alla mia arduino mega 2560 tutto funziona (il tasto select premuto per piu’ di 2 sec. attiva il menu) se collego anche il motor shield (senza alimentazione esterna, ne carico di alcun motore passo passo). Sto sbagliando qualcosa?
    Ringrazio e saluto.

    1. Ciao Claudio,
      immagino che la frase terminasse con un: se collego anche il motor shield (senza alimentazione esterna, ne carico di alcun motore passo passo) non funziona.

      Il problema è descritto in alcuni commenti a questo articolo, ci sono alcune piazzole in corrispondenza dei pin A0 ed A1 presenti sulla motor schied che vanno tagliate perché in conflitto con la KeyPad LCD che usa A0 come pin per leggere i pulsanti.

      Mauro

    • Aloisio on 1 Set 2013 at 19:09
    • Reply

    fantastico progetto!!! ho preso il kit su robot domestici come consigliavi ma la motorshield che mi hanno spedito non e’ arduino…. in realta’ si chiama motorshield_fe.Ho fatto diverse prove ma sono arrivato ad una mia conclusione:lo sketch che hai creato non va’ bene con quella marca!secondo te che ne pensi? cmq Mauro stai facendo un super lavoro con i tuoi tutorial appena i tuoi corsi si avvicineranno al sud italy saro’ uno dei vostri,sono uno scenografo e vorrei applicare queste tecnologie alle mie creazioni ciao ciao Mauro

    1. Ciao Aloisio,
      I kit Dolly che ho realizzato sono sia con la motor shield arduino sia con la motor shield fe.
      Una differenza sostanziale tra i due è la presenza della Keypad LCD inserita solo nel secondo kit ed utilizzata nel progetto Dolly.

      Se il tuo kit è quello con la Keypad e non ha la motor shield arduino puoi chiedere la sostituzione.

      Mauro

    • Filippo on 6 Dic 2013 at 12:47
    • Reply

    Ciao Mauro. Sto cercando di utilizzare il tuo sketch per l’LCD shield per fare un progetto in cui voglio dare la possibilità all’utente di cambiare alcune variabili tramite display LCD. Ho fatto una prova per verificare il funzionamento dell’LCD shield montandola a castello su un arduino uno e sembra andare tutto. Dato che però per il mio progetto non potrò montare l’LCD a castello ho bisogno di collegare i vari pin della shield con dei fili. La domanda è : i pin sono tutti indispensabili o ce ne sono alcuni che potrei non collegare? In questo modo potrei lasciare alcuni pin liberi per altre componenti del mio progetto. Sono nuovo nel mondo arduino quindi mi scuso se la domanda può sembrare un po’ sciocca, grazie per la disponibilità

    1. Ciao Filippo,
      la domanda non è sciocca.
      Per comprendere quali pin della shield keypad Lcd devi collegare puoi seguire lo schema del produttore che ti indica i pin a cui è collegato il display e di certo il pin A0 a cui sono collegati i pulsanti.

      Sui primi ti invito a consultare lo schema del produttore in quanto da modello a modello cambiano i pin a cui è connessa.

      Mauro

        • Filippo on 8 Dic 2013 at 20:07
        • Reply

        Ok grazie mille, nello schema del produttore mi dice che i pin da collegare sono il 4 5 6 7 8 9 10, ma se io avessi già questi pin occupati potrei per esempio su un arduino mega collegare la shield ad altri pin? funzionerebbe comunque? In teoria anche se non sono i pin indicati dal produttore sono comunque dei pin digitali…..Grazie ancora

        1. Ciao Filippo,
          certo, puoi, devi verificare come e dove lo schetch usa quei pin e modificarli lí.

          Mauro

    • andrea on 27 Apr 2015 at 10:33
    • Reply

    buon giorno sono sempre io..

    oltre alle domande sul altro post.
    vorrei chiedere una info ..
    se volessi mettere al posto dello stepper un motoriduttore dc. ed utilizzare il suo sketch è potrebbe essere semplice cambiare il tutto ? sopratutto la (parte dei passi convertendola in milli secondi.) ?

    per uno che di arduino non ci capisce niente potrebbe esssere semplice?
    in caso contrario potrei commissionarglielo come lavoro? (convertire lo sketch per un motore con motoriduttore dc)
    attendo info … la ringrazio di cuore buona giornata.

    1. Ciao Andrea,
      convertire il passo-passo in motore Dc penso voglia dire che vuoi utilizzare il dolly sia per time-lapse sia per riprese con slider, giusto?
      Sto lavorando ad una scheda che possa fare entrambe le operazioni usando un motoriduttore ed il tutto già dotato di sketch per tutti gli appassionati, ad oggi tale scheda è in fase di progettazione ma se sei interessato iscriviti alla newsletter la useremo proprio per comunicare a tutti gli appassionati la disponibilità.

      In merito alla possibilità che chiedi di fare da solo le modifiche è possibile, studiando i miei corsi on-line gratuiti ed i miei tutorial hai tutti gli elementi che ti servono, non posso dire che sia una conversione semplice, anche io ci sto ancora lavorando per calibrare i tempi, ma la buona volontà premia.
      Per i progetti su commissione sono, solitamente, disponibile a realizzarli tuttavia in questo periodo ho dato disponibilità per molti progetti in corso d’opera e per i prossimi 2/3 mesi dubito di poter dedicare tempo ad altri progetti, se vuoi ci sentiamo tra fine luglio e inizio settembre per riparlarne così ti aggiorno anche sullo stato di uscita della scheda dedicata ai dolly

        • andrea on 27 Apr 2015 at 14:14
        • Reply

        ciao mauro
        per me il tuo progetto è una notevole evoluzione, il primo che ho seguito era su time lapse italia, ed era relativamente piu semplice , infatti veniva gestito da arduino e da scheda adafruit.
        il tutto funzionava bene .. perche riusciva ad sostenere verticalmente a 85°di pendenza (canon 60d + battery grip+18-35 sigma ) un totale circa 3 kg e passa.

        ho gia un ottimo motoriguttore capace di spostarmi anche 10 kg.
        ma da i test che ho fatto la tua versione è mangifica, è solo il mio stepper che non è adatto ..

        se utilizzassi un alimentatore da 25 A e 12 V?? dici che brucio qualcosa?

        mi sarebbe piacicuto ovviamente per risparmiare tempo poter commissionarti il lavoro .. ora mi iscrivo subito ed attendo con ansia (questa nuova scheda)
        p.s
        se installo il listato della tua dolly quinta parte (la conclusione) il tutto va egregiamente motore a parte. mase installo il tuo ultimo listato della seconda versione con fine corsa, allora mi si impalla tutta la scheda, ho letto che forse c’e un errore nell listato giusto ?
        qualche suggerimento ?:-))
        ti ringrazio

        1. Ciao Andrea,
          hai provato con quel motore da 10Kg e non riesci?
          Utilizzare 25A se il motore assorbe solo 0,8 e il driver in ogni caso non è in grado di erogare più di 2A per fase di picco mi sembra sprecato.

          Quello che stai commentando è la quarta parte del progetto Dolly Photo, aggiungi il commento sul listato che non funziona nell’articolo corretto ed io provo a verificare quanto mi segnali sul corretto funzionamento.

            • andreA on 27 Apr 2015 at 21:38

            ciao si in precedenza con un altra scheda e listato ho utilizzato quel motore ma avevo necessita di avere un display ed un prodotto piu completo , quello è un motore dc con riduttore…
            ..
            cercherò su un nema 17 da 12v e meno di 2 A per fase ^^

            poi aspetto con ansia il progetto che mi hai citato poco fa (scheda che possa fare entrambe le operazioni usando un motoriduttore ed il tutto già dotato di sketch per tutti gli appassionati)
            bhe mi piacerebbe molto saperne di piu, mi sono gia iscritto alla nsletter

          1. Ottimo Andrea.

    • Giorgio on 12 Ott 2015 at 23:38
    • Reply

    Ciao Mauro
    in questa parte del progetto parli di alimentatore stabilizzato ma se utilizzassi un batteria al piombo ? 12v potrebbe andar bene ugualmente ? Che Amperaggio consigli ?

    grazie
    Giorgio

    1. Ciao Giorgio,
      una batteria va bene.
      Per l’assorbimento devi verificarlo con un tester dopo aver realizzato il progetto, varia molto in funzione della meccanica e del tipo di motore utilizzato.

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.