Timer Arduino Menyela

Timer interupsi memungkinkan Anda untuk melakukan tugas pada interval waktu yang sangat spesifik terlepas dari apa pun yang terjadi dalam kode Anda. Dalam instruksi ini saya akan menjelaskan cara mengatur dan menjalankan interupsi dalam Bersihkan Timer pada Mode Bandingkan Pertandingan atau CTC. Langsung ke langkah 2 jika Anda mencari kode sampel.

Biasanya ketika Anda menulis sketsa Arduino, Arduino melakukan semua perintah yang dienkapsulasi dalam fungsi loop () {} dalam urutan yang ditulis, namun, sulit untuk menghitung waktu peristiwa dalam loop (). Beberapa perintah membutuhkan waktu lebih lama daripada yang lain untuk dieksekusi, beberapa bergantung pada pernyataan kondisional (jika, sementara ...) dan beberapa fungsi perpustakaan Arduino (seperti digitalWrite atau analogRead) terdiri dari banyak perintah. Pengatur waktu Arduino memungkinkan Anda untuk sejenak menghentikan urutan normal dari peristiwa yang terjadi dalam fungsi loop () pada interval waktu yang tepat, sementara Anda menjalankan serangkaian perintah terpisah. Setelah perintah-perintah ini selesai, Arduino mengambil lagi di mana ia berada di loop ().

Interupsi berguna untuk:

Mengukur sinyal yang masuk pada interval jarak yang sama (frekuensi sampling konstan)

Menghitung waktu antara dua peristiwa

Mengirim sinyal frekuensi tertentu

Secara berkala memeriksa data serial yang masuk

lebih banyak...

Ada beberapa cara untuk melakukan interupsi, untuk saat ini saya akan fokus pada tipe yang menurut saya paling berguna / fleksibel, yang disebut Clear Timer on Compare Match atau CTC Mode. Selain itu, dalam instruksi ini saya akan menulis secara spesifik tentang timer ke Arduino Uno (dan Arduino lainnya dengan ATMEL 328/168 ... Lilypad, Duemilanove, Diecimila, Nano ...). Ide-ide utama yang disajikan di sini berlaku untuk papan Mega dan yang lebih lama juga, tetapi pengaturannya sedikit berbeda dan tabel di bawah ini khusus untuk ATMEL 328/168.

Langkah 1: Prescaler dan Daftar Pertandingan Bandingkan

Uno memiliki tiga timer yang disebut timer0, timer1, dan timer2. Masing-masing penghitung waktu memiliki penghitung yang bertambah pada setiap centang jam penghitung waktu. Interupsi timer CTC dipicu ketika penghitung mencapai nilai yang ditentukan, disimpan dalam register pertandingan perbandingan. Setelah penghitung waktu mencapai nilai ini, penghitung waktu akan dihapus (atur ulang ke nol) pada centang berikutnya pada jam penghitung waktu, maka penghitung waktu akan terus menghitung hingga nilai kecocokan pembanding lagi. Dengan memilih nilai kecocokan pembanding dan mengatur kecepatan penghitung waktu menambah penghitung, Anda dapat mengontrol frekuensi penghentian penghitung waktu.

Parameter pertama yang akan saya diskusikan adalah kecepatan penghitung waktu menambah penghitung. Jam Arduino berjalan pada 16MHz, ini adalah kecepatan tercepat yang penghitung waktu dapat meningkatkan penghitung mereka. Pada 16MHz setiap centang penghitung mewakili 1 / 16.000.000 per detik (~ 63ns), sehingga penghitung akan membutuhkan 10 / 16.000.000 detik untuk mencapai nilai 9 (penghitung diindeks 0), dan 100 / 16.000.000 detik untuk mencapai nilai dari 99.

Dalam banyak situasi, Anda akan menemukan bahwa pengaturan kecepatan penghitung ke 16MHz terlalu cepat. Timer0 dan timer2 adalah timer 8 bit, artinya mereka dapat menyimpan nilai penghitung maksimum 255. Timer1 adalah timer 16 bit, artinya timer dapat menyimpan nilai penghitung maksimum 65535. Setelah penghitung mencapai maksimum, timer akan kembali ke nol. (ini disebut overflow). Ini berarti pada 16MHz, bahkan jika kita mengatur register pencocokan pembanding ke nilai penghitung maks, interupsi akan terjadi setiap 256 / 16.000.000 detik (~ 16us) untuk penghitung 8 bit, dan setiap 65.536 / 16.000.000 (~ 4 ms) detik untuk Penghitung 16 bit. Jelas, ini tidak terlalu berguna jika Anda hanya ingin menyela sesaat.

Sebagai gantinya Anda dapat mengontrol kecepatan kenaikan penghitung waktu dengan menggunakan sesuatu yang disebut prescaler. Prescaler menentukan kecepatan timer Anda sesuai dengan persamaan berikut:

(kecepatan timer (Hz)) = (kecepatan clock Arduino (16MHz)) / prescaler

Jadi 1 prescaler akan menambah penghitung di 16MHz, 8 prescaler akan menambah itu di 2MHz, 64 prescaler = 250kHz, dan seterusnya. Seperti ditunjukkan dalam tabel di atas, prescaler dapat sama dengan 1, 8, 64, 256, dan 1024. (Saya akan menjelaskan arti CS12, CS11, dan CS10 pada langkah berikutnya.)

Sekarang Anda dapat menghitung frekuensi interupsi dengan persamaan berikut:

frekuensi interupsi (Hz) = (Arduino clock speed 16, 000, 000Hz) / (prescaler * (bandingkan register pertandingan + 1))
+1 ada di sana karena register kecocokan pembanding tidak diindeks

menata ulang persamaan di atas, Anda dapat memecahkan untuk nilai register pencocokan membandingkan yang akan memberikan frekuensi interupsi yang Anda inginkan:

bandingkan register pertandingan = [16, 000, 000Hz / (prescaler * frekuensi interupsi yang diinginkan)] - 1
ingat bahwa ketika Anda menggunakan timer 0 dan 2 angka ini harus kurang dari 256, dan kurang dari 65536 untuk timer1

jadi jika Anda ingin interupsi setiap detik (frekuensi 1Hz):
bandingkan register pertandingan = [16.000.000 / (prescaler * 1)] -1
dengan prescaler 1024 Anda dapatkan:
bandingkan register pertandingan = [16.000.000 / (1024 * 1)] -1
= 15.624
sejak 256 <15.624 <65.536, Anda harus menggunakan timer1 untuk interupsi ini.

Langkah 2: Menyusun Timer Penginterupsi


Kode pengaturan timer dilakukan di dalam fungsi setup () {} dalam sketsa Arduino.

Kode yang terlibat untuk mengatur penghenti waktu sedikit menakutkan untuk dilihat, tetapi sebenarnya tidak terlalu sulit. Saya cukup banyak hanya menyalin kode utama yang sama dan mengubah prescaler dan membandingkan register pertandingan untuk mengatur frekuensi interupsi yang benar.

Struktur utama pengaturan interupsi terlihat seperti ini:
 ////www.instructables.com/id/Arduino-Timer-Interrupts/ void setup () cli (); // stop interruptts // set timer0 interrupt at 2kHz TCCR0A = 0; // atur seluruh register TCCR0A menjadi 0 TCCR0B = 0; // sama untuk TCCR0B TCNT0 = 0; // menginisialisasi nilai penghitung ke 0 // set membandingkan daftar pencocokan untuk kenaikan 2khz OCR0A = 124; // = (16 * 10 ^ 6) / (2000 * 64) - 1 (harus <256) // nyalakan mode CTC TCCR0A // end setup 
Perhatikan bagaimana nilai OCR # A (nilai kecocokan perbandingan) berubah untuk masing-masing pengaturan waktu ini. Seperti dijelaskan dalam langkah terakhir, ini dihitung menurut persamaan berikut:

bandingkan register pertandingan = [16, 000, 000Hz / (prescaler * frekuensi interupsi yang diinginkan)] - 1
ingat bahwa ketika Anda menggunakan timer 0 dan 2 angka ini harus kurang dari 256, dan kurang dari 65536 untuk timer1

Juga perhatikan bagaimana pengaturan antara tiga timer sedikit berbeda pada baris yang mengaktifkan mode CTC:
TCCR0A | = (1 << WGM01); // untuk timer0
TCCR1B | = (1 << WGM12); // untuk timer1
TCCR2A | = (1 << WGM21); // untuk timer2
Ini mengikuti langsung dari lembar data ATMEL 328/168.

Akhirnya, perhatikan bagaimana pengaturan untuk prescalers mengikuti tabel pada langkah terakhir (tabel untuk timer 0 diulangi di atas),
TCCR2B | = (1 << CS22); // Tetapkan CS # 2 bit untuk 64 prescaler untuk timer 2
TCCR1B | = (1 << CS11); // Tetapkan CS # 1 bit untuk 8 prescaler untuk timer 1
TCCR0B | = (1 << CS02) | (1 << CS00); // Tetapkan CS # 2 dan CS # 0 bit untuk prescaler 1024 untuk timer 0

Perhatikan pada langkah terakhir bahwa ada opsi prescaling berbeda untuk penghitung waktu yang berbeda. Misalnya, timer2 tidak memiliki opsi 1024 prescaler.

Perintah yang ingin Anda jalankan selama penghenti waktu ini terletak di sketsa Arduino yang dienkapsulasi sebagai berikut:
ISR (TIMER0_COMPA_vect) {// ubah 0 ke 1 untuk timer1 dan 2 untuk timer2
// interupsi perintah di sini
}
Bit kode ini harus ditempatkan di luar fungsi setup () dan loop (). Selain itu, cobalah untuk menjaga rutinitas interupsi sesingkat mungkin, terutama jika Anda menginterupsi pada frekuensi tinggi. Bahkan mungkin perlu menangani port / pin dari chip ATMEL secara langsung daripada menggunakan fungsi digitalWrite () dan digitalRead (). Anda dapat menemukan lebih banyak info tentang itu di sini.

Contoh - sketsa berikut mengatur dan mengeksekusi 3 interupsi waktu:

 // penghenti waktu // oleh Amanda Ghassaei // Juni 2012 ////www.instructables.com/id/Arduino-Timer-Interrupts/ / * * Program ini adalah perangkat lunak bebas; Anda dapat mendistribusikan ulang dan / atau memodifikasi * di bawah ketentuan Lisensi Publik Umum GNU yang diterbitkan oleh * Free Software Foundation; baik versi 3 dari Lisensi, atau * (sesuai pilihan Anda) versi selanjutnya. * * / // pengaturan timer untuk timer0, timer1, dan timer2. // Untuk arduino uno atau papan apa pun dengan ATMEL 328/168 .. diecimila, duemilanove, lilypad, nano, mini ... // kode ini akan memungkinkan ketiga interupsi timer arduino. // timer0 akan menyela pada 2kHz // timer1 akan menyela pada 1Hz // timer2 akan menyela pada 8kHz // variabel penyimpanan boolean toggle0 = 0; boolean toggle1 = 0; boolean toggle2 = 0; void setup () // atur pin sebagai output pinMode (8, OUTPUT); pinMode (9, OUTPUT); pinMode (13, OUTPUT); cli (); // stop interruptts // set timer0 interrupt pada 2kHz TCCR0A = 0; // atur seluruh register TCCR2A menjadi 0 TCCR0B = 0; // sama untuk TCCR2B TCNT0 = 0; // inisialisasi nilai penghitung ke 0 // set bandingkan daftar pertandingan untuk peningkatan 2khz OCR0A = 124; // = (16 * 10 ^ 6) / (2000 * 64) - 1 (harus <256) // nyalakan mode CTC TCCR0A // end setup ISR (TIMER0_COMPA_vect) { // timer0 interrupt 2kHz toggle pin 8 // menghasilkan gelombang pulsa frekuensi 2kHz / 2 = 1kHz (membutuhkan dua siklus untuk gelombang penuh-beralih tinggi kemudian beralih rendah) jika (toggle0) {digitalWrite (8, HIGH); toggle0 = 0; } else {digitalWrite (8, LOW); toggle0 = 1; }} ISR (TIMER1_COMPA_vect) {// timer1 interrupt 1Hz toggle pin 13 (LED) // menghasilkan gelombang pulsa frekuensi 1Hz / 2 = 0, 5kHz (membutuhkan dua siklus untuk gelombang penuh-beralih tinggi kemudian beralih rendah) jika (toggle1) { digitalWrite (13, HIGH); toggle1 = 0; } else {digitalWrite (13, LOW); toggle1 = 1; }} ISR (TIMER2_COMPA_vect) {// timer1 interrupt 8kHz toggle pin 9 // menghasilkan gelombang pulsa frekuensi 8kHz / 2 = 4kHz (membutuhkan dua siklus untuk gelombang penuh-beralih tinggi kemudian beralih rendah) jika (toggle2) {digitalWrite (9, TINGGI); toggle2 = 0; } else {digitalWrite (9, LOW); toggle2 = 1; }} void loop () {// lakukan hal-hal lain di sini} 

Gambar di atas menunjukkan output dari penghenti waktu ini. Gambar 1 menunjukkan gelombang persegi berosilasi antara 0 dan 5V pada 1 kHz (timer0 interrupt), gambar 2 menunjukkan LED yang terpasang ke pin 13 menyala selama satu detik kemudian mematikan selama satu detik (timer1 menyela), gambar 3 menunjukkan gelombang pulsa berosilasi antara 0 dan 5V pada frekuensi 4khz (timer2 interrupt).

Langkah 3: Contoh 1: Speedometer Sepeda

Dalam contoh ini saya membuat speedometer sepeda bertenaga arduino. Ia bekerja dengan menempelkan magnet pada roda dan mengukur jumlah waktu yang dibutuhkan untuk melewati sakelar magnet yang dipasang pada rangka - waktu untuk satu putaran penuh roda.

Saya mengatur timer 1 untuk menyela setiap ms (frekuensi 1kHz) untuk mengukur sakelar magnet. Jika magnet melewati sakelar, sinyal dari sakelar tinggi dan variabel "waktu" disetel ke nol. Jika magnet tidak dekat saklar "waktu" akan bertambah dengan 1. Dengan cara ini "waktu" sebenarnya hanya pengukuran jumlah waktu dalam milidetik yang telah berlalu sejak magnet terakhir kali dilewati oleh saklar magnetik. Info ini digunakan nanti dalam kode untuk menghitung rpm dan mph sepeda.

Inilah sedikit kode yang mengatur timer1 untuk interupsi 1kHz

cli (); // stop interupsi
// setel timer1 interrupt pada 1kHz
TCCR1A = 0; // atur seluruh register TCCR1A ke 0
TCCR1B = 0; // sama untuk TCCR1B
TCNT1 = 0; // menginisialisasi nilai penghitung ke 0
// setel penghitung waktu untuk kenaikan 1khz
OCR1A = 1999; // = (16 * 10 ^ 6) / (1000 * 8) - 1
// harus menggunakan timer1 16 bit untuk bc ini 1999> 255, tetapi bisa beralih ke timer 0 atau 2 dengan prescaler yang lebih besar
// nyalakan mode CTC
TCCR1B | = (1 << WGM12);
// Tetapkan CS11 bit untuk 8 prescaler
TCCR1B | = (1 << CS11);
// aktifkan timer bandingkan interupsi
TIMSK1 | = (1 << OCIE1A);
sei (); // memungkinkan interupsi

Berikut kode lengkap jika Anda ingin melihatnya:
 // sepeda speedometer // oleh Amanda Ghassaei 2012 ////www.instructables.com/id/Arduino-Timer-Interrupts/ ////www.instructables.com/id/Arduino-Timer-Interrupts/ / * * Ini program adalah perangkat lunak bebas; Anda dapat mendistribusikan ulang dan / atau memodifikasi * di bawah ketentuan Lisensi Publik Umum GNU yang diterbitkan oleh * Free Software Foundation; baik versi 3 dari Lisensi, atau * (sesuai pilihan Anda) versi selanjutnya. * * / // perhitungan sampel // jari-jari ban ~ 13, 5 inci // keliling = pi * 2 * r = ~ 85 inci // kecepatan maks 35mph = ~ 616inches / detik // max rps = ~ 7.25 #define reed A0 / / pin terhubung ke baca switch // variabel penyimpanan radius float = 13.5; // radius ban (dalam inci) - GANTI INI UNTUK SEPEDA SEPEDA MOTOR ANDA SENDIRI int reedVal; lama = 0; // waktu antara satu putaran penuh (dalam ms) float mph = 0.00; lingkar mengambang; lampu latar boolean; int maxReedCounter = 100; // min time (dalam ms) dari satu rotasi (untuk debouncing) int reedCounter; void setup () {reedCounter = maxReedCounter; keliling = 2 * 3, 14 * radius; pinMode (1, OUTPUT); // tx pinMode (2, OUTPUT); // saklar lampu latar pinMode (reed, INPUT); // redd switch checkBacklight (); Serial.write (12); // clear // SETUP TIMER- interupsi timer memungkinkan pengukuran waktunya diatur sebelumnya dari saklar buluh // untuk info lebih lanjut tentang konfigurasi timer Arduino lihat //arduino.cc/playground/Code/Timer1 cli ( ); // stop interupsi // set timer1 interrupt pada 1kHz TCCR1A = 0; // setel seluruh register TCCR1A menjadi 0 TCCR1B = 0; // sama untuk TCCR1B TCNT1 = 0; // inisialisasi nilai penghitung ke 0; // setel penghitung waktu untuk kenaikan 1khz OCR1A = 1999; // = (16 * 10 ^ 6) / (1000 * 8) - 1 // nyalakan mode CTC TCCR1B | = (1 << WGM12); // Tetapkan CS11 bit untuk 8 prescaler TCCR1B | = (1 << CS11); // aktifkan timer bandingkan interupsi TIMSK1 | = (1 <0) {// jangan biarkan reedCounter menjadi reedCounter negatif - = 1; // decrement reedCounter}}} lain {// jika saklar buluh terbuka jika (reedCounter> 0 ) {// jangan biarkan reedCounter menjadi negatif reedCounter - = 1; // decrement reedCounter}} jika (waktu> 2000) {mph = 0; // jika tidak ada pulsa baru dari reed switch- ban masih, atur mph ke 0} lain {waktu + = 1; // pewaktu penambahan}} batal displayMPH () {Serial.write (12); // hapus Serial.write ("Speed ​​="); Serial.write (13); // memulai baris baru Serial.print (mph); Serial.write ("MPH"); //Serial.write("0.00 MPH "); } void loop () {// cetak mph tampilan sekali keduaMPH (); keterlambatan (1000); checkBacklight (); } 

Langkah 4: Contoh 2: Komunikasi Serial

Proyek ini adalah tombol pad backlit 4x4. Proyek ini terhubung ke komputer saya melalui usb, mengirimkan informasi tentang tombol-tombol ke komputer dan menerima informasi tentang cara menyalakan LED. Ini sebuah video:



Untuk proyek ini, saya menggunakan penghitung waktu2 untuk secara berkala memeriksa apakah ada data serial yang masuk, membacanya, dan menyimpannya dalam matriks "ledData []". Jika Anda melihat kode Anda akan melihat bahwa loop utama sketsa adalah apa yang sebenarnya bertanggung jawab untuk menggunakan info di ledData untuk menyalakan LED yang benar dan memeriksa status tombol (fungsi yang disebut "shift ( ) "). Interupsi rutin sesingkat mungkin - hanya memeriksa byte yang masuk dan menyimpannya dengan tepat.

Berikut ini adalah pengaturan untuk timer2:

cli (); // stop interupsi
// set timer2 interrupt setiap 128us
TCCR2A = 0; // atur seluruh register TCCR2A ke 0
TCCR2B = 0; // sama untuk TCCR2B
TCNT2 = 0; // menginisialisasi nilai penghitung ke 0
// atur bandingkan daftar pertandingan untuk kenaikan 7.8khz
OCR2A = 255; // = (16 * 10 ^ 6) / (7812.5 * 8) - 1 (harus <256)
// nyalakan mode CTC
TCCR2A | = (1 << WGM21);
// Tetapkan CS21 bit untuk 8 prescaler
TCCR2B | = (1 << CS21);
// aktifkan timer bandingkan interupsi
TIMSK2 | = (1 << OCIE2A);
sei (); // memungkinkan interupsi

Inilah sketsa Arduino lengkap:
 // BUTTON TEST w / 74HC595 dan 74HC165 dan komunikasi serial // oleh Amanda Ghassaei // Juni 2012 ////www.instructables.com/id/Arduino-Timer-Interrupts/ / * * Program ini adalah perangkat lunak bebas; Anda dapat mendistribusikan ulang dan / atau memodifikasi * di bawah ketentuan Lisensi Publik Umum GNU yang diterbitkan oleh * Free Software Foundation; baik versi 2 dari Lisensi, atau * (sesuai pilihan Anda) versi selanjutnya. * * / /. firmware ini akan mengirim data bolak-balik dengan patch maxmsp "beat slicer" // koneksi pin #define ledLatchPin A1 #define ledClockPin A0 #define ledDataPin A2 #define buttonLatchPin 9 #define buttonClockPin 10 #define buttonDataPin A3 / / variabel pengulangan byte i; byte j; byte k; byte ledByte; // penyimpanan untuk negara-negara yang dipimpin, 4 byte byte ledData [] = {0, 0, 0, 0}; // penyimpanan untuk tombol, 4 byte byte buttonCurrent [] = {0, 0, 0, 0}; tombol byteTerakhir [] = {0, 0, 0, 0}; tombol byteEvent [] = {0, 0, 0, 0}; byte buttonState [] = {0, 0, 0, 0}; // tombol debounce counter- 16 byte byte buttonDebounceCounter [4] [4]; void setup () = (1 << WGM21); // Tetapkan CS21 bit untuk 8 prescaler TCCR2B // buttonCheck - memeriksa keadaan tombol yang diberikan. // fungsi cek tombol ini sebagian besar disalin dari firmware monome 40j oleh brian crabtree dan joe lake void buttonCheck (baris byte, indeks byte) {if (((buttonCurrent [baris] ^ buttonTerakhir [baris]) & (1 << indeks) ) && // jika keadaan tombol fisik saat ini berbeda dari ((tombol [Arus] ^ tombolState [baris]) & (1 << indeks))) {// status tombol fisik terakhir DAN kondisi saat ini yang dilepas jika (tombolCurrent [baris] & (1 << indeks)) // jika keadaan tombol fisik saat ini ditekan tombolEvent [baris] = 1 << indeks; // antri acara tombol baru segera buttonState [row] else {buttonDebounceCounter [row] [index] = 12; } // jika tidak, tombol itu sebelumnya ditekan dan sekarang // telah dirilis jadi kami mengatur penghitung debounce kami. } lain jika (((buttonCurrent [row] ^ buttonLast [row]) & (1 << index)) == 0 && // jika keadaan tombol fisik saat ini sama dengan (buttonCurrent [baris] ^ buttonState [row] ) & (1 <0 && --buttonDebounceCounter [row] [index] == 0) {// jika penghitung debounce // telah dikurangi menjadi 0 (artinya tombol // telah menyala untuk // kButtonUpDefaultDebounceCount / / iterations /// buttonEvent [row] = 1 << index; // mengantri acara perubahan status button jika (buttonCurrent [row] & (1 << index)) = (1 << index); else {buttonState [ row] & = ~ (1 << index);}}}} shift kosong () {for (i = 0; i <4; i ++) {buttonLast [i] = buttonCurrent [i]; byte dataToSend = (1 < > 3; // latchpin low digitalWrite (buttonLatchPin, LOW); for (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 jika serial tersedia} // end do while (Serial.available ()> 8); } void loop () {shift (); // memperbarui leds dan menerima data dari tombol} 

unduh tambalan MaxMSP di bawah ini (ini juga akan berjalan di Max Runtime).

Lampiran

  • beat slicer.zip Unduh

Langkah 5: Contoh 3: DAC

Dalam proyek ini saya menggunakan penghitung waktu untuk menghasilkan gelombang sinus dari frekuensi tertentu dari Arduino. Saya menyolder DAC 8 bit R2R sederhana ke pin digital 0-7. DAC ini dibangun dari resistor 10k dan 20k yang diatur dalam pembagi tegangan multi-level. Saya akan memposting lebih lanjut tentang pembangunan DAC di instruksi lain, untuk sekarang saya sudah memasukkan foto di atas.
Saya menghubungkan output dari DAC ke osiloskop. Jika Anda memerlukan bantuan untuk memahami cara menggunakan / membaca osiloskop, lihat tutorial ini. Saya memuat kode berikut ke Arduino:
 // 63Hz sine wave // ​​oleh Amanda Ghassaei 2012 ////www.instructables.com/id/Arduino-Timer-Interrupts/ / * * Program ini adalah perangkat lunak bebas; Anda dapat mendistribusikan ulang dan / atau memodifikasi * di bawah ketentuan Lisensi Publik Umum GNU yang diterbitkan oleh * Free Software Foundation; baik versi 3 dari Lisensi, atau * (sesuai pilihan Anda) versi selanjutnya. * * / // mengirimkan gelombang sinus 63 Hz ke arduino PORTD DAC float t = 0; void setup () = (1 << CS21); // aktifkan timer bandingkan interupsi TIMSK2 ISR (TIMER2_COMPA_vect) {// peningkatan t t + = 1; if (t == 628) {// 40kHz / 628 = ~ 63Hz t = 0; }} void loop () {// gelombang frekuensi sinus ~ 63Hz // mengirim nilai sinus ke PORTD antara 0 dan 255 PORTD = byte (127 + 127 * sin (t / 100)); } 
Saya mengatur penghenti waktu yang menambah variabel t pada frekuensi 40kHz. Begitu t mencapai 627, ia akan kembali ke nol (ini terjadi dengan frekuensi 40.000 / 628 = 63Hz). Sementara itu, dalam loop utama Arduino mengirimkan nilai antara 0 (00000000 dalam biner) dan 255 (11111111 dalam biner) ke pin digital 0 hingga 7 (PORTD). Ini menghitung nilai ini dengan persamaan berikut:

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

Jadi ketika t bertambah dari 0 hingga 627 fungsi sinus bergerak melalui satu siklus lengkap. Nilai yang dikirim ke PORTD adalah gelombang sinus dengan frekuensi 63Hz dan amplitudo 127, berosilasi sekitar 127. Ketika ini dikirim melalui tangga resistor 8 bit DAC, ia mengeluarkan sinyal osilasi sekitar 2.5V dengan amplitudo 2.5V dan frekuensi 63Hz.

Frekuensi gelombang sinus dapat digandakan dengan mengalikan istilah (t / 100) dengan 2, empat kali lipat dengan mengalikan 4, dan seterusnya ...
Juga perhatikan bahwa jika Anda meningkatkan frekuensi penghitung waktu terlalu banyak dengan mengurangi prescaler atau OCR2A, gelombang sinus tidak akan menghasilkan dengan benar. Ini karena fungsi sin () mahal secara komputasi, dan pada frekuensi interupsi tinggi tidak memiliki cukup waktu untuk mengeksekusi. Jika Anda menggunakan interupsi frekuensi tinggi, alih-alih melakukan perhitungan selama rutin interupsi, pertimbangkan untuk menyimpan nilai dalam array dan cukup memanggil nilai-nilai ini menggunakan semacam indeks. Anda dapat menemukan contohnya di arduino waveform generator saya - dengan menyimpan 20.000 nilai dosa dalam sebuah array, saya dapat menampilkan gelombang sinus dengan frekuensi sampling 100kHz.

Langkah 6: Fungsi Timer dan Arduino

Satu hal terakhir yang perlu diperhatikan - pengaturan timer tertentu sebenarnya akan menonaktifkan beberapa fungsi perpustakaan Arduino. Timer0 digunakan oleh fungsi millis () dan delay (), jika Anda mengatur timer0 secara manual, fungsi-fungsi ini tidak akan berfungsi dengan benar.
Selain itu, ketiga pengatur waktu menanggung fungsi analogWrite (). Menyiapkan timer secara manual akan menghentikan fungsi analogWrite ().

Jika ada beberapa bagian dari kode Anda yang tidak Anda inginkan terputus, pertimbangkan untuk menggunakan cli () dan sei () untuk menonaktifkan dan mengaktifkan interupsi secara global.

Anda dapat membaca lebih lanjut tentang ini di situs web Arduino.

Artikel Terkait