Millis()

Fra HTX Arduino
Spring til navigation Spring til søgning

millis()[1] er en grundlæggende struktur i Arduino-miljøet, hvor man kan få en tidsmåling i millisekunder.

Funktionen har en opløsning på 1ms og den returnerer en variabel i en unsigned long, hvilket betyder at de løber over efter ca. 50 dage, det er man nødt til at tage højde for, hvis programmet skal fungere i længere tid.

Hvis man måler for den tid det tager at foretage et kald til millis(), så vil det i gennemsnit tage 1,19μs. Dette er man nødt til at tage med, hvis man ønsker at måle relativt præcist ved hjælp af kode. I denne tidsmåling er der taget højde for at loop-instruktionen tager 0,312μs for hvert loop.

Koden anvendt til denne test ligger i Denne ZIP-fil.

Overflow af millis()

Enhver variabel der tælles opad vil overflowe på et tidspunkt

Typen millis() returnerer er unsigned long fordi den lagres i 2^32 bits og kan således tælle fra 0 til 4294967295.

Hvis man regner på det, så er det 49,710 dages, altså 49 dage, 17 timer, 2 minutter og 47 sekunder, så det er ikke noget man vil opleve i en normal test, men produkter der skal kunne fungere i længere tid er nødt til at tage højde for det.

Håndtering af millis() omkring overflow[2]

Den umiddelbare måde at skrive koden på, er at man sætter en variabel til det tidspunkt hvor det næste overflow sker, og tester om millis() bliver større.

Det fungerer også fint, lige indtil man er omkring tidspunktet for overflow.

Dette har dog en uheldig sideeffekt når man lægger intervallet til og det næste tidspunkt giver overflow, så er det et lille tal, og så vil millis() være større indtil den løber over, så det vil gøre at man får lagt intervallet til hver gang man kommer forbi, hvilket virker meget uheldigt. Det vil rette sig ind igen når millis() er løbet over, men der vil gå den tid som er blevet lagt i de ekstra gange koden er kommet forbi.

Løsningen er at man i stedet trækker start-tidspunktet fra millis() og så sammenligner med intervallet. Denne subtraktion vil altid give et lille tal, også selvom millis() er løbet over.

Koden kan se ud som følger:

unsigned long startTid = 0;
const unsigned long interval = 1000;

....

  if ((millis() - startTid) > interval) {
    startTid += interval;
    ....
  }

Opbygning af et ur med millis()

Et godt argument for at bruge millis() er at opnå en præcis, så man kan bruge tiden til et ur. Det kunne gøres på følgende måde:

unsigned long startTid = 0;
const unsigned long interval = 1000;  // Et sekunds interval

byte second = 0;
byte minute = 56;
byte hour = 10;

void loop() {
  if ((millis() - startTid) > interval) {
    startTid += interval;
    second++;
    if (second >= 60) {
      second = 0;
      minute++;
      if (minute >= 60) {
        minute = 0;
        hour++;
        if (hour >= 24) {
          hour = 0;
        }
      }
    }
  }
}

Nulstilling af millis()[3]

Normalt vil det svaret på hvordan man nulstiller millis() være det gør man ikke. Man udnytter de teknikker der er angivet ovenfor, for at kunne håndtere tingene korrekt, så vil det ikke være nødvendigt at nulstille.

Skulle man alligevel have ønsket om at kunne gøre det, så kan man tiltvinge sig adgang - man skal bare sørge for at gøre det korrekt.

Den interne variabel man skal have fat i skal erklæres inden setup(). Dette gøres i følgende kode:

extern volatile unsigned long timer0_millis;

Når man vil nulstille denne variabel kan man ikke bare sætte den = 0, da millis() bliver opdateret af interrupt og variablen består af flere bytes, så man kan risikere at man kun får nulstillet en del af variablen. Dette forhindre ved at nulstille på følgende måde:

noInterrupts ();
timer0_millis = 0;
interrupts ();

Referencer

  1. Arduino reference om millis()
  2. millis Overflow fra Gammon Forum
  3. Resetting millis() to zero fra Arduinos forum
Programmering
Programmeringsbegreber Initialisering - Sekvens - Algoritme - Hexadecimal - Det Binære Talsystem - HEX-fil - ASCII - Interrupt - Events - Styresystem - Autocomplete - Selvstudie Programmering - Hour Of Code - Stepwise Improvement - Syntaks - Prog-links - Microcontroller - ChatGPT
Grundlæggende C C float - C double - C-løkker - Datatyper - Konstanter - Regnearter - Funktioner - Return - Returværdi - Rekursion - Semikolon
Variabel Typer boolean - byte - int - unsigned int - word - long - unsigned long - short - float - double - char - unsigned char - string - char array - String - object - Array - 2-dimensionelt Array - void
Program-klassikere Polling - State-machine - Trykknap - Forkant - Bagkant - Prel
Arduino Arduino til Programmering - C til Arduino - Programmering Shield - Arduino PC-software - Arduino Udviklingsmiljø - Arduino Pin Library - Funktion - Arduino Seriel - Arduino String - Arduino String Split - Arduino StateChangeDetection - setup() - loop() - Compilerdirektiver - Asynkron kommunikation - millis() - micros() - Scratch for Arduino - Send fra Arduino til Excel - [[]] - [[]]
Processing Grafik i Processing‎ - Keyboard i Processing - Mus i Processing‎ - Tid i Processing‎ - Draw() - Setup() - Tal Input til Processing - Syntaksfarvning - Kommunikation fra Arduino til Processing - Kommunikation fra Processing til Arduino
javaScript Javascript input‎ - Javascript output‎ - Javascript strukturer‎ - Javascript syntaks‎ - Tid i javaScript - Objekt‎ - AJAX
Serverprogrammering PHP - MySQL - Task Scheduler - WeMOS
PIC JAL - [[]]
Scratch for Arduino S4A Installation - S4A programmering - S4A undervisningsforløb - S4A begrænsninger
Program Dokumentation Algoritme - Flowchart - Pseudokode - Datastruktur - Dataabstraktion - Pulsplaner - Program-kommentar - Teori - Test - UML