Kysymys:
Arduinon tarkka tarkkuus sarjaliikennettä varten
user3284376
2014-03-11 14:13:09 UTC
view on stackexchange narkive permalink

Käytän Arduino Unoa lähettämään aika- ja jännitetietoja sarjaportin kautta Pythonille piirtämään. Peräkkäisten aikaleimojen välinen aikaväli näyttää kuitenkin kasvavan ajan myötä, mikä vaikuttaa piirtämiseeni. Tämä pätee erityisesti silloin, kun baudinopeudeksi on asetettu 9600, jossa alkuperäiset aikaeroni ovat ehkä 1320 ja kasvavat 16400: een suhteellisen lyhyen ajan kuluttua. Kun tämä nopeus asetetaan korkeintaan 115200 bps: iin, muutos on hitaampaa ja vähemmän havaittavaa, noin 1340: stä 1500: een, jopa suhteellisen pitkän lähetyksen jälkeen. Kaikki ajat ilmoitetaan mikrosekunteina.

Haluaisin tietää, voinko vähentää tai poistaa tämän vaikutuksen ja jos en ymmärrä miksi se on olemassa. Olen lukenut asioita häiriöistä ja viivästyksistä, jotka aiheuttavat tämän, mutta en ymmärrä täysin käsillä olevan elektroniikan monimutkaisuutta ja haluaisin tietää:

  1. Voinko saada tarkempaa ajoitusta?
  2. Mikä aiheuttaa tämän muutoksen ajoituksessa?

Tässä on mitä minulla on tällä hetkellä:

  #include <eHealth.h>extern haihtuva allekirjoittamaton pitkä ajastin0_overflow_count; float fanalog0; int analoginen0; allekirjoittamaton pitkä aika; tavu serialByte; void setup () {Serial.begin (9600);} void loop () {while (Serial.available () >0) {serialByte = Serial.read (); if (serialByte == 'S') {kun (1) {fanalog0 = eHealth.getECG (); // Käytä ajastinta0 = > 1 rasti 4: n välein joka kerta = (timer0_overflow_count << 8) + TCNT0; // Mikrosekunnin muunnos. aika = (aika * 4); // Tulosta tiedosto simulointia varten //Serial.print(time); //Serial.print (""); Sarjaprintti (fanalog0,5); Serial.print ("\ n"); if (Serial.available () >0) {serialByte = Serial.read (); jos (serialByte == 'F') rikkoutuu; }}}}}  
Mitä tarkoitat tarkalla? Laskurin antamat ajat ovat melko tarkkoja, tarkkoja ja hyvällä tarkkuudella. Haluatko, että ajat ovat deterministisiä (ts. Aina samat)?
Anteeksipyyntöjä, kyllä ​​luulen, että tarkoitin sitä, jotta niiden välinen ero olisi johdonmukainen ja jos ei, syy miksi
Lisää aikaleima PC: n päähän Arduino-pään sijaan tai käytä RTC (reaaliaikainen kello) -moduulia. RTC-moduulit ovat melko halpoja löytää useista verkkokaupoista, varmista vain, että kauppa linkittää taulukkoon. Toinen tapa on ohjelmoida ajastin ja käyttää keskeytyspalvelurutiinia kohtuullisen tarkan ajoituksen saamiseksi.
Mitä "eHealth.getECG ()" tekee? Kestääkö puhelu aina saman ajan?
Voitteko määrittää, kuinka kauan "suhteellisen lyhyt aika" kestää? Onko se aina sama Arduinon uudelleenkäynnistyksen jälkeen?
getECG () kutsuu toimintoa, joka ottaa EKG-arvon aiheeseen liitetyistä elektrodeista. Se on jännite-arvo, ja lyhyt aika kestää yleensä 10-15 sekuntia
"GetECG ()" -menetelmän lähettäminen voi auttaa selittämään havaitsemasi käyttäytymisen. Onko tämä menetelmä, jonka kirjoitit itse vai saitko sen kirjastosta?
Vaikka minulla ei ole EKG-aineistoa, olen yrittänyt toistaa kuvaamasi käyttäytymisen (ja korvannut `getECG ()` yksinkertaisella `viiveellä (10)`). 9600 bps: n nopeudella en voinut havaita muutosta ajoituksessa, kuten kuvaat.
Aikaleima PC-päässä olisi hyvä välttämään * kertyvien * virheiden syntyminen, mutta se lisää jonkin verran * värinää * johtuen * asynkronisesta paketoinnista * USB-sarjan kautta. Joten tarkkojen aikavälien suhteen lyhyellä aikavälillä olisi parempi kiinnittää aikaleima lähteeseen.
`getECG ()` muuntaa vain analogisen arvon analogisesta 0 jännitteen arvoksi 0 - 5, sen yksinkertainen laskenta.
Kolme vastused:
#1
+4
jippie
2014-03-11 22:16:43 UTC
view on stackexchange narkive permalink

Käytä ajastinta ja ISR: tä (keskeytä palvelurutiini) tarkentaaksesi ajastusta.

Katsokaa 1 ms: n ajastettua keskeytystäni. Ajatuksena on, että järjestelmässä on kohtuullisen tarkka 1 ms: n "syke", jota voidaan käyttää muiden tapahtumien käynnistämiseen. PoC: ssä sitä käytetään vilkkumaan LED-taajuudella ½ Hz, mutta pääsy uusiin muuttujiin millisecondCounter ja secondCounter antaa sinun laukaista tapahtumia pääpiirissä mielivaltaisesti (mutta tarkasti ajoitetut) hetket.

PoC: si on erittäin mielenkiintoinen, mutta siinä on virhe (helppo korjata) siinä, että se lukee 2-tavuisen arvon, kun keskeytykset ovat käytössä (`` loop (): ssa ''), ISR muuttaa tätä arvoa. Voi tapahtua, että `silmukka ()` lukee huonon arvon (keskellä ISR: n tekemää muutosta). Olen kirjoittanut kommentin blogiisi siitä.
@jfpoilpret mielenkiintoinen asia, jonka teet siellä, ei ole koskaan ajatellut keskeytystä, joka tapahtuu puolivälissä noudettaessa arvoa RAM-muistista. Tarkistan purkamisen tänä iltana ja päivitän artikkelin. Ehkä hyvä syy kirjoittaa myös toinen artikkeli: o)
Loin näytteen PoC: stä ja huomasin ongelman esiintyvän vähintään kerran 10 sekunnissa UNO: lla. Mutta tietysti todellisuudessa se riippuu suuresti siitä, mitä teet `` silmukassasi () '': näytteeni sai juuri millisekunnin arvon, vertaa sitä edelliseen luettuun arvoon ja jos ero> 0 (muu kuin nollata laskuri nollaksi), näytä viesti.
@jfpoilpret ei koskaan huomannut sitä. Käytän sitä vain sydämenlyönninä seuratessani kissojeni ruokasäiliöitä ja tekemällä LED-salaman, kun kissani voivat olla pettyneitä;
@jfpoilpret-koodi päivitetään. Täytyy istua alas kirjoittaa mukava blogi tästä. Thnx
Vaikka Uno saavuttaa helposti 1 ms: n tarkkuuden, sen aikaväli on yleensä huonompi kuin 1000 ppm. Toisin sanoen se tavallisesti kulkeutuu yli 1 ms sekunnissa. Ei ole harvinaista, että UNO: t ajautuvat yli 1 sekunnin välein 10 minuutissa.
@UdoKlein Tarkan ajan pitämiseksi sinun on kuitenkin käytettävä RTC: tä, mutta 1000ppm on paljon kideoskillaattorille. Odotin suuruusluokkaa 100ppm
UNO: lla ei ole ohjainta varten kideoskillaattoria. Siinä on vain kideoskillaattori sarjaliitäntää varten. Pääohjain suoritetaan resonaattorista. Täten UNO: n tyypillinen poikkeama on >> 1000 ppm. Vanhemmat Arduinos (kristallilla) olivat aikaisemmin ~ 30 ppm tai parempia.
@UdoKlein http: // arduino.cc / fi / uploads / Main / Arduino_Uno_Rev3-schematic.pdf näyttää edelleen 16 MHz: n kiteen.
Siinä näkyy kide, joka on kytketty lohkoon ATMEGA16U2, ja resonaattori, joka on kytketty ATMEGA328P-PU: han. 16U2 on sarjaliitäntä, 328P on "The Arduino". Kiinnostavaa kyllä, 16U2 pystyy työntämään kellonsa toiseen siruun, esim. 328P.
@UdoKlein Etsin osanumeroa ja seisoin korjattu. Hankala suunnittelupäätös.
#2
+3
zmo
2014-03-11 20:28:40 UTC
view on stackexchange narkive permalink

Voin ajatella muutamia asioita, jotka voivat vaikuttaa sarjakuvausajojen "yhdenmukaisuuteen":

  • tulostettavan datan koko

tämä voi olla ilmeisin asia ajatella, mutta todellakin mitä enemmän tulostat, sitä enemmän se kestää sen käsittelemiseksi.

Ratkaisu: tulosta muoto merkkijono tunnetun pituiseksi merkkijonoksi.

  • puskuroidun sarjakäytön avulla

unix-palvelussa pääset sarjaporttiin puskuroidulla tai puskuroimattomalla tavalla. Puskuroidun tavan käyttäminen pitkään voi tehdä siitä hieman hitaampaa puskurin täyttyessä, yleensä se tapahtuu, kun tietoja saapuu nopeammin kuin luet niitä ...

Ratkaisu: käytä puskuroimattomaa sarjaliitäntää ( eg : Darwin / OSX: ssä se on /dev/cu.usbmodemXXX /dev/tty.usbmodemXXX)

  • ajastinten prioriteetti

näyttää siltä, ​​että käytät TC-keskeytystä, ja AVR: llä on prioriteetit keskeytysten käsittelyssä, en tiedä Atmega328: n prioriteettijärjestystä, ja se ei ole yksi eniten dokumentoiduista ominaisuuksista, joten en tiedä kuinka turvallinen TC0 on verrattuna UART-keskeytykseen.

Ratkaisu: etsi keskeytysten prioriteeteista ja ajastimesta lisätietoja dokumentaatiosta / taulusta tarvittaessa ; ja / tai tee testi ilman, että toinen ajastin on käynnissä.

  • lukemasi tiedot vievät enemmän aikaa lukemiseen ajan myötä

jotkut ohjainten on keskiarvoistettava tai tehtävä joitain toimintoja edellisten arvojen yli, joten mitä enemmän arvoja mitataan, sitä pidempi puskuri on ja sitä kauemmin arvon laskeminen kestää, kunnes olet saavuttanut puskurin enimmäiskoon.

Ratkaisu: tarkastele käyttämäsi kirjaston lähdekoodia ja joko optimoi se, poista laskutapa, jos sellaista on, tai ota huomioon kasvava käsittelyaika.

  • välttämällä arduino-kehyksen yleiskustannuksia

mutta jos todella haluat optimoida arduinon sarjalähdön, sinun tulisi välttää arduinon yläpuolisen käytön käyttöä ... Mutta se on vähemmän tyylikäs ja mukava käyttää.

I ' Olen melko varma, että puuttuu muita pisteitä, mutta se on ensimmäinen asia, jonka tarkistan ennen kaivamista eteenpäin.

HTH

#3
+2
Udo Klein
2014-04-28 13:52:37 UTC
view on stackexchange narkive permalink

Koodisi sisältää lähdön keston myöhemmissä mittauksissa. Tällöin mitataan eri aikoja ulostulon pituudesta riippuen. Tämä voidaan korjata muotoilemalla kiinteän pituiseksi tulosteeksi.

Seuraava asia on, että UNO: lla on erittäin huono aikaväli. Katso täältä vertailu eri Arduino-tyypeistä DCF77-aikaviitteeseen.

Johtopäätös: jos tarvitset tarkkaa ajoitusta, hanki joko Arduino kristallilla tai siirry RTC: lle . Voin suositella erittäin tarkasti DS3231 / DS3232 RTC -laitteita, koska ne saavuttavat yleensä 2 ppm tarkkuuden heti laatikosta.



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...