Arduino thời gian sử dụng millis () là không chính xác hay chính xác?


9

Tôi đã sử dụng Arduino để ghi lại một số dữ liệu. Trong bản phác thảo Arduino của tôi, tôi cũng đã sử dụng millis()chức năng này để tôi có thể theo dõi thời gian mà mỗi giá trị tôi đang đo được thực hiện. Tuy nhiên, tôi nhận thấy rằng thời gian không chính xác. Ví dụ 30 giây trong cuộc sống thực chỉ xuất hiện dưới dạng 10 giây (ví dụ tạo thành).

Tôi có đúng không khi nói rằng chức năng trì hoãn Arduino ảnh hưởng đến việc duy trì thời gian sử dụng millis()? Nói cách khác, giả sử tôi có độ trễ 50ms, điều đó có nghĩa là millis()chức năng cũng dừng trong khoảng thời gian đó và sau đó tiếp tục và cứ như vậy trong suốt thời gian kết nối? Tôi nhận thấy điều này khi tôi thử vẽ một số dữ liệu và thấy rằng tần số của các đỉnh trong dữ liệu của tôi quá thường xuyên trong khoảng thời gian đã trôi qua. Vì vậy, tôi muốn biết liệu đó có phải là lý do cho sự không phù hợp về thời gian này không và nếu có, làm cách nào để khắc phục điều này để tôi có thể giữ thời gian mỗi mẫu xảy ra?

Để đưa ra một số bối cảnh ở đây là bản phác thảo của tôi:

#include <eHealth.h>    

unsigned long time;
// The setup routine runs once when you press reset:
void setup() {
  Serial.begin(9600);  
}

// The loop routine runs over and over again forever:
void loop() {

  float ECG = eHealth.getECG();
  time = millis();
  Serial.print(time);
  Serial.print(" ");
  Serial.print(ECG, 5); 
  Serial.println("");    

  delay(50);
}

Bạn đang sử dụng một trong những bảng Uno chính thức?
Peter Bloomfield

1
Thời gian thực tế thay vì các giá trị tạo thành (một màn hình nối tiếp đánh dấu thời gian các dòng là lý tưởng) có thể sẽ giúp tìm ra điều gì đang xảy ra.
Ignacio Vazquez-Abrams

3
Việc tính toán millis()bị gián đoạn điều khiển, vì vậy delay()không nên ảnh hưởng đến nó.
microtherion

Tôi có cùng một vấn đề nhưng chỉ khi tôi tích hợp nó (millis ()) vào mã phức tạp. Tôi đoán độ phức tạp của mã ảnh hưởng đến độ chính xác của nó theo cách nó ngày càng đi vào sự chậm trễ với độ phức tạp của mã. Có cách nào để tránh điều này? có thể sử dụng mô-đun RTC riêng biệt?
Josip7171

Câu trả lời:


10

millis()bị gián đoạn điều khiển nên delay()sẽ không ảnh hưởng đến nó, ít nhất là không phải trên bảng dựa trên ATmega.

Điều đó không phải để nói rằng điều đó millis()là hoàn toàn chính xác. Mỗi tích tắc của bộ đếm thời gian không chính xác là 1ms, nhưng là 1.024ms. Lỗi này dần dần tích lũy cho đến khi một sự điều chỉnh được thực hiện. Điều này có thể được nhìn thấy trong quá trình thực hiện trình xử lý ngắt TIMER0_OVF (bộ đếm thời gian 0 tràn).

Một nguồn không chính xác khác là bộ tạo dao động / tinh thể, không chính xác là 16 MHz. Mặc dù vậy, nó khá gần và miễn là nhiệt độ không thay đổi quá nhiều, tương đối ổn định.

Ở trên có nghĩa là bạn có thể mất khoảng 1ms khi sử dụng millis(). Điều này không giống như vấn đề của bạn.

Một vấn đề tiềm năng khác sẽ là những gì getECG()đang làm - nó có thể rất chậm.

float eHealthClass::getECG(void)
    {
        float analog0;
        // Read from analogic in. 
        analog0=analogRead(0);
        // binary to voltage conversion
        return analog0 = (float)analog0 * 5 / 1023.0;   
    }

analogRead() là chậm, nhưng không quá chậm để tác động đến một vòng lặp như thế này.

Một vấn đề khác tôi đã thấy mọi người gặp phải là khi họ thay đổi tốc độ đồng hồ nhưng không thay đổi chính xác bảng.txt. Điều này có nghĩa là các hằng số được sử dụng trong việc millis()thực hiện là sai và thời gian là sai.

Nếu bạn thực sự muốn đọc các giá trị sau mỗi 50ms, một cách tốt hơn để thực hiện điều này là làm như sau

static long lastUpdate;

if (millis() - lastUpdate > 50)
{
    lastUpdate = millis();
    //Do stuff
}

Chúng tôi thực sự cần phải xem dấu thời gian bạn đang nhận được. Nếu bạn thực sự thấy 30s hiển thị là 10, thì có một cái gì đó khác ở nơi làm việc.


2
Xin lưu ý rằng, đối với Uno, đồng hồ không được điều khiển bằng pha lê mà chỉ sử dụng bộ cộng hưởng gốm không chính xác hơn tinh thể.
jfpoilpret

@jfpoilpret Ah tốt để biết. Nhìn vào sơ đồ , đây sẽ là thiết bị CSTCE16M0V53-R0 Murata CITHOCK .
Chris O

Bộ cộng hưởng có dung sai ban đầu kém (thường 0,5-2%) và độ ổn định nhiệt độ kém, nhưng nếu bạn hiệu chỉnh các vòng thời gian khi sử dụng chúng, chúng có thể ổn miễn là nhiệt độ không di chuyển.
Cyberg Ribbon

2
Millis () vẫn hoạt động trên bộ đếm thời gian tích tắc sau mỗi 1.024ms, nhưng họ đã thêm bù lỗi, dưới dạng tăng bất cứ khi nào một biến số của đồng hồ lỗi quá cao. Tôi nghĩ rằng đó là thuật toán của Roman Black. Vì vậy, thời gian nên gần hơn với 1ms chính xác. github.com/arduino/Arduino/blob/master/hardware/arduino/cores/ cường
EternityForest

Đối với những người vẫn quan tâm, hãy xem nhận xét mà tôi đã đăng trên câu trả lời của JRobert, tôi không muốn trả lời bằng câu trả lời của riêng mình vì tôi không có, tôi vừa viết lại vấn đề.
dùng3284376

2

Nếu ngắt bị tắt trong bất kỳ eHealth.getECG()thời lượng cuộc gọi phân đoạn đáng kể nào , millis()số lượng có thể bị tụt lại phía sau. Nếu không, millis()sẽ trả lại thời gian chính xác hơn nhiều so với các lỗi 3x bạn đã mô tả.

Bạn cho biết tín hiệu được lấy mẫu của bạn xuất hiện với tần suất cao hơn so với những gì bạn mong đợi, điều này có thể xảy ra nếu tốc độ mẫu của bạn thấp hơn bạn dự định. Bạn có giả định tốc độ mẫu 20Hz không? Vòng lặp của bạn có thể mất nhiều thời gian hơn 50ms, bạn sẽ thấy trong thời gian in, nhưng những vòng lặp đó vẫn nên theo dõi thời gian. Nếu bạn không tính đến điều đó nhưng giả sử 50ms / mẫu, bạn sẽ thấy dữ liệu tăng tốc rõ rệt.

Nếu đây không phải là vấn đề, thì bước tiếp theo sẽ là chuyển đổi đầu ra trong khi bạn vào loop()và đo tần số của sóng vuông kết quả bằng máy đo tần số (một số DVM rẻ tiền có thể thực hiện điều này) hoặc phạm vi '. Làm điều tương tự với một sản phẩm nào loop(). Thử nghiệm đầu tiên sẽ tỷ lệ lấy mẫu thực tế hoặc khoảng thời gian của bạn; thứ hai sẽ cho bạn biết liệu millis()(tức là, tần số timer0) có phải là những gì bạn mong đợi hay không.


1
Tôi đã chơi xung quanh với nó hơn nữa và nhận ra rằng vấn đề không nằm ở Arduino, chức năng millis () đối với hầu hết các phần hoạt động rất tốt, một số giá trị không cách nhau chính xác 8ms (trễ) bạn đã nói rằng đó là dự kiến. Lỗi 3x tôi mô tả là đúng với phía Python của những thứ tôi sử dụng để nhận dữ liệu. Bất kỳ ý tưởng nào có thể là kết quả của, tôi đang sử dụng pyserial của Python và nó chậm như địa ngục.
dùng3284376

Tôi không biết đủ về việc triển khai của bạn để cung cấp cho bạn nhiều hơn dự đoán 1/2 @, nhưng phía Python có đủ chậm để làm rơi mẫu không?
JRobert

0

Tương tự ở đây. Tôi có thể thêm rằng nếu các ngắt bị tắt, thời gian đo là "thời gian thực". Dù sao, tôi không hiểu tại sao độ trễ này, vì nếu vòng lặp mất quá nhiều thời gian, dù sao thì millis () sẽ trả về giá trị thời gian thực (chỉ với khoảng cách nhiều hơn giữa mỗi giá trị)


1
"Cùng ở đây" đề cập đến điều gì? Câu trả lời nên tự đứng, vì StackExchange có thể sắp xếp lại mọi thứ (không giống như một diễn đàn). Vì vậy, "giống nhau ở đây" có thể có nghĩa là bất cứ điều gì tùy thuộc vào câu trả lời / câu hỏi mà câu trả lời của bạn xuất hiện bên dưới.
Nick Gammon

Bài đăng này sẽ thích hợp hơn như một bình luận, mặc dù (phải thừa nhận) bạn thiếu danh tiếng.
Greenonline

Xin lỗi, tôi mặc dù khi bạn trả lời một cái gì đó, rõ ràng đó là đề cập đến bài viết chính, nếu không nó sẽ là một bình luận
user48711
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.