Làm thế nào để tôi có được một thời gian chính xác?


16

Tôi đã tạo ra một chiếc đồng hồ bằng Arduino, nhưng thời gian dường như trôi đi. Tôi nhận thức được vấn đề tái đầu tư ; Đồng hồ dường như trôi đi khoảng 15 phút trong suốt một tuần.

Tôi đang sử dụng PCB tùy chỉnh với bộ cộng hưởng này từ Digi-key. Mã này đọc hàm millis () ở đầu mỗi vòng lặp và hoạt động từ giá trị đó.

Câu hỏi của tôi là: Làm thế nào tôi có thể đo thời gian với Arduino, đủ chính xác để tạo ra một chiếc đồng hồ để bàn có thể vượt qua?


3
Hàm mili giây được cung cấp với dữ liệu từ một ngắt, cần một vài chu kỳ đồng hồ để chạy. Điều này thêm một lượng thời gian rất nhỏ cho mỗi đánh dấu.
TheDoctor

3
@TheDoctor: Điều này không chính xác. Ngắt không làm chậm bộ đếm thời gian phần cứng ổ đĩa millis().
Edgar Bonet

Câu trả lời:


15

Lưu ý: mặc dù câu trả lời của tôi đã được chấp nhận và có số phiếu bầu cao hơn, hãy đảm bảo bạn đã đọc câu trả lời tuyệt vời của Edgar Bonet về cách làm cho Arduino của bạn giữ thời gian mà không cần RTC.

Tôi đã khá thành công khi sử dụng Đồng hồ thời gian thực DS1307. Đây là một liên kết đến bảng dữ liệu của nó .

Dưới đây là một số tính năng của nó:

  • Nó sử dụng giao diện IC để liên lạc với Arduino, giúp dễ dàng lập trình bằng các thư viện phù hợp (có sẵn trên Net).

  • Nó được kết nối với Arduino thông qua các chân SCL và SDA (tương tự A4 và A5), do đó chỉ sử dụng 2 chân.

  • Nó đòi hỏi rất ít thành phần bên ngoài để chạy.

  • CNTT có thể được kết nối với pin tế bào đồng xu để nó sẽ giữ thời gian ngay cả khi Arduino bị tắt. Trong chế độ năng lượng thấp, pin đồng xu kéo dài trong nhiều năm.

  • Nó trôi rất ít (trong trường hợp của tôi nó chỉ trôi vài giây mỗi tuần).

  • Nó không đắt lắm.

Nếu bạn không có ý định sử dụng RTC, bạn có thể thay thế tinh thể thường được sử dụng để cung cấp đồng hồ cho arduino cho mô-đun dao động tinh thể như thế này từ Farnel hoặc khác . Họ đến trong gói 4 pin như trong hình ảnh dưới đây. Họ sẽ tạo ra một đồng hồ chính xác hơn nhiều cho arduino của bạn.

Hình ảnh dao động tinh thể Hình ảnh dao động tinh thể Hình ảnh dao động tinh thể

Cả hai mô-đun được đề cập có dung sai 50 ppm và hoạt động ở mức 5V.

Một lần nữa, để rõ ràng, các mô-đun dao động tinh thể này không bị nhầm lẫn với tinh thể 2 pin thông thường như thế này dưới đây. Đó là một phần của mạch đồng hồ bên ngoài cho MCU, ví dụ.

Dao động tinh thể


DS1302 có đủ tốt hay tôi nên chuyển sang DS1307?
Kelly S. Pháp

14

Bạn không cần RTC để chế tạo đồng hồ: chip ATmega có tất cả phần cứng cần thiết để thực hiện các nhiệm vụ của chính RTC. Đây là cách thực hiện:

  1. Nhận một tinh thể đồng hồ 32768 Hz: mua nó hoặc tháo rời một chiếc đồng hồ cũ. Những tinh thể này, được thiết kế đặc biệt để giữ thời gian, có độ trôi nhiệt độ cực nhỏ. Bạn cũng sẽ cần một trong những thứ đó nếu bạn muốn sử dụng chip RTC.

  2. Định cấu hình cầu chì ATmega của bạn để chạy bộ dao động RC 8 MHz. Điều này sẽ làm cho millis()chức năng của bạn không chính xác khủng khiếp, và cũng giải phóng các chân XTAL1 và XTAL2.

  3. Kết nối tinh thể đồng hồ với các chân TOSC1 và TOSC2. Đây là các chân tương tự như XTAL1 và XTAL2 (9 và 10 trên 328P). Các tên khác nhau được sử dụng để có nghĩa là các chức năng khác nhau.

  4. Định cấu hình Timer / Counter 2 cho hoạt động không đồng bộ, chế độ đếm bình thường, bộ đếm gộp trước được đặt thành 128 và cho phép ngắt tràn bộ định thời.

Bây giờ bạn sẽ nhận được một ngắt TIMER2_OVF với tốc độ rất ổn định một lần mỗi giây. Bạn chỉ cần tiến lên hiển thị đồng hồ thêm một giây trong ISR. Ở giữa các ngắt, bạn có thể đặt MCU ở chế độ ngủ rất sâu (chế độ ngủ tiết kiệm năng lượng: không có gì chạy ngoài Timer / Counter 2) và chạy trong nhiều năm trên một vài tế bào AA. Trừ khi màn hình hiển thị là đói điện, rõ ràng.

Tôi đã làm chính xác điều này để xây dựng đồng hồ treo tường 24 giờ một tay của tôi . Liên kết này bây giờ chỉ đến bản dịch tiếng Anh của tài liệu gốc bằng tiếng Pháp.

Hiệu chuẩn thạch anh

Nếu bạn không hiệu chỉnh thạch anh của mình, bạn có thể mong đợi một sự trôi dạt đáng kể, thường là vài giây mỗi tuần . Tốc độ trôi phụ thuộc vào điện dung đi lạc của các dấu vết kết nối tinh thể với MCU. Về nguyên tắc, nó có thể được loại bỏ bằng cách thêm một số điện dung bổ sung, tinh chỉnh. Điều đáng chú ý là bạn sẽ có cùng một vấn đề trôi dạt với RTC.

Nếu bạn hài lòng với loại chính xác này, thì hãy sống với nó và hạnh phúc. Tuy nhiên, nếu bạn quan tâm để đo độ trôi, bạn sẽ nhận thấy rằng nó rất ổn định. Sau đó, bạn có thể dễ dàng bù đắp phần mềm và đạt được độ chính xác vài giây mỗi năm .

Thuật toán để sửa lỗi trôi rất đơn giản. Từ độ lệch đo được, bạn tìm ra độ trễ chính xác giữa các ngắt, rất gần với 10 9  nano giây, sau đó:

#define ONE_SECOND    1000000000  // in nanoseconds
#define ONE_INTERRUPT  999993482  // for example

ISR(TIMER2_OVF_vect)
{
    static uint32_t unaccounted_time;

    unaccounted_time += ONE_INTERRUPT;
    while (unaccounted_time >= ONE_SECOND) {
        advance_display_by_one_second();
        unaccounted_time -= ONE_SECOND;
    }
}

Trong ví dụ trên, thạch anh hơi quá nhanh và phần mềm bù lại bằng cách bỏ lỡ một vài ngày. Nếu thạch anh quá chậm, mã tương tự sẽ thay vào đó đánh dấu hai lần một vài ngày một lần.

Kiểu hiệu chuẩn này cũng có thể được thực hiện đối với RTC, nhưng nó sẽ phức tạp hơn đáng kể vì RTC báo cáo thời gian ở dạng hỏng không tự nhiên cho vay đối với các phép toán số học.


Wow đó là một thiết kế thực sự khéo léo! Tôi thực sự thích cách bạn đã đưa ra đủ hình ảnh để làm cho thiết kế rõ ràng, ngay cả đối với những người Mỹ đơn điệu ngớ ngẩn :) Tôi thực sự thích xem tài liệu dự án rõ ràng như thế này!
John Walthour

2
@ JohnWalthour: Cảm ơn! Bây giờ bạn đang khuyến khích tôi viết một bản dịch. :-)
Edgar Bonet

2
@ JohnWalthour: Xong rồi! Các liên kết bây giờ chỉ đến bản dịch tiếng Anh.
Edgar Bonet

Nói rõ hơn, khi bạn nói, "chip ATmega có tất cả phần cứng cần thiết", điều đó không hoàn toàn đúng khi bạn phải lấy một viên pha lê mới. Tôi nghĩ rằng giải pháp của bạn là trơn tru và không ở trên thay thế tinh thể nhưng tôi đã hơi bối rối khi bạn nói rằng tôi không cần phần cứng và sau đó quay lại và nói rằng tôi cần thay thế một phần cứng.
Kelly S. Pháp

@ KellyS.Fbler: Câu của tôi là, chip ATmega có tất cả phần cứng cần thiết để thực hiện các nhiệm vụ của chính RTC (nhấn mạnh thêm). Nhưng sau đó, điều quan trọng cần lưu ý là hầu hết các RTC, bao gồm DS1307 có mặt khắp nơi, cần một tinh thể bên ngoài để hoạt động. ATmega không khác: nó có tất cả những gì cần thiết để thay thế RTC , nhưng không thay thế tinh thể mà bạn sẽ phải kết nối với RTC. Hãy lưu ý rằng một RTC mô-đunnhiều hơn chỉ là một RTC, vì nó không bao gồm các tinh thể.
Edgar Bonet

6

Bộ cộng hưởng mà bạn chỉ định có độ ổn định 0,3%, trong đó bộ tạo dao động tinh thể hoặc tinh thể (như được đề cập bởi Ricardo) là 50ppm. Ổn định hơn nhiều lần. Chưa kể đến sự trôi dạt nhiệt độ của bộ cộng hưởng là khủng khiếp. Làm nóng bằng ánh sáng mặt trời sẽ thay đổi nó. Do đó, một bộ cộng hưởng không nên được sử dụng để giữ thời gian trong thời gian dài.

Do đó sử dụng một bộ dao động tinh thể hoặc tinh thể sẽ có được những gì bạn muốn. Sử dụng nó trên ATmega và đặt các cầu chì tương ứng hoặc chúng ta kết nối với một RTC.


50ppm ổn định 0,005% ở đâu?
Matthew G.

Tôi khái quát về thông số kỹ thuật đó, để giữ câu trả lời ngắn gọn. Lưu ý sự ổn định sang một bên Res. có dung sai lớn hơn nhiều và có thể khá tắt. Như John W đang trải nghiệm. "phần đúng cho công việc phù hợp"
mpflaga

Ồ, tôi chỉ tò mò về thuật ngữ @mpflaga ... mới đối với tôi.
Matthew G.

4

Nếu bạn không muốn sử dụng phần cứng bổ sung như Đồng hồ thời gian thực (ví dụ: DSDS1307), bạn có thể cải thiện đáng kể độ chính xác về thời gian bằng cách vô hiệu hóa tất cả các ngắt không sử dụng. Theo mặc định, các bản phác thảo Arduino đi kèm với các thói quen ngắt khác nhau được kích hoạt và thường chúng không được sử dụng cho bản phác thảo của bạn. Cách nhanh nhất để tìm hiểu xem bạn có thể làm mà không cần thử và vô hiệu hóa chúng bằng cách phát hànhnoInterrupts();


3
−1 (mặc dù điều này xứng đáng 4) bởi vì: 1. Trừ khi bạn thực sự cần chúng, tất cả các ngắt đều bị tắt theo mặc định, ngoại trừ duy nhất là TIMER0_OVF, cần thiết cho việc giữ thời gian. 2. Độ chính xác về thời gian của Arduinos bị giới hạn chủ yếu bởi chất lượng của bộ cộng hưởng. 3. Ngắt không ảnh hưởng đến độ chính xác millis()trừ khi bạn quản lý để dành hơn một phần nghìn giây tại một thời điểm phục vụ chúng, trong trường hợp đó bạn có vấn đề khác ... 4. Vô hiệu hóa các ngắt với noInterrupts()sẽ ngăn không millis()cho thời gian!
Edgar Bonet

2

Tôi hiểu rất nhiều tinh thần với Arduino là tiết kiệm và đôi khi lê bước qua một vấn đề. Tôi sử dụng Arduino (và giờ là chipKIT, vì nó có RAM gấp 10 lần và tốc độ xung nhịp gấp 10 lần) cho nơi làm việc của tôi và tôi cần "các chức năng ngoại vi" để tăng tốc và hoạt động nhanh nhất có thể.

Tôi sử dụng đồng hồ thời gian thực sparkfun trong một trong những dự án của tôi và rất hài lòng với nó. Họ cũng có một biến thể "Chết trên" .

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.