Le modifiche e implementazioni fatte al Dolly Photo e presentate in questo articolo si concludono con questo articolo in cui trovi come il Dolly Photo incrementa la velocità di impostazione.
L’esigenza che mi è stat esposta da chi ha provato il Dolly Photo versione 1.0 è stata quella di poter essere più veloce in fase di impostazione del progetto fotografico.
In pratica quando sei su un campo e vuoi iniziare una nuova sequenza di fotografie con il Dolly Photo versione 1.0 impostare i parametri di avvio risulta molto lento in quanto ogni pressione dei pulsanti LEFT e RIGHT incrementa di un solo valore il contatore su cui stai agendo.
Nella versione 2.0 ho modificato questa impostazione anche in funzione del fatto che i tempi sono definiti in millisecondi e non in secondi come nella precedente vesione, ottieni così che il Dolly Photo incrementa la velocità di impostazione.
Principio di funzionamento
Il principio è banale: incrementi di 10 unità ad ogni pressione del pulsante RIGHT e decrementi di 1 alla pressione del pulsante LEFT.
Se ti chiedi come mai RIGHT incrementa di 10 e LEFT decrementa di 1 la risposta è semplice: in questo modo sei certo di poter impostare tutti i valoro che desideri rapidamente.
Se ad esempio vuoi che il Dolly Photo incrementa la velocità di impostazione dell’intervallo tra i passi fino al valore 36 premerai quattro volte il pulsante RIGHT arrivando a 40 e quattro volte il pulsante LEFT indietreggiando a 36.
Sketch Dolly Photo incrementa la velocità di impostazione
Lo sketch che ti riporto presenta tutte le ultime funzioni descritte negli articoli precedenti ed aggiunge anche questa funzione:
/********************************************************** * Dolly Photo Arduino * * Data creazione 25 febbraio 2013 * Ultima modifica 13 marzo 2013 * * autore: Mauro Alfieri * web: mauroalfieri.it * tw: @mauroalfieri * /**********************************************************/ #include <LiquidCrystal.h> /**********************************************************/ #define MOTDTIME 2000 #define LCDTIME 3000 #define SETMODETIME 2000 #define TIMESCATTO 500 #define TIMEFASE 35 #define TARATURA 800 #define DEBUG /**********************************************************/ #define SCATTO 2 #define PWMA 3 #define D4 4 #define D5 5 #define D6 6 #define D7 7 #define RS 8 #define EN 9 #define BACKLIGHT 10 #define PWMB 11 #define DIRA 12 #define DIRB 13 #define BUTTON A0 #define SSTART A1 #define SSTOP A2 /**********************************************************/ char line0[16] = "Dolly Foto ver2"; char line1[16] = "mauroalfieri.it"; /**********************************************************/ int SELECT[] = {810,830}; int LEFT[] = {610,640}; int RIGTH[] = {0,20}; int UP[] = {190,210}; int DOWN[] = {390,420}; int buttonPress = 0; int nFase = 0; int scatto = 0; int passo = 0; /**********************************************************/ unsigned long timeToBlacklight = 0; unsigned long timeToSetMode = 0; unsigned long timeSetting = 0; unsigned long timeDelay = 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[6] = {"Impostazioni","Verifica","Reset Carrello","Reset Auto","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 intervalloScatto = 30; int tempoAltPrima = 0; int tempoAltDopo = 0; int numeroScatti = 0; /**********************************************************/ LiquidCrystal lcd( RS,EN,D4,D5,D6,D7 ); /**********************************************************/ void setup() { #ifdef DEBUG Serial.begin( 9600 ); Serial.println("Avvio"); #endif /**********************************************************/ pinMode( BACKLIGHT,OUTPUT ); digitalWrite( BACKLIGHT,LOW ); /**********************************************************/ pinMode( SCATTO,OUTPUT ); digitalWrite( SCATTO,LOW ); /**********************************************************/ #ifdef SSTART pinMode( SSTART,INPUT ); digitalWrite( SSTART,LOW ); #endif /**********************************************************/ #ifdef SSTOP pinMode( SSTOP,INPUT ); digitalWrite( SSTOP,LOW ); #endif /**********************************************************/ 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 ); lcd.clear(); lcdBlacklightOff(); } /**********************************************************/ void loop() { /**********************************************************/ #ifdef DEBUG Serial.print( " Button: " ); Serial.print( analogRead( BUTTON ) ); Serial.print( " TimeToBlecklight " ); Serial.print( timeToBlacklight ); Serial.print( " TimeToSetMode " ); 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(); lcd.clear(); } /**********************************************************/ 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) { digitalWrite( BACKLIGHT,HIGH ); blacklightStatus = true; timeToBlacklight = millis(); } return buttonPress; } /**********************************************************/ void lcdBlacklightOff() { digitalWrite( BACKLIGHT,LOW ); blacklightStatus = false; timeToBlacklight = 0; } /**********************************************************/ void lcdBlacklightOn() { digitalWrite( BACKLIGHT,HIGH ); blacklightStatus = true; timeToBlacklight = millis(); } /**********************************************************/ 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 < 4 ) { 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 ) { autoreset(); } if ( setModeLevel == 4 ) { 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 += 10; lcd.clear(); } if ( (ctrlButton( analogRead( BUTTON )) == 2 ) && passiXscatto >= 1) { passiXscatto -= 1; lcd.clear(); } sprintf(buffer, "%s %d", secondario[(setModeLevel+1)], passiXscatto); break; case 2: if ( (ctrlButton( analogRead( BUTTON )) == 3 ) && intervalloScatto <= 9999999) { intervalloScatto += 10; lcd.clear(); } if ( (ctrlButton( analogRead( BUTTON )) == 2 ) && intervalloScatto >= 1) { intervalloScatto -= 1; lcd.clear(); } sprintf(buffer, "%s %dms", secondario[(setModeLevel+1)], intervalloScatto); break; case 4: if ( (ctrlButton( analogRead( BUTTON )) == 3 ) && tempoAltPrima <= 9999999) { tempoAltPrima += 10; lcd.clear(); } if ( (ctrlButton( analogRead( BUTTON )) == 2 ) && tempoAltPrima >= 1) { tempoAltPrima -= 1; lcd.clear(); } sprintf(buffer, "%s %dms", secondario[(setModeLevel+1)], tempoAltPrima); break; case 6: if ( (ctrlButton( analogRead( BUTTON )) == 3 ) && tempoAltDopo <= 9999999) { tempoAltDopo += 10; lcd.clear(); } if ( (ctrlButton( analogRead( BUTTON )) == 2 ) && tempoAltDopo >= 1) { tempoAltDopo -= 1; lcd.clear(); } sprintf(buffer, "%s %dms", secondario[(setModeLevel+1)], tempoAltDopo); break; case 8: if ( (ctrlButton( analogRead( BUTTON )) == 3 ) && numeroScatti <= 9999999) { numeroScatti += 10; lcd.clear(); } if ( (ctrlButton( analogRead( BUTTON )) == 2 ) && numeroScatti >= 1) { numeroScatti -= 1; 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 %dms", secondario[(setModeLevel+1)], intervalloScatto); break; case 4: sprintf(buffer, "%s %dms", secondario[(setModeLevel+1)], tempoAltPrima); break; case 6: sprintf(buffer, "%s %dms", 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( 10 ); } /**********************************************************/ stop(); /**********************************************************/ lcd.clear(); } /**********************************************************/ void autoreset() { #ifdef SSTART /**********************************************************/ stop(); /**********************************************************/ lcd.clear(); lcd.setCursor(0,0); lcd.print( "Menu " ); lcd.setCursor(0,1); lcd.print( "Reset Automatico" ); /**********************************************************/ delay( SETMODETIME ); /**********************************************************/ lcd.clear(); lcd.setCursor(0,0); lcd.print( "Reset in corso" ); lcd.setCursor(0, 1); lcd.write(1); // SELECT lcd.setCursor(1, 1); lcd.write(1); // SELECT lcd.setCursor(5, 1); lcd.write(3); // STOP /**********************************************************/ while ( analogRead( SSTART ) > TARATURA ) { nFase = fase( nFase ); nFase--; if ( ctrlButton( analogRead( BUTTON )) == 3 ) { stop(); lcd.setCursor(0, 1); lcd.write(3); // STOP lcd.setCursor(1, 1); lcd.write(" "); lcd.setCursor(5, 1); lcd.write(" "); return; } } delay( 500 ); #endif } /**********************************************************/ void avvio() { lcd.clear(); lcd.setCursor(0,0); lcd.print( "Menu " ); lcd.setCursor(0,1); lcd.print( "Avvio" ); /**********************************************************/ delay( SETMODETIME ); /**********************************************************/ lcd.clear(); lcd.setCursor(0,0); lcd.print( "Go " ); lcd.setCursor(3, 0); lcd.write(4); // PAUSA lcd.setCursor(0, 1); lcd.write(3); // STOP lcd.setCursor(5, 1); lcd.write(2); // PLAY /**********************************************************/ if ( !pausa() ) return; /**********************************************************/ for ( scatto=0; scatto <= numeroScatti; scatto++ ) { lcd.setCursor(7, 0); lcd.print( "scatto:" ); lcd.setCursor(14, 0); lcd.print( scatto ); /**********************************************************/ for ( int passo=1; passo <= passiXscatto; passo++ ) { lcd.setCursor(7, 1); lcd.print( "passo:" ); lcd.setCursor(13, 1); lcd.print( passo ); if ( ctrlButton( analogRead( BUTTON )) == 3 ) { if ( !pausa() ) return; } nFase = fase( nFase ); nFase++; int _intervallo = intervalloScatto; if ( !ctrlDelay( _intervallo )) return; } /**********************************************************/ int _tempo = tempoAltPrima; if ( !ctrlDelay( _tempo )) return; /**********************************************************/ digitalWrite( SCATTO, HIGH ); delay( TIMESCATTO ); digitalWrite( SCATTO, LOW ); /**********************************************************/ lcd.setCursor(7, 0); lcd.print( "scatto:" ); lcd.setCursor(14, 0); lcd.print( scatto ); /**********************************************************/ _tempo = tempoAltDopo; if ( !ctrlDelay( _tempo )) return; /**********************************************************/ } /**********************************************************/ } /**********************************************************/ boolean pausa() { lcdBlacklightOn(); /**********************************************************/ boolean play = false; /**********************************************************/ lcd.setCursor(3, 0); lcd.write(4); // PAUSA lcd.setCursor(5, 1); lcd.write(2); // PLAY /**********************************************************/ while ( !play ) { if ( ctrlButton( analogRead( BUTTON )) == 3 ) { lcd.setCursor(3, 0); lcd.write(2); // PLAY lcd.setCursor(5, 1); lcd.write(4); // PAUSA delay( 500 ); play = true; } if ( ctrlButton( analogRead( BUTTON )) == 2 ) { stop(); play = true; return false; } delay( 100 ); } /**********************************************************/ return true; } /**********************************************************/ boolean ctrlDelay(int tempo) { // lcdBlacklightOff(); // Decommenta per risparmio energetico timeDelay = millis(); boolean dtime = true; #ifdef DEBUG Serial.print( "Delay: " ); Serial.print( tempo ); Serial.print( " Millis: " ); Serial.print( timeDelay ); Serial.print( " \n " ); #endif while ( dtime ) { if ( tempo < (millis()-timeDelay)) { dtime = false; } if ( ctrlButton( analogRead( BUTTON )) == 3 ) { delay( 500 ); pausa(); } if ( ctrlButton( analogRead( BUTTON )) == 2 ) { stop(); dtime = false; return false; } if ( analogRead( SSTOP ) < TARATURA ) { stop(); dtime = false; return false; } Serial.print( (millis()-timeDelay) ); Serial.print( "\n" ); } return true; } /**********************************************************/ 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); } /**********************************************************/
leggendolo troverai che le linee che si preoccupano di farti impostare i parametri del Dolly Photo incrementa la velocità di impostazione sono quelle contenute nella funzione impostazioni() ed in particolare le linee 346-383 che riporto per approfondirle meglio:
switch ( setModeLevel ) { case 0: if ( (ctrlButton( analogRead( BUTTON )) == 3 ) && passiXscatto <= 99999) { passiXscatto += 10; lcd.clear(); } if ( (ctrlButton( analogRead( BUTTON )) == 2 ) && passiXscatto >= 1) { passiXscatto -= 1; lcd.clear(); } sprintf(buffer, "%s %d", secondario[(setModeLevel+1)], passiXscatto); break; case 2: if ( (ctrlButton( analogRead( BUTTON )) == 3 ) && intervalloScatto <= 9999999) { intervalloScatto += 10; lcd.clear(); } if ( (ctrlButton( analogRead( BUTTON )) == 2 ) && intervalloScatto >= 1) { intervalloScatto -= 1; lcd.clear(); } sprintf(buffer, "%s %dms", secondario[(setModeLevel+1)], intervalloScatto); break; case 4: if ( (ctrlButton( analogRead( BUTTON )) == 3 ) && tempoAltPrima <= 9999999) { tempoAltPrima += 10; lcd.clear(); } if ( (ctrlButton( analogRead( BUTTON )) == 2 ) && tempoAltPrima >= 1) { tempoAltPrima -= 1; lcd.clear(); } sprintf(buffer, "%s %dms", secondario[(setModeLevel+1)], tempoAltPrima); break; case 6: if ( (ctrlButton( analogRead( BUTTON )) == 3 ) && tempoAltDopo <= 9999999) { tempoAltDopo += 10; lcd.clear(); } if ( (ctrlButton( analogRead( BUTTON )) == 2 ) && tempoAltDopo >= 1) { tempoAltDopo -= 1; lcd.clear(); } sprintf(buffer, "%s %dms", secondario[(setModeLevel+1)], tempoAltDopo); break; case 8: if ( (ctrlButton( analogRead( BUTTON )) == 3 ) && numeroScatti <= 9999999) { numeroScatti += 10; lcd.clear(); } if ( (ctrlButton( analogRead( BUTTON )) == 2 ) && numeroScatti >= 1) { numeroScatti -= 1; lcd.clear(); } sprintf(buffer, "%s %d", secondario[(setModeLevel+1)], numeroScatti); break;
il principio è descritto nel paragrafo precedente ed espresso nelle linee 04-05: noti che la prima linea controlla la pressione del bottone RIGHT mentre la linea 5 controlla la pressione del pulsante LEFT.
La pressione del pulsante RIGHT incrementa il contatore passiXscatto di 10 unità alla volta.
La pressione del pulsante LEFT decrementa il medesimo contatore di una sola unità alla volta.
Le linee 11-12: fanno la stessa operazione per il contatore intervalloScatto;
le linee 18-19: incrementano e decrementano il contatore tempoAltPrima che definisce il tempo in millisecondi da attendere prima di ciascuno scatto;
linee 25-26: agiscono sul contatore tempoAltDopo con cui definisci il tempo di attesa tra lo scatto ed il primo passo della successiva sequenza di passi del motore passo-passo;
linea 32-33: imposti i valori del contatore numeroScatti che definisce quanti scatti dovrai eseguire in tutto il progetto fotografico.
Video Dolly Photo incrementa la velocità di impostazione
Ecco il video che avrai già visto se hai seguito il blog e la serie di articoli sul Dolly Photo versione 2, se è il primo articolo che leggi su questo argomento ti consiglio di dare un occhio ai precedenti articoli dedicati all’argomento.
Buon divertimento !!!
52 commenti
Vai al modulo dei commenti
Ciao,
Ho un po’ abbandonato il progetto, ma vedendo le migliorie mi e’ venuta voglia di riprenderlo 🙂
Grande Mauro!!!
ciao Mauro, due domande mi sorgono, il dolly di questo articolo è la diretta evoluzione di questo : https://www.mauroalfieri.it/elettronica/dolly-keypad-lcd-prima-parte.html ?
Quindi mi viene il problema di dove collegare lo shutter che va alla reflex
Grazie mille
Autore
Ciao Gianmaria,
più che di evoluzione io parlerei di serie di articoli collegati.
Il progetto Dolly é più complesso di quello c’è sembra e per realizzarlo ho dedicato lacune settimane di esperimenti.
Ad ogni esperimento riuscito ho pubblicato i risultati e le evoluzioni del progetto, quindi leggendo tutti gli articoli non solo imparerai come si realizza la parte elettronica e i corretti settaggi ma scoprirai anche il pin a cui collegare la reflex, é tutto descritto negli articoli.
Ti do un suggerimento il pin che cerchi si chiama SCATTO nel mio sketch.
Credimi, prendere solo l’ultimo sketch, non leggendo neppure tutto il materiale prodotto equivale a ottenere un prodotto mal funzionante e spesso un progetto fallimentare senza acquisire le competenze per usarlo e migliorarlo, che é ciò per cui scrivo articoli dettagliati.
É come andare in un negozio e comprare un oggetto già fatto, nulla di deplorevole, ma non é una cosa ha hai realizzato e di cui conosci ogni singolo comportamento.
Mauro
concordo a pieno, grazie, sto attendendo gli ultimi pezzi poi in caso scrivo qui se ho problemi 😀
Ciao,
trovo il tuo blog uno dei migliori per semplicità e chiarezza, ma ho un grosso problema con la lettura degli sketch, per spiegarmi meglio devo incollare quello che vedo io sul mio computer.
Ecco una una parte che ho incollato dallo sketch sopra:
[ codice rimosso in automatico ]
Non riesco a risolvere l’errore, ho provato nelle impostazione del mio browser (firefox) ma niente, hai qualche idea?
Grazie e continua così
Autore
Ciao Lupo Solitario,
come avrai letto in fondo ad ogni articolo non è possibile incollare codice nei commenti.
Grazie,
per la risposta comunque ho risolto da solo.
Ciao Mauro,
Grazie per aver condiviso il progetto. Vorrei chiederti alcune cose.
Sto usando un motore passo passo da 2.8V e 1.68A per fase.
La scheda motor shield r3 ha un regolatore di tensione interno o devo alimentarla, ai morsetti per lo stepper, con la tensione corretta (2.8V)?
Ti ringrazio in anticipo.
Andrea
Autore
Ciao Andrea,
la motor shield r3 non ha un regolatore interno, devi fornirgli una tensione in ingresso che usa per il controllo del motore.
Fai solo attenzione al voltaggio minimo che non ricordo quale sia.
Ho capito, grazie mille per la risposta.
Farò un tentativo allora.
Buona giornata
Ciao Mauro,
ho ancora bisogno del tuo aiuto.
Finalmente ho ricevuto tutto il materiale e ho iniziato ad implementare il tuo progetto. Uso :
-Arduino UNO R3
-Motor shield R3
-LCD Keypad v 1.1
Il problema è quello che ho letto anche in altri tuoi articoli, quando monto una sull’altra tutte e tre le schede ho un conflitto. Ho letto che consigli di tagliare i pin A0 che sono quelli per i tasti della scheda LCD. Innanzitutto volevo chiedere che cosa significa tagliare? Vedo però che nello sketch definisci A0 come button… Comunque, utilizzando il tuo ultimo programma, con gli stessi collegamenti ho il conflitto. A te invece nel video funziona… Cosa sbaglio?
Ti ringrazio.
Andrea
Autore
Ciao Andrea,
grazie per aver acquistato il kit, hai contribuito a sostenere il blog.
In corrispondenza dei pin A0 ed A1 lato inferiore della motor shield trovi due piazzole circolari con una fenditura centrale.
Con un taglierino devi incidere le due fenditure in modo che non ci sia continuità tra i due semicerchi.
Grazie a te che hai condiviso con tutti il tuo progetto!!!
Ah, perfetto. Allora separo il collegamento con il taglierino. Farò lo stesso anche con il pin Vin in modo da rendere indipendente l’alimentazione di Arduino da quella del motore esterno.
Devo fare lo stesso anche con i contatti del pin 8 e 9 (Brake A e B)?
Grazie
Andrea
Autore
Ciao Andrea,
il Vin non va separato.
Si se vuoi usare i pin 8 e 9 per altri scopi e non per il freno-motore.
Ah, quindi il Vin dietro la scheda non va separato?
Volevo separarlo perchè il motore passo passo è da 2.8V, mentre alimenterei Arduino a 7/9V.
Facendo delle prove ho visto che se alimento Arduino a 9V anche ai morsetti Vin e GND della motor shield (quelli di fianco alle connessioni per il motore passo passo) ho la stessa tensione di 9V.
Quindi ho pensato che separando il pin sul retro potrei avere 9V per arduino uno, il driver della motor shield e l’LCD, ed alimentare esternamente a 2.8V il motore passo passo.
Grazie.
Andrea
Autore
Ciao Andrea,
non avevo mai notato che ci fosse un collegamento e che questo fosse riportato sul connettore di alimentazione della shield.
Trovo utile questa connessione se vuoi alimentare arduino dalla motor shield direttamente, tuttavia il contrario è pericoloso per la richiesta di corrente da parte dei motori.
Incidi pure anche questa pista.
Il motore del kit funziona a 12v e non a 2,8v
Ok, perfetto.
Non appena avrò ultimato il progetto ti farò sapere.
Grazie mille. Una buona giornata.
Andrea
Ciao Mauro,
Ho di nuovo bisogno del tuo aiuto. Ho risolto il problema del conflito dell’LCD ma ecco un’altro problemino. Il motore passo passo esegue uno step in un verso ed uno nel verso opposto. Ho letto del problema in un articolo in cui spiegavi come risolverlo. Ho separato le connessioni dei pin 8 e 9 ma il problema persiste. Ho caricato uno sketch che fa eseguire dei semplici step e tutto funziona. Mentre ricaricando lo sketch completo va avanti ed indietro..
Dove sbaglio?
Grazie mille!!!!
Andrea
Autore
Ciao Andrea,
apparentemente il problema che riscontri è dovuto ad un errore di collegamento delle fasi, ma se hai provato con un altro mio sketch e funziona con le medesime connessioni direi che potrebbe esserci qualche errore nello sketch.
Prova a confrontare i due sketch per capire se ci siano delle differenze nella parte di controllo del motore, se trovi qualcosa di poco chiaro indicami in quali righe e provo a verificare.
Una Domanda molto importante. Vorrei alimentare arduino dalla motor shiled con una batteria ricaricabile a lunga durata. Potete consigliarmi su cosa acquistare?
Autore
Ciao Paolo,
tutte le domande sono molto importanti.
Io suggerirei una batteria da 12v per l’amperaggio dipende dall’assorbimento dei tuo progetto e dalle ore e modalità di funzionamento.
Ho scelto questo motore 42byghm809, è uno stepper a 400 passi.
Angolo step: 0.9°
2 fasi
Tensione nominale: 3V
Corrente nominale: 1.7A/Fase
Diametro albero: 5mm
Holding Torque: 48N.cm
Form Factor NEMA 17
400 step/giro
Che batteria mi consigli a lunga durata non troppo voluminosa?
Autore
Ciao Paolo,
LiPo, devi solo far attenzione a come la maneggi perché tendono ad esplodere, guarda qualche video su youtube.
Si anche io pensavo per le lipo. Ma ho difficoltà con i voltaggi, Il motore lavora a 3v e arduino a 5v se non erro.
Autore
Ciao Paolo,
nel mio kit ho evitato alimentando tutto a 12v ed utilizzando motori adeguati.
Se hai problemi con le tensioni puoi decidere di usare la doppia alimentazione o un DC-DC per convertire una delle tensioni in step-down, trovi alcuni articoli dedicati ai convertitori DC-DC nel blog
Letto tutto l’articolo dei convertitori DC-DC Che spettacolo! Risolto in problema! Grazie Ti Voglio Bene!!
Autore
Ciao Paolo,
sono contento che ti sia stato utile il mio articolo.
Vorrei avere qualche info o dritta su come hai gestito i Menu e Sotto Menu. Grazie infinite.
Autore
Ciao Paolo,
è tutto decritto nei miei articoli, linea per linea, prova a leggerli e se qualcosa non ti è chiara ponimi una domanda specifica.
Ho acquistato il kit, caricato il programma, ma il sistema parte e si ferma sulla scritta “in attesa di comandi”, da cui non si muove anche premendo il pulsante select (o altri) per due o più secondi. Ho ricaricato il programma più volte e cambiato l’arduino. Non so se possa essere di aiuto, ma noto che il led sull’arduino (non quello dell’alimentazione) rimane fisso giallo, mentre in altri progetti che funzionano regolarmente è rosso.
Grazie in anticipo del supporto
luigi
Autore
Ciao Luigi,
se controlli nei commenti troverai che altri hanno segnalato problemi simili e li abbiamo risolti tagliando le piste presenti sulla motor shield in corrispondenza dei pin A0 ed A1
Ho scoperto in un’altro thread (uMade) sullo stesso progetto che avrei dovuto sezionare le piste D0 e D1 sullo sketch controllo motori.
Ora sembra funzionare.
Grazie mille!
Luigi
Autore
Ciao Luigi,
perfetto !!
Una (spero ultima) domanda: non mi è chiaro dove collegare i fili per l’attuazione dello scatto nella fotocamera: in una delle sezioni è previsto un fotoaccoppiatore, ma nella versione 2 non sono riuscito a trovare i riferimenti.
Mi manca qualcosa?
Grazie di nuovo
Luigi
Autore
Ciao Luigi,
il sistema di connessione del foto accoppiatore o opto isolatore è sempre il medesimo.
Nello sketch puoi leggere
#define SCATTO 2
quindi collegalo pure al pin 2
Grazie. Ho ordinato da robotics 3D i fotoaccoppiatori. Spero di riuscire a montare anche questa parte entro il weekend.
Buona serata
Avrei una domanda, tutto funziona alla grande ma…
se importo numero di passi 5, e nessuno tempo di pausa ne prima ne dopo. perché è comunque presente una pausa tra l’esecuzione dei passi e l’altra? come posso eliminare questo tempo?
Se tutto è zero ovviamente.
Autore
Ciao Paolo,
il tempo che intercorre tra i passi è modificabile direttamente nella funzione che esegue i passi, leggi nella descrizione dello sketch come funziona per eseguire facilmente la modifica. Ricorda che i tempi li devi tarare bene sul tuo motore per evitare che il motore sibili e non esegua spostamenti.
Sto utilizzando un nema 11 con una puleggia a 36 denti. E purtroppo sto impazzendo. Non riesco a farlo girare in rotazione continua senza pause. Nonostante il tempo di alt prima e dopo siano a impostati a zero. So che sei super impegnato ma potresti darmi qualche dritta in più per risolvere il problema. Sono quasi alla fine della parte meccanica. E mi dispiacerebbe moltissimo non per ultimare il progetto.
Autore
Ciao Paolo,
ti ho già risposto in un precedente commento, puoi leggere lo sketch e troverai il punto in cui modificare i tempi tra un passo ed il successivo.
Scrivo gli sketch e li commento linea per linea proprio perché chiunque possa eseguire le modifiche che desidera.
Grazie Mauro sempre paziente. Credo di aver capito. Mi trae in inganno il tempo di posta cioè il tempo dove il carrello rimane fermo per la fase scatto. Devo riuscire a mettere questo tempo che sia uguale al tempo “intervallo tra i passi”. Sicuramente è più semplice cosi che un nuovo menu che imposti il tempo di posa.
Nulla da fare anche impostando TIMESCATTO 0 è sempre presente un 330ms circa di delay. Davvero Mauro non riesco a capire.
Autore
Ciao Paolo,
hai provato a impostare il numero di scatti a 1 e il numero di passi al massimo numero di passi che ti servono per percorrere lo spostamento desiderato.
Se leggi il codice, e la mia descrizione, vedrai che in tal caso tutti i tempi di attesa relativa allo scatto non vengono presi in considerazione.
Il mio dubbio a questo punto è “tu cosa stai cercando di ottenere ?”
Se la risposta è uno slider video da un Dolly allora posso consigliarti di riscrivere lo sketch e non cercare di adattare questo che è pensato per fare tutt’altro.
No Mauro mi serve per i Time Laps ma uso una Gopro, su questa non è possibile utilizzare un cavo per farla scattare. Quello che cerco di ottenere è azzerare il tempo di posa.
Esempio:
Numero Passi per Scatto 60
Intervallo tra i Passi 100
Tempo di Alt Prima 0
Tempo di Alt Dopo 0
Numero scatti 900
Ecco cosa succede il motore fa 60 passi (tra un passo e l’altro trascorrono 100ms) poi scatta, bene perfetto pero qui fa una pausa di circa 330ms e poi il ciclo si ripete. Io vorrei che questo tempo fosse zero o uguale all’intervallo tra i passi.
Non so se sono riuscito a spiegarmi.
Autore
Ciao Paolo,
puoi eliminiare il DEBUG commentando la linea 23, in questo modo i Serial.print non vengono eseguiti ed i tempi si riducono.
Considera che ogni operazione eseguita dallo sketch impegna il processore per alcuni millisecondi e la comunicazione seriale è impegnativa.
In ogni caso se non ti occorre avere il tempo di pausa per lo scatto puoi inserire:
Numero Passi per Scatto 54000 // ( 60 x 900 )
Intervallo tra i Passi 100
Tempo di Alt Prima 0
Tempo di Alt Dopo 0
Numero scatti 1
Come ti avevo suggerito nel precedente commento.
Grazie, Grazie e ancora Grazie! Questa sera provo! Una volta ultimato ti mando le foto e video! Grazie ancora buon lavoro.
Autore
Bene Paolo !!!
Sono qui questa volta solo per dirti che…. FUNZIONAAAAA!!! Ho commentato tutti i DEBU e Serial.print. Ora è davvero funzionale. Lo posso usare sia per la GoPro che per La mia fotocamera (Aumentato Tempo di Alt Prima e e Dopo)
Grazie ancora Mauro.
Autore
Bene Paolo sono contento che tu sia riuscito ma sopratutto che ora sai come modificare da solo il codice per realizzare tutti i progetti fotografici che desideri.
Ciao Mauro! Che motor shild hai usato?
Autore
Ciao Giovanni,
la motor shield ufficiale arduino.cc
Trovi tutti i dettagli negli articoli dedicati al dolly presenti nel blog.
Ciao Mauro! Utilizzo per il contenuto costo un driver pololu a4988 ed una shield LCD di questo tipo: [ link rimosso ]
Sapresti dirmi per cortesia dove prendere dalla shield gli output del motore passo a passo? Inoltre facendo varie prove senza collegare nessun input dei motori al pololu ma soltanto alimentando il motore e il driver, il motore girava da solo facendo strani rumori e vibrando. Preciso che il motore è di una vecchia stampanta, nessun data sheet purtroppo.. L’ho alimentato a circa 11 v e ho utilizzato un condesatore 1500 6.5 v.. ti allego il collegamento del pololu che ho trovato online.. Grazie mille e scusa per le numerose domande. https://www.pololu.com/product/1182
Autore
Ciao Giovanni,
per shield intendi una su cui montare il driver A4988? se si penso ne esistano diverse che puoi scegliere dal catalogo robotics-3d.com
La seconda domanda non l’ho compresa.