Arduino: resolusi mikrodetik yang lebih baik daripada micros ()?

11

Dokumentasi micros () mencatat bahwa nilai kembali akan selalu kelipatan 4.

Apakah ada cara untuk mendapatkan resolusi mikrodetik klik yang lebih tinggi, lebih disukai turun ke level 1 mikrodetik?

Turun ke level AVR dapat diterima.

Mark Harrison
sumber
1
Mengapa Anda bersikeras memulai judul Anda dengan tag ketika saya membuatnya menjadi pertanyaan bahasa Inggris yang sempurna?
stevenvh
4
Maaf Steven, saya dengan tulus berpikir (dan berpikir) itu adalah cara yang baik untuk mengungkapkan pertanyaan secara ringkas dan jelas. Ada banyak diskusi tentang ini, dan dalam beberapa kasus Jeff setuju bahwa itu adalah cara bertanya yang baik. Diskusi ada di sini; heatmaps adalah apa yang meyakinkan saya bahwa untuk gaya pertanyaan ini perlu untuk menekankan lingkungan operasi. meta.stackexchange.com/questions/10647/writing-good-titles/... Tapi, untuk menghormati jawaban Anda yang sangat baik, saya akan dengan senang hati mengubahnya kembali jika Anda pikir itu yang terbaik.
Mark Harrison
Apakah mungkin menggunakannya untuk fungsi pulsein ()? Saya perlu mengukur panjang pulsa di le resolusi dari 1 usec.
Ruang ini disediakan untuk jawaban atas pertanyaan di atas. Jika Anda memiliki sesuatu untuk ditanyakan, mulailah pertanyaan Anda sendiri.
Olin Lathrop

Jawaban:

9

Ya, tergantung laju jam dasar Arduino Anda. Sebagai contoh di sini adalah frekuensi input penghitung waktu dan periode setelah pra-penskalaan, untuk penghitung waktu pencacah ATMega2560 2, dan kecepatan clock dasar 16MHz. Timer memiliki opsi nilai "prescaler" yang menentukan frekuensi / periode, ditunjukkan pada tabel ini:

    TCCR2B bits 2-0    Prescaler    Freq [KHz], Period [usec] after prescale
          0x0          (TC stopped)      --         --
          0x1                1        16000.        0.0625
          0x2                8         2000.        0.500
          0x3               32          500.        2.000
          0x4               64          250.        4.000
          0x5              128          125.        8.000
          0x6              256           62.5      16.000
          0x7             1024           15.625    64.000

Untuk resolusi pengaturan waktu yang lebih baik, Anda menggunakan nilai yang disebut TCNT2. Ada build in counter yang beroperasi dari 0 hingga 255 karena timernya 8 bit. Ketika penghitung mencapai nilai yang diberikan oleh TCNT2 itu memicu interupsi. Gangguan ini disebut TIMER2_OVF_vect.

diberikan informasi ini, tingkat interupsi yang dihasilkan adalah: 16MHz / (prescaler * (255 - TCNT2))

Anda bisa menjalankan timer dengan kecepatan 16MHz (62.5nSec) penuh meskipun itu jauh lebih cepat dari yang Anda butuhkan; 2MHz dengan hitungan awal (255-2) akan memberi Anda tingkat interupsi 1MHz. Bagilah dengan 2 di ISR ​​Anda:

extern uint32_t MicroSecClock = 0;

ISR(TIMER2_OVF_vect) {// this is a built in function that gets called when the timer gets to the overflow counter number
  static uint_8 count;            // interrupt counter

  if( (++count & 0x01) == 0 )     // bump the interrupt counter
    ++MicroSecClock;              // & count uSec every other time.

  digitalWrite(53,toggle);// pin 53 is arbitrary
  TCNT2 = 253;                    // this tells the timer when to trigger the interrupt. when the counter gets to 253 out of 255(because the timer is 8 bit) the timmer will trigger an interrupt
  TIFR2 = 0x00;                   // clear timer overflow flag
};

Lembar data untuk MCU Anda adalah sumber daya dasar; artikel ini akan memberi Anda (dan memberi saya!) awal yang baik.

JRobert
sumber
4

Mark, saya memutuskan untuk menulis satu set fungsi baru, berdasarkan Arduino Atmega328 Timer2, dan menggunakan overflow interupsi, untuk mendapatkan presisi hingga 0,5 us. Kode saya tersedia untuk diunduh dan digunakan di sini:

http://electricrcaircraftguy.blogspot.com/2014/02/Timer2Counter-more-precise-Arduino-micros-function.html

Berikut adalah deskripsi singkat: "Saya menulis" perpustakaan "untuk mendapatkan presisi 0,5us pada fungsi penggantian" micros () ", sehingga saya bisa mendapatkan hasil yang berulang dengan membaca sinyal PWM atau PPM, hingga dalam 1us. Saya mencari di sekitar internet dan tidak dapat menemukan sesuatu yang sebanding (atau yang mudah digunakan, dan mempertahankan kemampuan Arduino untuk menulis sinyal PWM melalui Servo Libary), jadi saya pikir ini adalah kontribusi utama pertama saya ke dunia Arduino dan Kontrol Radio. "

Gabriel Staples
sumber
3

Jika jatuh ke Level AVR dapat diterima (seperti yang Anda sebutkan dalam pertanyaan Anda), Anda dapat mengatur timer dan bahkan mendapatkan detak jam AVR.

Anda perlu merujuk ke lembar data AVR Anda karena berbeda dalam ATMegas dan ATTinys yang berbeda. Tetapi prosedurnya selalu sama. Yang perlu Anda lakukan adalah:

  • tentukan prescaler mana yang akan digunakan (misalnya set ke 1, yaitu tanpa prescaling jika Anda menginginkan kecepatan clock CPU yang sebenarnya), lihat dokumentasi TCCR
  • mengatur timer overflow interrupt, handler interrupt dan mengaktifkan interupsi secara global
  • aktifkan timer di Timer / Counter Control Register TCCR

Dengan begitu bisa mendapatkan kutu yang tepat dari register penghitung waktu, namun Anda harus menghitung luapan secara manual. Ini setepat mungkin oleh teknologi.

Berikut adalah beberapa contoh kode untuk AT90S2313 yang sudah usang, tetapi ini memberi Anda petunjuk yang baik tentang apa yang harus dilakukan pada dasarnya:

/* uC: AT90S2313 */
#include <avr/io.h>
#include <avr/interrupt.h>

int main(void)
{
  // set up timer 0
  TCCR0 = (1<<CS01); // Prescaler 8

  // enable overflow interrupt
  TIMSK |= (1<<TOIE0);

  // activate interrupts
  sei();

  while(1)
  {
     /* Do whatever you like */
  }
}


ISR (TIMER0_OVF_vect)
{    
   /*
      This gets called everytime there in an overflow in the timer register  
   */
}
FeeJai
sumber
Terima kasih FeeJai. Bisakah saya mengatur interupsi ini dalam konteks sketsa Arduino?
Mark Harrison
1
Saya tidak terbiasa dengan kerangka Arduino. Tetapi jika itu tidak mengatur semua timer secara internal, Anda pasti bisa. Kalau tidak, Anda masih bisa membaca register penghitung waktu dan menghitung sendiri.
FeeJai
Ya, Anda sedang memprogram dalam C ++ lengkap di Arduino dan dapat menggunakan semua register dan simbol seperti TIMSK, TOIE0dll. (Menyalin penyetelan timer dari atmega328p datasheet). Sepertinya Anda tidak dapat menggunakan makro ISR (), alih-alih gunakan arduino.cc/en/Reference/AttachInterrupt .
joeforker