Pages: [1]   Go Down
Author Topic: interrupt sul timer  (Read 2258 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Shannon Member
****
Karma: 136
Posts: 10526
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao
ho un'applicazione che sfrutta dei sensori (nunchuk) che però alle volte si impallano( okok, è che salta qualche cavetto ogni tanto :-), devo decidermi a imparare kikad e farmi sto benedetto PBC ), bloccando tutto lo scetch.
Dato che il mezzo gestito è un coso volante la cosa è problematica, volevo mettere un interrupt sul timer che venisse lanciato almeno una volta al secondo, che se rileva che il loop non gira spegne i motori.
Non voglio però andare a modificare prescaler o roba del genere, in modo da non incasinare il resto del codice (uso varie librerie e vorrei evitare di stare a spulciare i casini che possono nascere)

il codice di test (che non va) che ho scritto finora:
credo non funzioni perchè aspetto l'evento overflow del timer2 che avviene chissà ogni quanto... o no?
Code:
void setup(){
  Serial.begin(19200);
  TIMSK2 |= B00000100;
}
unsigned long time = micros();
void loop(){
}

ISR(TIMER2_OVF_vect) {
  Serial.println(micros()-time);
  time=micros();
};
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

0
Offline Offline
Faraday Member
**
Karma: 31
Posts: 2908
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao lesto credo che per abilitare l'interrupt devi usare il registro TCCR2B, guarda il datasheet perchè ricordo che i timer sono un pò diversi.

Questo codice è preso da il pid atmel:
Code:
// Set up timer, enable timer/counte 0 overflow interrupt
  TCCR0A = (1<<CS00);
  TIMSK0 = (1<<TOIE0);
  TCNT0 = 0;

e questa e la routine di interrupt:
Code:
/* Specify the desired PID sample time interval
 * With a 8-bit counter (255 cylces to overflow), the time interval value is calculated as follows:
 * TIME_INTERVAL = ( desired interval [sec] ) * ( frequency [Hz] ) / 255 */
#pragma vector = TIMER0_OVF_vect
__interrupt void TIMER0_OVF_ISR( void )
{
  static uint16_t i = 0;
  if(i < TIME_INTERVAL)
    i++;
  else{
    gFlags.pidTimer = TRUE;
    i = 0;
  }
}

Il watchdog dovrebbe servire proprio a questo, è un contatore che devi azzerare durante il programma prima che vada in overflow se ci và resetta e riparte da capo il programma, però credo che questo venga usato nel bootloader, purtroppo questa parte non l'ho ancora studiata.

Ciao.


Logged

AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

0
Offline Offline
Shannon Member
****
Karma: 136
Posts: 10526
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

giusto quello che mi serviva! +1  smiley-grin

per il watchdog ho dato un'occhiata ma pare non essere supportato dal bootloader, ma è supportato da quello adafruit
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

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

Ciao lesto, anche se credo che tu non ne abbia bisogno, ti dò un piccolo consiglio...
togli la sctittura sulla seriale dalla routine di interrupt e sostituiscila con una variabile che viene controllata appena il loop riprende smiley-wink così avrai una risposta più rapida del sw nell'eventualità di trigger ripetuti.
Logged

0
Offline Offline
Faraday Member
**
Karma: 31
Posts: 2908
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
giusto quello che mi serviva! +1  smiley-grin
Ok grazie.

Quote
per il watchdog ho dato un'occhiata ma pare non essere supportato dal bootloader, ma è supportato da quello adafruit
Qua bisogna vedere nel sorgente del bootloader perchè in quello dell'UNO c'è.
Eccolo:
Code:
void watchdogConfig(uint8_t x) {
  WDTCSR = _BV(WDCE) | _BV(WDE);
  WDTCSR = x;
}

Ora non so come funziona la cosa, forse puoi avviare il watchdog anche nello sketch c'è da vedere se non va in contrasto con il bootloader.

Quote
Ciao lesto, anche se credo che tu non ne abbia bisogno, ti dò un piccolo consiglio...
togli la sctittura sulla seriale dalla routine di interrupt e sostituiscila con una variabile che viene controllata appena il loop riprende smiley-wink così avrai una risposta più rapida del sw nell'eventualità di trigger ripetuti.

In effetti all'interno delle routine ISR, il global interrupt è disabilitato, quindi un'interrupt che si verifica quando si è all'interno di una ISR non ha esito, anche chimare una funzione che fà affidamento sugli interrupt non funziona e il motivo è ovvio.
C'è un metodo per modificare il comportamento degli interrupt e la trovi nella doc delle libc, ora non ricordo mi pare siano due macro o tre.
Alternativa è quella di usare __asm__ __volatile__ {your code....},  ad esempio li dentro puoi scivere in seriale direttamente nel registro della seriale, dovrebbe funzionare.

Il codice all'interno delle ISR dovrebbe essere il più a basso livello possibile o comunque deve entra ed uscire molto velocemente.

Ciao.
Logged

AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

0
Offline Offline
Shannon Member
****
Karma: 136
Posts: 10526
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

so che la serial funziona sicuramente negli interrupt esterni, comunque si tratta solo di debug.
un'altra cosa che non ho capito bene è cosa può fare il watchdog. Mi pare che lui resetti l'arduino.
Io ho semplicemente bisogni di mettere a 0 con la libreria Servo 4 uscite (quelle dei motori)..

ah nel forum inglese mi han detto di usare variabili volatili se sono "in comune" tra ISR e normale codice

link: http://arduino.cc/forum/index.php?topic=50864.msg363112;topicseen#msg363112

p.s. non prendetemi in giro per il mio pessimo inglese
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

0
Offline Offline
Faraday Member
**
Karma: 31
Posts: 2908
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
p.s. non prendetemi in giro per il mio pessimo inglese
hahaha io sto messo peggio.

Quote
Mi pare che lui resetti l'arduino.
Io ho semplicemente bisogni di mettere a 0 con la libreria Servo 4 uscite (quelle dei motori)..

Si si, serve nel caso il programma dovesse andare in loop escludendo delle parti di codice vitale, se accade che entra in loop non previsto e li azzeri il watchdog non hai fatto niente. Nel tuo caso non ti serve allora perchè a quello che ho capito se un cavetto si scollega non gira più nel loop, io ho capito così, potrebbe essere più semplice.
PseudoCode
in runner = 0
int count = 0
ISR_OVF()
{
     if (count == 0) save_runner = runner
     if (count => 1)
    {
         if (save_runner ==  runner) spegni i motori
    }
    count++
}

void loop()
{
    runner++   
}

Non c'è bisogno di volatile se fuori da ISR non modifichi la variabile così mi è stato detto però è meglio usare volatile in fase di sviluppo.

Se hai lo schema elettrico decente e non è molto complesso (tipo 200 componenti) posso farlo io il disegno con kicad.

Ciao.
Logged

AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

0
Offline Offline
Shannon Member
****
Karma: 136
Posts: 10526
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

emh.. cos'è ISR_OVF()? un'iterrupt di overflow ma su che timer?


[offtopic]
grazie per il kicad, ma voglio imparare ad usarlo... il bromografo fai da te è già pronto e testato :-)
però non trovo i componenti passivi nella libreria(resistenze, condensatori.. dove siete??).. ho trovato l'atmega ecc...

se non ho capito male, finito lo schema elettrico poi da solo ti tira fuori il pbc (mi serve a faccia singola)
[/offtopic]
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

0
Offline Offline
Faraday Member
**
Karma: 31
Posts: 2908
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
emh.. cos'è ISR_OVF()? un'iterrupt di overflow ma su che timer?
Si è la routine di interrupt, su quale timer lo hai già scritto ISR(TIMER2_OVF_vect).
Il timer2 su arduino non viene usato.

[OT]
Per kicad c'è il porting delle librerie di eagle ma non ricordo dove fai prima a cercare su google, se non trovi fa sapere che tra i tremilatriliardi di file su 8 partizioni farò il possibile di trovarlo.

Quote
se non ho capito male, finito lo schema elettrico poi da solo ti tira fuori il pbc (mi serve a faccia singola)
Bello sarebbe, a me come vengono in automatico non mi piace, al limite si procede così, i connettori si posizionano nella posizione finale e li blocchi, così per il resto che sai dove lo vuoi mettere di preciso, il resto C?, R?, L?, Q?, U? li lasci liberi e fai fare l'autoposizionamento.
Poi chiedi di fare l'auto tracciamento o sbroglio automatico.
Non pensare di ottenere il miglior posizionamento alla prima volta, riprova più volte i passi precedenti, quando ti sembra ok, puoi passare a definire alcune piste manualmente o ad ingrandire qualche pad a sistemare le scritte.

Cosa che mi ha fatto impazzire all'inizio e che devi disegnare il contorno del pcb "pcb edge" altrimenti non funge nulla.

Ciao.
Logged

AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

0
Offline Offline
Shannon Member
****
Karma: 136
Posts: 10526
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ciao belli, ho risolto: in pratica ho sbagliato ad attivare il bit di interrupt!
TIMSK2|=B00000001;
è l'attivazione giusta!
e anzichè scrivere B00000001 si usa fare (è più leggibile e forse pure "portabile") 1<<TOIE2

quindi:
Code:

void setup(){
  Serial.begin(19200);
  TIMSK2 |= (1<<TOIE2);
}
volatile unsigned long time = micros();
volatile int loopOk=0;
void loop(){
  loopOk++;
  //Serial.println("a");
}

ISR(TIMER2_OVF_vect) {
  if (micros()-time >= 1000000){//every second
    time=micros();
    if (loopOk!=0){
      Serial.println("loop ok");
      loopOk=0;
    }else{
      Serial.println("loop bloccato");
    }
  }
};
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Pages: [1]   Go Up
Jump to: