Go Down

Topic: Interrupt contemporanei (Read 7568 times) previous topic - next topic

psoftware

Si, avevo dimenticato di scriverlo e so con certezza che usare DigitalWrite rende l'esecuzione più lenta...specialmente perchè devo cambiare lo stato di tre pin contemporaneamente. Ma il tutto è ancora un mezzo abbozzo, devo ottimizzare per bene il sorgente...

PaoloP

Puoi pubblicare il pezzo di codice della ISR?

psoftware

E' abbastanza semplice...

Code: [Select]
int Cycle;

ISR(TIMER1_COMPA_vect)//timer1 interrupt 1Hz toggles pin 13 (LED)
{
  if(Cycle==0)
  {
    digitalWrite(2, HIGH);
    digitalWrite(4, LOW);
    digitalWrite(7, HIGH);
  }
  else if(Cycle==1)
    digitalWrite(7, LOW);
  else if(Cycle==2)
  {
    digitalWrite(4, HIGH);
  }
  else if(Cycle==3)
  {
    digitalWrite(2, LOW);
  }
  else if(Cycle==4)
  {
    digitalWrite(7, HIGH);
  }
  else if(Cycle==5)
  {
    digitalWrite(4, LOW);

    Cycle=0;
    return;
  }

  Cycle++;
}


Nel loop non c'è niente...ho messo giusto qualche riga per acquisire dei dati in seriale e testare la "stabilità" dei segnali PWM tramite un oscilloscopio. In pratica questo codice genera tre PWM a 50hz su tre pin diversi, duty cycle al 50% percento, "sfasate" a 120 gradi tra loro... ovviamente "sfasate" fra virgolette perchè parliamo di mezze onde quadre e non di sinusoidi. I segnali sono generati correttamente, di questo almeno sono soddisfatto :D

psoftware

Ovviamente il tutto può essere sistemato con un case, o sfasando i segnali in modo più "matematico". Per questo dicevo che fosse solo un mezzo abbozzo  :smiley-mr-green:

Le onde vengono generate come da allegato (scusate la bassa risoluzione dell'immagine e le modifiche che ho fatto, mi servivano per studiare come generare i tre segnali).

Gli interrupt sono generati alla frequenza di 50 [Hz]/6 , perchè appunto i segnali cambiano stato ogni 1/3 di P greco (studiando i pwm come se fossero sinusoidi)

gpb01


E' abbastanza semplice...


Come ti è stato detto NON usare le digitalWrite() in una ISR ... sono lente ! Impara ad usare l'accesso diretto alle porte ... studia QUI ...

Guglielmo
Search is Your friend ... or I am Your enemy !

PaoloP

#20
Apr 07, 2014, 10:29 pm Last Edit: Apr 07, 2014, 10:33 pm by PaoloP Reason: 1
Dovresti fare una cosa del genere
Code: [Select]
volatile byte Cycle = 1;

ISR(TIMER1_COMPA_vect)//timer1 interrupt 1Hz toggles pin 13 (LED)
{
 switch (Cycle) {
   case 1:
     PORTD |= (1 << PORTD2); // HIGH
     PORTD &= ~(1 << PORTD4); // LOW
     PORTD |= (1 << PORTD7); // HIGH
     break;

   case 2:
     digitalWrite(7, LOW);
     break;

   case 3:

     digitalWrite(4, HIGH);
     break;

   case 4:
     digitalWrite(2, LOW);
     break;

   case 5:
     digitalWrite(7, HIGH);
     break;


   case 6:
     digitalWrite(4, LOW);
     Cycle = 0;
 }
 Cycle++;
}


Il resto la lascio a te.
Ti conviene definire lo stato di tutti e tre pin in ogni case.

Maurotec

Se anziché PD2, PD4 e PD7 potessi usare PB0(8), PB1(9) e PB2(10) potresti semplificare molto
il codice, cioè si semplifica per il micro, ma si complica per il programmatore.
Se carichi 100110010011001101 e shifti di 3 a destra nei bit LSB ti ritrovi il codice della sequenza da imporre
direttamente alla porta B. Dopo sei volte shift a destra di tre devi ricaricare il valore 100110010011001101.

Più complicato a spiegarlo che a farlo.

Ciao.

icio

Praticamente stai realizzando un inverter trifase finalizzato a alimentatore trifase simile a questo ?

http://www.dmxpassion.altervista.org/pg010.html


psoftware

Bravo Icio, esattamente in quel modo, ma uso come sorgente un mini impianto idroelettrico in continua :)

In ogni caso ho capito come usare direttamente i registri dell'ATMega, è relativamente molto semplice... ci sarei arrivato comunque da solo a quel sorgente. In ogni caso la problematica principale ancora non l'abbiamo risolta... come funziona la funzionalità busy dell'interfaccia seriale UART? Anche se non fosse implementata in HardwareSerial, come funziona in teoria?

Ho provato a fare dei test... avvio la generazione dei segnali ma nel frattempo invio dei caratteri alla scheda e me li faccio reinviare indietro... non ho notato grossi problemi, nè in ricezione e nè in trasmissione. Devo approfondire i test

PaoloP


Se anziché PD2, PD4 e PD7 potessi usare PB0(8), PB1(9) e PB2(10) potresti semplificare molto
il codice


Credo abbia scelto quei pin perche gli altri della stessa porta sono PWM.
Forse gli servono.

leo72

Manco 2 gg e mi perdo queste discussioni interessanti  ;)

Togli tutte quelle digitalWrite dalla ISR così essa verrà eseguita molto più velocemente.
Poi sarebbe da capire cos'è che fa il resto del circuito, perché se non hai molte necessità potresti eliminare tutti gli altri interrupt e lasciare solo quello del timer in uso.

PS.
tornando un attimo all'inizio del thread, non è che se la CPU sta eseguendo una ISR i segnali degli interrupt in arrivo vengono accodati. Non c'è un buffer. Esistono (come qualcuno ha detto) dei bit che registrano questi interrupt. Alla fine della ISR, viene controllato che non ci sia da eseguire un'altra ISR di un interrupt arrivato nel frattempo. Il problema dei bit è che se arrivano 2 segnali dello STESSO interrupt, il micro registra solo che c'è stato un segnale, non quanti segnali sono arrivati. Per cui 3 INT0 sono registrati sempre con lo stesso bit, per cui la CPU sa solo che c'è da eseguire la relativa ISR. Non che la deve eseguire 3 volte.

psoftware

Uhm...perfetto, sei stato molto chiaro, ora capisco meglio come funziona, erano questioni che mi ponevo da un po' di tempo.
Il problema è che bisogna capire se è possibile accomunare il funzionamento di quella ISR con gli interrupt generati da HardwareSerial. Da quello che si evince devo far si che l'esecuzione della ISR relativa ai PWM venga eseguita il più velocemente possibile, così che ci siano meno possibilità che gli interrupt generati dalla trasmissione/ricezione seriale vengano "scartati" o eseguiti in ritardo a causa dell'esecuzione prolungata della ISR.

Ho fatto un po' di test ma non ho avuto grossi problemi... la ricezione/trasmissione seriale avviene con successo, l'ho testata con una baudrate di 115200, mentre i segnali pwm vengono generati. Invio dei caratteri alla scheda, da cui me li faccio reinviare.
Per i segnali è un po' difficile fare dei test, perchè la frequenza è troppo alta ed è impossibile analizzare gli errori del segnale con un semplice oscilloscopio...

icio

I maggiori problemi nella costruzione del tuo inverter per turbina idroelettrica non la incontrerai nel software ma nell'hardware, 
circuito di controllo spwm, controllo della tensione e corrente di uscita, protezioni, scelta o costruzione dei giusti trasformatori o della reattanza AC trifase etc..


psoftware

Naah... non per caso studio nell'indirizzo Elettrotecnica ed Automazione (elettronica compresa), e sto studiando per bene il circuito elettronico che sarà pilotato da Arduino. Per le protezioni non ci sono problemi, sto trovando solo qualche difficoltà nel circuito di amplificazione ma ho quasi risolto... l'unica cosa che mi preoccupa ora è solo che il segnale venga generato senza difetti

icio

Va bene  ma che te ne fai di 3 onde quadre sfasate? Devi generare 3 sinusoidi!

Go Up