Bagaimana Arduino dapat mengeluarkan frekuensi pembawa tertentu (yaitu 56 kHz)?


9

Saya sedang mengerjakan proyek optik ruang bebas untuk mengirim data secara nirkabel di antara dua titik. Untuk mencapai hal ini, saya menggunakan LED IR yang terhubung ke Arduino Uno yang berdenyut dengan frekuensi pembawa 56 kHz untuk pemancar dan Arduino kedua dengan modul detektor IR 56 kHz untuk penerima.

Saya mencoba menggunakan delayMicroseconds () antara pin high dan pin low command untuk membuat frekuensi carrier. Jenis ini berfungsi, tetapi frekuensinya tidak selalu sama dan ada penundaan tambahan untuk sinyal berdenyut (yaitu waktu yang diperlukan untuk memanggil fungsi dan penurunan) dapat mengubahnya.

Membaca datasheet untuk ATmega328 tampaknya ada cara untuk mengatur pulsa yang lebih akurat menggunakan timer chip. Apakah itu mungkin, dan jika demikian, bagaimana Anda membuat pulsa 56 kHz menggunakan timer?


Apa akurasi yang Anda butuhkan untuk frekuensi 56KHz Anda? Yaitu rentang frekuensi apa yang dapat diterima dalam proyek Anda? Saya bertanya karena menggunakan pengatur waktu Arduino saja, ketepatan memiliki keterbatasan.
jfpoilpret

55.5khz hingga 56.5khz akan ideal untuk mempertahankan tingkat responsif yang tinggi dalam detektor.
jlbnjmn

Jawaban:


10

Memang mungkin untuk menghasilkan sinyal 56 kHz dengan timer Arduino .

Timer sebenarnya dapat dilihat sebagai register khusus, di MCU, yang memiliki nilai (mulai dari 0) yang bertambah pada frekuensi yaitu frekuensi clock MCU (16 MHz pada Arduino Uno), kemungkinan dibagi dengan faktor yang disebut prescaler . Ketika nilai itu mencapai batas, yang disebut Bandingkan Kecocokan , yang Anda tentukan, maka dua hal terjadi:

  • Nilai register penghitung waktu diatur ulang ke 0.
  • Satu fungsi panggilan balik ISR (interupsi layanan rutin) dipanggil (Anda dapat mendefinisikannya untuk menunjuk ke kode Anda sendiri).

Idenya adalah untuk menggunakan ISR untuk mengubah output dari pin logis setiap kali disebut ( HIGH, lalu LOW, lalu HIGH...).

Sekarang, untuk menghasilkan gelombang persegi 56 kHz, Anda perlu ISR Anda dipanggil 56000 * 2kali per detik ( * 2karena Anda perlu mengubah nilai output dua kali per periode).

Anda dapat memilih nilai prescaler yang Anda inginkan untuk penghitung waktu di antara daftar berikut:

  • 1 (frekuensi clock tidak dibagi, karenanya 16 MHz)
  • 8 (frekuensi clock dibagi 8, karenanya 2 MHz)
  • 64
  • 256
  • 1024

Ada dua ukuran timer / penghitung pada Arduino Uno (sebenarnya disebut timer / counter ): 8 bit dan 16 bit.

Pada Arduino Uno (ATmega328P), Anda memiliki tiga penghitung waktu secara keseluruhan, tetapi beberapa dapat digunakan oleh perpustakaan inti Arduino atau perpustakaan lain yang digunakan dalam sketsa Anda (Anda harus memeriksanya sendiri):

  • timer0 (8-bit)
  • timer1 (16-bit)
  • timer2 (8-bit): yang ini memiliki lebih banyak opsi prescaling (1, 8, 32, 64, 128, 256, dan 1024)

Sekarang Anda perlu menghasilkan gelombang 56 kHz dari 16 MHz, karenanya, tanpa prescaling, Anda perlu menghitung ke:

16000000 / (56000 * 2) - 1 = 141.857( - 1karena penghitung waktu dihitung dari 0 hingga nilai ini dan direset hanya setelah tercapai)

Dari perhitungan ini, kita bisa menggambar dua pengamatan:

  1. 141.857 bukan bilangan bulat dan karenanya Anda tidak akan dapat menghasilkan gelombang tepat 56 kHz.
  2. Tanpa prescaling, Anda memerlukan timer 16-bit karena 285 tidak dapat dianggap sebagai integer 8-bit yang tidak ditandatangani.

Mulai sekarang Anda memiliki dua opsi:

  1. Gunakan timer 16-bit ( timer1 ), gunakan prescaler = 1, dan pilih 142sebagai Bandingkan Pertandingan; yang akan memberi Anda frekuensi berikut:16000000 / (2 * (142 + 1)) = 55944 Hz
  2. Gunakan timer 8-bit ( timer0 ), gunakan prescaler = 8, dan pilih 17sebagai Bandingkan Pertandingan; yang akan memberikan kurang presisi dengan frekuensi berikut: 16000000 / (8 * 2 * (17 + 1)) = 55555 Hzyang masih dalam kisaran yang diperlukan.

Sekarang, mengenai cara menulis sketsa Anda untuk itu, saya menyarankan Anda untuk memeriksa instruksi ini yang sangat lengkap dan sangat menarik untuk dibaca.

Tentu saja, lembar data lengkap ATmega328P juga penting jika Anda ingin memahami, dalam detail sekecil apa pun, apa yang Anda lakukan.

Beberapa catatan penting:

  • ISR dijalankan dengan interupsi yang dinonaktifkan dan karenanya harus sesingkat mungkin. Secara khusus, ada beberapa fungsi dari perpustakaan Arduino yang tidak boleh dipanggil dari ISR.
  • Arduino Uno clock tidak terlalu akurat (menggunakan resonator keramik, bukan kuarsa, yang akan jauh lebih akurat), jadi ini berarti frekuensi output akan bergeser lebih jauh.

2
Juga ketika batas yang ditentukan tercapai, perangkat keras dapat beralih pin. Jadi tidak perlu menggunakan ISR sama sekali. Akan selalu ada jitter dengan ISR karena instruksi tidak dapat terganggu setelah dimulai. Namun perangkat keras akan selalu beralih pin pada tingkat yang diinginkan.
Nick Gammon

Agak mengejutkan bahwa Arduino Uno menggunakan resonator keramik, tetapi sumbernya adalah Arduino UNO FAQ (dekat "Apakah Uno menggunakan resonator atau kristal untuk jam prosesor?" ).
Peter Mortensen

3

Saya menemukan tone()berguna untuk menghasilkan pulsa frekuensi tinggi pada pin apa pun. Seharusnya bisa menangani 56 KHz. (Sunting: Seperti dicatat oleh jfpoilpret, jarak terdekat yang sebenarnya Anda dapatkan pada Arduino 16 MHz adalah sekitar 55,944 KHz)

Kesulitan jelas akan menggabungkannya dengan sinyal data Anda. Saya tidak berpikir Anda bisa melakukannya dalam perangkat lunak tanpa menggunakan kode tingkat rendah. Seharusnya cukup mudah dalam perangkat keras, karena ini digital.

Yang perlu Anda lakukan adalah meng-output sinyal data Anda pada pin yang berbeda, dan kemudian menggabungkannya dengan operator menggunakan gerbang AND. Sinyal gabungan dapat langsung menuju pemancar IR Anda.

Jika Anda tidak memiliki gerbang AND, maka cukup mudah untuk membuatnya sendiri menggunakan sepasang transistor. Cukup cari "transistor dan gerbang" secara daring.


Penerima sering memiliki output rendah aktif secara umum. Jika Anda menghubungkan bagian atas LED ke 56khz, dan bagian bawah ke pin data Anda, ketika pin data menjadi rendah Anda mendapatkan output IR, yang akan membuat penerima menjadi rendah. Tidak diperlukan dan gerbang, hanya sebuah led dan resistor. Hanya masalah yang terbatas pada apa pun pin io saat ini dapat mengemudi.
EternityForest

2

Jawaban yang diterima dari jfpoilpret ditulis dengan sangat baik, sangat valid dan dalam 99% kasus saya akan melakukan persis apa yang dia jelaskan. Solusi-solusinya berada dalam parameter yang Anda tentukan, sehingga harus bekerja dengan sangat baik. Tapi apa yang lebih baik daripada " sangat baik "? Kesempurnaan! Bagaimanapun, pertanyaannya adalah tentang menghasilkan nilai yang tepat. Seperti yang dikatakan cukup dekat adalah baik dalam banyak kasus (bisa dibilang semua), dan bahkan ketika berurusan dengan sesuatu sebagai jam ketika 1 detik harus 1 detik, Anda masih harus menderita ketidaksempurnaan bagian yang diwariskan.

Apa yang akan saya sarankan tidak selalu mungkin. Dalam beberapa kasus, itu mungkin, tetapi dengan kerumitan dan usaha yang jauh lebih banyak daripada kasus ini. Apakah itu layak bergantung pada kasus per kasus. Tujuan saya sebagian besar untuk menunjukkan alternatif untuk referensi di masa depan yang lebih baik dalam kasus-kasus agak pinggiran. Ini ditulis dengan pemikiran pengguna Arduino pemula yang tidak memiliki pengalaman luas dalam bidang elektronik.

Bagi orang yang lebih lanjut ini mungkin akan terlihat terlalu verbose dan dumbed. Tetapi saya percaya bahwa orang-orang yang sama itu mungkin sudah mengetahuinya dan tidak membutuhkan jawaban ini. Ini juga berlaku untuk setiap mikrokontroler dan setiap pabrikan dan arsitektur. Tetapi untuk mikrokontroler lain, Anda perlu berkonsultasi dengan lembar data yang benar untuk mengetahui register yang tepat dan nama dan nilai yang sudah ditentukan sebelumnya.

Dalam kasus Anda, Anda memerlukan frekuensi tertentu dan hal yang menyenangkan tentang itu, adalah bahwa sebenarnya 56 kHz sebenarnya dapat dicapai dengan sangat mudah (tidak termasuk ketidaksempurnaan praktis dari bagian-bagian). Jadi ini juga contoh kasus yang sempurna.

Menghasilkan sinyal tergantung pada sumber waktu dan jam dari mikrokontroler, seperti yang dijelaskan dengan baik oleh jfpoilpret. Jawabannya berkaitan dengan masalah satu sudut pandang saja dan itu mengutak-atik timer. Tetapi Anda juga bisa mengutak-atik sumber jam, atau bahkan lebih baik dengan keduanya untuk hasil yang sinergis dan mengagumkan. Dengan mengubah parameter lingkungan, dalam hal ini meretas sistem dan mengganti sumber jam, kita dapat menangani masalah khusus dengan lebih banyak, lebih mudah dan lebih sederhana.

Pertama yang mengingatkan, karena mengubah status pin, Anda perlu menjalankan ISR dua kali lebih banyak daripada frekuensi sinyal. Ini adalah 112.000 kali per detik. 56.000 dan 16.000.000 tidak bertambah dengan sangat baik seperti yang telah ditunjukkan. Kita perlu mengubah frekuensi sinyal atau frekuensi kebijaksanaan. Mari kita hadapi sekarang dengan frekuensi sinyal yang tidak berubah dan temukan kecepatan clock yang lebih baik.

Akan lebih mudah untuk memilih jam dengan urutan besarnya lebih besar dari 56 kHz (atau 112 kHz, tetapi secara praktis sama), karena Anda hanya menambahkan nol dan matematika seperti ini paling sederhana bagi kebanyakan orang. Sayangnya segala sesuatu di dunia ini adalah semacam kompromi dengan sesuatu. Tidak setiap nilai akan berfungsi.

Contoh pertama adalah dengan kecepatan generator kebijaksanaan yang terlalu rendah.

Jika Anda memilih jam 56.000 Hz, Anda tidak akan dapat melakukan apa pun karena Anda perlu memanggil ISR setiap siklus dan tidak dapat melakukan hal lain. Ini sama sekali tidak berguna. Jika Anda memilih kecepatan 10 kali lebih cepat (560 kHz), Anda akan memiliki 9 (10 siklus untuk timer untuk mencapai nilai maksimal - satu siklus untuk memanggil fungsi ISR) siklus mikrokontroler untuk melakukan pekerjaan Anda dan ini sangat mungkin tidak cukup. Anda cukup sering membutuhkan lebih banyak daya komputasi.

Jika Anda memilih nilai yang terlalu bagus di sisi lain, karena 56 MHz mikrokontroler tidak dapat bekerja dengannya. Itu terlalu cepat. Jadi, hanya memilih nilai terbesar di toko tidak akan memotongnya juga.

Original Arduino Uno R3 memiliki stock clock pada 16 MHz, jadi apa pun yang lebih lambat itu dijamin bekerja. Nilai selanjutnya yang merupakan urutan besarnya lebih besar dari 56 dan lebih rendah dari 16 MHz adalah 5,6 MHz. Ini akan menyebabkan Anda dapat memanggil ISR setiap 50 siklus dan akan menciptakan frekuensi timer 112.000 Hz yang sempurna. Dan sinyal Anda akan persis 56 kHz. Anda akan memiliki 49 siklus MCU untuk menjalankan program Anda di antara panggilan ISR, tetapi masih sekitar 1/3 dari kecepatan jam asli. Seseorang dapat menggunakan 112 sebagai basis dan menggunakan clock 11,2 MHz dan ini akan memberikan sekitar 2/3 dari resonator 16 MHz stok. Fungsi ISR ​​akan dipanggil setiap 100 siklus dan masih menghasilkan sinyal 56 kHz yang sempurna.

Namun ada dua masalah utama dengan nilai-nilai ini.

  • Masalah pertama sangat tergantung pada kebutuhan Anda: Anda mengorbankan sekitar 1/3 (dengan 11,2 MHz) daya komputasi maksimum Anda untuk mendapatkan frekuensi sinyal yang tepat yang menggunakan nilai register yang mudah ditemukan (OCR iirc ). Anda mungkin baik-baik saja dengan itu atau tidak.

  • Masalah kedua adalah showstopper yang sulit : Sangat mudah untuk menemukan nilai, tetapi sangat sering mereka tidak ada sebagai sumber jam yang diproduksi. Ini adalah halaman web resonator Farnell yang hanya kekurangan 5,6 MHz dan 11,2 MHz.

Untuk menghindari hal ini, kita dapat melihat nilai-nilai resonator yang tersedia dan mencari tahu hal lain yang dapat digunakan untuk menghasilkan nilai-nilai yang tepat diinginkan. Jika kita membagi 56 dengan 4 kita mendapatkan 14 dan untungnya ada resonator 14 MHz. Ini memberi kami kecepatan yang jauh lebih tinggi dan lebih banyak daya dan sama mudahnya untuk menemukan nilai register. Untuk memanggil ISR 112.000 kali per detik, kita perlu memasukkan nilai desimal 124 atau heksadesimal 0x7C dalam register OCR, jadi dengan menghitung 124 siklus + 1 untuk memanggil ISR, kita mendapatkan nilai sempurna yang kita inginkan.

NB

  1. ISR - interupsi layanan rutin (ini adalah kode yang dieksekusi hanya pada interupsi yang dihasilkan)
  2. Seberapa besar program Anda tergantung pada ukuran memori! Ini tidak ada hubungannya dengan kecepatan jam dan tidak ada hubungannya dengan seberapa sering Anda memanggil ISR.
  3. Ketika mikrokontroler mulai dengan perintah program penghitung bertambah. Jika interupsi dihasilkan, ISR dipanggil dan nilai ini disimpan dalam register khusus. Ketika kode ISR selesai, nilai penghitung program dipulihkan dari register khusus ini dan program berlanjut dari tempat kode itu terputus seolah-olah tidak pernah terjadi.

    Saya akan memberikan contoh yang sangat bodoh. Jika Anda seorang purist, saya peringatkan Anda: Hidung dan perdarahan mata bisa terjadi.

    Bayangkan Anda harus berjalan dari suatu tempat ke tempat lain. Petunjuk rute langkah demi langkah adalah program utama Anda dan perintahnya. Seberapa cepat Anda berjalan atau berlari, tergantung pada "kecepatan clock" Anda, tetapi tidak pada instruksi rute (30 langkah maju, 1 belokan 90 grad. Kiri, 10 langkah maju, 45 grad. Kanan, dll.) Mereka selalu sama . Sekarang bayangkan seorang anak kecil atau politisi lokal yang serakah melepaskan ikatan sepatu Anda sesekali. Ini adalah acara yang menghasilkan interupsi. Kemudian Anda berhenti setelah langkah terakhir Anda, berlutut dan ikat sepatu Anda lagi. Ini adalah program ISR Anda.

    Kemudian Anda melanjutkan dari tempat Anda berhenti; Anda tidak memulai dari awal. Ketika Anda berjalan tanpa peduli di dunia dan sepanjang waktu, Anda tidak peduli bahkan jika Anda harus mengikat sepatu Anda setiap langkah lainnya. Namun, jika Anda melakukannya dengan batasan waktu, seperti berlari 100 meter di Olimpiade (atau berlari dari pemangsa pemakan daging yang lapar), berhenti dan mengikat sepatu Anda dapat memiliki konsekuensi yang mengerikan. Hal yang sama terjadi pada mikrokontroler. Bahkan jika Anda hanya mengeksekusi satu baris kode, program Anda akan terus berjalan, walaupun lambat. Jika Anda tidak peduli dengan kecepatan sama sekali, itu tidak akan menjadi masalah. Jika Anda harus melakukan beberapa waktu terkait, seperti menggunakan tindakan tergantung waktu lainnya, gangguan dapat sangat tidak diinginkan dan bermasalah.

  4. Kurang itu lebih! Jam yang lebih cepat tidak selalu lebih baik. Perangkat yang lebih lambat menggunakan daya yang jauh lebih sedikit. Ini bisa menjadi titik penting dalam perangkat yang dioperasikan dengan baterai.

  5. Siklus yang diperlukan berasal dari rumus ini:
    (kecepatan clock / (nilai prescaler * frekuensi panggilan ISR yang diperlukan)) - 1


TLDR: Desolder osilator keramik 16 MHz dan ganti dengan yang lain yang memungkinkan secara tepat 56 kHz oleh divisi integer (mis. 14 MHz dan bagi dengan 250).
Peter Mortensen

0

Anda dapat menghidupkan dan mematikan carrier hanya dengan mengaktifkan mode pin carrier antara output dan input. Saya telah menggunakan ini untuk mengontrol pompa panas melalui port 37KHz infrared (remote control).


0

Tidak perlu menggunakan ISR untuk membuat operator. Hanya mengatur timer untuk menghasilkan output PWM 50% pada frekuensi operator yang diperlukan. ISR kemudian hanya bertugas memodulasi pembawa - biasanya pada interval 0,5 atau 1 ms - tingkat yang jauh lebih nyaman. Dalam pengalaman saya, kesalahan 5% dalam frekuensi operator ditoleransi oleh sebagian besar penerima IR. Saya menggunakan Freetronics EtherMega 2560 (yang memiliki banyak timer) tapi saya yakin CPU lain juga akan melakukannya.


Bagaimana tepatnya modulasi carrier diimplementasikan? Mengubah mode untuk pin penangkap keluaran waktu antara input (carrier off) dan output (carrier on)?
Peter Mortensen
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.