Sök…


Syntax

  • osignerad lång millis ()

  • osignerade långa mikros ()

  • ogiltig fördröjning (osignerade långa millisekunder)

  • void delayMicroseconds (osignerade långa mikrosekunder)

  • Se den förflutna Millis-rubriken för konstruktörer och operatörer i den klassen. Kortfattat:

    • elapsedMillis elapsedMillisObject; skapar ett objekt för att hålla reda på tiden sedan den skapades eller eftersom någon annan uttryckligen ställd tidpunkt
    • elapsedMillisObject = 0; återställa tiden som spåras av objektet till "sedan nu"
    • osignat långt deltaT = förflutetMillisObject; låter oss titta på den spårade tiden
    • elapsedMillisObject + = och - = dessa fungerar som förväntat

Anmärkningar

Blockering kontra icke-blockerande kod

För mycket enkla skisser kan det vara lämpligt att skriva blockeringskod med delay() och delayMicroseconds() . När saker och ting blir mer komplicerade kan användningen av dessa funktioner ha vissa nackdelar. Några av dessa är:

  • Slösa bort CPU-tid: Mer komplexa skisser kan behöva CPU för något annat medan du väntar på att en LED-blinkande period slutar.
  • oväntade förseningar: när delay() kallas i subroutiner som inte uppenbarligen kallas, till exempel i bibliotek som du inkluderar.
  • saknade händelser som inträffar under förseningen och som inte hanteras av en avbrottshanterare, till exempel pressade knapptryckningar: En knapp kan tryckas in i 100 ms, men detta kan skuggas av en delay(500) .

Implementeringsinformation

millis() förlitar sig vanligtvis på en hårdvarutimer som kör med en hastighet som är mycket högre än 1 kHz. När millis() kallas returnerar implementeringen ett värde, men du vet inte hur gammalt det faktiskt är. Det är möjligt att det "nuvarande" millisekundet just har börjat, eller att det kommer att avslutas direkt efter det funktionssamtalet. Det betyder att när du beräknar skillnaden mellan två resultat från millis() kan du vara av med allt mellan nästan noll och nästan ett millisekund. Använd micros() om högre precision behövs.

elapsedMillis att elapsedMillis källkoden för elapsedMillis avslöjas att den verkligen använder millis() internt för att jämföra två punkter i tid, så det lider också av denna effekt. Återigen finns det alternativet elapsedMicros för högre precision, från samma bibliotek.

blockerar blinkande med försening ()

Ett av de mest raka sätten att få en LED-blinkning är: slå på den, vänta lite, stäng av den, vänta igen och upprepa oändligt:

// set constants for blinking the built-in LED at 1 Hz
#define OUTPIN LED_BUILTIN
#define PERIOD 500

void setup()
{
  pinMode(OUTPIN, OUTPUT);      // sets the digital pin as output
}

void loop()
{
  digitalWrite(OUTPIN, HIGH);   // sets the pin on
  delayMicroseconds(PERIOD);        // pauses for 500 miliseconds      
  digitalWrite(OUTPIN, LOW);    // sets the pin off
  delayMicroseconds(PERIOD);        // pauses for 500 milliseconds

  // doing other time-consuming stuff here will skew the blinking
}

Men att vänta som gjort i exemplet ovan slösar CPU-cykler, eftersom det bara sitter där i en slinga och väntar på att en viss tidpunkt ska gå förbi. Det är vad de icke-blockerande sätten, med millis() eller elapsedMillis , gör bättre - i den meningen att de inte bränner så mycket av maskinvarans kapacitet.

Blinkar inte med det förflutnaMillis-biblioteket (och klass)

Det förflutnaMillis-biblioteket ger en klass med samma namn som håller reda på tiden som gick sedan det skapades eller sattes till ett visst värde:

#include <elapsedMillis.h>

#define OUTPIN LED_BUILTIN
#define PERIOD 500

elapsedMillis ledTime;

bool ledState = false;

void setup() 
{                
  // initialize the digital pin as an output.
  pinMode(OUTPIN, OUTPUT);     
}

void loop()
{
    if (ledTime >= PERIOD) 
    {                
        ledState = !ledState;
        digitalWrite(OUTPIN, ledState);
        ledTime = 0;
    }
    // do other stuff here
}

Du kan se i exemplet att ledTime objektet tilldelas noll när LED-stiftet växlades. Detta kanske inte är förvånande vid första anblicken, men det har en effekt om mer tidskrävande saker händer:

Överväg en situation där jämförelsen mellan ledTime och PERIOD görs efter 750 millisekunder. ledTime ställer ledTime till noll betyder det att alla följande växlingsoperationer kommer att vara 250 ms "sent". Om PERIOD , PERIOD , subtraherades från ledTime , skulle lysdioden se en kort period och fortsätta att blinka som om ingenting hänt.

Detta är mycket nära ett exempel från arduino docs :

// set constants for blinking the built-in LED at 1 Hz
#define OUTPIN LED_BUILTIN
#define PERIOD 500  // this is in milliseconds

int ledState = LOW;

// millis() returns an unsigned long so we'll use that to keep track of time
unsigned long lastTime = 0;

void setup() {
  // set the digital pin as output:
  pinMode(OUTPIN, OUTPUT);
}

void loop() {
  unsigned long now = millis();
  if (now - lastTime >= PERIOD) // this will be true every PERIOD milliseconds
  {
    lastTime = now;
    if (ledState == LOW)
    {
      ledState = HIGH;
    }
    else
    {
      ledState = LOW;
    }
    digitalWrite(OUTPIN, ledState);
  }

  // now there's lots of time to do other stuff here
}

Att använda millis() på detta sätt - till tidsoperationer på ett icke-blockerande sätt - är något som behövs ganska ofta, så elapsedMillis använda det elapsedMillis biblioteket för detta.

Mät hur lång tid något tog med hjälp av elapsedMillis och elapsedMicros

#include <elapsedMillis.h>

void setup() {
  Serial.begin(115200);
  elapsedMillis msTimer;
  elapsedMicros usTimer;

  long int dt = 500;
  delay(dt);

  long int us = usTimer;
  long int ms = msTimer;

  Serial.print("delay(");Serial.print(dt);Serial.println(") took");
  Serial.print(us);Serial.println(" us, or");
  Serial.print(ms);Serial.println(" ms");
}

void loop() {
}

I det här exemplet används ett elapsedMillis objekt och ett elapsedMicros objekt för att mäta hur lång tid något tog, genom att skapa dem strax innan uttrycket vi vill att tiden körs och få sina värden efteråt. De kommer att visa något olika resultat, men millisekundresultatet kommer inte att vara av med mer än ett millisekund.

Mer än 1 uppgift utan dröjsmål ()

Om du har mer än 1 uppgift att utföra upprepade gånger med olika intervall, använd detta exempel som utgångspunkt:

unsigned long intervals[] = {250,2000}; //this defines the interval for each task in milliseconds
unsigned long last[] = {0,0};           //this records the last executed time for each task

void setup() {
  pinMode(LED_BUILTIN, OUTPUT); //set the built-it led pin as output
  Serial.begin(115200);         //initialize serial
}

void loop() {
  unsigned long now = millis();
  if(now-last[0]>=intervals[0]){ last[0]=now; firstTask(); }
  if(now-last[1]>=intervals[1]){ last[1]=now; secondTask(); }
  
  //do other things here
}

void firstTask(){
  //let's toggle the built-in led
  digitalWrite(LED_BUILTIN, digitalRead(LED_BUILTIN)?0:1);
}

void secondTask(){
  //say hello
  Serial.println("hello from secondTask()");
}

För att lägga till en annan uppgift att utföra var 15: e sekund, förläng variablernas intervals och last :

unsigned long intervals[] = {250,2000,15000};
unsigned long last[] = {0,0,0};

Lägg sedan till ett if uttalande för att utföra den nya uppgiften. I det här exemplet thirdTask jag det thirdTask .

if(now-last[2]>=intervals[2]){ last[2]=now; thirdTask(); }

Förklara slutligen funktionen:

void thirdTask(){
  //your code here
}


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow