esecuzione interrupt

Ciao a tutti
ho il seguente problema:
devo utilizzare un flussometro,come gestisco gli interrupt,nel senso :

int flussometro=7;

 void impulso()  
    {  
      count++;  //incrementa count di 1
    }

void setup()  
    {
   
      pinMode(flussometro,INPUT); 
	  
      
      attachInterrupt(0,impulso,RISING);  
    }

cosi funziona bene

ma se io volessi aggiungere un altro flussometro come imposto l'interrupt,
come devo riscrivere il codice,posso usare lo stesso piedino ho devo prima dichiarare un altro piedino come interrupt tipo 1,e poi riscrivere:

attachInterrupt(1,impulso,RISING);

(ho letto che le schede hanno diversi piedini dedicati al interrupt) tipo Arduino Uno ha il 2e3
(ma io nello sketch ho usato il 0 ed ha funzionato lo stesso)

grazie

ciao kirpidik,

allora...nella maggior parte delle schede arduino solo alcuni pin hanno la possibiltà di essere usati per l'interrupts...vedi il reference QUI
in alcune schede invece li puoi utilizzare tutti.

il numero dell'interrupt non è il numero del pin...quindi tu nel tuo attachInterrupt(0,impulso,RISING) non hai indicato il numero del PIN ma il numero dell'interrupt...questo numero, se non sbaglio, ne identifica anche la priorità nel caso di utilizzo di più interrupt diversi in quanto solo uno alla volta può essere eseguito.

come scritto nelle reference la funzione richiamata dall'interrupt deve eseguire solo cose essenziali...nel senso che deve essere più semplice possibile...nel tuo caso aumentare una variabile va benissimo...quello che deve avere questa variabile è la sua dichiarazione come "volatile"...vedi sempre le reference per chiarire di cosa si tratta (allocazione e gestione nella memoria).

se hai due strumenti/sonde che necessitano di un interrupt, tipo conteggio flusso acqua, si devi creare un'altra ISR (interrup service routine...leggasi funzione chiamata) e legarla ad un secondo pin/interrupt.

Arduino ha due pin che puoi usare per l'interrupt

grazie a tutti per le risposte
ho eseguito diverse prove
1)io collegavo il flussometro al piedino 7(che era sbagliato )nel senso che se volevo collegare un rele che fosse azionato dal segnale del flussometro non ci riuscivo (il segnale variava un po a casaccio tra alto e basso)
2)collegando il flussometro ai piedini 2/3 funzionava tutto ed anche molto stabile
la mia domanda adesso e la seguente
visto che arduino uno ha solo i due piedini come interrupt ,usando questo comando posso impostare ìl un piedino diverso come interrupt

attachInterrupt(digitalPinToInterrupt(flussometro), impulso, RISING);

La risposta è contenuta nella tua domanda: Arduino Uno supporta solo 2 external interrupt, sui pin 2 e 3, per cui puoi usare solo quelli con quel comando.

Se te ne servono di più, puoi usare i Pin Change Interrupt, che sono disponibili su tutti i pin, sebbene siano un po' più lenti e macchinosi da usare. Per fortunata, c'è una bella libreria che ti aiuta: GitHub - GreyGnome/EnableInterrupt: New Arduino interrupt library, designed for Arduino Uno/Mega 2560/Leonardo/Due.

1 Like

grazie ancora
ho provato la libreria degli interrupt più che macchinosi, lenti direi(visto che mi devono azionare dei relè ho bisogno che il cambio sia quasi istantaneo)
comunque per non farlo troppo complicato ho diviso in due parti, parte controllo generale e parte controllo flussometro, per controllo generale ho usato l'Arduino uno ,invece per il controllo del flussometro ho usato due schede di arduino nano
pero ho riscontrato un problema:

quando metto un solo flussometro funziona tutto bene
invece quando provo ad aggiungerne il secondo diventa instabile...la causa quale potrebbe essere ?

(anche sulla scheda arduino nano uso soltanto i piedini 2 e 3 come interrupt)
il codice che uso e questo :

volatile int contatoreFlussometroFreddo;  
volatile int contatoreFlussometroCaldo;  
int pinFlussometroFreddo = 2;   
int pinFlussometroCaldo = 3;   

const int digitalPinRelayTest1 = 4;
const int digitalPinRelayTest2 = 5;


//const int digitalPinRelay8 = 8;
//const int digitalPinRelay9 = 9;
//const int digitalPinRelay10 = 10;


void incrementaContatoreFlussometroFreddo() {
    contatoreFlussometroFreddo++;  //incrementa contatoreFlussometroFreddo di 1
}

void incrementaContatoreFlussometroCaldo() {
    contatoreFlussometroCaldo++;  //incrementa contatoreFlussometroCaldo di 1
}

void setup() {
    Serial.begin(9600);

    pinMode(digitalPinRelayTest1, OUTPUT);
    pinMode(digitalPinRelayTest2, OUTPUT);

    pinMode(pinFlussometroFreddo, INPUT);
    pinMode(pinFlussometroCaldo, INPUT);

    Serial.begin(9600);
    attachInterrupt(digitalPinToInterrupt(pinFlussometroFreddo), incrementaContatoreFlussometroFreddo, RISING);
    attachInterrupt(digitalPinToInterrupt(pinFlussometroCaldo), incrementaContatoreFlussometroCaldo, RISING);

    digitalWrite(digitalPinRelayTest1, LOW);
    digitalWrite(digitalPinRelayTest2, LOW);
}

void loop() {
    // Reset dei contatori
    contatoreFlussometroFreddo = 0;
    contatoreFlussometroCaldo = 0;

    sei();     //attiva interrupt
    delay(1000);
    cli();   // disattiva  interrupt


    /*
    equivalente a :
    interrupts();   //Abilita gli interrupt
    delay (1000);   //Pausa di 1 secondo
    noInterrupts(); //Disabilita gli interrupt
    */


    int flussoFreddo = (contatoreFlussometroFreddo*60/7.5);
    int flussoCaldo = (contatoreFlussometroCaldo*60/7.5);

    if(flussoFreddo < 250) {
        digitalWrite(digitalPinRelayTest1, HIGH);
    } else {
        digitalWrite(digitalPinRelayTest1, LOW);
    }
    if(flussoCaldo < 250) {
        digitalWrite(digitalPinRelayTest2, HIGH);
    } else {
        digitalWrite(digitalPinRelayTest2, LOW);
    }

    Serial.print(flussoFreddo, DEC);
    Serial.print("L/hour\r\n");

    Serial.print(flussoCaldo, DEC);
    Serial.print("L/hour\r\n");
}

ciao...se non ho capito male ogni arduino NANO controlla 2 flussometri (caldo e freddo)...giusto?
nel tuo skecth ad ogni avvio loop() azzeri i due contatori degli impulsi...e metti un delay(1000) per rallentare il loop() con l'intento di farlo ciclare ogni secondo...poi moltiplichi gli impulsi ricevuti *60 dividendo per 7.5...questo dovrebbe darti i litri minuto...giusto!?

io farei...nella ISR...misura del tempo trascorso tra un impulso ed il precedente(benedetto millis())...userei questo per stimare il numero impulsi e calcolare la portata...

si esatto, pero a me non interessa calcolare la quantità,il tot di litri che passano
io ho soltanto bisogno che (ipotizziamo una perdita ) il flusso del liquido va a diminuire ed in quel instante deve dare l'impulso al rele
tutto qui

ciao,

se ho capito...tu vorresti misurare l'acqua in ingresso, ad una caldaia(?), quindi fredda e verificare quanta ne esce...o meglio quanta ne arriva a destinazione quindi calda!?

ok...dato che, secondo me, non è bene determinare una perdita da una lettura secca di un dato ma questo va "filtrato/mediato" salverei in due array le letture fatte per calda e fredda, e ne determinerei l'andamento considerando un tot% di tolleranza dei flussometri.

no ,il circuito e il seguente:
un circuito chiuso (composto da pompa e flussometro ) fino a quando il flussometro indica un certo valore (ex 100) tutto funziona quando il flussometro arriva a indicare un valore minore a quello da me indicato ex (50) deve dare il segnale
questo,essendo il circuito chiuso si può verificare soltanto quando ce una perdita nel sistema

non ho capito come devo crearmi l ISR
e soprattutto dove devo inserirlo

ciao

ISR (Interrupt Service Routine) è la funzione che abbini al tuo attachedInterrupt()...quindi una ce l'hai già.

ok...non cambia nulla...adesso sono un po' impegnato...appena possibile ti preparo un esempio per capire cos'intendo.

Io non ho trovato sul reference una informazione tra virgolette importante

la lunghezza dei NOMI delle variabili

ho pensato che se ti va con un solo flussometro ma con due no, la cosa potrebbe essere indotta da una certa confusione sulle variabili

sono ragionevolmente sicuro che attualmente in C le variabili vengono riconosciute dai PRIMI 63 caratteri
ma lo standard è stato rimaneggiato varie volte, non vorrei che lo IDE di arduino, o il suo compilatore, si fermi a meno

è una prova semplice da fare, cambia nome alle variabili con nome lungo, e usa nomi, anche di fantasie, non più lunghi di 10 caratteri, esempio cont1 cont2 flux1 flux2

ci metti pochi minuti, e ci togliamo il dubbio

interessante la teoria della lunghezza delle variabili...sicuramente da approffondire.

per quanto riguarda l'esempio:

#define pinISR 18

volatile float litresMin;
volatile unsigned long myMillis;
volatile boolean firstTime;

void setup() {
  Serial.begin(9600);
  pinMode(pinISR, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(pinISR), litres, FALLING);
  firstTime = false;
}

void loop() {

}

void litres() { // questa è una ISR
  if (!firstTime) {
    myMillis = millis();
    firstTime = true;
  }
  else {
    litresMin = (60000.00 / (millis() - myMillis)) / 7.5;
    myMillis = millis();
    Serial.println(litresMin);
  }
}

come vedi tutto viene fatto nella funzione litres(); c'è una flag di primo impulso; la funzione modifica la variabile float litresMin, così hai qualche decimale, calcolando il tempo tra due impulsi...ovviamente essendo un calcolo sulle float devi gestire gli eventuali risultati NaN (not a number) ed inf (infinito)...che si possono generare.

docsavage:
Io non ho trovato sul reference una informazione tra virgolette importante

la lunghezza dei NOMI delle variabili

ho pensato che se ti va con un solo flussometro ma con due no, la cosa potrebbe essere indotta da una certa confusione sulle variabili

sono ragionevolmente sicuro che attualmente in C le variabili vengono riconosciute dai PRIMI 63 caratteri
ma lo standard è stato rimaneggiato varie volte, non vorrei che lo IDE di arduino, o il suo compilatore, si fermi a meno

è una prova semplice da fare, cambia nome alle variabili con nome lungo, e usa nomi, anche di fantasie, non più lunghi di 10 caratteri, esempio cont1 cont2 flux1 flux2

ci metti pochi minuti, e ci togliamo il dubbio

Interessante osservazione, tra l'altro valida per chiunque, non solo nel caso in esame.
Sarebbe da approfondire in un thread separato.

Unico vero approfondimento: se lo OP fa la prova sappiamo.....

io per me non uso nomi lunghi, troppo rischio di sbagliare a scriverli

docsavage:
Io non ho trovato sul reference una informazione tra virgolette importante
la lunghezza dei NOMI delle variabili

E non la troverai perché è una cosa che riguarda il livello del compilatore, l'attuale toolchain è C99 compliant, anzi dovrebbe essere C11, pertanto vengono considerati i primi 63 caratteri del nome di una variabile, quelli ulteriori vengono ignorati, se la variabile è external vengono considerati solo i primi 31 caratteri.
In tutti i casi se hai due variabili con lo stesso nome, ovviamente globali o locali nella stessa funzione, il compilatore si ferma e segnala l'errore.

E allora ho finito le idee..

speedyant:
Interessante osservazione, tra l'altro valida per chiunque, non solo nel caso in esame.
Sarebbe da approfondire in un thread separato.

ORSO2001:
interessante la teoria della lunghezza delle variabili...sicuramente da approffondire.

per quanto riguarda l'esempio:

#define pinISR 18

volatile float litresMin;
volatile unsigned long myMillis;
volatile boolean firstTime;

void setup() {
  Serial.begin(9600);
  pinMode(pinISR, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(pinISR), litres, FALLING);
  firstTime = false;
}

void loop() {

}

void litres() { // questa è una ISR
  if (!firstTime) {
    myMillis = millis();
    firstTime = true;
  }
  else {
    litresMin = (60000.00 / (millis() - myMillis)) / 7.5;
    myMillis = millis();
    Serial.println(litresMin);
  }
}



come vedi tutto viene fatto nella funzione litres(); c'è una flag di primo impulso; la funzione modifica la variabile float litresMin, così hai qualche decimale, calcolando il tempo tra due impulsi...ovviamente essendo un calcolo sulle float devi gestire gli eventuali risultati NaN (not a number) ed inf (infinito)...che si possono generare.

Buongiorno :slight_smile:
grazie mille per l'esempio ,e soprattutto grazie per la spiegazione

provvedo subito a fare delle prove ed ha vedere se funziona
ps:eri guardandomi diversi esempi sono arrivato a scrivere questo

    attachInterrupt(0, incrementaContatoreFlussometroFreddo, CHANGE);
    attachInterrupt(1,incrementaContatoreFlussometroCaldo, CHANGE);

se devo dire la verità non lo fatto seguendo una logica ,ho guardato i vari esempi ed facevo delle prove ed ha funzionato :slight_smile:
faccio le prove poi scrivo i risultati
grazie ancora

docsavage:
Io non ho trovato sul reference una informazione tra virgolette importante

la lunghezza dei NOMI delle variabili

ho pensato che se ti va con un solo flussometro ma con due no, la cosa potrebbe essere indotta da una certa confusione sulle variabili

sono ragionevolmente sicuro che attualmente in C le variabili vengono riconosciute dai PRIMI 63 caratteri
ma lo standard è stato rimaneggiato varie volte, non vorrei che lo IDE di arduino, o il suo compilatore, si fermi a meno

è una prova semplice da fare, cambia nome alle variabili con nome lungo, e usa nomi, anche di fantasie, non più lunghi di 10 caratteri, esempio cont1 cont2 flux1 flux2

ci metti pochi minuti, e ci togliamo il dubbio

anche per me vale la stessa cosa di "docsavage" usando nomi troppo lunghi rischio poi di perdermeli durante la scrittura del programma (soprattutto se il programma e molto lungo )
comunque faro delle prove per vedere se cambia qualcosa
cosi almeno ci togliamo il dubbio

grazie :slight_smile:

Mah...

Anche se non è la causa, continuare ad allungare i nomi aumenta certamente la difficoltà di lettura

Poi mettere lo interrupt a change raddoppia le letture rispetto ad esempio a falling

Invece per astro:
Posso essere d'accordo Che sia cosa che riguarda il compilatore.....
Ma da qualche parte dovrà Pure essere scritto....

Ed it : ci siamonincrociati