Chiedo scusa per l' ennesima domanda sugli Interrupt

Ciao,
Stavo cercando di (capire) gli Interrupt! :blush:
Senza purtroppo i risultati sperati, … non sono convinto del risultato, il mio test:

#include <LiquidCrystal_I2C.h>
#include <Wire.h>
int numeroImpulsi = 0;   
double   TempAttuale, loopTime,  lastTime;
LiquidCrystal_I2C lcd(0x27, 4, 5, 6, 0, 1, 2, 3, 7, NEGATIVE);  

void setup()
{
   lcd.begin(20,4);    
   attachInterrupt(1, ContaImpulso, CHANGE);
   TempAttuale = millis();
   loopTime = TempAttuale;  
}

void loop()
    {
    lcd.clear();
    lcd.setCursor(0,1);
    lcd.print("Numero impulsi: ");
    lcd.print(numeroImpulsi);
    delay ( 1000 ); 
    }

// inizio Interrupt
void ContaImpulso()
{
  numeroImpulsi++;
     TempAttuale = millis();
     if(TempAttuale >= (loopTime + 6000)){   
             numeroImpulsi = 0;  
             loopTime = millis();
                                        }
}

Sono almeno sulla strada giusta o devo rifare tutto?

Che cosa vuoi ottenere dallo sketch ?

Senza sapere quello è difficile aiutarti.

Una domanda, perchè metti millis in un double invece che in un unsigned long ?

http://arduino.cc/en/Reference/millis

Grazie. Primo errore modificato in:

unsigned long   TempAttuale, loopTime,  lastTime;

Lo scopo è contare quanti giri fa un dispositivo in un dato tempo (pensavo 6 secondi).

#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#define counterDelay 6000

int numeroImpulsi = 0;  
int numeroImpulsiTot = 0;  
int numeroReset = 0; 
unsigned long   TempAttuale, loopTime,  lastTime;


LiquidCrystal_I2C lcd(0x27, 4, 5, 6, 0, 1, 2, 3, 7, NEGATIVE);  

void setup()
{
   lcd.begin(20,4);    
   attachInterrupt(1, ContaImpulso, CHANGE);
   loopTime = millis();  
}

void loop()
    {
    lcd.clear();
    lcd.setCursor(0,1);
    lcd.print("impulsi: ");
    lcd.print(numeroImpulsi);
    lcd.setCursor(1,1);
    lcd.print("impulsi Tot: ");
    lcd.print(numeroImpulsiTot);
    lcd.setCursor(2,1);
    lcd.print("num reset: ");
    lcd.print(numeroReset);
    delay ( 1000 ); 
    }

// inizio Interrupt
void ContaImpulso()
{
     numeroImpulsi++;
     numeroImpulsiTot++;
     TempAttuale = millis();
     if(TempAttuale  - loopTime > counterDelay){   
             numeroImpulsi = 0; 
             numeroReset ++;
             loopTime = TempAttuale;
      }
}

Così almeno capisci se sta ricevendo impulsi o no, anche se sul display vedi sempre 0
Se sei agli inizi con la programmazione ti consiglio di abituarti a rispettare l’indentazione del codice, aiuta molto a organizzare mentalmente il tutto …
Come mai usi CHANGE come parametro per attachinterrupt invece che FALLING o RISING ?

Unica cosa. Se sono partiti quei 6 secondi e il dispositivo all'interno di quel lasso di tempo ha una pausa (non gira) allora il codice ContaImpulso() non viene eseguito e perciò neppure la verifica se il conteggio deve essere azzerato perchè scaduti i 6 secondi.

Eh, la posso salvare in corner dicendo che era un effetto voluto :cold_sweat: ?

madmatt71: Come mai usi CHANGE come parametro per attachinterrupt invece che FALLING o RISING ?

Usando un Sensore effetto hall pensavo: Se il magnetino della ruota si fermava sul sensore avrei così perso un dato, nel caso di arresto e/o di partenza.

nid69ita: il conteggio deve essere azzerato perchè scaduti i 6 secondi.

Tu hai capito esattamente il dubbio che mi ero posto! Come azzerare il conteggio in caso di assenza di movimento

P.S. Conto il tempo tra i due impulsi e se è vicino a 6 sec azzero numeroImpulsi?

Secondo me 1. quella gestione della millis() da dentro ContaImpulso() la devi spostare in loop() 2. le variabili modificate all'interno di un interrupt devono avere il qualificatore volatile davanti

volatile int numeroImpulsi = 0;
  1. per debug va bene come detto da @mad avere un contatore di totale e numero di reset Però io non li metterei su LCD ma solo Serial monitor Poi toglierei il dalay() dalla loop() e stamperei su LCD il valore di numeroImpulsi solo se cambiato. Perciò dovresti memorizzare il precedente.

nid69ita: stamperei su LCD il valore di numeroImpulsi solo se cambiato. Perciò dovresti memorizzare il precedente.

Ma secondo me può succedere che la velocità di rotazione sia sempre identica in un determinato periodo.

@nid69: Decisamente il controllo del teset va spostato nel loop, e se non puo' essere approssimatoal momento piu' vicino dato da delay deve anche usare un timer.. @giuseppe E' difficile tradurre un 'secobdo me' in istruzioni per un microprocessore..quello che nid ti suggeriva era per non aggiornare l'lcd (operazione dispendiosa e che se fatta troppo frequentemente puo' introdurre flicker) di tenere conto del valore di impulsi precedente per scrivere solo se necessario ..

Mi trovo sempre in difficoltà quando per un certo periodo (maggiore di 6 sec) non si muove nulla e la funzione ContaImpulso() non viene richiamata. Quindi pensavo di contare il tempo trai due inpulsi:

void ContaImpulso()
{
   TempoPrecedente = TempAttuale; 
     numeroImpulsi++;
                  ...
     TempAttuale = millis();
     if(TempAttuale  - loopTime > counterDelay){   
             numeroImpulsi = 0; 
                ...
             loopTime = TempAttuale;
      }
      // calcola intervallo tra due inpulsi
      intervallo = (TempAttuale - TempoPrecedente);
     
}

Anche questo è dentro la funzione ContaImpulso() e purtroppo capisco che [u]non[/u] imbocco la strada giusta ... :blush: