Arduino: độ phân giải microsecond tốt hơn micros ()?


11

Tài liệu micros () lưu ý rằng giá trị trả về sẽ luôn là bội số của 4.

Có cách nào để có được một nhấp chuột có độ phân giải cao hơn micro giây, tốt nhất là xuống mức 1 micro giây không?

Giảm xuống mức AVR là chấp nhận được.


1
Tại sao bạn cứ khăng khăng bắt đầu tiêu đề của mình bằng một thẻ khi tôi đặt nó thành một câu hỏi hoàn toàn bằng tiếng Anh?
stevenvh

4
Xin lỗi Steven, tôi chân thành nghĩ (và nghĩ) đó là một cách hay để diễn đạt câu hỏi ngắn gọn và rõ ràng. Có rất nhiều cuộc thảo luận về điều này, và Jeff đã đồng ý trong một số trường hợp rằng đó là một cách tốt để hỏi. Cuộc thảo luận ở đây; các bản đồ nhiệt là điều đã thuyết phục tôi rằng đối với những câu hỏi kiểu này, nó trả tiền để nhấn mạnh môi trường hoạt động. meta.stackexchange.com/questions/10647/writer-good-title/ , Nhưng, vì tôn trọng câu trả lời tuyệt vời của bạn, tôi sẽ vui lòng thay đổi lại nếu bạn nghĩ nó tốt nhất.
Đánh dấu Harrison

Có thể sử dụng nó cho hàm Pulsein () không? Tôi cần đo độ dài xung trong độ phân giải les hơn 1 usec.

Không gian này được dành riêng cho câu trả lời cho câu hỏi ở trên cùng. Nếu bạn có điều gì muốn hỏi, hãy bắt đầu câu hỏi của riêng bạn.
Olin Lathrop

Câu trả lời:


9

Có, tùy thuộc vào tốc độ xung nhịp cơ bản của Arduino của bạn. Ví dụ, đây là tần số và thời gian đầu vào của bộ đếm thời gian sau khi chia tỷ lệ trước, đối với bộ đếm thời gian 2 của bộ đếm ATMega2560 và tốc độ xung nhịp cơ bản là 16 MHz. Bộ định thời đã tích hợp sẵn các tùy chọn giá trị "prescaler" xác định tần suất / thời gian, được hiển thị trong bảng này:

    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

Để giải quyết thời gian tốt hơn, bạn sử dụng một giá trị được gọi là TCNT2. Có bộ đếm tích hợp đi từ 0 đến 255 vì bộ đếm thời gian là 8 bit. Khi bộ đếm đạt đến giá trị được gán bởi TCNT2, nó sẽ kích hoạt ngắt. Ngắt này được gọi là TIMER2_OVF_vect.

được cung cấp thông tin này, tốc độ ngắt kết quả sẽ là: 16MHz / (prescaler * (255 - TCNT2))

Bạn có thể có được bộ hẹn giờ để chạy ở mức 16 MHz (62,5nSec) đầy đủ mặc dù cách đó nhanh hơn bạn cần; 2 MHz với số đếm ban đầu là (255-2) sẽ cung cấp cho bạn tốc độ ngắt 1 MHz. Chia cho 2 trong ISR của bạn:

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
};

Bảng dữ liệu cho MCU của bạn là tài nguyên cơ bản; bài viết này sẽ cung cấp cho bạn (và đã cho tôi một khởi đầu tốt.


4

Đánh dấu, tôi quyết định viết một bộ chức năng mới, dựa trên Arduino Atmega328 Timer2 và sử dụng các ngắt tràn, để có độ chính xác đến 0,5us. Mã của tôi có sẵn để tải xuống và sử dụng ở đây:

http: // Electricalrcaircraftguy.blogspot.com/2014/02/Timer2Count-more-precise-Arduino-micros-feft.html

Dưới đây là một mô tả ngắn gọn: "Tôi đã viết" libary "để có độ chính xác 0,5us trên hàm thay thế" micros () ", để tôi có thể nhận được kết quả lặp lại khi đọc tín hiệu PWM hoặc PPM, trong vòng 1us. Tôi đã tìm kiếm xung quanh Internet và không thể tìm thấy thứ gì đó có thể so sánh (hoặc dễ sử dụng và duy trì khả năng ghi tín hiệu của Arduino thông qua Servo Libary), vì vậy tôi nghĩ đây là đóng góp lớn đầu tiên của tôi cho thế giới Arduino và Radio Control. "


3

Nếu việc giảm xuống mức AVR là chấp nhận được (như bạn đã đề cập trong câu hỏi của mình), bạn có thể thiết lập bộ đếm thời gian và thậm chí có thể đánh dấu vào đồng hồ của AVR.

Bạn cần tham khảo bảng dữ liệu của AVR vì nó khác với các ATMegas và ATTinys khác nhau. Nhưng thủ tục luôn giống nhau. Những gì bạn cần làm là:

  • quyết định sử dụng bộ đếm gộp nào (ví dụ: đặt nó thành 1, tức là không đặt trước nếu bạn muốn tốc độ xung nhịp CPU thực tế), hãy tham khảo tài liệu TCCR
  • thiết lập ngắt tràn bộ đếm thời gian, trình xử lý ngắt và kích hoạt ngắt trên toàn cầu
  • kích hoạt bộ hẹn giờ trong thanh ghi điều khiển bộ đếm thời gian / bộ đếm TCCR

Bằng cách đó có thể có được các đánh dấu chính xác từ thanh ghi hẹn giờ, tuy nhiên bạn cần phải đếm số lần tràn thủ công. Điều này là chính xác nhất có thể bởi công nghệ.

Dưới đây là một số mã ví dụ cho AT90S2313 đã lỗi thời, nhưng nó cung cấp cho bạn những gợi ý hay về cơ bản:

/* 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  
   */
}

Cảm ơn PhíJai. Tôi có thể đặt các ngắt này trong bối cảnh của bản phác thảo Arduino không?
Đánh dấu Harrison

1
Tôi không quen thuộc với khung arduino. Nhưng nếu nó không thiết lập tất cả các bộ hẹn giờ trong nội bộ, bạn chắc chắn có thể. Nếu không, bạn vẫn có thể đọc các thanh ghi hẹn giờ và tự tính toán.
PhíJai

Có, bạn đang lập trình C ++ đầy đủ trong Arduino và có thể sử dụng tất cả các thanh ghi và ký hiệu TIMSK, TOIE0v.v. (sao chép thiết lập bộ đếm thời gian từ bảng dữ liệu atmega328p). Có vẻ như bạn không thể sử dụng macro ISR (), thay vào đó hãy sử dụng arduino.cc/en/Reference/AttachInterrupt .
joeforker
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.