Pages: [1] 2 3 ... 6   Go Down
Author Topic: chiarimenti sugli interrupt  (Read 3358 times)
0 Members and 1 Guest are viewing this topic.
Camisano Vicentino (VI), Italy
Offline Offline
God Member
*****
Karma: 4
Posts: 952
ƎR like no other.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

ieri mi chiedevo come funzionassero gli interrupt, perchè forse dovrebbero avermelo insegnato a scuola... e quindi ho letto queste 2 pagine sul reference:
http://arduino.cc/en/Reference/Interrupts
http://arduino.cc/en/Reference/AttachInterrupt
ma mi restano ancora dei dubbi, cosa sono fisicamente? cosa hanno di così diverso dal fare un if(digitalRead(X)){...} ? perchè dicono che solo alcuni pin possono essere utilizzati per fare ciò? che differenza c'è tra le 2 funzioni AttachInterrupt e Interrupts?  potete spiegarmi un po'?
grazie mille in anticipo! smiley-wink
Logged

Riccardo Ertolupi of the Vicenza Thunders Team: http://www.VicenzaThunders.com

Deep south of Italy
Offline Offline
Faraday Member
**
Karma: 7
Posts: 2961
The quieter you become, the more you can hear
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

sostanzialmente il digitalread devi farlo tu ogni volta per vedere se è cambiato qualcosa, l'interrupt ti avvisa lui smiley
Logged

Camisano Vicentino (VI), Italy
Offline Offline
God Member
*****
Karma: 4
Posts: 952
ƎR like no other.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

ah ok quindi è più veloce del digitalRead, no?
posso usare qualsiasi pin per fare questo lavoro? cosa significa questa frase "Most Arduino boards have two external interrupts: numbers 0 (on digital pin 2) and 1 (on digital pin 3). The Arduino Mega has an additional four: numbers 2 (pin 21), 3 (pin 20), 4 (pin 19), and 5 (pin 18)." ? che differenza c'è tra le 2 funzioni AttachInterrupt e Interrupts?
grazie ancora!
Logged

Riccardo Ertolupi of the Vicenza Thunders Team: http://www.VicenzaThunders.com

Offline Offline
Jr. Member
**
Karma: 0
Posts: 86
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Gli interrupt sono delle routine (funzioni) che vengono eseguite quando c'e' l'evento associato, indipendentemente dal punto in cui il main "scorre".
In alcuni casi pero' si puo' richiedere che un blocco del codice del main non si debba interrompare a causa di un interrupt, per fare cio' prima del blocco ci metti un detachInterrupt. Quando ad esempio il blocco critico e' finito e vuoi riabilitare gli interrupt ci metti un interrupts().
Abbiamo detto che se c'e' un interrup viene eseguita una funzione il "gestore dell'interrupt" con attachInterrupt(interrupt, function, mode)associ l'interrupt alla sua funzione "gestore dell'interrup".
Logged

Camisano Vicentino (VI), Italy
Offline Offline
God Member
*****
Karma: 4
Posts: 952
ƎR like no other.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

ok grazie capito smiley e la storia dei pin? sono tutti disponibili per fare ciò?
Logged

Riccardo Ertolupi of the Vicenza Thunders Team: http://www.VicenzaThunders.com

0
Offline Offline
Faraday Member
**
Karma: 39
Posts: 5608
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

di default si possono usare solo i pin che tu stesso hai riposrato, quindi su arduinoUNO solo due pin.

pero' c'e' una libreria che ti permette di usarli su tutti (vado a memoria, per ora non l'ho mai usati)
Logged

- [GUIDA] IDE1.x - Nuove Funzioni - Sketch Standalone - Bootloader - VirtualBoard
http://arduino.cc/forum/index.php/topic,88546.0.html
- [LIBRERIA] ST7032i LCD I2C Controller Library
http://arduino.cc/forum/index.php/topic,96163.0.html

0
Offline Offline
Shannon Member
****
Karma: 117
Posts: 10106
:(){:|:&};: TOX id: fcb8e918bef08581e23f6ddf9d4dba77697c25b217bf372736ed959a95fde36df5b8c5b90fbb
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

allora, arduino mette a disposizione 2 pin, che hanno interrup CHANGE, LOW, FALLING, RISING ovvero in cambio stato, quando basso, solo quando il segnale "cade" da 1 a 0, solo quando il segnale "sale" da 0 a 1.

in realtà tutti i pin sono attivabili come CHANGE impostando un paio di registri. In pratica i PIN sono raggrupptai in gruppi da 8, e ogni gruppo ha il controllore di interrupt CHANGE:
a questo punto se confronti lo stato degli 8 pin con quello dell'ultimo interrupt, ti accorgi di quali pin sono cambiati e intraprendi le azioni specifiche.

se cerchi sul forum c'è del codice, molto tempo fa ho messo il codice per leggere 6 canali PPM con gli interrupt, che in pratica non è altro che contare quanto tempo rimane HIGH un pin :-)
Logged

my Arduino code: https://github.com/lestofante/arduinoSketch
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

BZ (I)
Offline Offline
Brattain Member
*****
Karma: 235
Posts: 20221
+39 349 2158303
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Gli interrupt possono essere fatti partire da molti avvenimenti; esterni (pin 2 e 3) o interni tipo contatori timer ecc.

La diffrenuza tra interrupt e pull é il seguente:

Con la tecnica pull devi guardare regolarmente se un evento si é verificato ( quardi ogni minuto se i spagetti sono pronti e percui devi essere presente e non puoi fare altre cose). Con un interrupt viene interrotto il programma principale e eseguito il codice Interrupt ( metti la sveglai e quando suona gli spaghetti son pronti. nel fratempo puoi apparecchiare la tavola, andare in cantina a prendere la birra, leggere il nostro Forum ecc.)

Ciao Uwe
Logged

0
Offline Offline
Faraday Member
**
Karma: 39
Posts: 5608
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

lesto quindi se ho capito il LOW, FALLING, RISING non si puo' fare su tutti ?
Logged

- [GUIDA] IDE1.x - Nuove Funzioni - Sketch Standalone - Bootloader - VirtualBoard
http://arduino.cc/forum/index.php/topic,88546.0.html
- [LIBRERIA] ST7032i LCD I2C Controller Library
http://arduino.cc/forum/index.php/topic,96163.0.html

0
Offline Offline
Shannon Member
****
Karma: 117
Posts: 10106
:(){:|:&};: TOX id: fcb8e918bef08581e23f6ddf9d4dba77697c25b217bf372736ed959a95fde36df5b8c5b90fbb
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

bhe, puoi ricavarlo via software :-)
Logged

my Arduino code: https://github.com/lestofante/arduinoSketch
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Deep south of Italy
Offline Offline
Faraday Member
**
Karma: 7
Posts: 2961
The quieter you become, the more you can hear
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

l'unico interrupt ottenibile su tutti i pin è il pinchange interrupt, credo che ci sia una libreria apposita che si chiama pcint o qualcosa di simile.
Logged

piacenza
Offline Offline
God Member
*****
Karma: 0
Posts: 589
prima della pazzia c'è la passione
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ciao
tempo fa avevo scritto questo ma non lo ho mai provato
Code:
// versione con 3 shiftout 74hc595

// PinChangeIntExample, version 1.2 Fri Feb  3 19:41:08 CST 2012
// See the Wiki at http://code.google.com/p/arduino-pinchangeint/wiki for more information.
//-------- define these in your sketch, if applicable ----------------------------------------------------------
// You can reduce the memory footprint of this handler by declaring that there will be no pin change interrupts
// on any one or two of the three ports.  If only a single port remains, the handler will be declared inline
// reducing the size and latency of the handler.
#define NO_PORTB_PINCHANGES // to indicate that port B will not be used for pin change interrupts
#define NO_PORTC_PINCHANGES // to indicate that port C will not be used for pin change interrupts
// #define NO_PORTD_PINCHANGES // to indicate that port d will not be used for pin change interrupts
// You can reduce the code size by 20-50 bytes, and you can speed up the interrupt routine
// slightly by declaring that you don't care if the static variables PCintPort::pinState and/or
// PCintPort::arduinoPin are set and made available to your interrupt routine.
// #define NO_PIN_STATE        // to indicate that you don't need the pinState
// #define NO_PIN_NUMBER       // to indicate that you don't need the arduinoPin
// if there is only one PCInt vector in use the code can be inlined
// reducing latency and code size
// define DISABLE_PCINT_MULTI_SERVICE below to limit the handler to servicing a single interrupt per invocation.
// #define       DISABLE_PCINT_MULTI_SERVICE
//-------- define the above in your sketch, if applicable ------------------------------------------------------
#include <PinChangeInt.h>

// This example demonstrates a configuration of 3 interrupting pins and 2 interrupt functions.
// All interrupts are serviced immediately, but one of the pins (pin 4) will show you immediately
// on the Terminal.  The other function connected to 2 pins sets an array member that is queried in loop().
// You can then query the array at your leisure.
// This makes loop timing non-critical.

// Add more Pins at your leisure.
// For the Analog Input pins used as digital input pins, and you can use 14, 15, 16, etc.
// or you can use A0, A1, A2, etc. (the Arduino code comes with #define's
// for the Analog Input pins and will properly recognize e.g., pinMode(A0, INPUT);
#define PIN1 2
#define PIN2 3
#define PIN3 4
#define PIN4 5
#define PIN5 6
#define PIN6 7


int statosensore1=HIGH;
int statosensore2=HIGH;
int statosensore3=HIGH;
int statosensore4=HIGH;
int statosensore5=HIGH;
int statosensore6=HIGH;

int i=0;
int j=0;
int count[6]={0,0,0,0,0,0};
float freq[6]={0,0,0,0,0,0};
//float freq1=0;
unsigned long tempo[10]={0,0,0,0,0,0,0,0,0,0};

//shiftout
int latchPinOUT = 10;//ST_CP di 74HC595 pin 12
int clockPinOUT =9;//SH_CP di 74HC595 pin 11
int dataPinOUT = 8;//DS di 74HC595  pin 14
byte ledRossiH = B00000000; 
byte ledVerdi = B00000000;
byte ledRossiL = B00000000;

void setup()
{
    pinMode(PIN1, INPUT); digitalWrite(PIN1, HIGH);  // add more attachInterrupt code as required
  PCintPort::attachInterrupt(PIN1, sensore1, FALLING); 
    pinMode(PIN2, INPUT); digitalWrite(PIN2, HIGH);  // add more attachInterrupt code as required
  PCintPort::attachInterrupt(PIN2, sensore1, FALLING);
    pinMode(PIN3, INPUT); digitalWrite(PIN3, HIGH);  // add more attachInterrupt code as required
  PCintPort::attachInterrupt(PIN3, sensore1, FALLING);
    pinMode(PIN4, INPUT); digitalWrite(PIN4, HIGH);  // add more attachInterrupt code as required
  PCintPort::attachInterrupt(PIN4, sensore1, FALLING);
    pinMode(PIN5, INPUT); digitalWrite(PIN5, HIGH);  // add more attachInterrupt code as required
  PCintPort::attachInterrupt(PIN5, sensore1, FALLING);
    pinMode(PIN6, INPUT); digitalWrite(PIN6, HIGH);  // add more attachInterrupt code as required
  PCintPort::attachInterrupt(PIN6, sensore1, FALLING);
 
  Serial.begin(9600);
 
    //shiftout
  pinMode(latchPinOUT, OUTPUT);
  pinMode(clockPinOUT, OUTPUT);
  pinMode(dataPinOUT, OUTPUT);
 }

void loop()
{
  if (statosensore1==LOW)       // sensore 1
{
  count[0]++;
//   Serial.println(count[0]);
  //  Serial.println(i);
  tempo[i]=millis(); i++;
    //   Serial.println(tempo[0]);
      //   Serial.println(tempo[9]);
   if(i==10)
  {
    freq[0]=count[0]*1000/(tempo[9]-tempo[0]);
   i=0;
   count[0]=0;
     // Serial.println(freq[0]);
   }
  statosensore1=HIGH;
}
 if (statosensore2==LOW)        // sensore 2
{
  count[1]++;
    tempo[i]=millis(); i++;
 if(i==10)
  {
    freq[1]=count[1]*1000/(tempo[9]-tempo[0]);
   i=0;
   count[1]=0;
   }
  statosensore1=HIGH;
}
 if (statosensore3==LOW)        // sensore 3
{
  count[2]++;
    tempo[i]=millis(); i++;
 if(i==10)
  {
    freq[2]=count[2]*1000/(tempo[9]-tempo[0]);
   i=0;
   count[2]=0;
   }
  statosensore1=HIGH;
}
 if (statosensore4==LOW)        // sensore 4
{
  count[3]++;
    tempo[i]=millis(); i++;
 if(i==10)
  {
    freq[3]=count[3]*1000/(tempo[9]-tempo[0]);
   i=0;
   count[3]=0;
   }
  statosensore1=HIGH;
}
 if (statosensore5==LOW)        // sensore 5
{
  count[4]++;
    tempo[i]=millis(); i++;
 if(i==10)
  {
    freq[4]=count[4]*1000/(tempo[9]-tempo[0]);
   i=0;
   count[4]=0;
   }
  statosensore1=HIGH;
}
 if (statosensore6==LOW)        // sensore 6
{
  count[5]++;
    tempo[i]=millis(); i++;
 if(i==10)
  {
    freq[5]=count[5]*1000/(tempo[9]-tempo[0]);
   i=0;
   count[5]=0;
   }
  statosensore1=HIGH;
}


for(j=0;j<=5;j++)
{
 //Serial.println(j);
 Serial.println(freq[0]);
 
if(freq[j]>10 && freq[j]<15)
{
  Serial.println("ok");
     bitWrite(ledRossiH,j,0);
   bitWrite(ledVerdi,j,1);
     bitWrite(ledRossiL,j,0);
}
else

  Serial.println("ko");
   bitWrite(ledRossiH,j,1);
   bitWrite(ledVerdi,j,0);
     bitWrite(ledRossiL,j,1);
}
     digitalWrite(latchPinOUT,1);                       //Pull latch LOW to start sending data
      shiftOut(dataPinOUT, clockPinOUT, MSBFIRST, ledRossiL);    //Send the data byte rossi
      shiftOut(dataPinOUT, clockPinOUT, MSBFIRST, ledVerdi);    //Send the data byte verdi
      shiftOut(dataPinOUT, clockPinOUT, MSBFIRST, ledRossiH);    //Send the data byte rossi
     digitalWrite(latchPinOUT,0);                      //Pull latch HIGH to stop sending data

}

}

//---------------------------funzioni
void sensore1()
{
  statosensore1=LOW;
}
void sensore2()
{
  statosensore2=LOW;
}
void sensore3()
{
  statosensore3=LOW;
}
void sensore4()
{
  statosensore4=LOW;
}
void sensore5()
{
  statosensore5=LOW;
}
void sensore6()
{
  statosensore6=LOW;
}

* PinChangeInt.h (15.34 KB - downloaded 9 times.)
* keywords.txt (0.29 KB - downloaded 2 times.)
Logged


Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 313
Posts: 21624
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

lesto quindi se ho capito il LOW, FALLING, RISING non si puo' fare su tutti ?
Gli interrupt, trad. "interruzione", come ha detto Uwe sono sia interni che esterni. Parlando di pin, dobbiamo parlare di interrupt esterni. Questi sono di 2 tipi: INT e PCINT. Il primo tipo consta di 2 interrupt, INT0 e INT1, agganciati a 2 specifici pin, il pin D2 ed il pin D3. Ogni interrupt ha il suo registro. Il secondo tipo si compone di 24 interrupt, da PCINT0 a PCINT23, uno per ogni pin di I/O del micro. Questi ultimi sono gestiti cumulativamente da 3 interrupt, PCI0, PCI1 e PCI2, ognuno tramite un apposito registro, ogni registro controlla 8 pin (8 bit=8 pin=8 PCINT). Ogni interrupt può "sentire" il passaggio a LOW, il FALLING del segnale (da HIGH a LOW), il RISING (da LOW a HIGH) oppure qualunque altro cambiamento di stato (anche lo stato HIGH).
I PCINT sentono invece un qualsiasi cambio di stato sul pin.

Siccome gli interrupt INT0 e INT1 possono lavorare in modo asincrono, ossia senza l'utilizzo del clock di sistema, quando devono rilevare il segnale LOW, questi interrupt possono essere utilizzati anche durante il risparmio energetico con modalità di sleep più aggressive dell'IDLE, l'unica che tiene agganciato il clock di sistema ai pin, l'unica quindi che fa funzionare i PCINT.

La libreria è scaricabile da qui:
http://www.arduino.cc/playground/Main/PcInt

Logged


0
Offline Offline
Shannon Member
****
Karma: 117
Posts: 10106
:(){:|:&};: TOX id: fcb8e918bef08581e23f6ddf9d4dba77697c25b217bf372736ed959a95fde36df5b8c5b90fbb
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

stefa24 il tuo è un uso improprio degli interrupt, perchè misciato col metodo alternativo detto "polling", ovvero ciclare all'infinito per vedere i cambiamenti.

io tuo codice ha la stessa funzione del mio per leggere la durata di uno stato alto, ma è fortemente dipendente dalla durata del loop.

InputPin.cpp
Code:
#include "InputPin.h"

/*
Let You read digital pin 2,4,5,6,7
based on BIRONPILOTV59, tnx to ciskje
by Lesto
*/

#define MAXUNSIGNEDLONGCVALUE 4294967295
#define MASKPCINT0 (1<<2)
#define MASKPCINT1 (1<<4)
#define MASKPCINT2 (1<<5)
#define MASKPCINT3 (1<<6)

volatile byte _oldbit, _newbit, _changed;

InputPin::InputPin(){
  pinMode(2, INPUT); // 3 is used for esc
  pinMode(4, INPUT);
  pinMode(5, INPUT);
  pinMode(6, INPUT);
  // interrupt on pin change PCINT2
  PCICR |= (1 << PCIE2);

  PCMSK2 = (1 << PCINT18) | // pin2
  (1 << PCINT20) | // pin4
  (1 << PCINT21) | // pin5
  (1 << PCINT22); // pin6

  _oldbit = PIND;
}

//putted here because interrupt dosn't want it in .h
unsigned long _startIn[4];
volatile  unsigned long _rawIn[4];
unsigned long _time;

ISR(PCINT2_vect) {
  _time=micros();
  
  _newbit=PIND;
  _changed=_newbit^_oldbit;
  
  if (_changed&MASKPCINT0){

    if (_newbit&MASKPCINT0) {
      _startIn[0]=_time;
    }else{
      _rawIn[0]=_time-_startIn[0];
    }
  }

  if (_changed&MASKPCINT1)
    if (_newbit&MASKPCINT1)
      _startIn[1]=_time;
    else
      _rawIn[1]=_time-_startIn[1];

  if (_changed&MASKPCINT2)
    if (_newbit&MASKPCINT2)
      _startIn[2]=_time;
    else
      _rawIn[2]=_time-_startIn[2];

  if (_changed&MASKPCINT3)
    if (_newbit&MASKPCINT3)
      _startIn[3]=_time;
    else
      _rawIn[3]=_time-_startIn[3];
  _oldbit=_newbit;
//  blockedRX=0;
}

int InputPin::getDuration(int i){
 // Serial.print("ok:");
//  Serial.print(rawIn[i]);
  //      Serial.println(rawIn[0]);
      // Serial.print("okIND2:");
        //Serial.println(rawIn, BIN);
  return _rawIn[i];
}

InputPin.h
Code:
#ifndef InputPin_h
#define InputPin_h


#include "WProgram.h"

class InputPin{
  
  public:
    InputPin();
    int getDuration(int i);
    int x, y, z;
  private:
};
#endif

come puoi notare il calcolo della durata è eseguito all'interno dell'interrupt, e il tutto è completamente indipendente dal loop, soprattutto il calcolo della durata del segnale. In questo modo nel loop posso dedicarmi a calcoli che mi portano via anche giorni, senza per questo andare ad influenzare la lettura. certo perderei tutte le letture tranne l'ultima effettuata, ma col tuo metodo avresti una sola lettura di segnale alto con durata X giorni + qualcosa.

Tra l'altro si nota bene come funziona la storia degli interrupt a basso livello:
PARTE DI SETUP:
1. l'attivazione di uno dei 3 registri (che contiene 8 pin) PCIE2, in questo caso
2. l'attivazione dell'interrupt sul vero e proprio pin, attraverso un registo in cui ogni bit rappresenta un pin. in questo PCMSK2 viene attivato per i pin PCINT18, PCINT20, PCINT21, PCINT22
3. il salvataggio dello stato attuale dei pin che stiamo analizzando (o meglio, del gruppo di 8 che contiene quelli che ci interessano) (_oldbit = PIND;)
PARTE "ATTIVA":
1. un itnterrupt in arrivo chiama la funzione di interrupt corrispondente, in questo caso ISR(PCINT2_vect)
2. lettura stato attuale dei pin con _newbit=PIND;
3. troviamo i pin che son stati modificati: _changed=_newbit^_oldbit;
4. con un pò di logica a BIT estraiamo i pin cambiati(corrispettivo bit ad 1 in _changed), ed eventualmente anche il loro stato (da _newbit o PIND)
5. esecuzione del codice che vi interessa, e salvataggio delle info (in questo caso la durata del segnale alto) in un array/variabile "volatile"
6. salvataggio dell'attuale stato dei pin con _oldbit=_newbit;

ps. il codice, come potete leggere dai commenti è basato sul codice del bironpilot di ciskje, del forum baronerosso.it
Logged

my Arduino code: https://github.com/lestofante/arduinoSketch
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Camisano Vicentino (VI), Italy
Offline Offline
God Member
*****
Karma: 4
Posts: 952
ƎR like no other.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

scusate ma ho ancora dei dubbi, questi dubbi non riguardo a come gli interrupt funzionino ma come devo fare per usarli  smiley-red
allora io avevo bisogno di usare 4/5 pin di interrupt su un arduino mega2560, e possibile no?
in un'altra discussione mi era stato suggerito di usare la libreria PcInt per avere un maggior numero di pin di interrupt, la libreria dovrebbe essere questa:
http://arduino.cc/playground/Main/PinChangeInt
http://arduino.cc/playground/Main/PcInt
siccome ero in difficoltà Leo mi ha dato la sua libreria, ma quando vado a inserire la libreria dall'ide non scrive la riga include<...>, ho guardato un po' il codice della libreria e mi pare diverso da quella che c'è nel playground, sono molto confuso smiley-confuse spero che qualcuno qui possa aiutarmi a chiarirmi le idee  smiley-wink
grazie a tutti in anticipo! smiley-wink
Logged

Riccardo Ertolupi of the Vicenza Thunders Team: http://www.VicenzaThunders.com

Pages: [1] 2 3 ... 6   Go Up
Jump to: