Arduino Timer si interrompe

Le interruzioni del timer consentono di eseguire un'attività a intervalli di tempo molto specifici, indipendentemente da ciò che sta succedendo nel codice. In questo manuale spiegherò come impostare ed eseguire un interrupt in Cancella timer in modalità Confronta partita o CTC. Vai direttamente al passaggio 2 se stai cercando un codice di esempio.

Normalmente quando si scrive uno schizzo di Arduino, Arduino esegue tutti i comandi incapsulati nella funzione loop () {} nell'ordine in cui sono scritti, tuttavia è difficile calcolare il tempo degli eventi nel loop (). Alcuni comandi richiedono più tempo di altri per essere eseguiti, alcuni dipendono da istruzioni condizionali (se, mentre ...) e alcune funzioni della libreria Arduino (come digitalWrite o analogRead) sono costituite da molti comandi. Gli interrupt del timer di Arduino consentono di mettere momentaneamente in pausa la normale sequenza di eventi che si svolgono nella funzione loop () a intervalli di tempo precisi, mentre si esegue un set separato di comandi. Una volta eseguiti questi comandi, Arduino riprende da dove si trovava nel loop ().

Gli interrupt sono utili per:

Misurazione di un segnale in entrata ad intervalli equidistanti (frequenza di campionamento costante)

Calcolo del tempo tra due eventi

Invio di un segnale di una frequenza specifica

Controllare periodicamente i dati seriali in arrivo

molto di piu...

Ci sono alcuni modi per fare gli interrupt, per ora mi concentrerò sul tipo che trovo più utile / flessibile, chiamato Clear Timer on Compare Match o CTC Mode. Inoltre, in questo istruttore scriverò in particolare dei timer per Arduino Uno (e qualsiasi altro Arduino con ATMEL 328/168 ... Lilypad, Duemilanove, Diecimila, Nano ...). Le idee principali qui presentate si applicano anche alle schede Mega e precedenti, ma l'installazione è leggermente diversa e la tabella seguente è specifica per ATMEL 328/168.

Passaggio 1: Prescaler e il registro delle partite di confronto

Uno ha tre timer chiamati timer0, timer1 e timer2. Ognuno dei timer ha un contatore che viene incrementato su ogni tick dell'orologio del timer. Gli interrupt del timer CTC vengono attivati ​​quando il contatore raggiunge un valore specificato, memorizzato nel registro delle corrispondenze di confronto. Una volta che un contatore di timer raggiunge questo valore, questo si azzererà (ripristinando a zero) al successivo tick dell'orologio del timer, quindi continuerà a contare nuovamente fino al valore di confronto del confronto. Scegliendo il valore di confronto del confronto e impostando la velocità con cui il timer aumenta il contatore, è possibile controllare la frequenza degli interrupt del timer.

Il primo parametro che tratterò è la velocità con cui il timer aumenta il contatore. L'orologio Arduino funziona a 16MHz, questa è la velocità più alta che i timer possono incrementare i loro contatori. A 16 MHz ogni segno di spunta del contatore rappresenta 1/16.000.000 di secondo (~ 63ns), quindi un contatore impiegherà 10/16.000.000 di secondi per raggiungere un valore di 9 (i contatori sono 0 indicizzati) e 100 / 16.000.000 di secondi per raggiungere un valore di 99.

In molte situazioni, troverete che l'impostazione della velocità del contatore su 16 MHz è troppo veloce. Timer0 e timer2 sono timer a 8 bit, il che significa che possono memorizzare un valore di contatore massimo di 255. Timer1 è un timer a 16 bit, il che significa che può memorizzare un valore di contatore massimo di 65535. Una volta che un contatore raggiunge il suo massimo, tornerà a zero (questo si chiama overflow). Ciò significa che a 16MHz, anche se impostiamo il registro di confronto del confronto sul valore massimo del contatore, gli interruzioni si verificheranno ogni 256/16.000.000 di secondi (~ 16us) per i contatori a 8 bit e ogni 65.536 / 16.000.000 (~ 4 ms) secondi per il Contatore a 16 bit. Chiaramente, questo non è molto utile se si desidera interrompere solo una volta al secondo.

Invece puoi controllare la velocità dell'incremento del contatore del timer usando qualcosa chiamato prescaler. Un prescaler determina la velocità del timer in base alla seguente equazione:

(velocità del timer (Hz)) = (velocità di clock Arduino (16 MHz)) / prescaler

Quindi un prescaler 1 incrementerà il contatore a 16MHz, un prescaler 8 lo incrementerà a 2MHz, un prescaler 64 = 250kHz e così via. Come indicato nelle tabelle sopra, il prescaler può essere uguale a 1, 8, 64, 256 e 1024. (Spiegherò il significato di CS12, CS11 e CS10 nel passaggio successivo).

Ora puoi calcolare la frequenza di interruzione con la seguente equazione:

frequenza di interruzione (Hz) = (velocità di clock Arduino 16.000.000Hz) / (prescaler * (confronta registro delle corrispondenze + 1))
il +1 è presente perché il registro delle corrispondenze di confronto è indicizzato zero

riorganizzando l'equazione sopra, puoi risolvere il valore del registro di confronto delle corrispondenze che fornirà la frequenza di interruzione desiderata:

confronta registro partite = [16.000.000Hz / (prescaler * frequenza di interruzione desiderata)] - 1
ricordare che quando si usano i timer 0 e 2 questo numero deve essere inferiore a 256 e inferiore a 65536 per timer1

quindi se vuoi un interrupt ogni secondo (frequenza di 1Hz):
confronta registro partite = [16.000.000 / (prescaler * 1)] -1
con un prescaler di 1024 ottieni:
confronta registro partite = [16.000.000 / (1024 * 1)] -1
= 15.624
da 256 <15.624 <65.536, è necessario utilizzare timer1 per questo interrupt.

Passaggio 2: strutturare gli interrupt del timer


Il codice di impostazione del timer viene eseguito all'interno della funzione setup () {} in uno schizzo di Arduino.

Il codice relativo all'impostazione degli interrupt del timer è un po 'scoraggiante da guardare, ma in realtà non è poi così difficile. Praticamente copio lo stesso pezzo di codice principale e cambio il prescaler e confronto il registro delle corrispondenze per impostare la frequenza di interruzione corretta.

La struttura principale della configurazione di interrupt è simile alla seguente:
 ////www.instructables.com/id/Arduino-Timer-Interrupts/ void setup () cli (); // stop interrupt // imposta timer0 interruzione a 2kHz TCCR0A = 0; // imposta l'intero registro TCCR0A su 0 TCCR0B = 0; // lo stesso per TCCR0B TCNT0 = 0; // inizializza il valore del contatore su 0 // imposta il registro di confronto confronto per incrementi di 2 kHz OCR0A = 124; // = (16 * 10 ^ 6) / (2000 * 64) - 1 (deve essere <256) // attiva la modalità CTC TCCR0A // termina la configurazione 
Notare come cambia il valore di OCR # A (il valore di confronto del confronto) per ciascuna di queste impostazioni del timer. Come spiegato nell'ultimo passaggio, questo è stato calcolato secondo la seguente equazione:

confronta registro partite = [16.000.000Hz / (prescaler * frequenza di interruzione desiderata)] - 1
ricordare che quando si usano i timer 0 e 2 questo numero deve essere inferiore a 256 e inferiore a 65536 per timer1

Notare anche come le impostazioni tra i tre timer differiscano leggermente nella linea che attiva la modalità CTC:
TCCR0A | = (1 << WGM01); // per timer0
TCCR1B | = (1 << WGM12); // per timer1
TCCR2A | = (1 << WGM21); // per timer2
Ciò deriva direttamente dalla scheda tecnica di ATMEL 328/168.

Infine, nota come l'impostazione per i prescaler segue le tabelle nell'ultimo passaggio (la tabella per il timer 0 è ripetuta sopra),
TCCR2B | = (1 << CS22); // Imposta CS # 2 bit per 64 prescaler per timer 2
TCCR1B | = (1 << CS11); // Imposta CS # 1 bit per 8 prescaler per il timer 1
TCCR0B | = (1 << CS02) | (1 << CS00); // Imposta i bit CS # 2 e CS # 0 per il prescaler 1024 per il timer 0

Si noti nell'ultimo passaggio che esistono diverse opzioni di prescaling per i diversi timer. Ad esempio, timer2 non ha l'opzione di 1024 prescaler.

I comandi che si desidera eseguire durante questi interrupt del timer si trovano nello schizzo di Arduino incapsulato nel seguente modo:
ISR (TIMER0_COMPA_vect) {// cambia lo 0 in 1 per timer1 e 2 per timer2
// interrompe i comandi qui
}
Questo bit di codice dovrebbe trovarsi al di fuori delle funzioni setup () e loop (). Inoltre, cerca di mantenere la routine di interruzione il più breve possibile, specialmente se stai interrompendo ad alta frequenza. Potrebbe anche valere la pena indirizzare direttamente le porte / i pin del chip ATMEL invece di utilizzare le funzioni digitalWrite () e digitalRead (). Puoi trovare maggiori informazioni al riguardo qui.

Esempio: il seguente schizzo imposta ed esegue 3 interruzioni del timer:

 // timer si interrompe // di Amanda Ghassaei // giugno 2012 ////www.instructables.com/id/Arduino-Timer-Interrupts/ / * * Questo programma è un software gratuito; puoi ridistribuirlo e / o modificarlo * secondo i termini della GNU General Public License come pubblicato dalla * Free Software Foundation; o la versione 3 della Licenza o * (a tua scelta) qualsiasi versione successiva. * * / // impostazione timer per timer0, timer1 e timer2. // Per arduino uno o qualsiasi scheda con ATMEL 328/168 .. diecimila, duemilanove, lilypad, nano, mini ... // questo codice abiliterà tutti e tre gli interrupt del timer arduino. // timer0 si interromperà a 2kHz // timer1 si interromperà a 1Hz // timer2 si interromperà a 8kHz // variabili di memorizzazione toggle booleano0 = 0; toolle booleano1 = 0; boolean toggle2 = 0; void setup () // imposta i pin come output pinMode (8, OUTPUT); pinMode (9, OUTPUT); pinMode (13, OUTPUT); cli (); // stop interrupt // imposta timer0 interrupt a 2kHz TCCR0A = 0; // imposta l'intero registro TCCR2A su 0 TCCR0B = 0; // lo stesso per TCCR2B TCNT0 = 0; // inizializza il valore del contatore su 0 // imposta confronta il registro delle corrispondenze per incrementi di 2 kHz OCR0A = 124; // = (16 * 10 ^ 6) / (2000 * 64) - 1 (deve essere <256) // attiva la modalità CTC TCCR0A // termina ISR impostazione (TIMER0_COMPA_vect) { // timer0 interrompe 2kHz attiva / disattiva il pin 8 // genera un'onda di impulso di frequenza 2kHz / 2 = 1kHz (richiede due cicli per l'onda completa: attiva / disattiva alta, quindi attiva) se (attiva / disattiva0) {digitalWrite (8, HIGH); toggle0 = 0; } else {digitalWrite (8, LOW); toggle0 = 1; }} ISR (TIMER1_COMPA_vect) {// timer1 interruzione 1Hz attiva il pin 13 (LED) // genera un'onda di impulso di frequenza 1Hz / 2 = 0, 5kHz (richiede due cicli per l'onda completa, attiva / disattiva basso) se (attiva / disattiva1) { digitalWrite (13, HIGH); toggle1 = 0; } else {digitalWrite (13, LOW); toggle1 = 1; }} ISR (TIMER2_COMPA_vect) {// timer1 interrompe 8kHz attiva / disattiva il pin 9 // genera un'onda di impulso di frequenza 8kHz / 2 = 4kHz (richiede due cicli per l'onda piena attiva / disattiva alta poi attiva / disattiva) se (toggle2) {digitalWrite (9, HIGH); toggle2 = 0; } else {digitalWrite (9, LOW); toggle2 = 1; }} void loop () {// fai altre cose qui} 

Le immagini sopra mostrano le uscite di questi interrupt del timer. La figura 1 mostra un'onda quadra oscillante tra 0 e 5 V a 1 kHz (interruzione timer0), la figura 2 mostra il LED collegato al pin 13 che si accende per un secondo quindi si spegne per un secondo (interruzione timer1), la figura 3 mostra un'onda di impulso che oscilla tra 0 e 5 V ad una frequenza di 4 khz (interruzione timer2).

Passaggio 3: Esempio 1: tachimetro bici

In questo esempio ho realizzato un tachimetro per bici con motore Arduino. Funziona collegando un magnete alla ruota e misurando il tempo necessario per passare da un interruttore magnetico montato sul telaio, il tempo per una rotazione completa della ruota.

Ho impostato il timer 1 per interrompere ogni ms (frequenza di 1kHz) per misurare l'interruttore magnetico. Se il magnete passa dall'interruttore, il segnale dall'interruttore è alto e il "tempo" variabile viene impostato su zero. Se il magnete non è vicino all'interruttore, il "tempo" viene incrementato di 1. In questo modo "tempo" è in realtà solo una misurazione della quantità di tempo in millisecondi che è trascorsa dall'ultimo passaggio del magnete dall'interruttore magnetico. Queste informazioni vengono utilizzate più avanti nel codice per calcolare il numero di giri e il mph della bici.

Ecco il bit di codice che imposta timer1 per gli interrupt da 1kHz

cli (); // stop interrupt
// imposta l'interruzione timer1 a 1kHz
TCCR1A = 0; // imposta l'intero registro TCCR1A su 0
TCCR1B = 0; // stesso per TCCR1B
TCNT1 = 0; // inizializza il valore del contatore su 0
// imposta il conteggio del timer per incrementi di 1 kHz
OCR1A = 1999; // = (16 * 10 ^ 6) / (1000 * 8) - 1
// ha dovuto usare il timer1 a 16 bit per questo bc 1999> 255, ma poteva passare ai timer 0 o 2 con prescaler più grande
// attiva la modalità CTC
TCCR1B | = (1 << WGM12);
// Imposta CS11 bit per 8 prescaler
TCCR1B | = (1 << CS11);
// abilita l'interruzione confronto timer
TIMSK1 | = (1 << OCIE1A);
sei (); // consenti interrupt

Ecco il codice completo se vuoi dare un'occhiata:
 // tachimetro per bici // di Amanda Ghassaei 2012 ////www.instructables.com/id/Arduino-Timer-Interrupts/ ////www.instructables.com/id/Arduino-Timer-Interrupts/ / * * Questo il programma è software libero; puoi ridistribuirlo e / o modificarlo * secondo i termini della GNU General Public License come pubblicato dalla * Free Software Foundation; o la versione 3 della Licenza o * (a tua scelta) qualsiasi versione successiva. * * / // calcoli di esempio // raggio del pneumatico ~ 13, 5 pollici // circonferenza = pi * 2 * r = ~ 85 pollici // velocità massima di 35 mph / ~ 616 pollici / secondo // velocità massima = ~ 7, 25 #define reed A0 / / pin collegato per leggere l'interruttore // variabili di memorizzazione float radius = 13.5; // raggio del pneumatico (in pollici) - MODIFICARE QUESTO PER LA PROPRIA BICI int reedVal; long time = 0; // tempo tra una rotazione completa (in ms) float mph = 0.00; circonferenza del galleggiante; retroilluminazione booleana; int maxReedCounter = 100; // tempo minimo (in ms) di una rotazione (per il debouncing) int reedCounter; void setup () {reedCounter = maxReedCounter; circonferenza = 2 * 3, 14 * raggio; pinMode (1, OUTPUT); // tx pinMode (2, OUTPUT); // interruttore di retroilluminazione pinMode (reed, INPUT); // interruttore rosso checkBacklight (); Serial.write (12); // cancella // IMPOSTAZIONE TIMER: l'interruzione del timer consente di misurare con precisione i tempi dell'interruttore reed // per maggiori informazioni sulla configurazione dei timer arduino, vedere //arduino.cc/playground/Code/Timer1 cli ( ); // stop interrupt // imposta l'interruzione timer1 a 1kHz TCCR1A = 0; // imposta l'intero registro TCCR1A su 0 TCCR1B = 0; // lo stesso per TCCR1B TCNT1 = 0; // inizializza il valore del contatore su 0; // imposta il conteggio del timer per incrementi di 1 kHz OCR1A = 1999; // = (16 * 10 ^ 6) / (1000 * 8) - 1 // attiva la modalità CTC TCCR1B | = (1 << WGM12); // Imposta bit CS11 per 8 prescaler TCCR1B | = (1 << CS11); // abilita l'intervallo di confronto timer TIMSK1 | = (1 <0) {// non lasciare che reedCounter diventi negativo reedCounter - = 1; // decrement reedCounter}}} else {// se l'interruttore reed è aperto se (reedCounter> 0 ) {// non lasciare che reedCounter diventi negativo reedCounter - = 1; // decrementa reedCounter}} se (tempo> 2000) {mph = 0; // se non sono ancora presenti nuovi impulsi dall'interruttore reed, impostare mph / ora 0} else {time + = 1; // increment timer}} void displayMPH () {Serial.write (12); // clear Serial.write ("Speed ​​="); Serial.write (13); // avvia una nuova riga Serial.print (mph); Serial.write ("MPH"); //Serial.write("0.00 MPH "); } void loop () {// stampa mph una volta al secondo displayMPH (); ritardo (1000); checkBacklight (); } 

Passaggio 4: Esempio 2: comunicazione seriale

Questo progetto è una pulsantiera retroilluminata 4x4. Il progetto si collega al mio computer tramite USB, invia informazioni sui pulsanti al computer e riceve informazioni su come illuminare i LED. Ecco un video:



Per questo progetto, ho usato gli interrupt timer2 per verificare periodicamente la presenza di dati seriali in ingresso, leggerli e archiviarli nella matrice "ledData []". Se dai un'occhiata al codice, vedrai che il loop principale dello sketch è ciò che è effettivamente responsabile dell'utilizzo delle informazioni in ledData per illuminare i LED corretti e controllare lo stato dei pulsanti (una funzione chiamata "shift ( ) "). La routine di interruzione è la più breve possibile: basta controllare i byte in arrivo e memorizzarli in modo appropriato.

Ecco l'impostazione per timer2:

cli (); // stop interrupt
// imposta l'interruzione timer2 ogni 128us
TCCR2A = 0; // imposta l'intero registro TCCR2A su 0
TCCR2B = 0; // stesso per TCCR2B
TCNT2 = 0; // inizializza il valore del contatore su 0
// imposta il registro delle corrispondenze per incrementi di 7, 8 kHz
OCR2A = 255; // = (16 * 10 ^ 6) / (7812.5 * 8) - 1 (deve essere <256)
// attiva la modalità CTC
TCCR2A | = (1 << WGM21);
// Imposta CS21 bit per 8 prescaler
TCCR2B | = (1 << CS21);
// abilita l'interruzione confronto timer
TIMSK2 | = (1 << OCIE2A);
sei (); // consenti interrupt

Ecco lo schizzo completo di Arduino:
 // BUTTON TEST w / 74HC595 e 74HC165 e comunicazione seriale // di Amanda Ghassaei // giugno 2012 ////www.instructables.com/id/Arduino-Timer-Interrupts/ / * * Questo programma è un software gratuito; puoi ridistribuirlo e / o modificarlo * secondo i termini della GNU General Public License come pubblicato dalla * Free Software Foundation; o la versione 2 della Licenza o * (a tua scelta) qualsiasi versione successiva. * * / // questo firmware invierà i dati avanti e indietro con la patch maxmsp "beat slicer" // connessioni pin #define ledLatchPin A1 #define ledClockPin A0 #define ledDataPin A2 #define buttonLatchPin 9 #define buttonClockPin 10 #define buttonDataPin A3 A3 / / variabili di loop byte i; byte j; byte k; byte ledByte; // memoria per stati led, 4 byte byte ledData [] = {0, 0, 0, 0}; // memoria per pulsanti, 4 byte byte buttonCurrent [] = {0, 0, 0, 0}; byte buttonLast [] = {0, 0, 0, 0}; byte buttonEvent [] = {0, 0, 0, 0}; byte buttonState [] = {0, 0, 0, 0}; // button debounce counter- 16 byte byte buttonDebounceCounter [4] [4]; void setup () = (1 << WGM21); // Imposta bit CS21 per 8 prescaler TCCR2B // buttonCheck - controlla lo stato di un dato pulsante. // questa funzione buttoncheck è in gran parte copiata dal firmware del monome 40h da brian crabtree e joe lake void buttonCheck (riga byte, indice byte) {if ((((buttonCurrent [riga] ^ buttonLast [riga]) & (1 << indice) ) && // se lo stato del pulsante fisico corrente è diverso da ((buttonCurrent [riga] ^ buttonState [riga]) & (1 << indice)))) {// ultimo stato del pulsante fisico E lo stato debounce corrente se (buttonCurrent [riga] & (1 << indice)) // se lo stato del pulsante fisico corrente è premuto buttonEvent [riga] = 1 << indice; // mette immediatamente in coda un nuovo evento pulsante buttonState [riga] else {buttonDebounceCounter [riga] [indice] = 12; } // altrimenti il ​​pulsante era precedentemente premuto e ora // è stato rilasciato, quindi abbiamo impostato il nostro contatore di rimbalzo. } else if ((((buttonCurrent [row] ^ buttonLast [row]) & (1 << index)) == 0 && // se lo stato del pulsante fisico corrente è lo stesso di (buttonCurrent [row] ^ buttonState [row] ) & (1 <0 && --buttonDebounceCounter [riga] [indice] == 0) {// se il contatore di debounce è // è stato decrementato a 0 (il che significa che // il pulsante è stato impostato su // kButtonUpDefaultDebounceCount / / iterations /// buttonEvent [riga] = 1 << indice; // accoda un evento di modifica dello stato del pulsante se (buttonCurrent [riga] & (1 << indice)) = (1 << indice); else {buttonState [ riga] & = ~ (1 << indice);}}}} void shift () {for (i = 0; i <4; i ++) {buttonLast [i] = buttonCurrent [i]; byte dataToSend = (1 < > 3; // latchpin low digitalWrite (buttonLatchPin, LOW); per (k = 0; k <4; k ++) {buttonCheck (i, k); if (buttonEvent [i] <  1) & 3; byte ledx = (ledByte >> 3) & 3; if (ledstate) = 8 >> ledx; else {ledData [ledy] & = ~ (8 >> ledx); }} // end se serial serial} // end do while (Serial.available ()> 8); } void loop () {shift (); // aggiorna i led e riceve i dati dai pulsanti} 

scarica la patch MaxMSP di seguito (verrà eseguita anche in Max Runtime).

allegati

  • beat slicer.zip Download

Passaggio 5: Esempio 3: DAC

In questo progetto ho usato un interrupt timer per emettere un'onda sinusoidale di una frequenza specifica dall'Arduino. Ho saldato un semplice DAC R2R a 8 bit ai pin digitali 0-7. Questo DAC è stato costruito da resistori da 10k e 20k disposti in un divisore di tensione multilivello. Pubblicherò di più sulla costruzione del DAC in un altro istruttore, per ora ho incluso la foto sopra.
Ho collegato l'uscita dal DAC fino a un oscilloscopio. Se hai bisogno di aiuto per capire come usare / leggere l'oscilloscopio dai un'occhiata a questo tutorial. Ho caricato il seguente codice su Arduino:
 // onda sinusoidale 63Hz // di Amanda Ghassaei 2012 ////www.instructables.com/id/Arduino-Timer-Interrupts/ / * * Questo programma è un software gratuito; puoi ridistribuirlo e / o modificarlo * secondo i termini della GNU General Public License come pubblicato dalla * Free Software Foundation; o la versione 3 della Licenza o * (a tua scelta) qualsiasi versione successiva. * * / // invia un'onda sinusoidale a 63Hz all'arduino PORTD DAC float t = 0; void setup () = (1 << CS21); // abilita l'interruzione del confronto timer TIMSK2 ISR (TIMER2_COMPA_vect) {// incremento t t + = 1; if (t == 628) {// 40kHz / 628 = ~ 63Hz t = 0; }} void loop () {// onda sinusoidale di frequenza ~ 63Hz // invia valori sinusoidali a PORTD tra 0 e 255 PORTD = byte (127 + 127 * sin (t / 100)); } 
Ho impostato un interrupt del timer che incrementa la variabile t ad una frequenza di 40kHz. Quando t raggiunge 627 si ripristina a zero (ciò accade con una frequenza di 40.000 / 628 = 63Hz). Nel frattempo, nel loop principale, Arduino invia un valore compreso tra 0 (00000000 in binario) e 255 (11111111 in binario) ai pin digitali da 0 a 7 (PORTD). Calcola questo valore con la seguente equazione:

PORTD = byte (127 + 127 * sin (t / 100));

Pertanto, con incrementi di t da 0 a 627, la funzione seno si sposta di un ciclo completo. Il valore inviato a PORTD è un'onda sinusoidale con frequenza 63Hz e ampiezza 127, oscillante intorno a 127. Quando questo viene inviato attraverso il DAC della scala di resistori a 8 bit, emette un segnale oscillante intorno a 2, 5 V con un'ampiezza di 2, 5 V e una frequenza di 63 Hz.

La frequenza dell'onda sinusoidale può essere raddoppiata moltiplicando il termine (t / 100) per 2, quadruplicato moltiplicando per 4 e così via ...
Si noti inoltre che se si aumenta eccessivamente la frequenza del timer, diminuendo il prescaler o OCR2A, l'onda sinusoidale non verrà emessa correttamente. Questo perché la funzione sin () è computazionalmente costosa e alle alte frequenze di interruzione non ha abbastanza tempo per essere eseguita. Se si utilizzano interrupt ad alta frequenza, invece di eseguire un calcolo durante la routine di interrupt, prendere in considerazione la memorizzazione di valori in un array e la semplice chiamata di questi valori utilizzando un qualche tipo di indice. Ne puoi trovare un esempio nel mio generatore di forme d'onda arduino: memorizzando 20.000 valori di sin in un array, sono stato in grado di emettere onde sinusoidali con una frequenza di campionamento di 100kHz.

Passaggio 6: Funzioni timer e Arduino

Un'ultima cosa da notare: alcune impostazioni del timer disabiliteranno effettivamente alcune delle funzioni della libreria di Arduino. Timer0 viene utilizzato dalle funzioni millis () e delay (), se si imposta manualmente timer0, queste funzioni non funzioneranno correttamente.
Inoltre, tutti e tre i timer sottoscrivono la funzione analogWrite (). L'impostazione manuale di un timer interromperà il funzionamento di analogWrite ().

Se esiste una parte del codice che non si desidera interrompere, si consiglia di utilizzare cli () e sei () per disabilitare e abilitare gli interrupt a livello globale.

Puoi leggere di più al riguardo sul sito Web di Arduino.

Articoli Correlati