Mi aiutate a migliorare il progetto intervallometro?

Da niubbo vi chiedo aiuto/consigli per implementare il mio intervallometro (per realizzare timelapse) per la Nikon D40 di cui ho già postato il risultato qualche giorno fà.
Attuale:
-ho collegato un led IR sull'uscita 13 e la terra, e utilizzato lo script preso da questo sito:
http://www.vonroth.com/Arduino/NikonIrControl/

ok tutto funziona, il risultato ottimo
limite: bisogna caricare ogni volta lo script se si vogliono variane i secondi di intervallo tra uno scatto e l'altro quindi, come potete immaginare, non posso portarmi dietro sempre un portatile per riprogrammare l'arduino quando sono in giro a fare foto.

Desiderio:
-possibilità di variare il delay (potenziometro/trimmer?) e magari attaccarci un display lcd per visualizzare quanti sec stò impostando.
Grazie per tutti gli eventuali aiuti (mi racc. dettagliati :wink:

Io nella versione che avrei voluto realizzare, ma che a questo punnto sto aspettando che realizzi tu :slight_smile:
avevo previsto uno schermo lcd 2x8, coi pin sul lato corto. Il controllo lo avevo pensato sostanzialmente con un pulsante "start/stop" e una serie di time lapse predefiniti, che tramite un'altro pulsante che premi cicli.
Fede

ciao
per la poca esperienza che ho posso dirti che sotto delay invece di un valore fisso metti una variabile che leggi con analogread() e a un ingresso analogico attacchi un potenziometro e associ al valore del potenziometro il tuo intervallo dei tempi con una proporzione

stefano

Cello62:
Da niubbo vi chiedo aiuto/consigli per implementare il mio intervallometro (per realizzare timelapse) per la Nikon D40 di cui ho già postato il risultato qualche giorno fà.
ok tutto funziona, il risultato ottimo
limite: bisogna caricare ogni volta lo script se si vogliono variane i secondi di intervallo tra uno scatto e l'altro quindi, come potete immaginare, non posso portarmi dietro sempre un portatile per riprogrammare l'arduino quando sono in giro a fare foto.

Desiderio:
-possibilità di variare il delay (potenziometro/trimmer?) e magari attaccarci un display lcd per visualizzare quanti sec stò impostando.
Grazie per tutti gli eventuali aiuti (mi racc. dettagliati :wink:

Io per il mio progetto che vedi qui: mini intervallometro, ho utilizzato un potenziometro, e tramite il codice mi sono creato la scala di valori.
In questo modo basta associare ai diversi gradi di rotazione un valore corrispondente (infatti nel mio progetto dovrei mettere un'etichetta che indichi i valori).

Facendo così hai la possibilità di sapere quanto imposti, ed inoltre la scala può passare da pochi secondi fino anche svariate ore.

Se non capisci il codice ti spiego meglio.

Io per il mio intervallometro ho evitato il display proprio per tenerlo il più portatile possibile. In ogni caso non mi fa impazzire come cosa, perchè aumenta i costi e la complessità generale del progetto..

Allora grazie a lollotek sono riuscito a implementare l'intervallometro collegando un potenziometro sull'uscita analogica 2 dell'Arduino con la possibilità ora di variare a piacimento il delay e quindi i sec tra uno scatto e l'altro in un intervallo di tempo che rientra nel range del valore restituito dalla variabile così come riportato nell'esempio del codice sotto.

#include <nikonIrControl.h>

int CameraIrPin = 13; // LED connected to digital pin 13
int configPin = 2; // collego il potenziometro al pin analogico 0
int selection = 0; // inizializzo la variabile di attesa
void setup() // run once, when the sketch starts
{
pinMode(CameraIrPin, OUTPUT); // sets the digital pin as output
}
void loop() // run over and over again
{
selection = analogRead(configPin);
cameraSnap(CameraIrPin);
delay(1000 + (selection * 5)); // selection va da 1 a 1024, quindi avrai un timer minimo 1 secondo e max 6 secondi (1024 *5 + 1000)
}

Next step
Posso collegare un display per visualizzare il valore restituito dalla variabile e quindi i sec? come si fa?
Possiedo già un display 16x2 ed ho imparato a collegarlo e fare dei testi con questo tutorial:
http://www.ladyada.net/learn/lcd/charlcd.html
ma mi manca un passaggio..
grazie per gli aiuti.

My 2 cents...

Se vuoi scegliere un intervallo di tempo (es 1 secondo - 60 secondi) in base al potenziometro su ingresso analogico, puoi usare la funzione map(valore, min1, max1, min2, max2);

Prendendo l'esempio di prima potresti avere

int intervallo = map (analogRead(0), 0, 1023, 1, 60);
...
delay(intervallo * 1000)

Ci sono aggiornamenti sul progetto?
Comunque le dritte che ti avevo dato privatamente era giusto per il concetto base, poi quello che è suggerito forno è più che corretto.
Io per il mio intervallometro portatile ho fatto una modifica ulteriore:

#define LENARRAY 9 // attenzione, questo valore deve corrispondere al numero di elementi dell'array
int confArray[LENARRAY] = {5, 8,15,30,60,180,600,1800,3600}; # secondi di attesa preconfigurati

void loop(){

selection = analogRead(0); # lettura del potenziometro collegato all'entrata analogica 0
selection = map(selection,0, 1023, 1, LENARRAY) ; # ridimensiono il valore letto alla lunghezza del mio array di valori predefiniti
wait(confArray[selection]) # attesa in basa alla selezione effettuata

}

il codice è leggermente modificato rispetto a quello che ho usato, proprio per fare un esempio.
con questo metodo puoi regolare la sensibilità del potenziometro aggiungendo e togliendo valori all'array. Inoltre puoi mettere valori che non siano per forza in scala tra di loro, come invece avresti son un normale map.

ciao

Ciao lollo
Attualmente sto usando questo:

#include <LiquidCrystal.h>
#include <nikonIrControl.h>


LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

int CameraIrPin = 13;   // LED connected to digital pin 13
int configPin = 2; // collego il potenziometro al pin analogico 2
int selection = 0;  // inizializzo la variabile di attesa

void setup()   // run once, when the sketch starts
{
  pinMode(CameraIrPin, OUTPUT); // sets the digital pin as output
  
  }
void loop()     // run over and over again
{
  selection = analogRead(configPin);
  cameraSnap(CameraIrPin);
  delay(5000 + (selection * 24)); // selection va da 1 a 1023,
  //quindi avrai un timer minimo 5 secondi e max 29 secondi 
  //(1023 *5 + 1000)
  lcd.begin(16,2) ;
  lcd.setCursor(0,0) ;
  lcd.print("INT SCATTO NIKON");
  
  lcd.setCursor(3,1); 
  
  lcd.print(( selection * 24 + 5000)/1000);
  
  lcd.print(" secondi");
}

Tutto ok ma sarei più soddisfatto se riuscissi ad arrivare ad un risultato tipo questo
http://www.highonsolder.com/blog/2009/7/20/arduino-intervalometer-for-time-lapse-photography.html
La mia macchina non supporta l'entrata "shutter" via jack ma il codice ed il progetto è ben realizzato, anche se non sono capace di farlo.., ho provato a far girare il codice e la cosa che mi piace molto è la variazione sul display in tempo reale delle impostazioni, nel mio bisogna aspettare che ritorni l'output del potenziometro-

#include <LiquidCrystal.h>                //library for LCD control

// LiquidCrystal display with:
// RS, EN, D4, D5, D6, D7
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);    //Set which LCD pins are used for data

//I-O setup
const int potentiometer = 0;              //Potentiometer analog input pin
const int mode = 2;                       //Mode button input pin
const int shutter = 3;                    //Shutter relay output pin

//Variables
long interval = 5000;                      //time between shutter presses
long previousMillis = 0;                   //previous millisecond value
int hold = 1000;                           //time shutter should be held open
int M = 0;                                 //Mode button state
int Mstate = 0;                            //previous Mode button state
int StartSet = 0;                          //Mode state
int pot;                                   //potentiometer reading
long range;                                //potentiometer position
int count = 0;                             //picture count
int ModeSW = 0;                           //Low-High set mode toggle

//Press & Hold variables
#define debounce 50                       // ms debounce period to prevent flickering when pressing or releasing the button
#define holdTime 2500                     // ms hold period: how long to wait for press+hold event
long btnDnTime;                           // time the button was pressed down
long btnUpTime;                           // time the button was released
boolean ignoreUp = false;                 // whether to ignore the button release because the click+hold was triggered

//Initialize I-O
void setup() {                    
  pinMode(shutter, OUTPUT);             
  pinMode(mode, INPUT);
  lcd.begin(16, 2);                        //set LCD for 16 columns & 2 rows of display
}

void loop(){
  M = digitalRead(mode);                   //read Mode button state     
  
  //Test for button pressed and store the down time
  if (M == HIGH && Mstate == LOW && (millis() - btnUpTime) > long(debounce))
  {
    btnDnTime = millis();
  }
  
  //Test for button release and store the up time
  if (M == LOW && Mstate == HIGH && (millis() - btnDnTime) > long(debounce))
  {
    if (ignoreUp == false) ModeSW = !ModeSW;      //test if Low-High set mode should be toggled
    else ignoreUp = false;
    btnUpTime = millis();
  }
  
  //Test for button held down for longer than the hold time
  if (M == HIGH && (millis() - btnDnTime) > long(holdTime))
  {
    StartSet = !StartSet;                  //toggle Set mode to Timing mode or vice versa
    ignoreUp = true;
    btnDnTime = millis();
  }
  Mstate = M;
  
  //Test for Set Mode
  if(StartSet == LOW){           
    lcd.home();                             //set cursor to LCD column 1, row 1
    lcd.print("Set Mode   ");               //display "Set Mode" on LCD                   
    count = 0;                              //reset picture count
    if(ModeSW == LOW) LowRange();           //test Low-High set mode
    else HighRange();
  }
  
  //Test for Timing Mode
  else{
    lcd.home();                             //set cursor to LCD column 1, row 1
    lcd.print("Timing Mode");               //display "Timing Mode" on LCD
    Shutter();                              //call Shutter triggering function
    lcd.setCursor(0, 1);                    //set cursor to LCD column 1, row 2
    lcd.print(count);                       //display picture count number on LCD
    lcd.print(" Pictures   ");              //display "Pictures" on LCD
  }
}

//Low Set Mode function
long LowRange(){
  long seconds;                             //shutter timing interval in seconds
  pot = analogRead(potentiometer);          //read potentiometer value
  range = map(pot, 0, 1023, 12, 1);         //divide potentiometer range into 5 second steps
  interval = 5000 * range;                  //convert steps into 60 second range in milliseconds
  seconds = interval/1000;                  //convert milliseconds to seconds
  lcd.setCursor(0, 1);                      //set cursor to LCD column 1, row 2
  lcd.print(seconds);                       //display shutter timing interval in seconds on LCD
  lcd.print(" seconds    ");                //display "seconds" on LCD
  return interval;                          //return shutter timing interval value to loop
}

//High Set Mode function
long HighRange(){
  float minutes;                            //shutter timing interval in minutes
  pot = analogRead(potentiometer);          //read potentiomenter value
  range = map(pot, 0, 1023, 20, 1);         //divide pot range into 30 second steps
  interval = 30000 * range;                 //convert steps into 10 minute range in milliseconds
  minutes = interval/60000;                 //convert milliseconds into minutes 
  lcd.setCursor(0, 1);                      //set cursor to LCD column 1, row 2
  lcd.print(minutes);                      //display shutter timing interval in minutes on LCD
  lcd.print(" minutes ");                  //display "minutes on LCD
  return interval;                          //return shutter timing interval value to loop
}

//Shutter triggering function
int Shutter(){
  
  //Test that timing interval has passed
  if((millis() - previousMillis) > interval){       
    previousMillis = millis();                      //save the last time shutter was triggered
    digitalWrite(shutter, HIGH);                    //trigger shutter relay coil
    delay(hold);                                    //wait preset shutter hold time
    digitalWrite(shutter, LOW);                    //release shutter relay coil
    ++count;                                      //increment picture count
    return count;                                   //return picture count value to loop
  }
  else return count;
}

Allora, tu visualizzi i dati in ritardo perché tra uno scatto e l'altro utilizzi il dalay, il metodo più semplice, ma facendo così il codice non prosegue finchè questo lasso di tempo non finisce.
ti consiglio di guardare l'esempio "Blink without Delay" in examples->2.digital nell'idea di arduino.
Li mostra un metodo dove confronta ad ogni giro quanto tempo è passato rispetto ad un altro momento. facendo così puoi fare un calcolo e verificare se devi o meno eseguire l'istruzione "a tempo", ma senza tenere "bloccato" il codice.

comunque ho provato a modificare il codice, ovviamente non è testato visto che non ho l'hardware necessario..

#include <LiquidCrystal.h>
#include <nikonIrControl.h>


LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

int CameraIrPin = 13;   // LED connected to digital pin 13
int configPin = 2; // collego il potenziometro al pin analogico 2
int selection = 0;  // inizializzo la variabile di attesa

#define LENARRAY 9 // attenzione, questo valore deve corrispondere al numero di elementi dell'array
int confArray[LENARRAY] = {5, 8,15,30,60,180,600,1800,3600}; // secondi di attesa preconfigurati
long previousMillis = 0; 

void setup()   // run once, when the sketch starts
{
  pinMode(CameraIrPin, OUTPUT); // sets the digital pin as output
  lcd.begin(16,2) ;  // spostato in inizializzazione, non è necessario eseguire ad ogni loop
}

void loop()     // run over and over again
{
  selection = analogRead(configPin);
  selection = map(selection,0, 1023, 1, LENARRAY) ; // ridimensiono il valore letto alla lunghezza del mio array di valori predefiniti

  lcd.setCursor(0,0) ;
  lcd.print("SET: ");
  lcd.print(selection);
  lcd.print(" sec.");
  
  lcd.setCursor(0,1); 
  lcd.print("WAIT: ");
  unsigned long currentMillis = millis();
  lcd.print(currentMillis - previousMillis/1000);
  
  // controllo se il tempo è scaduto
  if(currentMillis - previousMillis > (confArray[selection]*1000)) {
    previousMillis = currentMillis;   // mi salvo il momento dell'ultimo scatto effettuato
    cameraSnap(CameraIrPin);
  }
}

Questo dovrebbe visualizzare in tempo reale l'intervallo di tempo selezionato nella prima riga, mentre nella seconda quanti secondi sono passati dall'ultimo scatto.
se vuoi aumentare il range di valori ne aggiungi degli altri a confArray, e poi imposti LENARRAY uguale al numero degli elementi dell'array.

First of all, grazie di cuore per l'interessamento
Allora, ho provato a farlo girare, succede che il valore di set (ruotando il potenziometro) parte come minimo da 1 secondo e quindi , se ho capito bene gli array, essendo la lista array 0,1,2,3,4,5,6,7,8 in realtà

int confArray[LENARRAY] = {5, 8,15,30,60,180,600,1800,3600};

il primo scatto (quando legge 1 sec) lo fa dopo 8 secondi, a 2 sec dopo 15 sec e così via, se volessi il valore di 5 (come da casella 0) devo cambiare la lista, ovviamente non è un problema è solo per capire.
Il contatore invece continua a correre, mi sembrava di aver capito che doveva resettarsi dopo ogni intervallo giusto?

Domani cmq ci smanetto per capirci meglio.
Grazie ancora

Ho fatto un paio di modifiche commentandole con "EDIT".
Oggi ho ripreso a lavorare (sig..) quindi al max posso fare altri test questa sera

fammi sapere come va..

#include <LiquidCrystal.h>
#include <nikonIrControl.h>


LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

int CameraIrPin = 13;   // LED connected to digital pin 13
int configPin = 2; // collego il potenziometro al pin analogico 2
int selection = 0;  // inizializzo la variabile di attesa

#define LENARRAY 9 // attenzione, questo valore deve corrispondere al numero di elementi dell'array
int confArray[LENARRAY] = {5, 8,15,30,60,180,600,1800,3600}; // secondi di attesa preconfigurati
long previousMillis = 0; 

void setup()   // run once, when the sketch starts
{
  pinMode(CameraIrPin, OUTPUT); // sets the digital pin as output
  lcd.begin(16,2) ;  // spostato in inizializzazione, non è necessario eseguire ad ogni loop
}

void loop()     // run over and over again
{
  selection = analogRead(configPin);
  selection = map(selection,0, 1023, 1, LENARRAY) ; // ridimensiono il valore letto alla lunghezza del mio array di valori predefiniti

  lcd.setCursor(0,0) ;
  lcd.print("SET: ");
  lcd.print(confArray[selection]); //EDIT - ora mostra i secondi selezionati e non la posizione dell'array
  lcd.print(" sec.");
  
  lcd.setCursor(0,1); 
  lcd.print("WAIT: ");
  unsigned long currentMillis = millis();
  lcd.print((currentMillis - previousMillis)/1000); //EDIT - messa tra parentesi la sottrazione dandole la priorità
  
  // controllo se il tempo è scaduto
  if((currentMillis - previousMillis) > (confArray[selection]*1000)) {
    previousMillis = currentMillis;   // mi salvo il momento dell'ultimo scatto effettuato
    cameraSnap(CameraIrPin);
  }
}

occhio, prendi un potenziometro lineare e non logaritmico, altrimenti sarà ifficile impostare il corretto valore.

Non mi piace l'idea di leggere la analog ogni loop, perchè il valore può essere ballerino e rompere le balle. io aggiungerei un pulsantino, leggi il potenziomentro fichè non è premuto il pulsantino, a quel punto salvi l'ultima analog e fai scattare il timer per il delay.

lollotek:
Oggi ho ripreso a lavorare (sig..) quindi al max posso fare altri test questa sera

fammi sapere come va..

Ciao , io invece domani parto per una sett., ho sofferto ma ora tocca a me..
Allora, ancora due problemi, a livello di visualizzazione display, lo scatto invece rispetta i tempi impostati.
-La scritta sec rimane a video quando si switcha tra un impostazione e l'altra e il WAIT va bene all'inizio ma dopo aggiunge le decine al conteggio e fa casino , provo a postarti un video

il casino sul wait è dettato dal fatto che non "pulisci" lo schermo... puoi usare una clear, oppure aggiungere uno spazio dopo il numero, così se usi solo unità lo spazio va a cancellare la vecchia unità, che si è spostata di lato causa decina. la stessa identica cosa avviene anche per "sec".
per evitare sbattimenti con gli spazi puoi usare una più radicale clear, solo che se fatta troppo spesso il led "flicchera", ovvero noti che le scritte scopaiono e riappaiono, oltre a essere sgradevole all'occhio, può rendere più difficile la lettura se in presenza di fonti di forte luce.

con lo spazio dopo sec in effetti funziona,

 lcd.print(" sec ");

Il wait invece passando da 8 sec a 15 ad es., parte da 5 e aggiunge 10 (15/25/35/ etc) arriva a 100 e riparte da 5.

anche il problema dove ti sembra che conta a base 10 è legato al refresh mancante del display, praticamente lui lascia la seconda cifra che era presente precedentemente, e quindi a te sembra che conti per decine.
anche li basta scrivere un po' di spazi per assicurarsi che rimuova eventuali caratteri in eccesso.
Ho comunque modificato il codice, ora dovrebbe indicarti quanti secondi mancano allo scatto e non quanti sono trascorsi, e poi non dovrebbe più avere problemi di refresh.
Buone ferie..

#include <LiquidCrystal.h>
#include <nikonIrControl.h>


LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

int CameraIrPin = 13;   // LED connected to digital pin 13
int configPin = 2; // collego il potenziometro al pin analogico 2
int selection = 0;  // inizializzo la variabile di attesa

#define LENARRAY 9 // attenzione, questo valore deve corrispondere al numero di elementi dell'array
int confArray[LENARRAY] = {5, 8,15,30,60,180,600,1800,3600}; // secondi di attesa preconfigurati
long previousMillis = 0; 

void setup()   // run once, when the sketch starts
{
  pinMode(CameraIrPin, OUTPUT); // sets the digital pin as output
  lcd.begin(16,2) ;  // spostato in inizializzazione, non è necessario eseguire ad ogni loop
}

void loop()     // run over and over again
{
  selection = analogRead(configPin);
  selection = map(selection,0, 1023, 1, LENARRAY) ; // ridimensiono il valore letto alla lunghezza del mio array di valori predefiniti

  lcd.setCursor(0,0) ;
  lcd.print("SET : ");
  lcd.print(confArray[selection]); //EDIT - ora mostra i secondi selezionati e non la posizione dell'array
  lcd.print(" sec      "); // EDIT2: aggiunti spazi per pulizia
  
  lcd.setCursor(0,1); 
  lcd.print("WAIT: ");
  unsigned long currentMillis = millis();
  lcd.print(confArray[selection] - ((currentMillis - previousMillis)/1000)); //EDIT - messa tra parentesi la sottrazione dandole la priorità 
                                                                             // EDIT2: ora fa il conto alla rovescia
  lcd.print("       ");  // EDIT2: mi assucuro di ripulire gli elementi dopo il numero scritto
  
  // controllo se il tempo è scaduto
  if((currentMillis - previousMillis) > (confArray[selection]*1000)) {
    previousMillis = currentMillis;   // mi salvo il momento dell'ultimo scatto effettuato
    cameraSnap(CameraIrPin);
  }
}

Grandissimo
ora va da Dio

Grazie mille per la gentilezza