Vraag:
Arduino tijd bijhouden met millis () is niet nauwkeurig of correct?
user3284376
2014-03-10 04:28:49 UTC
view on stackexchange narkive permalink

Ik heb de Arduino gebruikt om wat gegevens op te nemen. In mijn Arduino-sketch heb ik ook de functie millis () gebruikt, zodat ik het tijdstip kan bijhouden waarop elke waarde die ik meet, wordt genomen. Ik merkte echter dat de timing niet klopt. Bijvoorbeeld 30 seconden in het echte leven komt uit als 10 seconden (verzonnen voorbeeld).

Heb ik gelijk als ik zeg dat de Arduino-vertragingsfunctie de tijdwaarneming beïnvloedt met millis () ? Met andere woorden: stel dat ik een vertraging van 50 ms heb, betekent dat dan dat de functie millis () ook voor die duur stopt en vervolgens doorgaat, enzovoort gedurende de duur van de verbinding? Ik merkte dit toen ik probeerde wat gegevens uit te zetten en ontdekte dat de frequentie van de pieken in mijn gegevens te frequent was gezien de tijd die was verstreken. Dus ik wil weten of dat de reden is voor deze discrepantie in timing en zo ja, hoe los ik dit op zodat ik de tijd kan houden waarop elk sample voorkomt?

Om wat context te geven is hier mijn schets :

  #include <eHealth.h> unsigned lange tijd; // De setup-routine wordt eenmaal uitgevoerd wanneer u op reset drukt: void setup () {Serial.begin (9600); } // De lusroutine loopt voor altijd keer op keer: void loop () {float ECG = eHealth.getECG (); tijd = millis (); Serial.print (tijd); Serial.print (""); Serial.print (ECG, 5); Serial.println (""); delay (50);}  
Gebruik je een van de officiële Uno-borden?
Werkelijke timing in plaats van verzonnen waarden (een seriële monitor die de lijnen timestamps is ideaal) zou waarschijnlijk helpen om erachter te komen wat er aan de hand is.
De berekening van `millis ()` wordt gestuurd door onderbrekingen, dus `delay ()` zou hier geen invloed op moeten hebben.
Ik heb hetzelfde probleem, maar alleen als ik het integreer (millis ()) in complexe code. Ik denk dat de complexiteit van de code de nauwkeurigheid ervan beïnvloedt, aangezien deze steeds meer vertraagt ​​met de complexiteit van de code. Is er een manier om dit te vermijden? misschien met behulp van een aparte RTC-module?
Drie antwoorden:
Cybergibbons
2014-03-10 14:15:13 UTC
view on stackexchange narkive permalink

millis () is interrupt-gestuurd, dus delay () heeft er geen invloed op, althans niet op een op ATmega gebaseerd bord.

Dat wil niet zeggen dat millis () ook helemaal correct is. Elk tikje van de timer is niet precies 1 ms, maar is 1,024 ms. Deze fout stapelt zich geleidelijk op totdat er een correctie is aangebracht. Dit is te zien aan de implementatie van de TIMER0_OVF (timer 0 overflow) interrupt-handler.

Een andere bron van onnauwkeurigheid is de oscillator / kristal zelf, die niet precies 16 MHz is. Het is echter redelijk dichtbij, en zolang de temperatuur niet te veel verandert, is het relatief stabiel.

Het bovenstaande betekent dat je ongeveer 1 ms vrij bent bij gebruik van millis () . Dit klinkt niet als uw probleem.

Een ander mogelijk probleem zou zijn wat getECG () aan het doen is - het kan erg traag zijn.

  float eHealthClass :: getECG (void) {float analog0; // Lezen van analoog inch analog0 = analogRead (0); // binair naar spanning conversie retour analog0 = (float) analog0 * 5 / 1023.0; }  

analogRead () is traag, maar niet zo traag dat het een lus als deze beïnvloedt.

Een ander probleem dat ik heb gezien hebben is wanneer ze de kloksnelheid veranderen, maar boards.txt niet correct veranderen. Dit betekent dat de constanten die worden gebruikt in de millis () -implementatie verkeerd zijn en dat de tijden verkeerd zijn.

Als u werkelijk waarden elke 50 ms wilt lezen, is dit een veel betere manier om te implementeren dit is om het volgende te doen

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

We zouden echt de tijdstempels moeten zien die je krijgt. Als je de jaren 30 daadwerkelijk als 10en ziet, dan is er iets anders aan het werk.

Houd er rekening mee dat voor de Uno de klok niet kristalaangedreven is, maar alleen een keramische resonator gebruikt die minder nauwkeurig is dan een kristal.
@jfpoilpret Ah, goed om te weten. [Kijkend naar het schema] (http://arduino.cc/en/uploads/Main/Arduino_Uno_Rev3-schematic.pdf), zou dit het CSTCE16M0V53-R0 [Murata CERALOCK-apparaat] (http://www.mouser.com / ProductDetail / Murata-Electronics / CSTCE16M0V53-R0 /? Qs = HPA2Xx% 252bU0WhPWbRcNuzhZw ==).
Resonatoren hebben een slechte initiële tolerantie (vaak 0,5-2%) en een slechte temperatuurstabiliteit, maar als je timing-loops kalibreert wanneer je ze gebruikt, kunnen ze prima werken zolang de temperatuur niet beweegt.
Millis () werkt nog steeds op een timer die elke 1,024 ms tikt, maar ze voegden foutcompensatie toe, in de vorm van incrementering wanneer een foutmetervariabele te hoog wordt. Ik denk dat het eigenlijk het algoritme van Roman Black is. De timing zou dus veel dichter bij 1 ms moeten liggen. Https://github.com/arduino/Arduino/blob/master/hardware/arduino/cores/arduino/wiring.c
Voor degenen die nog steeds geïnteresseerd zijn, zie de opmerking die ik heb gepost op het antwoord van JRobert, ik wilde niet antwoorden met mijn eigen antwoord omdat ik er geen heb, ik heb het probleem zojuist opnieuw geformuleerd.
Een meer geoptimaliseerde `getECG`:` float eHealthClass :: getECG (void) {return analogRead (0) * 5 / 1023.0; } `
JRobert
2014-03-11 21:08:00 UTC
view on stackexchange narkive permalink

Als interrupts zijn uitgeschakeld voor een significante fractie van de eHealth.getECG () aanroepduur, kan het aantal van millis () achterblijven. Anders zou millis () een veel nauwkeurigere tijd moeten retourneren dan de 3x fouten die je hebt beschreven.

U zei dat uw gesamplede signaal hoger in frequentie lijkt dan u had verwacht, wat kan gebeuren als uw samplefrequentie lager is dan u had bedoeld. Gaat u uit van een samplefrequentie van 20 Hz? Je lus kan behoorlijk wat langer duren dan 50 ms, wat je zou zien in de afgedrukte tijden, maar die zouden nog steeds de kloktijd moeten volgen. Als je daar geen rekening mee zou houden, maar 50 ms / sample had aangenomen, zou je een schijnbare versnelling van de gegevens zien.

Als dit niet het probleem is, is de volgende stap het omschakelen van een uitvoer terwijl u zich in loop () bevindt, en meet de frequentie van de resulterende blokgolf met een frequentiemeter (sommige goedkope DVM's kunnen dit doen) of een 'scope. Doe hetzelfde met een lege loop () . Het eerste experiment zal uw werkelijke bemonsteringsfrequentie of -interval bepalen; de tweede zal je vertellen of millis () (dat wil zeggen, de timer0-frequentie) is wat je verwachtte.

Ik heb er verder mee gespeeld en ben tot het besef gekomen dat het probleem niet bij de Arduino ligt, de millis () -functie werkt voor het grootste deel heel goed, sommige waarden zijn niet precies 8ms (vertraging) van elkaar verwijderd, maar van wat je hebt gezegd dat dat te verwachten is. De 3x-fout die ik heb beschreven, geldt voor de Python-kant van de dingen die ik gebruik om de gegevens te ontvangen. Enig idee waar dat het resultaat van zou kunnen zijn, ik gebruik Python's pyserial en het is traag als de hel.
Ik weet niet genoeg over uw implementatie om u meer dan een 1 / 2@'d-schatting te geven, maar is de Python-kant traag genoeg om samples te laten vallen?
user48711
2015-09-04 01:29:18 UTC
view on stackexchange narkive permalink

Hier hetzelfde. Ik kan hieraan toevoegen dat als onderbrekingen zijn uitgeschakeld, de gemeten tijd "realtime" is. Hoe dan ook, ik begrijp niet waarom deze vertraging, want als de lus te lang duurt, zou de millis () hoe dan ook real-time waarden moeten retourneren (alleen met meer afstand tussen elke waarde)

Waar verwijst "hier hetzelfde" naar? Antwoorden zouden op zichzelf moeten staan, aangezien StackExchange dingen kan herschikken (in tegenstelling tot een forum). Dus "hetzelfde hier" kan van alles betekenen, afhankelijk van onder welk antwoord / vraag je antwoord verschijnt.
Dit bericht zou geschikter zijn als opmerking, hoewel je (toegegeven) onvoldoende reputatie hebt.
Sorry, maar als je iets beantwoordt, is het duidelijk dat het verwijst naar het hoofdbericht, anders zou het een opmerking zijn


Deze Q&A is automatisch vertaald vanuit de Engelse taal.De originele inhoud is beschikbaar op stackexchange, waarvoor we bedanken voor de cc by-sa 3.0-licentie waaronder het wordt gedistribueerd.
Loading...