Milis () kullanarak Arduino zaman tutma doğru veya doğru değil mi?


9

Bazı verileri kaydetmek için Arduino'yu kullanıyorum. Arduino çizimimde millis()fonksiyonu da kullandım, böylece ölçtüğüm her bir değerin alındığı zamanı takip edebiliyorum. Ancak, zamanlamanın doğru olmadığını fark ettim. Örneğin, gerçek hayatta 30 saniye sadece 10 saniye olarak ortaya çıkar (örnek oluşur).

Arduino gecikme işlevinin kullanmaya devam etme süresini etkilediğini söyleyerek doğru muyum millis()? Başka bir deyişle, 50 ms'lik bir gecikmeme sahip olduğumuzu varsayalım, bu millis()fonksiyonun bu süre boyunca da durduğu ve daha sonra bağlantı süresi boyunca devam ettiği anlamına mı geliyor? Bazı verileri çizmeyi ve verilerimdeki tepe noktalarının sıklığının geçen zaman göz önüne alındığında çok sık olduğunu bulmayı denediğimde bunu fark ettim. Bu yüzden bu zamanlama uyumsuzluğunun sebebi olup olmadığını bilmek istiyorum ve eğer öyleyse, nasıl her örnek oluşur zaman tutabilir böylece bunu nasıl düzeltebilirim?

Burada bir bağlam vermek benim kroki:

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

Resmi Uno kartlarından birini mi kullanıyorsunuz?
Peter Bloomfield

1
Yapılan değerler yerine gerçek zamanlama (çizgileri zaman damgalayan seri monitör idealdir) muhtemelen neler olduğunu anlamaya yardımcı olur.
Ignacio Vazquez-Abrams

3
Hesaplaması millis()kesinti güdümlüdür, bu yüzden delay()etkilememelidir.
microtherion

Ben aynı sorun var ama sadece karmaşık kod içine (millis ()) entegre zaman. Kod karmaşıklığı kod karmaşıklığı ile daha fazla gecikmeye gider şekilde doğruluğunu etkiler sanırım. Bundan kaçınmamın bir yolu var mı? ayrılmış RTC modülü kullanıyor olabilirsiniz?
Josip7171

Yanıtlar:


10

millis()kesinti güdümlüdür, bu yüzden delay()etkilemez, en azından ATmega tabanlı bir tahtada.

Bu da millis()tamamen doğru demek değildir . Zamanlayıcının her tik işareti tam olarak 1ms değil, 1.024ms'dir. Bu hata, bir düzeltme yapılana kadar yavaş yavaş birikir. Bu, TIMER0_OVF (zamanlayıcı 0 taşması) kesme işleyicisinin uygulanmasında görülebilir.

Başka bir yanlışlık kaynağı, tam olarak 16MHz olmayan osilatör / kristalin kendisidir. Yine de oldukça yakındır ve sıcaklık çok fazla değişmediği sürece nispeten kararlıdır.

Yukarıdaki, kullanırken yaklaşık 1 ms olabileceğiniz anlamına gelir millis(). Bu senin sorunun gibi görünmüyor.

Başka bir potansiyel sorun da ne getECG()olacağıdır - çok yavaş olabilir.

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() yavaştır, ancak böyle bir döngüyü etkileyecek kadar yavaş değildir.

İnsanların gördükleri başka bir sorun, saat hızını değiştirdikleri, ancak boards.txt dosyasını doğru bir şekilde değiştirmedikleri. Bu, millis()uygulamada kullanılan sabitlerin yanlış olduğu ve zamanların yanlış olduğu anlamına gelir .

Aslında her 50ms'de bir değer okumak istiyorsanız, bunu uygulamanın çok daha iyi bir yolu aşağıdakileri yapmaktır

static long lastUpdate;

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

Aldığınız zaman damgalarını gerçekten görmemiz gerekir. Aslında 30'ların 10'lar olarak görüldüğünü görüyorsanız, işte başka bir şey var.


2
Uno için saatin kristal tahrikli olmadığını, sadece bir kristalden daha az hassas bir seramik rezonatör kullandığını lütfen unutmayın.
jfpoilpret

@jfpoilpret Ah bilmek iyi. Şemaya bakıldığında , bu CSTCE16M0V53-R0 Murata CERALOCK cihazı olacaktır .
Chris O

Rezonatörlerin başlangıç ​​toleransı (genellikle% 0,5-2) ve sıcaklık stabilitesi düşüktür, ancak bunları kullanırken zamanlama döngülerini kalibre ederseniz, sıcaklık hareket etmediği sürece iyi olabilirler.
Cybergibbons

2
Millis () hala her 1.024 ms'de bir kronometre üzerinde çalışmaktadır, ancak bir hata ölçer değişkeni çok yükseldiğinde, artış şeklinde hata telafisi eklediler. Bence bu aslında Roman Black'in algoritması. Bu yüzden zamanlama tam olarak 1 ms'ye çok daha yakın olmalıdır. github.com/arduino/Arduino/blob/master/hardware/arduino/cores/…
EternityForest

Hâlâ ilgilenenler için JRobert'in cevabına gönderdiğim yoruma bakın, bir cevabım olmadığı için kendi cevabımla cevap vermek istemedim, sadece sorunu yeniden ifade ettim.
user3284376

2

Kesintiler önemli bir kesir eHealth.getECG()çağrısı süresi boyunca kapatılırsa , millis()sayımı geride kalabilir. Aksi takdirde, millis()açıkladığınız 3x hatadan çok daha doğru bir zaman döndürmelidir.

Örneklenmiş sinyalinizin frekansta beklediğinizden daha yüksek göründüğünü söylediniz. Bu, örnekleme hızınız istediğinizden düşükse gerçekleşebilir. 20Hz'lik bir örnekleme hızı var mı? Döngünüz, yazdırılan saatlerde göreceğiniz 50 ms'den biraz daha uzun sürebilir, ancak yine de saatin saatini izlemesi gerekir. Bunu hesaba katmadıysanız, ancak 50 ms / örnek kabul ettiyseniz, verilerin belirgin bir şekilde hızlandığını görürsünüz.

Sorun bu değilse, bir sonraki adım, siz bulunduğunuz sırada bir çıkışı değiştirmek loop()ve elde edilen kare dalganın frekansını bir frekans ölçerle (bazı ucuz DVM'ler bunu yapabilir) veya bir 'kapsamı ile ölçmek olacaktır. Aynı şeyi boş bir şeyle yapın loop(). İlk deney, gerçek örnekleme oranınız veya aralığınız olacaktır; ikincisi size millis()(yani, timer0 frekansının) beklediğiniz gibi olup olmadığını söyleyecektir .


1
Bununla daha fazla uğraşıyorum ve sorunun Arduino ile olmadığını, çoğunlukla millis () işlevinin çok iyi çalıştığını, bazı değerlerin tam olarak 8ms (gecikme) değil, beklenen bir şey olduğunu söyledin. Açıkladığım 3x hatası, verileri almak için kullandığım şeylerin Python tarafı için geçerlidir. Bunun ne olabileceğine dair herhangi bir fikir, Python'un psikolojik kullanıyorum ve cehennem kadar yavaş.
user3284376

1/2 @ 'den daha fazla tahminde bulunmanız için uygulamanız hakkında yeterli bilgim yok, ancak Python tarafı örnekleri bırakacak kadar yavaş mı?
JRobert

0

Burada aynı. Kesintiler kapalıysa, ölçülen sürenin "gerçek zamanlı" olduğunu ekleyebilirim. Her neyse, neden bu gecikmeyi anlamıyorum, çünkü döngü çok uzun sürerse, yine de millis () gerçek zamanlı değerleri döndürmelidir (sadece her değer arasında daha fazla mesafe ile)


1
"Burada aynı" ne anlama geliyor? StackExchange bir şeyleri yeniden sıralayabileceğinden (forumun aksine) yanıtlar kendi başlarına durmalıdır. Yani "burada aynı", cevabınızın altında hangi cevaba / soruya bağlı olduğuna bağlı olarak her şey anlamına gelebilir.
Nick Gammon

Bu yazı bir yorum olarak daha uygun olacaktır, ancak (itirafla) yeterli itibara sahip değilseniz.
Greenonline

Üzgünüm, bir şeye cevap verdiğinizde, ana
gönderiye
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.