(trådstarter)
   #21
 3,587     0
Hvis eksakt tidsstempling er viktig, kan du ikke vente med å stemple til dataene har vært gjennom en "strikk-buffer"! Da jeg testet USBen, varierte i enkelte oppsett tiden for å sende 4k data fra 17 til 23 msek. Variasjonen er selvsagt mindre når lasten er mindre (både på serielinje og PC), men uansett: Data må stemples når de sankes, ikke etter "lang" transport. Det koster deg 4 byte ekstra å overføre tidsstempel til PC, selv på 9600 bps er ikke det mer enn 3 ms ekstra. (Over USB betyr det ingenting.)

millis()-funksjonen er nok relativt stabil. OM så skulle skje at annen Arduiono-aktivitet forsinker avlesingen litt, reflekteres det i tidsstempelet som en reell forsinkelse av målingen - ikke av mottaket, som kan være forsinket av andre årsaker. Dessuten tillater det at om Arduino ikke får sendt data (f.eks. fordi PC ikke svarer), og den har mulighet for å legge dem unna (i RAM eller f.eks. et SD-kort), kan data overføres senere.

Også filteringen er kurant å gjøre på Arduino. Vil du ha rapport hvert minutt (her med tidsstempel, en enkel 8-bits xor-sjekksum og en 24-bits 010101... sentinel) er det greit å kode (setup() av f.eks. pinID[] er ikke tatt med her):

long now, nextReport;
byte report[20];

loop () {
. now = millis();
. if (now >= nextReport) {
. . for (int sensor = 0; sensor < 12; sensor ++) {
. . . report[sensor] = analogRead(pinID[sensor]);
. . }
. . int *tsPtr = (int*) &(sensor[12]);
. . *tsPtr = now;
. . byte cheksum = 0;
. . for (int byteno = 0; byteno < 16; byteno++) checksum ^= report[byteno];
. . report[16] = checksum;
. . report[17] = report[18] = report[19] = 0x15;
. . Serial.write(report, 20);
. . nextReport += 60000; // next report 1 minute after this one
. }
.
. <other work to do this iteration>

"now" er ingen absolutt tidsangivelse. Må du ha det (f.eks. hvis PCen ikke aner når Arduino ble startet) kan PCen i setup() sende til Arduinoen nåværende tid, som antall ms siden vilkårlig valgt av de femten Smile referansetidspunktene nevnt under https://en.wikipedia.org/wiki/Epoch_%28reference_date%29#Notable_epoch_dates_in_computing , så kan Aruduinoen legge dette til "now" for stempling av data. (Er du skikkelig nerd, bruker du NTP for å synkronisere Arduino-klokka med PCen!)

Løkka som skaffer data (her: leser sensorer) kan naturligvis være ganske ulik den over. Hvis du mottar GPS-data kontinuerlig, må du ha to bufre: En med siste komplette linje, en som GPSen fyller inn i. GPS-handteringen bytter om bufrene når den har mottatt ei komplett linje. Når det er tid for å sende, sender du bufferen med en komplett linje, den GPSen ikke skriver i.

Siden buffer er variabel lengde er det greiest å sende tidsstempel og sjekksum først, så de har fast plass i meldingen. Siden dette er tekst, er CR en god nok sentinel - selv om 0x0D kunne forekomme i tidsstempel/sjekksum, vet mottaker at de første 5 bytes er ikke-tekstlige, og vil ikke mistolke det som linjeslutt:

#define CR 0x0D
#define LF 0x0A

byte bufA[100], bufB[100];
int usedA = 0, usedB = 0;
bool GPSusesBufA = true;
long now, nextReport;

void loop() {
. now = millis();
. if (now >= nextReport) {
. . Serial.write((byte*)(&now), 4);
. . byte checksum = 0; // checksum covers CR, no LF and no timestamp
. . byte *bufPtr = GPSusesBufA? bufB : bufA;
. . int used = GPSusesBufA? usedB : usedA;
. . for (int byteno = 0; byteno < used; byteno++) checksum ^= *(bufPtr + byteno);
. . Serial.write(checksum);
. . Serial.write(bufPtr, used);
. . nextReport += 60000; // next report 1 minute after this one
. }

. if (Serial1.available()) { // GPS byte ready, assumed to be on the Serial1 port
. . byte GPSbyte = Serial1.read();
. . if (GPSbyte != LF) { // drop LF - we use CR only as line terminator
. . . if (GPSusesBufA) bufA[usedA++] = GPSbyte;
. . . else bufB[usedB++] = GPSbyte;
. . . if (GPSbyte == CR) {
. . . . GPSusesBufA = ! GPSusesBufA;
. . . . if (GPSusesBufA) usedA = 0;
. . . . else usedB = 0;
. . . }
. . }

. <other work to do this iteration>
}

Her antar jeg at det er tilstrekkelig buffer både for sending på Serial og mottak på Serial1 at du kan sende hele linja i en jafs til PCen. Hvis ikke, blir det litt mer komplisert - du må huske hvor langt ut i bufferen du har kommet mellom hver loop()-iterasjon og sånt.

Ang. databaser: På en enbruker PC har jeg aldri hatt behov for noe syrefast databasesystem! På den annen side: I dag kaller jo folk enhver samling av tabeller for en "database". Dessuten mangler de fleste hardware for å kjøre skikkelig database-sikkerhet - selv med et SQL DBMS lagres logg og tabeller på samme disk (den eneste på maskinen!). Da er liksom halve vitsen borte den dagen disken går til h.

Jeg har ikke satt opp noen oversikt over data jeg vil samle inn, men mistenker at de havner i et regneark. Det gjør det lett å lage grafer og massere data statistisk, jamnføre f.eks. avlest energihøsting mot teoretisk beregnet solinnstråling (gjort i regnearket) og korrigert for skydekke, mengden av diffust lys etc. Excel-formatet er et zippet XML-format, og det er ganske rett fram å unzippe det og lese inn til en DOM eller XDocument-struktur, massere data, legge inn mer data og lagre det igjen. Det er jo ikke livsnødvendige data vi snakker om her, så den daglige inkrementelle backupen er sikkerhet god nok for mitt bruk. Selv om jeg i prinsipp kan tape data for en hel dag, er det ingen katastrofe.

  (trådstarter)
   #22
 3,587     0
Det er herved avslørt at jeg enda ikke i praksis har lest analoge verdier fra sensorer Smile
I den første kodesnutten over: analogRead() returnerer en int, ikke en byte, så det er flaks om koden fungerer. Går sensor-verdien over 255 går det i bøtta. Og det gjør den gjerne.
Dette som en advarsel til de som tar koden fra meg ukritisk!

(Jeg antar at kompilatoren gjør en implisitt cast fra int til byte der den bruker LSB. Men jeg er vant med at implisitt cast til et mindre tallområde gir i det minste en liten advarsel! Her ga ikke kompilatoren så mye som et knyst!)
HSt
   #23
 36,582     Lillestrøm kommune     0
For hus automasjon så lever dere trolig godt med usikkerhet på tid på noen 10-talls millisekunder. Jeg kan legge til at på PC siden så er det mulig å oppdage at klokken går bakover rundt midnatt, klokken returnerer f eks. 25:00:05 før den rygger tilbake til 00:00:00 og starter dagen på nytt. Har en kode som antar at ny tid alltid er nyere en gammel så kan en med dette få evige løkker mm. (Fant dette i PC barndommen men problemet lever fortsatt). Det finnes ellers multimetre som sender tilsvarende som GPS'en de bryr seg ikke om flyt kontroll så en må bare svelge unna alle data som kommer.
  (trådstarter)
   #24
 3,587     0
At PC-klokka går tilbake rundt midnatt har jeg aldri hørt noen som helst påstå tidligere, og jeg finner det totalt absurd at det skulle skje. Internt opererer ikke PCen med timer og minutter og sekunder, men med antall "tikk" siden oppstart. Dette er en enkel teller som telles opp med ett tikk av gangen, monotont økende, i fast tempo.

I oppstart-rutinene vil operativsystemet enten lese av "BIOS-klokka" i maskinen (den går på batteri, og fortsetter å løpe selv om du slår av maskinen og trekker ut kontakten) eller kontakte en klokketjeneste på nettet ("NTP", Network Time Protocol, evt. en annen lignende tjeneste) og bestemme hvor mange tikk bakover i tid det er til et fast tidspunkt. F.eks. for Unix/Linux: GMT midnatt 1.jan 1970 - andre operativsystemer har andre faste tidspunkter. Dette blir startverdien for tikk-telleren. Hvor lang tid det er mellom hvert tikk kan variere både med hvor kraftig PC du har og hvilket operativsystem du bruker; det kan være så "mye" som noen millisekunder og så lite som 100 nanosekunder mellom hvert tikk.

Internt brukes kun tikk-telleren til tidsavhengige operasjoner. Kun når du ber om å få et tidspunkt på time:minutt:sekund-form vil operativsystemet regne seg fram til at når man tar hensyn til alskens skuddårsregler, skuddsekunder, lokal tidssone (hvis du har bedt om å få lokal tid) etc. svarer antallet tikk i øyeblikket til 46 år, 26 dager, 22 timer, 16 minutter, 41 sekunder og 211 millisekunder. Siden tiden regnes fra 1.jan 1970, blir dette presentert som 26. jan 2016, klokka 22:16:41.211.

Denne utregningen er essensielt et halvt dusin "divisjon med rest"-operasjoner (der resten blir brukt som dividend i beregning av neste mindre enhet). Med en monotont økende startverdi er det for meg plent umulig å forstå at det skal være mulig for noen PC-klokke å "gå bakover". Dessuten: Hvis klokka reellt hadde gått bakover, ville vi sett solide krasj i zillionvis av programmer som er avhengig av at klokka oppfører seg fornuftig og ikke finner på den typen "sprell".

En liten mistanke: For mange år siden (faktisk før de første PCene!) brukte jeg en formel for å beregne ukedag for en vilkårlig dato. Det var en flyttalls-beregning med flere "uforklarlige" multiplikasjonsfaktorer med sju-åtte desimalsifre, avrundinger her og der, avrundring og modulus-operasjoner på strategiske steder i beregningen. Formelen var korrekt tilbake til en gang på 1700-tallet, men for datoer før det, bommet den - først med én dag, lenger tilbake med to, tre, fire... Det kan hende at du har vært borti en tilsvarende funksjon fra PCens barndom for å "anslå" time:minutt:sekund uten å gjøre de "tunge" modulus-beregningene man benytter i dag. Divisjon / modulus er den aller tyngste aritmetiske enkelt-operasjonen å utføre, og i PCens barndom hadde ikke CPUen logikk for divisjon; det måtte gjøres av en programvare-rutine, som kunne bruke lang tid på oppgaven! Kanskje disse estimatene også bommet litt i grenseområdene, akkurat som ukedag-beregningen, men at man så gjennom fingrene med det dengang, siden det bare skjedde rundt midnatt, og da er det jo ingen som arbeider...

Det kan hende at slike programvare-funksjoner fortsatt henger igjen enkelte steder, selv om det høres usannsynlig ut. I dag spør man operativsystemet om tiden, og prøver ikke gjøre det "bedre" eller raskere gjennom private krumspring. Hvis du mener at det faktisk i dag fortsatt er slik at operativsystemets klokke-rapportering går baklengs, da er jeg usedvanlig interessert i å se en programvaresnutt som demonstrerer fenomenet. Jeg kan love deg at hvis det faktisk er tilfelle, skal jeg bruke massevis av energi på å forfølge saken!

Ellers har du selvsagt helt rett: For det aller meste av automatist avlesing er avvik på noen millisekunder fullstendig ignorerbart. Men her var det snakk om GPS: Du installerer GPS i huset ditt for å finne ut hvor mye det beveger seg Smile. Har du en GPS, er det fordi du flytter deg rundt i terrenget. Vil du bruke GPS-dataene til å f.eks. beregne hastigheten din, da blir noen titalls millisekunder raskt ganske viktig.

Min kommentar var likevel generell: Selv om det bare er noen millisekunders forskjell mellom når du registrerer en måling og når du lagrer den, er det konseptuelt sett to ulike tidspunkter. Du kan gjerne tidsstemple verdiene når du lagrer dem, men da må du ikke kalle det avlesingstidspunktet, men lagringstidspunktet. Den som bruker dataene skal vite at verdiene er avlest "lenge" før, enten det dreier seg om millisekunder (for fartsberegning) eller minutter/timer (kanskje fordi det var trøbbel med Arduino-til-PC-kommunikasjonen, og verdiene var bufret en god stund). Hvis verdiene tidsstemples med avlesings-tidspunktet når de avleses, ikke når de overføres/lagres, da har tidsstempelet en helt annen betydning, og behandles på en annen måte.
HSt
   #25
 36,582     Lillestrøm kommune     0
Dette klokken hopper bakover er verifisert med systemkall i flere ulike datainnsamling verktøy så beklager vi vet det skjer. Men siden vi har spesialkode som nettopp unngår programkrasj så er det noen år siden jeg sist sjekket dette så kanskje er dette nå utbedret. Det henger nok sammen med koblingen mellom PC'en tick klokke og hw-klokke, jeg vil anta at det er hw-klokken som starter om døgnet noen sekunder inn i det neste døgnet. (Problemet er som nevt at systemkallene returnerer timetallet 25 før de går til 0 og når de går til 0 starter også sekundteller på 0).

Men selvfølgelig en står fritt til å ignorere informasjonen vi fant det ut når egenutviklet programvare låste seg når vi bladde i gamle logger og etterhvert oppdaget at dette var ved midnatt. Tror vi logger med ca 1.7s intervall døgnkontinuerlig.
  (trådstarter)
   #26
 3,587     0
Vet du hvilke systemkall det er som brukes?
Er det noe som skjer "en sjelden gang innimellom", eller er det regelmessig og fullt reproduserbart?

Dette må jeg sette opp en test på for å se det med mine egne øyne. Før det tror jeg rett og slett ikke på det. Beklager å være så avvisende, men som skrevet i forrige innlegg: For det første er det ingen logisk forklaring på det (og PCer er logiske, selv når vi stiller spørsmålstegn ved logikken Laughing, for det andre fordi massevis av systemer ville krasje om det var slike feil i systemkallene.

Jeg trodde du hadde skrevet feil, men når du nå gjentar time "25" antar jeg at det faktisk er det. Normalt går jo klokka fra 23:59:59 til 00:00:00, så jeg trodde du fortalte at den gikk til 24:00:00. Men du forteller at den hopper over en hel time, også...

Hadde det vært snakk om å gå til 24:00:05 kan jeg tenke meg en annen mulig forklaring: Sett at en applikasjon kjører sin egen "tidsregning". Anta for enkelhet skyld at den gjør en operasjon hvert sekund, 86400 ganger i døgnet. Operasjonen tar ikke et sekund, så når jobben er gjort, legger den seg til å sove i ett sekund minus tiden den brukte. Hvis denne beregningen gjøres i heltall, med brøkdeler kastet i bøtta, kan det hende programmet sover litt for kort tid, og får tid til mer enn 86400 runder i døgnet. Hvis det da bruker sin egen rundeteller som grunnnlag for å presentere en tt:mm:ss-verdi, kunne den komme til å passere 24:00:00 med noen sekunder. Sett at programmereren, uten å skjønne årsaken til at tiden "ikke stemmer", har som "quick fix" lagt inn en resynkronisering med systemklokka hver midnattstime. Applikasjonen tror, på grunnlag av sin egen rundeteller/klokke, at det er fem sekunder over midnatt, men så får den en korreks fra systemklokka: Nei, midnatt er nå! Da er det ikke systemklokka som går baklengs, men applikasjonen som aktivt synkroniserer sin egen litt for raske klokke med den stabile systemklokka.

Det kan godt hende at flere programmer opptrer på samme måten, hvis de bruker samme bibliotek og det er i en biblioteksfunksjon denne avkortingsfeilen befinner seg. Men biblioteker er ikke operativsystemet; det er ikke systemkall. Hvem som helst kan utvikle et sett funksjoner og tilby det som et bibliotek.

Jeg skal sette opp en liten test som skal få lov til å gå over natta og lese ut tiden mer eller mindre kontinuerlig ved hjelp av direkte systemkall. Jeg så godt som tar for gitt at jeg ikke vil se noe av det du beskriver. Da kan det forklares med at jeg brukte "feil" systemkall, at det bare skjer nå og da, at månefasen var feil eller at det bare skjer når programmet er skrevet i Visual Basic 3 og kjørt på Windows XP (eller en annen konfigurasjon som det er praktisk talt umulig å gjenskape for å få bekreftet/avkreftet at det oppførte seg slik).

Om du har en liten kodesnutt som på reproduserbart vis demonstrerer det du forteller, og jeg kan få lov til å få en kopi av kodesnutten for å teste, ville jeg sette stor pris på det!

HSt
   #27
 36,582     Lillestrøm kommune     0
Vi fant dette første gang tilbake i MS-DOS verden og har sett dette siden når vi gikk over på forskjellige Windows plattformer.  Vi har brukt en data innsamlingsapplikasjon i lang tid så jeg er ikke 100% sikker på hvilket systemkall som ligger i bunn, men når vi testet dette så reproduserte dette godt, vi fant alltid feilen.  Jeg postet det egentlig bare som et tips hvis noen får kode som låser seg, tiden er ikke økende hvis en logger tett nok.

Det er bare å stille klokken på PC'en til en god stund før midnatt og så "kjøre over midnatt" stille tilbake og gjøre det på nytt hvis en vil prøve.

Litt for mye å gjøre om dagen mens om en uke eller 2 kan jeg evt. lete litt mer hvis du ønsker flere detaljer.

Det er OS'et som resynker med CMOS klokken i PC'en og dette skjer trolig når CMos klokken tar midnatt mens PC'en bare teller opp videre og passerer dermed 25:00:00