Go Down

Topic: Interrupt e blocco CPU (Read 1 time) previous topic - next topic

zikako74

Jun 07, 2013, 11:14 pm Last Edit: Jun 08, 2013, 12:04 am by leo72 Reason: 1
Ho realizzato un semplice circuito con un ATMEGA328 ma senza quarzo a 8MHz (premetto che i fuse sono correttamente settati per quella frequenza) , sostanzialmente alla partenza introduce un ritardo all'attivazione di una uscita e fa lampeggiare con un effetto di fading un led, dopodichè viene abilitato l'interrupt sulla porta 0 (pin2) e serve ad attivare due uscite ogni qual volta il medesimo viene portato allo stato LOW ed ha una isteresi per evitare rimbalzi (debounce) di circa 500ms.
Fin qui tutto bene ma ho notato che se attivo l'ingresso anche diverse volte il circuito funziona regolarmente ma se attivo l'ingresso e mi porta la variabile volatile "state" in HIGH e lascio le due uscite attive per circa un'ora se vado a riattivare l'ingresso per far portare le uscite allo stato opposto il circuito non risponde, quindi deduco che il processore si blocca.
Onestamente non sono riuscito a capire il perchè, qualcuno ha qualche idea a riguardo ?

Di seguito il codice:

Code: [Select]
int I0 = 2; //INPUT INTERRUPT 0
int kext = 8; //ext relay
int ledPin = 9; //out2
int k1 = 7; //k1 relay
int ledboost = 10; //out3
volatile int state = LOW;
long debouncing_time = 500; //Debouncing Time in Milliseconds
volatile unsigned long last_micros;

void setup()
{
 pinMode(I0, INPUT);
 pinMode(kext, OUTPUT);
 pinMode(k1, OUTPUT);
 pinMode(ledPin, OUTPUT);
 pinMode(ledboost, OUTPUT);
 //digitalWrite(kext, LOW);
 preheat();
 delay(10);
 digitalWrite(ledPin, HIGH);
 digitalWrite(kext, HIGH);

 delay(500);
 attachInterrupt(0, boostover, LOW);
}

void loop()
{
 //digitalWrite(pin, state);
 digitalWrite(k1, state);
 digitalWrite(ledboost, state);
}

void boostover()
{
  if((long)(micros() - last_micros) >= debouncing_time * 1000) {
   state = !state;
  last_micros = micros();
  }
}

void preheat()
{
 for(int fadeCnt = 0 ; fadeCnt <= 46 ; fadeCnt ++) {
 for(int fadeValue = 0 ; fadeValue <= 255; fadeValue ++) {
   // sets the value (range from 0 to 255):
   analogWrite(ledPin, fadeValue);        
   // wait for 30 milliseconds to see the dimming effect    
   delay( 8 );                            
 }

 // fade out from max to min in increments of 5 points:
 for(int fadeValue = 255 ; fadeValue >= 0; fadeValue --) {
   // sets the value (range from 0 to 255):
   analogWrite(ledPin, fadeValue);        
   // wait for 30 milliseconds to see the dimming effect    
   delay( 8 );                            
 }
  }
}


edit by mod: per favore includere il codice usando gli appositi tag

lestofante

#1
Jun 07, 2013, 11:55 pm Last Edit: Jun 08, 2013, 12:06 am by leo72 Reason: 1
metti il codice tra i tag [ code ]

cmq il problema è che dopo un pò la micros() (circa 5 minuti se ricordo bene) va in overflow.
Prima di tutto puoi usare la millis() (overflow dopo 45 gg) e poi se tu NON avessi castato lasottrazione da unsigned long a long, casualmente avresti azzeccato "l'anti oveflow", ovvero il modo per evitare l'overflow in modo del tutto trasparente:

codice ora
Code: [Select]

[...]
long debouncing_time = 500; //Debouncing Time in Milliseconds
[...]
if((long)(micros() - last_micros) >= debouncing_time * 1000) {
[...]


codice anti-overflow
Code: [Select]
[...]
unsigned long debouncing_time = 500; //Debouncing Time in Milliseconds
[...]
if(micros() - last_micros >= debouncing_time * 1000) {
[...]


x maggiori info vedi http://www.leonardomiliani.com/2012/come-gestire-loverflow-di-millis/ (in particolare ti ho suggerito la Soluzione 2)
Guida per principianti http://playground.arduino.cc/Italiano/newbie
Unoffical Telegram group https://t.me/genuino

uwefed

Code: [Select]
if((long)(micros() - last_micros) >= debouncing_time * 1000) {

cosa significa il (long) nel if?
Ciao Uwe

leo72

Trasforma il dato in un tipo signed per cui risente del segno diventando negativo se è maggiore di 2147483647.
Il motivo è spiegato nell'articolo che ho scritto e che ha linkato lesto.

zikako74

Ok, adesso è tutto chiaro... in effetti micros() va in overflow dopo 70 minuti quindi è perfettamente allineato con il problema che ho riscontrato dopo circa un ora che guarda caso è di 60 minuti, aggiungine altri 10 e siamo lì.

Grazie..... cmq il circuito è montato su uno stompbox valvolare :-)

uwefed


Trasforma il dato in un tipo signed per cui risente del segno diventando negativo se è maggiore di 2147483647.
Il motivo è spiegato nell'articolo che ho scritto e che ha linkato lesto.

Ma se le variabili usate sono unsigned long ha senso questa trasformazione?
Ciao Uwe

lestofante

dipende da cosa devi fare, leo usa il trucco della trasformazione per aggirare l'overflow, io lo faccio senza con il codice di prima
Guida per principianti http://playground.arduino.cc/Italiano/newbie
Unoffical Telegram group https://t.me/genuino

Go Up