Pages: [1] 2   Go Down
Author Topic: Interrupt, questo sconosciuto!!!  (Read 1085 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 14
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Buongiorno a tutto il forum,
sto sperimentando con arduino uno rev.3
In particolare mi interessa utilizzare gli interrupt che su arduino uno, come tutti saprete, sono disponibili sui pin digitali 2 e 3 (int0 e int1).

Ho messo su un circuito molto semplice, due pulsanti che abilitano ciascuno i 5v sui pin 2 e 3 (con resistenza di pull-down da 10k) ed un led sul pin 8.
Di seguito lo sketch:


Code:
//#################################################################
int ledpin = 8;
volatile int state = LOW;
int oldstate=LOW;
volatile int con = 0;
volatile int coff = 0;
void setup()
{
  pinMode(ledpin , OUTPUT);

  digitalWrite(ledpin , state);

  attachInterrupt(0, blinkon, RISING);
  attachInterrupt(1, blinkoff, RISING);

  Serial.begin(9600);
  Serial.println("Chronos Started...>");
}

void loop()
{

  if (oldstate!=state)
  {
    Serial.print("cambio stato -> ");
    Serial.print(state);
    Serial.print(" - ");
    Serial.print(con);
    Serial.print(",");
    Serial.println(coff);

    oldstate=state;
    digitalWrite(ledpin , state);
  }
  
 
}

//INT 0 led on
void blinkon()
{
  state = HIGH;
  con=con+1;
}

//INT 1 led off
void blinkoff()
{
  state = LOW;
  coff=coff+1;
}
//#################################################################

Come vedete è molto semplice.
La routine blinkon() sull'interrupt 0 intercetta il fronte di salita (RISING) e setta HIGH la variabile di stato.
La routine blinkoff() sull'interrupt 1 fa lo stesso e setta LOW lo stato della variabile che determina l'accensione e lo spegnimento del led.
Nel loop il led viene acceso o spento a seconda della variabile di stato.
Purtroppo, la pressione del pulsante collegato al pin 2 (int0), causa non solo il rilascio dell'interrupt 0 ma anche il rilascio dell'interrup 1.
Inizialmente non avevo messo l'output sulla seriale e non capivo perchè il led avesse un comportamento quasi casuale alla pressione di uno dei due tasti.
Di fatto, alla prima pressione del tasto sul pin 2, anche la variabile coff viene incrementata!!!!

Sapete dirmi dove sbaglio ???
grazie

edit by mod: per favore includi il codice usando gli appositi tag
« Last Edit: May 10, 2013, 02:17:06 am by xmas69 » 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

Stai usando i pin dell'interrupt sia per input che per output?

PS:
non l'ho provato ma il tuo codice non può compilare: in setup() hai messo un digitalWrite su "pin" ma "pin" non l'hai dichiarato.
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 14
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

scusa hai ragione,
è che ho fatto copia e incolla del codice e per renderlo più leggibile ho cambiato il nome della variabile in ledpin dimenticandomene una ;-)

in tutti gli esempi che ho trovato, quando viene utilizzata la funzione attachinterrupt(), non viene mai dichiarato se il pin è in input o in output e quindi non l'ho fatto nemmeno io.
sostanzialmente coumunque i due pin (2-3) sono esclusivamente in input!
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

Scusa, la domanda era nata leggendo questo passaggio:
Ho messo su un circuito molto semplice, due pulsanti che abilitano ciascuno i 5v sui pin 2 e 3 (con resistenza di pull-down da 10k)
Ho capito male  smiley-wink

Io ho provato questo codice:
Code:
//#################################################################
const byte ledpin = 13;
volatile byte state = LOW;
byte oldstate=LOW;
volatile int con = 0;
volatile int coff = 0;
void setup()
{
  pinMode(ledpin , OUTPUT);
    pinMode(2, INPUT_PULLUP);
    pinMode(3, INPUT_PULLUP);
  digitalWrite(ledpin, state);

  attachInterrupt(0, blinkon, FALLING);
  attachInterrupt(1, blinkoff, FALLING);

  Serial.begin(19200);
  Serial.println("Chronos Started...>");
}

void loop()
{

  if (oldstate!=state)
  {
    Serial.print("cambio stato -> ");
    Serial.print(state);
    Serial.print(" - ");
    Serial.print(con);
    Serial.print(",");
    Serial.println(coff);

    oldstate=state;
    digitalWrite(ledpin , state);
  }
 
 
}

//INT 0 led on
void blinkon()
{
  state = HIGH;
  con=con+1;
}

//INT 1 led off
void blinkoff()
{
  state = LOW;
  coff=coff+1;
}
//#################################################################
Siccome non avevo breadboard libere, ho usato un ponticello con un filo e per questo ho invertito la logica dell'interrupt per poter usare le pull-up interne dei pin 2 e 3.
A parte i notevoli rimbalzi che si leggono (come vedi, con un semplice pulsantino o ponticello l'interrupt legge decine di pressioni), il led a me non si comporta in modo strano.
Sei sicuro di non avere problemi di contatti sulla board di test?
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 14
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

grazie per il test,
probabilmente si tratta di problemi di DEBOUNCE.
Ho visto che hai aggiunto queste due istruzioni:
    pinMode(2, INPUT_PULLUP);
    pinMode(3, INPUT_PULLUP);
servono veramente?

Vorrei riprodurre in qualche modo la situazione per cui mi serve questo progetto.
In realtà ai pin 2 e 3, quando sarà tutto pronto, dovrò collegare due fotocellule a catarifrangente per rilevare il passaggio su una porta.
Come potrai immaginare il passaggio, e quindi l'interruzione del fascio della fotocellula, potrà essere nell'ordine dei decimi di secondo.

Come posso riprodurre questa situazione senza utilizzare i pulsanti che causano questi problemi di debounce???
Logged

Disperso nel nauseante oceano della burocrazia
Offline Offline
Edison Member
*
Karma: 74
Posts: 2459
Io sono l'ultimo,
e parlero' al vuoto
in ascolto.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Per il software non lo so, ma a livello hardware i rimbalzi li elimini piuttosto facilmente (a meno che non usi pulsanti residuo della seconda guerra punica smiley-wink smiley-grin) ... usi resistenze di pulldown da 10K, quindi quelle ci sono gia, mettici in parallelo due condensatori da 220nf o 330nF ceramici, e due resistenze da 100 ohm in serie al pulsante (uno per ogni ingresso ovviamente) ... non ti elimina TUTTO, ma almeno il 90% dei rimbalzi dovrebbe sparire gia cosi, senza diventare matti con routine di debounce smiley-wink

EDIT: se invece vuoi simulare le uscite delle fotocellule ad impulso, usa un normale 4093 o 40106, un paio di porte configurate a monostabile con la temporizzazione uguale a quella che ci si aspetta dalle fotocellule ti fanno il tuo simulatore a spesa quasi zero smiley-grin
« Last Edit: May 10, 2013, 02:48:20 am by Etemenanki » Logged

"Sopravvivere" e' attualmente l'unico lusso che la maggior parte dei Cittadini italiani,
sia pure a costo di enormi sacrifici, riesce ancora a permettersi.

Offline Offline
Newbie
*
Karma: 0
Posts: 14
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Grazie mille  !!!!!
mi metto subito a lavoro   smiley
Logged

Cagliari, Italy
Offline Offline
Tesla Member
***
Karma: 103
Posts: 6588
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ho trovato questo schemino


Qui c'è:
1 pull-up da 10K (si può evitare attivando la pull-up interna di Arduino)
1 condensatore in parallelo da 100nF
1 resistenza in serie da 470 ohm.

Sono valori diversi da quelli da te menzionati; possono andare bene ugualmente?
« Last Edit: May 10, 2013, 03:28:31 am by PaoloP » Logged

Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

Disperso nel nauseante oceano della burocrazia
Offline Offline
Edison Member
*
Karma: 74
Posts: 2459
Io sono l'ultimo,
e parlero' al vuoto
in ascolto.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I valori non sono critici, e ci si puo giocare in un'intervallo abbastanza ampio ... cambia solo una cosa, piu e' alto il valore del condensatore (e delle resistenze), piu toglie i disturbi, ma allo stesso tempo abbassa il tempo di risposta ... se ad esempio ci metti 1uF o piu, toglie ancora piu disturbi, ma potrebbe non leggerti pressioni ripetute molto ravvicinate e veloci ... di solito si gioca con quei valori in base all'utilizzo che ne vuoi fare.

A proposito, e' un pull-up. mi sembra di capire che lui ha usato un pull-down (ma il discorso di base non cambia, e' lo stesso principio smiley )
Logged

"Sopravvivere" e' attualmente l'unico lusso che la maggior parte dei Cittadini italiani,
sia pure a costo di enormi sacrifici, riesce ancora a permettersi.

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

@paolop
ma in quello schema r1 e c1 non sono in parallelo al pulsante
recentemente ho affrontato il problema con questa soluzione scritta in un altro linguaggio ma credo si possa intuire, se hai problemi dimmi che lo traduco

Code:
'funzione interrupt
GETINT0: 'sul pin 20
statosensore=1 'stato del sensore
If statosensore=1 Then 'sezione per i falsi allarmi
Debug Cr,"cambiamento dello stato falso allarme", Cr
Delay 80 'intervallo regolabile
If In(20)=0 Then
statosensore=1 'segnale valido
Else
statosensore=0
Endif
Endif

stefano
Logged


Cagliari, Italy
Offline Offline
Tesla Member
***
Karma: 103
Posts: 6588
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Mettere un delay dentro un'interrupt è un nonsenso. E come se mettessi una persona di guarda ma gli dici di dormire.
La R1 è la resistenza di pull-up. La R2 è in serie mentre C1 risulta in parallelo col pulsante.
Logged

Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

Offline Offline
Edison Member
*
Karma: 38
Posts: 1900
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Gli interrupt non sono solo disponibili ai piedini 2 e 3, ma qualsiasi piedino di ingresso può essere configurato come interrupt.

Per farlo è necessario infilare dentro l' IDE Arduino, un po' di codice C puro, ma niente di trascendentale. Questi ulteriori Interrupt funzionano solo con un Change di stato, per cui va abbinato un digitalWrite per vedere se il Change è andato in LOW o in HIGH.

Inoltre il delay dentro un interrupt funziona benissimo. L'ho usato per una prova rapida con il proposito di sostituirlo con un Timer Hardware configurato in C puro, ma funziona tanto bene, e senza jitter, che l'ho lasciato.

Per la cronaca, oscilloscopio digitale alla mano, usando la funzione Trigger per analizzare i fronti in ingresso-uscita di un delay, con 320mSec di ritardo di codice, in uscita avevo un fronte ESATTAMENTE a 320,00 mSec di ritardo, quindi precisione assoluta fino ai decimi di nanoSec.
Logged

Disperso nel nauseante oceano della burocrazia
Offline Offline
Edison Member
*
Karma: 74
Posts: 2459
Io sono l'ultimo,
e parlero' al vuoto
in ascolto.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

...
ma in quello schema r1 e c1 non sono in parallelo al pulsante
...

Non sono in parallelo perche' quello e' un'ingresso pull-up con chiusura a massa, ed R1 e' la resistenza di pull-up, appunto ... rimangono invece in parallelo quando usi un ingresso in pull-down con chiusura al positivo, ed R1 diventa la resistenza di pull-down, che va a massa e quindi rimane in parallelo al condensatore.
Logged

"Sopravvivere" e' attualmente l'unico lusso che la maggior parte dei Cittadini italiani,
sia pure a costo di enormi sacrifici, riesce ancora a permettersi.

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

Inoltre il delay dentro un interrupt funziona benissimo. L'ho usato per una prova rapida con il proposito di sostituirlo con un Timer Hardware configurato in C puro, ma funziona tanto bene, e senza jitter, che l'ho lasciato.

Per la cronaca, oscilloscopio digitale alla mano, usando la funzione Trigger per analizzare i fronti in ingresso-uscita di un delay, con 320mSec di ritardo di codice, in uscita avevo un fronte ESATTAMENTE a 320,00 mSec di ritardo, quindi precisione assoluta fino ai decimi di nanoSec.
Se hai messo un ritardo di 320 ms in un interrupt hai fatto l'ultima delle cose che si deve fare con un interrupt, ossia renderlo luuuungo  smiley-wink
Un interrupt deve essere il più breve possibile, se hai bisogno di un delay in un interrupt allora non ti serve un interrupt  smiley-razz
Logged


Offline Offline
Edison Member
*
Karma: 38
Posts: 1900
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Eh, lo so che è una porcata (un Informatico userebbe il termine "deprecato"), però avevo già esaurito gli interrupt quelli boni (che cmq rimangono a più alta priorità) e quindi ho dovuto usare una porta con la funzione Hardware PCINTx. Il problema più grosso è che quando setti il registro con la maschera degli Interrupt, non puoi agire su una singola porta, ma vai ad agire su tutta la sezione (es. tutto il PortB) della MCU, e poi è un interrupt farlocco, mezzo mascherabile e che funziona solo su CHANGE.

Però alla fine ha funzionato, perchè mentre agisce quel ritardo, non funziona niente di particolare.

Logged

Pages: [1] 2   Go Up
Jump to: