Seri iletişim için Arduino'da yüksek hassasiyetli zamanlama


11

Çizmek için Python seri port üzerinden zaman ve gerilim bilgileri göndermek için bir Arduino Uno kullanıyorum. Ancak, ardışık zaman damgaları arasındaki aralık zamanlamaları zaman içinde artmakta ve çizimimi etkilemektedir. Bu özellikle baud hızı 9600 olarak ayarlandığında doğrudur, burada başlangıçtaki zaman farklarım 1320 olabilir ve nispeten kısa bir süre sonra 16400'e yükselir. Bu oran maksimum 115200 bps'ye getirildiğinde, nispeten daha uzun bir gönderme işleminden sonra bile 1340 ila 1500 arasında değişiklik daha yavaş ve daha az fark edilir. Tüm süreler mikrosaniye olarak verilir.

Bu etkiyi azaltıp azaltamayacağımı veya ortadan kaldırabileceğimi ve neden var olduğunu anlamadıysam bilmek istiyorum. Buna neden olan kesintiler ve gecikmeler hakkında bir şeyler okudum, ancak eldeki elektroniklerin karmaşıklığını tam olarak takdir etmiyorum ve bilmek istiyorum:

  1. Zamanlamada daha fazla hassasiyet alabilir miyim?
  2. Zamanlamadaki bu değişikliğe ne sebep olur?

Şu anda sahip olduğum şey:

#include <eHealth.h>

extern volatile unsigned long timer0_overflow_count;
float fanalog0;
int analog0;
unsigned long time;    

byte serialByte;
void setup() {
  Serial.begin(9600);
}

void loop() { 
  while (Serial.available()>0){  
    serialByte=Serial.read();
    if (serialByte=='S'){        
      while(1){
        fanalog0=eHealth.getECG();  
        // Use the timer0 => 1 tick every 4 us
        time=(timer0_overflow_count << 8) + TCNT0;        
        // Microseconds conversion.
        time=(time*4);   
        //Print in a file for simulation
        //Serial.print(time);
        //Serial.print(" ");
        Serial.print(fanalog0,5);
        Serial.print("\n");

        if (Serial.available()>0){
          serialByte=Serial.read();
          if (serialByte=='F')  break;
        }
      }
    }
  }
}

"Kesin" ile ne demek istiyorsun? Sayaç tarafından verilen zamanlar oldukça hassas, doğru ve iyi bir çözünürlükle olacaktır. Zamanların deterministik olmasını ister misiniz (yani her zaman aynı)?
Cybergibbons

Özür dilerim, evet, demek istediğim budur, aralarındaki farkın tutarlı olması ve değilse, neden olmamalarının nedeni
user3284376

Zaman damgasını Arduino ucu yerine PC ucuna ekleyin veya bir RTC (gerçek zamanlı saat) modülü kullanın. RTC modülleri çeşitli web mağazalarında bulmak oldukça ucuz, sadece mağazanın veri sayfasına bağlandığından emin olun. Başka bir yöntem, bir zamanlayıcıyı programlamak ve makul doğru zamanlama elde etmek için bir kesme servis rutini kullanmaktır.
Mart'ta jippie

Ne yapar eHealth.getECG()? Bu çağrı her zaman aynı miktarda mı sürüyor?
jfpoilpret

"Nispeten kısa bir süre" nin ne kadar süreceğini belirtebilir misiniz? Arduino'yu yeniden başlattıktan sonra her zaman aynı mıdır?
jfpoilpret

Yanıtlar:


4

Zamanlamayı daha doğru hale getirmek için bir zamanlayıcı ve ISR (kesme servisi rutini) kullanın.

Benim 1 ms zamanlamalı kesme Proof of Concept'e bir göz atın . Fikir, sistemde diğer olayları tetiklemek için kullanılabilecek makul derecede doğru bir 1ms 'kalp atışı' sağlamaktır. PoC yılında yeni değişkenlere bir ½Hz de LED, ancak sahip erişimi yanıp için kullanılır millisecondCounterve secondCounteranları İsteğe bağlı olmak ana döngüde tetikleme olayları sağlar (ama doğru zamanlanmış).


2
PoC'niz çok ilginç ama kesintiler etkinleştirilirken (içeri) 2 baytlık bir değer okuması gerçeğinde bir kusur (düzeltilmesi kolay loop()) var, bu değer bir ISR tarafından değiştiriliyor. loop()Kötü bir değer okuyabilir (ISR tarafından yapılan bir modifikasyonun ortasında) olabilir. Blogunuzla ilgili bir yorum gönderdim.
jfpoilpret

@jfpoilpret orada ilginç bir nokta, asla RAM'den değeri alırken yarı yolda meydana gelen bir kesinti düşünmedim. Bu akşam demontajı kontrol edip makaleyi güncelleyeceğim. Belki de başka bir makale yazmak için iyi bir neden: o)
jippie

PoC'nizden bir örnek oluşturdum ve sorunun UNO'mda en az 10 saniyede bir meydana geldiğini görebiliyordum. Ama elbette gerçekte sizin yaptığınız şeye çok bağlıdır loop(): örneğim milisaniye değerini aldı, önceki okuma değerine saldıracak ve fark> 0 (sayacı 0'a sıfırlamak dışında) bir mesaj gösterecektir.
jfpoilpret

@jfpoilpret bunu gerçekten hiç farketmedi. Ben sadece kedilerim için yiyecek kovalarını izlemek ve kedilerim potansiyel olarak hayal kırıklığına uğrayacağında bir LED flaş yapmak için bir kalp atışı olarak kullanıyorum ...; o) Gelecekte ISR'leri kullanma şeklimi kesinlikle değiştirecek.
Mart'ta jippie

1
Bir ATMEGA16U2 bloğuna bağlı bir kristal ve ATMEGA328P-PU'ya bağlı bir rezonatör gösterir. 16U2 seri arayüz içindir, 328P "Arduino" dur. İlginçtir ki, 16U2 saatini başka bir çipe, örneğin 328P'ye itebilir.
Udo Klein

3

Seri yazma zamanlamalarının "tutarlılığını" etkileyebilecek birkaç şey düşünebilirim:

  • yazdırılacak verinin boyutu

bu düşünülmesi gereken en açık şey olabilir, ancak gerçekten ne kadar çok yazdırırsanız, o kadar çok işlem yapmanız gerekir.

Çözüm: dizeyi bilinen uzunlukta bir dizeye yazdırın.

  • arabelleğe alınmış seri kullanma

unix'te seri bağlantı noktasına arabelleğe alınmış veya arabelleğe alınmamış bir yolla erişebilirsiniz. Arabelleğe alınan yöntemi uzun süre kullanmak, arabellek dolarken biraz yavaşlayabilir, genellikle veri okuduğunuzdan daha hızlı geldiğinde olur…

Çözüm: Tamponsuz seri hattını kullanın ( örneğin : /dev/cu.usbmodemXXXyerine Darwin / OSX'te /dev/tty.usbmodemXXX)

  • zamanlayıcıların önceliği

Bir TC kesmesi kullandığınıza benziyor ve AVR'lerin kesmelerin ele alınışında öncelikleri var, Atmega328 için öncelik sırasını bilmiyorum ve etraftaki en belgelenmiş özelliklerden biri değil, bu yüzden bilmiyorum TC0 ile UART kesintisine karşı ne kadar güvenlidir.

Çözüm: Belgelere / veri sayfasında kesme öncelikleri hakkında daha fazla bilgi edinin ve gerekirse zamanlayıcıyı değiştirin; ve / veya diğer zamanlayıcıyı çalıştırmadan bir test yapın.

  • okuduğunuz verilerin zaman içinde okunması daha fazla zaman alır

bazı sürücülerin önceki değerler üzerinde ortalama işlem yapması veya bazı işlemler yapması gerekir.

Çözüm: Kullandığınız kütüphanenin kaynak koduna bakın ve optimize edin, varsa hesabı kaldırın veya artan işlem süresini dikkate alın.

  • Arduino çerçeve yükünden kaçınmak

Eğer varsa ama gerçekten arduino seri çıkışı optimize etmek istiyorsanız, arduino yükü kullanmaktan kaçınmalısınız ... Ama 's yolu daha az zarif ve konforlu kullanım.

Eminim eksik olduğum başka noktalar da var, ancak daha fazla kazmadan önce kontrol edeceğim ilk şeyler.

HTH


2

Kodunuz, sonraki ölçümlerde çıktının süresini içerir. Böylece çıktının uzunluğuna bağlı olarak farklı zamanları ölçeceksiniz. Bu, sabit uzunluktaki çıktıya biçimlendirilerek sabitlenebilir.

Bir sonraki konu, UNO'nun çok zayıf bir zaman tabanına sahip olmasıdır. DCF77 zaman referansı ile farklı Arduino tiplerinin karşılaştırması için buraya bir göz atın .

Sonuç: Hassas zamanlamaya ihtiyacınız varsa ya kristalli bir Arduino alın ya da bir RTC alın. DS3231 / DS3232 RTC'leri kesinlikle tavsiye ederim, çünkü bunlar genellikle kutudan 2 ppm doğruluk sağlar.

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.