Kysymys:
Arduino-ajan pitäminen millis () -arvojen avulla ei ole tarkka tai oikea?
user3284376
2014-03-10 04:28:49 UTC
view on stackexchange narkive permalink

Olen käyttänyt Arduinoa joidenkin tietojen tallentamiseen. Arduino-luonnoksessa käytin myös millis () -funktiota, jotta voin seurata ajankohtaa, jolloin kukin mittaamani arvo otetaan. Huomasin kuitenkin, että ajoitus ei ole oikea. Esimerkiksi 30 sekuntia tosielämässä tulee vain 10 sekunniksi (muodostettu esimerkki).

Olenko oikeassa sanoessani, että Arduino delay -toiminto vaikuttaa ajan pitoon käyttämällä millis () ? Toisin sanoen oletetaan, että viiveeni on 50 ms, tarkoittaako tämä sitä, että millis () -toiminto pysähtyy myös kyseiseksi ajaksi ja jatkuu sitten ja niin edelleen yhteyden ajan? Huomasin tämän, kun yritin piirtää joitain tietoja ja huomata, että tietojeni piikkien taajuus oli liian usein kuluneen ajan perusteella. Joten haluan tietää, onko tämä ajoituksen epäsuhta syy, ja jos on, kuinka voin korjata tämän, jotta voin pitää ajan, jonka kukin näyte esiintyy?

Tässä on kontekstini tässä luonnoksessa :

  #include <eHealth.h> unsigned long time; // Asennusrutiini suoritetaan kerran, kun painat reset: void setup () {Serial.begin (9600); } // Silmukkarutiini kulkee yhä uudelleen ikuisesti: void loop () {float EKG = eHealth.getECG (); aika = millis (); Sarja.tulos (aika); Sarjaprintti (""); Sarjaprintti (EKG, 5); Sarja.println (""); viive (50);}  
Käytätkö yhtä virallisista Uno-taulukoista?
Todellinen ajoitus muodostettujen arvojen sijaan (sarjaviesti, joka aikaleimaa linjat on ihanteellinen) auttaisi todennäköisesti selvittämään, mitä tapahtuu.
Luvun "millis ()" laskenta keskeytetään, joten "delay ()" ei saisi vaikuttaa siihen.
Minulla on sama ongelma, mutta vain kun integroin sen (millis ()) monimutkaiseen koodiin. Luulen, että koodin monimutkaisuus vaikuttaa sen tarkkuuteen tavalla, joka viivästyy yhä enemmän koodin monimutkaisuuden kanssa. Onko mitään keinoa välttää tämä? ehkä käyttää erillistä RTC-moduulia?
Kolme vastused:
#1
+10
Cybergibbons
2014-03-10 14:15:13 UTC
view on stackexchange narkive permalink

millis () on keskeytetty, joten delay () ei vaikuta siihen, ainakaan ATmega-pohjaisella levyllä.

Se ei tarkoita sitä, että millis () on myös täysin tarkka. Kukin ajastimen rasti ei ole tarkalleen 1 ms, mutta on 1,024 ms. Tämä virhe kerääntyy vähitellen, kunnes korjaus tehdään. Tämä näkyy TIMER0_OVF (ajastin 0 ylivuoto) -katkokäsittelijän toteutuksessa.

Toinen epätarkkuuden lähde on itse oskillaattori / kide, joka ei ole aivan 16 MHz. Se on kuitenkin melko lähellä, ja niin kauan kuin lämpötila ei muutu liikaa, on suhteellisen vakaa.

Yllä oleva tarkoittaa, että saatat olla noin 1 ms: n päässä käytettäessä millis () . Tämä ei kuulosta ongelmallasi.

Toinen mahdollinen ongelma olisi se, mitä getECG () tekee - se voi olla hyvin hidasta.

  float eHealthClass :: getECG (mitätön) {float analog0; // Luettu analogisesta sisään. Analog0 = analogRead (0); // binääri-jännite-muunnoksen paluu analoginen = = (kelluva) analoginen0 * 5 / 1023,0; }  

analogRead () on hidas, mutta ei niin hidas, että se vaikuttaisi tällaiseen silmukkaan.

Toinen ongelma, jonka olen nähnyt ihmisille on, kun he muuttavat kellonopeutta, mutta eivät vaihda boards.txt-tiedostoa oikein. Tämä tarkoittaa, että millis () -toteutuksessa käytetyt vakiot ovat väärät ja ajat ovat väärät.

Jos todella haluat lukea arvoja 50 ms välein, paljon parempi tapa toteuttaa tämä tapahtuu seuraavasti:

  staattinen pitkä lastUpdate; if (millis () - lastUpdate > 50) {lastUpdate = millis (); // Tee tavaraa}  

Meidän pitäisi todella nähdä saamasi aikaleimat. Jos näet todella 30-vuotiaiden näyttävän 10-vuotiailta, työssä on jotain muuta.

Huomaa, että Unolle kello ei ole kristallivetoinen, vaan käyttää vain keraamista resonaattoria, joka on vähemmän tarkka kuin kide.
@jfpoilpret Ah hyvä tietää. [Tarkasteltaessa kaaviota] (http://arduino.cc/en/uploads/Main/Arduino_Uno_Rev3-schematic.pdf) tämä olisi CSTCE16M0V53-R0 [Murata CERALOCK -laite] (http://www.mouser.com / ProductDetail / Murata-Electronics / CSTCE16M0V53-R0 /? Qs = HPA2Xx% 252bU0WhPWbRcNuzhZw ==).
Resonaattoreilla on heikko alkutoleranssi (usein 0,5-2%) ja heikko lämpötilastabiilisuus, mutta jos kalibroit ajoitussilmukat niitä käytettäessä, ne voivat olla kunnossa niin kauan kuin lämpötila ei liiku.
Millis () toimii edelleen ajastimessa, joka tikittää 1,024 ms välein, mutta ne lisäsivät virheenkorjauksen kasvun muodossa aina, kun virhemittarin muuttuja nousee liian korkeaksi. Luulen, että se on Roman Blackin algoritmi. Joten ajoituksen tulisi olla paljon lähempänä 1 ms tarkasti. Https://github.com/arduino/Arduino/blob/master/hardware/arduino/cores/arduino/wiring.c
Niille, jotka ovat edelleen kiinnostuneita, katso kommentti, jonka olen kirjoittanut JRobertin vastaukseen. En halunnut vastata omalla vastauksellani, koska minulla ei ole sitä, olen juuri muotoillut ongelman.
Optimoitu "getECG": "float eHealthClass :: getECG (void) {return analogRead (0) * 5 / 1023.0; } `
#2
+2
JRobert
2014-03-11 21:08:00 UTC
view on stackexchange narkive permalink

Jos keskeytykset kytketään pois päältä mistä tahansa merkittävästä murto-osasta eHealth.getECG () puhelun kesto, millis () -luku saattaa jäädä jälkeen. Muussa tapauksessa millis () : n pitäisi palauttaa paljon tarkempi aika kuin kuvailemasi 3x-virheet.

Sanoit, että näytesignaalisi taajuus on korkeampi kuin odotit, mikä voi tapahtua, jos näytteenottotiheys on alhaisempi kuin aiot. Oletatko 20Hz: n näytetaajuuden? Silmukka saattaa kestää melko vähän yli 50 ms, mikä näkyisi painetuissa ajoissa, mutta niiden tulisi silti seurata kelloaikaa. Jos et ottanut sitä huomioon, mutta oletit, että olet 50 ms / näyte, näet tietojen näennäisen nopeuden.

Jos tämä ei ole ongelma, seuraava askel olisi vaihtaa tulosta, kun olet loop () -laitteessa, ja mittaa tuloksena olevan neliöaallon taajuus taajuusmittarilla (jotkut edulliset DVM: t voivat tehdä tämän) tai 'ulottuvuudella. Tee sama asia tyhjällä -silmukalla () . Ensimmäinen koe määrittää todellisen näytteenottotaajuuden tai -välin; toinen kertoo, onko millis () (ts. ajastimen0 taajuus) odotettuasi.

Olen pelannut sitä edelleen ja olen huomannut, että asia ei ole Arduinossa, millis () -toiminto toimii suurimmaksi osaksi erittäin hyvin, jotkut arvot eivät ole tarkalleen 8 ms (viive), mutta mitä olet sanonut, että on odotettavissa. Kuvaamasi 3x-virhe pätee Python-puoleen asioista, joita käytän tietojen vastaanottamiseen. Mikä tahansa idea, mistä se voi olla seurausta, käytän Pythonin pyseriaalia ja se on hitaasti helvetissä.
En tiedä tarpeeksi toteutuksestasi antaa sinulle enemmän kuin 1 / [email protected]'d-arvauksen, mutta onko Python-puoli riittävän hidas näytteiden pudottamiseksi?
#3
  0
user48711
2015-09-04 01:29:18 UTC
view on stackexchange narkive permalink

Sama täällä. Voin lisätä, että jos keskeytykset poistetaan käytöstä, mitattu aika on "reaaliaikainen". Joka tapauksessa, en ymmärrä miksi tämä viive, koska jos silmukka kestää liian kauan, millis () pitäisi joka tapauksessa palauttaa reaaliaikaiset arvot (vain siten, että kunkin arvon välillä on enemmän etäisyyttä)

Mitä "sama täällä" viittaa? Vastausten tulisi olla itsenäisiä, koska StackExchange voi järjestää asioita uudelleen (toisin kuin foorumi). Joten "sama täällä" voi tarkoittaa mitä tahansa riippuen siitä, mikä vastaus / kysymyksesi vastauksesi näkyy alla.
Tämä viesti olisi sopivampi kommentti, vaikka (tosin) sinulla ei ole riittävää mainetta.
Anteeksi, vaikka vastaat johonkin, on selvää, että se viittaa pääpostiin, muuten se olisi kommentti


Tämä Q & A käännettiin automaattisesti englanniksi.Alkuperäinen sisältö on saatavilla stackexchange-palvelussa, jota kiitämme cc by-sa 3.0-lisenssistä, jolla sitä jaetaan.
Loading...