help + presentazione (ripetere un comando per N volte in un intervallometro)

Ciao a tutti, sono nuovo!
non so se c'è una sezione dove presentarsi, cmq lo faccio qui!
Leggo spesso questo forum per risolvere problemi che insorgono nello sviluppo del software per vari progetti...
Questa volta proprio non riesco a risolvere da me ...e ho bisogno del vostro aiuto per andare avanti.
Comincio a presentarvi ciò che sto costruendo.
Il progetto è un intervallometro per fotocamera, con display lcd 4x16 e tastierino numerico 3x4 per l'inserimento dei valori.
Sull'LCD viene visualizzato:
TIME (intervallo di scatto)
REPEAT (numero di scatti da effettuare)
FPS (frame per seconds)
MOVIE (lunghezza del filmato unendo tutti i fotogrammi REPEAT/FPS)

per l'inserimento dei dati, ho usato un tastierino numerico 3x4 collegato all'ingresso analogico 2 prendendo spunto da questo articolo

il problema è che non riesco a dire ad arduino di eseguire lo scatto per N volte, tante quante sono impostate nella variabile " rpt"...
ho provato con la funzione FOR, WHILE ma niente... suggerimenti?

vi posto il codice:

#include <LiquidCrystal.h>
#define lcdlight 2000
unsigned int rpt = 300;
int scatti = 0;
int value = LOW;
long previousMills = 0; 
unsigned int intervallo =1;
int luce=0;
int analogicoin=0;
int fps = 30;
int Lampeggio=0;


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

  void setup(){

  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);
  digitalWrite(11, HIGH);
  lcd.begin(16, 4); 
  lcd.setCursor(0, 0);
  lcd.print("Cava's");
  lcd.setCursor(0, 1);
  lcd.print("Intervallometer");
  lcd.setCursor(-4, 3);
  lcd.print("LOADING");
  delay(1000);
  lcd.setCursor(3, 3);
  lcd.print(".");
  delay(1000);
  lcd.setCursor(4, 3);
  lcd.print(".");
  delay(1000);
  lcd.setCursor(5, 3);
  lcd.print(".");
  delay(1000);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("TIME:");
  lcd.setCursor(0, 1);
  lcd.print("REPEAT:");
  lcd.setCursor(-4, 2);
  lcd.print("FPS:");
  lcd.setCursor(-4, 3);
  lcd.print("MOVIE:");
  digitalWrite(11, LOW);
  lcd.setCursor(11, 0);
  lcd.print(intervallo+intervallo);
  lcd.setCursor(11, 1);
  lcd.print(rpt);
  lcd.setCursor(7, 2);
  lcd.print(fps);
  lcd.setCursor(7, 3);
  lcd.print(rpt/fps);

}
void loop(){

  luce=analogRead(2);
  delay(15);
  if(analogicoin >= 657 && analogicoin <= 667){
    digitalWrite(11, HIGH);
  

  }  
  else{
    digitalWrite(11, LOW);


  }
  analogicoin=analogRead(2);
  delay(15);
  if(analogicoin >= 1002 && analogicoin <= 1012){
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("TIME:");
    lcd.setCursor(0, 1);
    lcd.print("REPEAT:");
    lcd.setCursor(-4, 2);
    lcd.print("FPS:");
    lcd.setCursor(-4, 3);
    lcd.print("MOVIE:");
    intervallo--;
    lcd.setCursor(7, 3);
    lcd.print(rpt/fps);
    lcd.setCursor(7, 2);
    lcd.print(fps);
    lcd.setCursor(11, 1);
    lcd.print(rpt);
    lcd.setCursor(11, 0);
    lcd.print(intervallo+intervallo);
    delay(250);
  }

  if(analogicoin >= 606 && analogicoin <= 616 ){
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("TIME:");
    lcd.setCursor(0, 1);
    lcd.print("REPEAT:");
    lcd.setCursor(-4, 2);
    lcd.print("FPS:");
    lcd.setCursor(-4, 3);
    lcd.print("MOVIE:");  
    intervallo++;
    lcd.setCursor(7, 3);
    lcd.print(rpt/fps);
    lcd.setCursor(7, 2);
    lcd.print(fps);
    lcd.setCursor(11, 1);
    lcd.print(rpt);
    lcd.setCursor(11, 0);
    lcd.print(intervallo+intervallo);
    delay(250);
  }
  analogicoin = analogRead(2);
  delay(15);
  if (analogicoin >= 944 && analogicoin <= 954) {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("TIME:");
    lcd.setCursor(0, 1);
    lcd.print("REPEAT:");
    lcd.setCursor(-4, 2);
    lcd.print("FPS:");
    lcd.setCursor(-4, 3);
    lcd.print("MOVIE:");  
    rpt--  ;
    lcd.setCursor(7, 3);
    lcd.print(rpt/fps);
    lcd.setCursor(7, 2);
    lcd.print(fps);
    lcd.setCursor(11, 0);
    lcd.print(intervallo+intervallo);
    lcd.setCursor(11, 1);
    lcd.print(rpt);
    delay(250);

  }
  if (analogicoin >= 580 && analogicoin <= 590) {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("TIME:");
    lcd.setCursor(0, 1);
    lcd.print("REPEAT:");
    lcd.setCursor(-4, 2);
    lcd.print("FPS:");
    lcd.setCursor(-4, 3);
    lcd.print("MOVIE:");  
    rpt++ ;
    lcd.setCursor(7, 3);
    lcd.print(rpt/fps);
    lcd.setCursor(7, 2);
    lcd.print(fps);
    lcd.setCursor(11, 0);
    lcd.print(intervallo+intervallo);
    lcd.setCursor(11, 1);
    lcd.print(rpt);
    delay(250);

  }
  if (analogicoin >= 882 && analogicoin <= 892) {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("TIME:");
    lcd.setCursor(0, 1);
    lcd.print("REPEAT:");
    lcd.setCursor(-4, 2);
    lcd.print("FPS:");
    lcd.setCursor(-4, 3);
    lcd.print("MOVIE:");  
    fps--;
    lcd.setCursor(7, 3);
    lcd.print(rpt/fps);
    lcd.setCursor(11, 0);
    lcd.print(intervallo+intervallo);
    lcd.setCursor(11, 1);
    lcd.print(rpt);
    lcd.setCursor(7, 2);
    lcd.print(fps);
    delay(250);
  }
  if (analogicoin >= 557 && analogicoin <= 567) {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("TIME:");
    lcd.setCursor(0, 1);
    lcd.print("REPEAT:");
    lcd.setCursor(-4, 2);
    lcd.print("FPS:");
    lcd.setCursor(-4, 3);
    lcd.print("MOVIE:");  
    fps++;
    lcd.setCursor(7, 3);
    lcd.print(rpt/fps);
    lcd.setCursor(11, 0);
    lcd.print(intervallo+intervallo);
    lcd.setCursor(11, 1);
    lcd.print(rpt);
    lcd.setCursor(7, 2);
    lcd.print(fps);
    delay(250);
  }

   if (millis() -  previousMills > intervallo*1000 ){
    previousMills = millis();  //Tiene in memoria l'ultimo lampeggio

    if (value == LOW)
      value = HIGH;
    else
      value = LOW;

    digitalWrite(12, value);
    
  
 }
 }

Ringrazio anticipatamente chi mi presterà attenzione, e spero di non aver posto un quesito troppo banale...
Grazie e ciao.
Marco

PS scheda utilizzata arduino 2009

il problema è che non riesco a dire ad arduino di eseguire lo scatto per N volte, tante quante sono impostate nella variabile " rpt"...
ho provato con la funzione FOR, WHILE ma niente... suggerimenti?

Io non posso aiutarti perchè non riesco ad abbinare il concetto di scatto al codice che hai postato.

Se nel codice comparisse una funzione chiamata "void scatto()" io capirei che li dentro avviene qualcosa che chiamiamo scatto, che poi sarà la variazione di un pin da basso ad alto e poi nuovamente basso.

Chiarisci quale parte del codice è lo scatto.

Per il resto, dividi il programma in funzioni a cominciare appunto dalla funzione scatto.

Il codice nel caso ci fosse la funzione scatto sarebbe:

for (uint8_t n_scatto = 0; n_scatto < rpt; n_scatto++) {
    scatto(); // chiamata alla funzione scatto
}

// con il while
unsigned int n_scatto = 0;
while (n_scatto < npr) {
    scatto(); // chiamata alla funzione scatto
    n_scatto++; // incrementa il contatore;
}

tutto ciò che c'è dentro le {} del for vengono eseguite fino a quando la condizione "n_scatto < rpt" risulta falsa, perchè n_scatto e stato incrementato a 300 e la condizione 300 < 300 risulta essere falsa.

Per il while è la stessa cosa, cioè cicla fintantoché la condizione "n_scatto < npr" risulta vera, e temina il while nel caso risultasse falsa.

Ciao.

E poi distaccati dall'idea di "computer".

Robe del genere:

lcd.print("LOADING");
  delay(1000);
  lcd.setCursor(3, 3);
  lcd.print(".");
  delay(1000);
  lcd.setCursor(4, 3);
  lcd.print(".");
  delay(1000);
  lcd.setCursor(5, 3);
  lcd.print(".");
  delay(1000);

Non hanno senso su un microcontrollore. :stuck_out_tongue:

Comunque guardando il tuo programma a me pare che tu abbia messo solo le funzioni di output e non quelle di input.

Se devi fare ancora la parte di input, ragiona così:
Nel loop, devi controllare la pressione di un pulsante della tastiera che informi il codice che l'utente vuole entrare in modalità programmazione. Fatto questo, entri in modalità programmazione, chiedendo all'utente i parametri. Una volta che hai incamerato i parametri, è facile passare il numero di ripetizioni al ciclo for. Tutto si traduce nell'usare la variabile che contiene il numero impostato dall'utente.

Innanzi tutto grazie per la risposta. :wink:
Dunque, il discorso scatto è alla fine del codice, dove c'è la funzione millis che fa lampeggiare un Led (che sarà poi il fotoaccoppiatore)

if (millis() -  previousMills > intervallo*1000 ){
    previousMills = millis();  //Tiene in memoria l'ultimo lampeggio

    if (value == LOW)
      value = HIGH;
    else
      value = LOW;

    digitalWrite(12, value);
    
  
 }
 }

io voglio che esegua questa parte solo il numero di volte impostato in rpt.

la parte di input c'è, posso aumentare o diminuire la frequenza del lampeggio premendo il pulsante che fa leggere ad arduino un valore compreso tra 1002 e 1012 oppure tra 945 e 954.
Con lo stesso concetto posso inserire le ripetizioni e il frame rate.

Per quanto riguarda la prima parte, quella con il "LOADING" non vedo perchè dovrei "distaccarmi" cioè, copisco il discorso che non ha logica su un microcontrollore, però l'ho inserito semplicemente perchè mi piaceva vederlo sull'lcd.

Grazie ancora, e scusate se commetto degli errori, da qualche parte dovrò pure iniziare! :wink:
Aloa
M.

Ciao a tutti e scusate se mi intrometto
@LEO72 tu dici:

E poi distaccati dall'idea di "computer".

Robe del genere:
Code:
lcd.print("LOADING");
delay(1000);
lcd.setCursor(3, 3);
lcd.print(".");
delay(1000);
lcd.setCursor(4, 3);
lcd.print(".");
delay(1000);
lcd.setCursor(5, 3);
lcd.print(".");
delay(1000);
Non hanno senso su un microcontrollore.

Anche a me è capitato di dover visualizzare a display diverse informazioni e sinceramente non so come poter sintetizzare la parte di codice da te sopra citato.
Ovvero la cosa che ho fatto di diverso è quella di aver creato delle void menu1,2,ecc,esterne al loop,all'interno delle quali ho dovuto però settare i vari cursori e stampa e poi,quando avevo l'esigenza nel loop,richiamavo semplicemente la void menu interessata. Questo per cercare di avere almeno un loop più chiaro nella lettura da parte mia e del controllore.
Domanda ,il mio ragionamento è sbagliato ? Come si può affrontare la cosa nel migliore dei modi ?
Grazie

Caspita mi rendo conto di quanto sono imbranato... :frowning:
Cmq per "dividere il programma in funzioni" dovrei definire un "void scatto ()" dentro la quale mettere la parte con MILLIS? e gestirlo con un FOR o un WHILE?

scusate se sparo min....ate! :stuck_out_tongue:

ciau
M,.

la parte di input c'è, posso aumentare o diminuire la frequenza del lampeggio premendo il pulsante che fa leggere ad arduino un valore compreso tra 1002 e 1012 oppure tra 945 e 954.
Con lo stesso concetto posso inserire le ripetizioni e il frame rate.

La parte di input la uso anche io, grazie a due pin analogici puoi gestire una tastiera con shift caps lock ecc.
Ma anche un solo input analogico è comodo e richiede poco codice anche perchè è immune dai rimbalzi che affligono i pulsanti digitali.

Caspita mi rendo conto di quanto sono imbranato... smiley-sad
Cmq per "dividere il programma in funzioni" dovrei definire un "void scatto ()" dentro la quale mettere la parte con MILLIS? e gestirlo con un FOR o un WHILE?

Ok, ti mancano le informazione base per programmare, niente paura.
Un programma può essere scritto senza funzioni aggiuntive anzi di solito l'esecuzione da parte della MCU è più rapida rispetto allo stesso programma diviso in funzioni.

Quindi la funzione serve principalmente al programmatore e a chi legge il codice in seguito. La suddivisione in funzioni è più o meno quello che facciamo con calzette per uomo e donna, banconote da 100 e 500 separate da quelle da 5 10 ecc. Con ovvie differenze il codice isolato dentro una funzione a necessità dei dati da elaborare e di fornire dati eleborati. I dati si passano grazie agli argomenti oppure le funzioni accedono alle variabili globali.

Una funzione deve essere pensata per fare il minimo indispensabile, e deve essere fatta ora e non più modificata in seguito.

Nel tuo caso, usi il la funzione loop per ripetere il codice. Io penso che a te serve ripetere solo questa porzione di codice:

if (value == LOW)
      value = HIGH;
    else
      value = LOW;

    digitalWrite(12, value);

In questo caso avverrano gli scatti nrp volte senza alcun intervallo di tempo tra uno scatto e l'altro, se è così ti basta mettere queste righe sotto for, al posto della funzione scatto().

Dimenticavo, in merito a:

Per quanto riguarda la prima parte, quella con il "LOADING" non vedo perchè dovrei "distaccarmi" cioè, copisco il discorso che non ha logica su un microcontrollore, però l'ho inserito semplicemente perchè mi piaceva vederlo sull'lcd.

Ho visto macchine per l'imbustamento sotto vuoto che all'accensione mostrano un gioco di scritte scorrevoli interminabile e posso dire con certezza che era così solo per bellezza perchè il circuito della macchina va a regime dopo 1 secondo. Però questa cosa dipende dal fatto che quelle schede sono generiche e chi le proggetta non sa dopo quanto tempo la macchina va a reggime così abbondano anche fino a 10 secondi di giochi nel display.

Magari nel tuo caso potresti far apparire la versione del programma, che salvi in una const char * PRG_VER 1 = "0.1.1"; e la mandi al display e poi fai comparire le scritte Wait...... seguite da quanti puntini vuoi, non usare loading perchè porta fuori strada anche te in seguito, magari ne fai una versione che carica dei dati da EEPROM e allora il loading ci sta.

Ciao.

Bisogna attendere un attimo tra uno scatto e l'altro. Se si inserisce il codice HIGH/LOW del pin in un ciclo for o while che sia la macchina non riesce a starci dietro (il micro è più veloce) e anzichè fare 10 scatti ne farà la metà o poco meno.

Quindi, tra uno scatto e l'altro bisogna prevedere un pochino di pausa per dar tempo alla macchina di ripigliarsi.

Bisogna attendere un attimo tra uno scatto e l'altro. Se si inserisce il codice HIGH/LOW del pin in un ciclo for o while che sia la macchina non riesce a starci dietro (il micro è più veloce) e anzichè fare 10 scatti ne farà la metà o poco meno.

Io cosa fa un'intervallometro non lo so, quindi chiedo.
Questo tempo lo decidi con il controllo "if (millis() - previousMills > intervallo*1000 ){"?

Se la risposta e si, il codice dovrebbe fare gli scatti all'infinito, giusto, e questo che vuoi evitare?

se è così proteggi lo scatto con una if, es

if (n_scatto < nrp) {
il codice per lo scatto qui
n_scatto++; // incremti il contatore scatti
}

in questo modo ogni volta che la if(millis()... esegue il suo codice scatta solo se non è stato raggiunto il numero massimo di scatti impostati in npr.

Per un nuovo ciclo di scatti ad intervalli devi azzerare n_scatto.

Ciao.

L'appunto sottolineato da GS88 lo risolverò poi...prima è bene riuscire a far eseguire questo scatto RPT volte...
solo che in questo modo

#include <LiquidCrystal.h>
#define lcdlight 2000
unsigned int rpt = 5;
int scatti = 0;
int value = LOW;
long previousMills = 0; 
unsigned int intervallo =1;
int luce=0;
int analogicoin=0;
int fps = 30;
int Lampeggio=0;


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

  void setup(){

  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);
  digitalWrite(11, HIGH);
  lcd.begin(16, 4); 
  lcd.setCursor(0, 0);
  lcd.print("Cava's");
  lcd.setCursor(0, 1);
  lcd.print("Intervallometer");
  lcd.setCursor(-4, 3);
  lcd.print("LOADING");
  delay(1000);
  lcd.setCursor(3, 3);
  lcd.print(".");
  delay(1000);
  lcd.setCursor(4, 3);
  lcd.print(".");
  delay(1000);
  lcd.setCursor(5, 3);
  lcd.print(".");
  delay(1000);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("TIME:");
  lcd.setCursor(0, 1);
  lcd.print("REPEAT:");
  lcd.setCursor(-4, 2);
  lcd.print("FPS:");
  lcd.setCursor(-4, 3);
  lcd.print("MOVIE:");
  digitalWrite(11, LOW);
  lcd.setCursor(11, 0);
  lcd.print(intervallo+intervallo);
  lcd.setCursor(11, 1);
  lcd.print(rpt);
  lcd.setCursor(7, 2);
  lcd.print(fps);
  lcd.setCursor(7, 3);
  lcd.print(rpt/fps);

}
void loop(){

  luce=analogRead(2);
  delay(15);
  if(analogicoin >= 657 && analogicoin <= 667){
    digitalWrite(11, HIGH);
  

  }  
  else{
    digitalWrite(11, LOW);


  }
  analogicoin=analogRead(2);
  delay(15);
  if(analogicoin >= 1002 && analogicoin <= 1012){
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("TIME:");
    lcd.setCursor(0, 1);
    lcd.print("REPEAT:");
    lcd.setCursor(-4, 2);
    lcd.print("FPS:");
    lcd.setCursor(-4, 3);
    lcd.print("MOVIE:");
    intervallo--;
    lcd.setCursor(7, 3);
    lcd.print(rpt/fps);
    lcd.setCursor(7, 2);
    lcd.print(fps);
    lcd.setCursor(11, 1);
    lcd.print(rpt);
    lcd.setCursor(11, 0);
    lcd.print(intervallo+intervallo);
    delay(250);
  }

  if(analogicoin >= 606 && analogicoin <= 616 ){
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("TIME:");
    lcd.setCursor(0, 1);
    lcd.print("REPEAT:");
    lcd.setCursor(-4, 2);
    lcd.print("FPS:");
    lcd.setCursor(-4, 3);
    lcd.print("MOVIE:");  
    intervallo++;
    lcd.setCursor(7, 3);
    lcd.print(rpt/fps);
    lcd.setCursor(7, 2);
    lcd.print(fps);
    lcd.setCursor(11, 1);
    lcd.print(rpt);
    lcd.setCursor(11, 0);
    lcd.print(intervallo+intervallo);
    delay(250);
  }
  analogicoin = analogRead(2);
  delay(15);
  if (analogicoin >= 944 && analogicoin <= 954) {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("TIME:");
    lcd.setCursor(0, 1);
    lcd.print("REPEAT:");
    lcd.setCursor(-4, 2);
    lcd.print("FPS:");
    lcd.setCursor(-4, 3);
    lcd.print("MOVIE:");  
    rpt--  ;
    lcd.setCursor(7, 3);
    lcd.print(rpt/fps);
    lcd.setCursor(7, 2);
    lcd.print(fps);
    lcd.setCursor(11, 0);
    lcd.print(intervallo+intervallo);
    lcd.setCursor(11, 1);
    lcd.print(rpt);
    delay(250);

  }
  if (analogicoin >= 580 && analogicoin <= 590) {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("TIME:");
    lcd.setCursor(0, 1);
    lcd.print("REPEAT:");
    lcd.setCursor(-4, 2);
    lcd.print("FPS:");
    lcd.setCursor(-4, 3);
    lcd.print("MOVIE:");  
    rpt++ ;
    lcd.setCursor(7, 3);
    lcd.print(rpt/fps);
    lcd.setCursor(7, 2);
    lcd.print(fps);
    lcd.setCursor(11, 0);
    lcd.print(intervallo+intervallo);
    lcd.setCursor(11, 1);
    lcd.print(rpt);
    delay(250);

  }
  if (analogicoin >= 882 && analogicoin <= 892) {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("TIME:");
    lcd.setCursor(0, 1);
    lcd.print("REPEAT:");
    lcd.setCursor(-4, 2);
    lcd.print("FPS:");
    lcd.setCursor(-4, 3);
    lcd.print("MOVIE:");  
    fps--;
    lcd.setCursor(7, 3);
    lcd.print(rpt/fps);
    lcd.setCursor(11, 0);
    lcd.print(intervallo+intervallo);
    lcd.setCursor(11, 1);
    lcd.print(rpt);
    lcd.setCursor(7, 2);
    lcd.print(fps);
    delay(250);
  }
  if (analogicoin >= 557 && analogicoin <= 567) {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("TIME:");
    lcd.setCursor(0, 1);
    lcd.print("REPEAT:");
    lcd.setCursor(-4, 2);
    lcd.print("FPS:");
    lcd.setCursor(-4, 3);
    lcd.print("MOVIE:");  
    fps++;
    lcd.setCursor(7, 3);
    lcd.print(rpt/fps);
    lcd.setCursor(11, 0);
    lcd.print(intervallo+intervallo);
    lcd.setCursor(11, 1);
    lcd.print(rpt);
    lcd.setCursor(7, 2);
    lcd.print(fps);
    delay(250);
  }

   if (millis() -  previousMills > intervallo*1000 ){
    previousMills = millis();  //Tiene in memoria l'ultimo lampeggio

    unsigned int scatto = 0;
    while (scatto < rpt) {
    if (value == LOW)
      value = HIGH;
    else
      value = LOW;

    digitalWrite(12, value);
  scatto++;  
  }
    
  
 }
 }

non va...
o meglio, il codice risulta corretto...dovrebbe lampeggiare 5 volte e poi fermarsi solo che va avanti all'infinito
(ho modificato il valore di RPT per poter verificare funzioni correttamente senza aspettare 300 lampeggi!)

mumble...

MauroTec:
Io cosa fa un'intervallometro non lo so, quindi chiedo.
Questo tempo lo decidi con il controllo "if (millis() - previousMills > intervallo*1000 ){"?

Se la risposta e si, il codice dovrebbe fare gli scatti all'infinito, giusto, e questo che vuoi evitare?

Ciao Mauro. Cosa fa un intervallometro lo so, ma non ho guardato il codice postato. La riga di codice sopra dovrebbe (dovrebbe) indicare ogni quanto eseguire uno scatto.

Il mio appunto era solo per l'autore del post.

Se hai una funzione di questo tipo (perchè l'autore deve anche ricordarsi dello shutter lag della sua macchina):

void scatto(unsigned int shutterLag){
    digitalWrite(PINS_SHUTTER,HIGH); 
    delay(shutterLag);
    digitalWrite(PINS_SHUTTER,LOW);
}

e metti quanto sopra in un ciclo come avevi fatto:

for (uint8_t n_scatto = 0; n_scatto < rpt; n_scatto++) {
   scatto(65);
}

difficilmente riuscirai a fare rpt scatti, anzi sicuramente no. Tutto li. Chiedo scusa se ho creato confusione.

prova così:
n_scatto la devi dichiarare globale dello stesso tipo di rpt e inizzializzarla a zero

//    delay(250);
//  }
//
    if (millis() -  previousMills > intervallo*1000 ){
        previousMills = millis();  //Tiene in memoria l'ultimo lampeggio
       
        if (n_scatto < rpt) {
            digitalWrite(12, HIGH);
            digitalWrite(12, LOW);
            n_scatto++;  
        }
  }
//    
//  
// }

Il codice esegue ad intervalli di tempo "intervallo" le due righe:
digitalWrite(12, HIGH);
digitalWrite(12, LOW);

e continua ad eseguirle ad ogni intervallo, fintantoché n_scatto < rpt, appena n_scatto eguaglia o supera rpt
quel pezzo di codice non viene più eseguito, per fare in modo che venga rieseguito una seconda volta devi azzerare la variabile n_scatto.

Mentre se è come a detto GS88 devi definire un secondo tempo, insomma fare come a detto lui, pari pari.

Ciao.

Ave o Foro!
Eccomi di nuovo a tediarvi con domande da niubbio! :blush:
Il mio progetto continua ed è praticamente ultimato.
L'ho assemblato e testato con la Reflex e pare tutto ok.
L'unico problema è che avendo usato la funzione "Delay" per gestire gli intervalli di scatto, ho come limite di massimo intervallo 65 secondi.
Oltre a questo valore la scheda impazzisce chiudendo il circuito di scatto a caso, con valori sballati. :frowning: :frowning:
Cercando in rete, mi pare di capire che "delay" abbia un limite, e questo limite sia proprio quello che ho riscontrato...ovvero sia, oltre ad un certo numero di millisecondi "delay" non va...
Percui ho pensato alla funzione "Millis" per poter gestire gli intevalli di scatto, ma nonostante abbia cercato e guardato i molti tutorial che si trovano, non riesco proprio a farlo funzionare...

Chiedo qundi aiuto, nello specifico:

  • impostare millis in modo che possa gestire il ritardo che gestiva "delay" sul led rosso (pin 9) e il fotoaccoppiatore (pin 10)
  • fare in modo che millis cicli tramite "while", in accordo con il valore impostato in "repeat"

ecco il codice

#include <LiquidCrystal.h>
#define verde 8
#define rosso 9
#define fotoaccoppiatore 10
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);
int button = 0;
int levetta= 0;
unsigned int time = 1;
unsigned int repeat = 300;
unsigned int scatto = 0;

void setup(){
  Serial.begin(9600);
  pinMode(10, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  lcd.begin(16, 4);
  lcd.setCursor(0, 0);
  lcd.print("Cava's");
  lcd.setCursor(0, 1);
  lcd.print("Intervallometer");
  lcd.setCursor(2, 3);
  lcd.print("Ver. 1.2.1");
  delay(1000);
  lcd.clear();
  lcd.setCursor(2, 1);
  lcd.print("Designed for");
  lcd.setCursor(-2, 2);
  lcd.print("Canon EOS 5d");
  delay(1000);
  lcd.clear();
  lcd.setCursor(11, 1);
  lcd.print(time);
  lcd.setCursor(7, 2);
  lcd.print(repeat);

}
void loop (){
  levetta=analogRead(4);
  if (levetta == 0) {                      //levetta a dx: entra nel modo "edit"
    digitalWrite(rosso, LOW);
    digitalWrite(verde, HIGH);
    lcd.setCursor(3, 0);
    lcd.print("EDIT MODE");
    lcd.setCursor(0, 1);
    lcd.print("TIME:");
    lcd.setCursor(-4, 2);
    lcd.print("REPEAT:");
    lcd.setCursor(-4, 3);
    lcd.print("MOVIE:");
    lcd.setCursor(7, 3);
    lcd.print(repeat/30);
    button=analogRead(5);
    if (button >= 929 && button <= 931){  // imposta i decrementi per l'intervallo di scatto
      lcd.clear();
      lcd.setCursor(3, 0);
      lcd.print("EDIT MODE");
      lcd.setCursor(0, 1);
      lcd.print("TIME:");
      lcd.setCursor(-4, 2);
      lcd.print("REPEAT:");
      lcd.setCursor(-4, 3);
      lcd.print("MOVIE:");

      time--;
      lcd.setCursor(7, 2);
      lcd.print(repeat);
      lcd.setCursor(7, 3);
      lcd.print(repeat/30);
      lcd.setCursor(11, 1);
      lcd.print(time);
      delay(250);


    }
    if (button >= 509 && button <= 511){  // imposta l'incremento per l'intervallo di scatto
      lcd.clear();
      lcd.setCursor(3, 0);
      lcd.print("EDIT MODE");
      lcd.setCursor(0, 1);
      lcd.print("TIME:");
      lcd.setCursor(-4, 2);
      lcd.print("REPEAT:");
      lcd.setCursor(-4, 3);
      lcd.print("MOVIE:");

      time++;
      lcd.setCursor(7, 2);
      lcd.print(repeat);
      lcd.setCursor(7, 3);
      lcd.print(repeat/30);
      lcd.setCursor(11, 1);
      lcd.print(time);
      delay(250);

    }
    if (button >= 888 && button <= 890){  // imposta il decremento per il numero di fotografie da eseguire
      lcd.clear();
      lcd.setCursor(3, 0);
      lcd.print("EDIT MODE");
      lcd.setCursor(0, 1);
      lcd.print("TIME:");
      lcd.setCursor(-4, 2);
      lcd.print("REPEAT:");
      lcd.setCursor(-4, 3);
      lcd.print("MOVIE:");

      repeat--;
      lcd.setCursor(11, 1);
      lcd.print(time);
      lcd.setCursor(7, 3);
      lcd.print(repeat/30);
      lcd.setCursor(7, 2);
      lcd.print(repeat);
      delay(250);
    }
    if (button == 1023){                 // imposta l'incremnto per il numero di fotografie da eseguire
      lcd.clear();
      lcd.setCursor(3, 0);
      lcd.print("EDIT MODE");
      lcd.setCursor(0, 1);
      lcd.print("TIME:");
      lcd.setCursor(-4, 2);
      lcd.print("REPEAT:");
      lcd.setCursor(-4, 3);
      lcd.print("MOVIE:");

      repeat++;
      lcd.setCursor(11, 1);
      lcd.print(time);
      lcd.setCursor(7, 3);
      lcd.print(repeat/30);
      lcd.setCursor(7, 2);
      lcd.print(repeat);
      delay(250);
    }


  } 
  else {                          // levetta a sx: entra nel modo "shot"
    unsigned int remain = repeat;
    digitalWrite(verde, LOW);
    digitalWrite(rosso, HIGH);
    lcd.setCursor(3, 0);
    lcd.print("SHOT MODE");
    lcd.setCursor(0, 1);
    lcd.print("TIME:");
    lcd.setCursor(-4, 2);
    lcd.print("REPEAT:");
    lcd.setCursor(-4, 3);
    lcd.print("MOVIE");   
    lcd.setCursor(11, 1);
    lcd.print(time);
    lcd.setCursor(7, 2);
    lcd.print(repeat); 
    lcd.setCursor(7, 3);
    lcd.print(repeat/30);   


    while (scatto < repeat) {    // intervalla gli scatti in accordo con il tempo impostato e il numero di fotografie da esegire
      lcd.clear();               // terminato il loop, accende il led rosso e rimane in stand-by
      lcd.setCursor(3, 0);
      lcd.print("SHOT MODE");
      lcd.setCursor(0, 1);
      lcd.print("TIME:");
      lcd.setCursor(-4, 2);
      lcd.print("REPEAT:");
      lcd.setCursor(-4, 3);
      lcd.print("MOVIE:");   
      lcd.setCursor(11, 1);
      lcd.print(time);
      lcd.setCursor(7, 3);
      lcd.print(repeat/30);   

      digitalWrite(rosso, HIGH);
      digitalWrite(fotoaccoppiatore, HIGH);
      lcd.setCursor(7, 2);
      lcd.print(remain);              
      delay(200);                   // impulso per lo scatto (chiude il circuito per 200 ms)
      digitalWrite(rosso, LOW);
      digitalWrite(fotoaccoppiatore, LOW);
      delay((time*1000)-200);       // intervallo di tempo tra uno scatto e l'altro meno il tempo impiegato
      scatto++;                     //  per la chiusura del circuito
      remain--;
      lcd.clear();
    }

  }

}

e qualche foto...


Shot at 2012-06-17


Shot at 2012-06-17

PS @leo72 hai visto che ho tolto i "non-sense" da computer??!! :wink:

Grazie
Aloa
Marco.

Creati una funzione tua che attenda:

void attesa(unsigned long miaAttesa) {
  unsigned long intervallo=millis()+miaAttesa; 
  while (intervallo>milis()) {} //non fa nulla finché non è passato l'intervallo previsto
}

basta chiamarla con attesa(100000) ad esempio per fargli attendere 100 secondi.

Ho visto il codice, non ho studiato tutti i passaggi, ma solo la parte finale del while.

A te serve millis() solo per il limite del delay?
Oppure ti serve millis per darti la possibilità di interagire con i comandi durante gli n scatti impostati?

In questo momento il micro esegue il codice nel while e non esce se prima non completa il numero previsto di scatti. Con millis() si può fare in modo che oltre a fare gli scatti ti permette di interagire con la pulsantiere, ma in questo caso dovrai anche gestire quali azioni è possibile compiere e quali no, ad esempio avviare una nuova sequenza quando già una è in esecuzione non deve essere possibile, ed altre potenzialmente dannose per la logica di funzionamento dell'intervallometro.

Ok ho capito cosa fa l'intervallometro.

Alcuni consigli sulla programmazione.

Il codice deve essere leggibile anche da altri e quindi la leggibilità va curata dedicandogli periodicamente del tempo, tempo che ti aiuta anche a modifcare il codice esistente in seguito.

Di solito si procede così:
Scrivi il codice di getto, sperimentando le parti che ti risultano meno comprensibili, cioè affronti in modo isolato il problema che ti riesce difficile comprendere perchè magari e la prima volta che lo affronti.
Nel tuo caso siamo già a buon punto, il codice fa quello che vuoi con qualche inesattezza, questo è il momento buono per fare quello che viene chiamato "refactor". Cioè dedichi tempo per sistemare la leggibilità del codice, nel tuo caso il primo passo potrebbe essere quello di usare una funzione per scatto e metterci dentro il codice che già hai e sai funzionare.

Il refactor lo faccio io per te:

/*********************************************************************************
 ** Autore:                                                                     **
 ** Licenza:                                                                    **
 ** Breve spiegazione:                                                          **
 ** Oppure quello che ti pare, qualunque nota inerente                          **
 ** al programma vuoi comunicare                                                **
 *********************************************************************************/ 


#include <LiquidCrystal.h>

// con qualche eccezione le macro e in particolare le costanti devono essere scritte 
// in maiuscolo ed è meglio che abbiano nomi poco comuni per evitare di usarli a seguito 
// di distrazione dimenticanza
// Poi VERDE cosa? LED, SPERANZA, cosa?

#define LED_VERDE 8
#define LED_ROSSO 9
#define LED_OPTO 10

// prima le define, poi le variabili di tipo standard e poi quelle di tipo personalizzato 
// come LiquidCrystal
int button = 0;						// si ma button cosa?
int levetta= 0;						// levetta si capisce perchè c'è ne solo una
unsigned int time = 1;				// mica si capisce tanto, time cosa?
unsigned int repeat = 300;			// si capisce, ma meglio n_repeat o in camel case nRepeat, scegli
unsigned int scatto = 0;            // stessa cosa di repeat

unsigned long currentTime = 0;
// uno spazio tra le dichiarazione dei tipo standard e quelli non standard
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);

void doClick();
// la funzione fa uno scatto
void doClick() {
  
  digitalWrite(LED_ROSSO, HIGH);
  digitalWrite(LED_OPTO, HIGH);
  delay(200);                   // impulso per lo scatto (chiude il circuito per 200 ms)
  digitalWrite(LED_OPTO, LOW);  
  digitalWrite(LED_ROSSO, LOW);

 
  // update global var
  scatto++;                     //  numero di scatti eseguiti
  remain--;                     // numero di scatti rimanenti  

  // update display
  lcd.setCursor(7, 2);
  lcd.print(remain);              
  

  // attendi time
  currentTime = millis();         		       // salva millis in currentTime
  while (millis() < currentTime + time )       // cicla finche millis() è minore di currentTime + time

  // update global var
  scatto++;                     //  numero di scatti eseguiti
  remain--;                     // numero di scatti rimanenti
}

void setup() {
  Serial.begin(9600);
  // set pin 	
  pinMode(10, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  
  // lcd init
  lcd.begin(16, 4);
  lcd.setCursor(0, 0);
  lcd.print("Cava's");
  lcd.setCursor(0, 1);
  lcd.print("Intervallometer");
  lcd.setCursor(2, 3);
  lcd.print("Ver. 1.2.1");

  delay(1000);

  lcd.clear();
  lcd.setCursor(2, 1);
  lcd.print("Designed for");
  lcd.setCursor(-2, 2);
  lcd.print("Canon EOS 5d");

  delay(1000);

  lcd.clear();
  lcd.setCursor(11, 1);
  lcd.print(time);
  lcd.setCursor(7, 2);
  lcd.print(repeat);
}
void loop (){
  levetta=analogRead(4);
  if (levetta == 0) {                      //levetta a dx: entra nel modo "edit"
    digitalWrite(LED_ROSSO, LOW);
    digitalWrite(LED_VERDE, HIGH);

    lcd.setCursor(3, 0);
    lcd.print("EDIT MODE");
    lcd.setCursor(0, 1);
    lcd.print("TIME:");
    lcd.setCursor(-4, 2);
    lcd.print("REPEAT:");
    lcd.setCursor(-4, 3);
    lcd.print("MOVIE:");
    lcd.setCursor(7, 3);
    lcd.print(repeat/30);
    button=analogRead(5);

    if (button >= 929 && button <= 931){  // imposta i decrementi per l'intervallo di scatto
      lcd.clear();
      lcd.setCursor(3, 0);
      lcd.print("EDIT MODE");
      lcd.setCursor(0, 1);
      lcd.print("TIME:");
      lcd.setCursor(-4, 2);
      lcd.print("REPEAT:");
      lcd.setCursor(-4, 3);
      lcd.print("MOVIE:");

      time--;				// decrement time

      lcd.setCursor(7, 2);
      lcd.print(repeat);
      lcd.setCursor(7, 3);
      lcd.print(repeat/30);
      lcd.setCursor(11, 1);
      lcd.print(time);
      delay(250);


    }
    if (button >= 509 && button <= 511){  // imposta l'incremento per l'intervallo di scatto
      lcd.clear();
      lcd.setCursor(3, 0);
      lcd.print("EDIT MODE");
      lcd.setCursor(0, 1);
      lcd.print("TIME:");
      lcd.setCursor(-4, 2);
      lcd.print("REPEAT:");
      lcd.setCursor(-4, 3);
      lcd.print("MOVIE:");

      time++;						// increment time

      lcd.setCursor(7, 2);
      lcd.print(repeat);
      lcd.setCursor(7, 3);
      lcd.print(repeat/30);
      lcd.setCursor(11, 1);
      lcd.print(time);
      delay(250);

    }
    if (button >= 888 && button <= 890){  // imposta il decremento per il numero di fotografie da eseguire
      lcd.clear();
      lcd.setCursor(3, 0);
      lcd.print("EDIT MODE");
      lcd.setCursor(0, 1);
      lcd.print("TIME:");
      lcd.setCursor(-4, 2);
      lcd.print("REPEAT:");
      lcd.setCursor(-4, 3);
      lcd.print("MOVIE:");

      repeat--;						// decrement n_repeat

      lcd.setCursor(11, 1);
      lcd.print(time);
      lcd.setCursor(7, 3);
      lcd.print(repeat/30);
      lcd.setCursor(7, 2);
      lcd.print(repeat);
      delay(250);
    }

    if (button == 1023){                 // imposta l'incremnto per il numero di fotografie da eseguire
      lcd.clear();
      lcd.setCursor(3, 0);
      lcd.print("EDIT MODE");
      lcd.setCursor(0, 1);
      lcd.print("TIME:");
      lcd.setCursor(-4, 2);
      lcd.print("REPEAT:");
      lcd.setCursor(-4, 3);
      lcd.print("MOVIE:");

      repeat++;
      lcd.setCursor(11, 1);
      lcd.print(time);
      lcd.setCursor(7, 3);
      lcd.print(repeat/30);
      lcd.setCursor(7, 2);
      lcd.print(repeat);
      delay(250);
    }


  } else {                          // levetta a sx: entra nel modo "shot"
    unsigned int remain = repeat;
    digitalWrite(verde, LOW);
    digitalWrite(rosso, HIGH);
    lcd.setCursor(3, 0);
    lcd.print("SHOT MODE");
    lcd.setCursor(0, 1);
    lcd.print("TIME:");
    lcd.setCursor(-4, 2);
    lcd.print("REPEAT:");
    lcd.setCursor(-4, 3);
    lcd.print("MOVIE");   
    lcd.setCursor(11, 1);
    lcd.print(time);
    lcd.setCursor(7, 2);
    lcd.print(repeat); 
    lcd.setCursor(7, 3);
    lcd.print(repeat/30);   
    
    // Nota che tutto il contenuto del while può essere messo in doClick function
    // tranne il while (scatto < repeat), tipo:
    // while (scatto < repeat) {
    //     doClick(); 
    // } 
    // le graffe non servono se il corpo del while è di una sola riga e vanno tolte nella fase finale
    // di refactor quando il codice è funzionante e collaudato   
    
    while (scatto < repeat) {    // intervalla gli scatti in accordo con il tempo impostato e il numero di fotografie da esegire
      lcd.clear();               // terminato il loop, accende il led rosso e rimane in stand-by
      lcd.setCursor(3, 0);
      lcd.print("SHOT MODE");
      lcd.setCursor(0, 1);
      lcd.print("TIME:");
      lcd.setCursor(-4, 2);
      lcd.print("REPEAT:");
      lcd.setCursor(-4, 3);
      lcd.print("MOVIE:");   
      lcd.setCursor(11, 1);
      lcd.print(time);
      lcd.setCursor(7, 3);
      lcd.print(repeat/30);   
		
      doClick();					  		// fa uno scatto
      //delay((time*1000)-200);       // intervallo di tempo tra uno scatto e l'altro meno il tempo impiegato
      //scatto++;                     //  per la chiusura del circuito
      //remain--;
      lcd.clear();
    }

  }

}

Ciao.

marcokava:
e qualche foto...


Shot at 2012-06-17

Complimenti per lo scatolotto. XD

Inoltre, potresti inserire all'interno del ciclo while lettura dello stato del pulsante rosso, con in break sotto if, in modo da poter uscire dal ciclo prima del tempo in caso di errori di impostazione.

attenzione a rendere "indipendente" la parte di scatto dalla parte LCD, altrimenti il ritardo causato dall'aggiornamento dell'LCD rovina i tempi impostati per lo scatto, se molto piccoli