Zoeken…


Syntaxis

  • niet-ondertekende lange millis ()

  • niet-ondertekende lange micro's ()

  • ongeldige vertraging (niet-ondertekende lange milliseconden)

  • ongeldige vertraging Microseconden (niet-ondertekende lange microseconden)

  • Zie de verouderde Millis-header voor constructors en operators van die klasse. In het kort:

    • elapsedMillis elapsedMillisObject; maakt een object om de tijd bij te houden sinds het is gemaakt of sinds een ander expliciet ingesteld tijdstip
    • elapsedMillisObject = 0; reset de tijd die door het object wordt gevolgd naar "sinds nu"
    • unsigned long deltaT = elapsedMillisObject; laten we kijken naar de bijgehouden tijd
    • elapsedMillisObject + = en - = deze werken zoals verwacht

Opmerkingen

Blokkerende versus niet-blokkerende code

Voor zeer eenvoudige schetsen kan het schrijven van blokkeercode met behulp van delay() en delayMicroseconds() geschikt zijn. Wanneer dingen complexer worden, kan het gebruik van deze functies enkele nadelen hebben. Sommige hiervan zijn:

  • CPU-tijd verspillen: complexere schetsen hebben de CPU mogelijk voor iets anders nodig in afwachting van een LED-knipperperiode.
  • onverwachte vertragingen: wanneer delay() wordt aangeroepen in subroutines die niet duidelijk worden genoemd, bijvoorbeeld in bibliotheken die u opneemt.
  • ontbrekende gebeurtenissen die plaatsvinden tijdens de vertraging en niet worden afgehandeld door een onderbrekingshandler, bijvoorbeeld pold-knopindrukken: een knop kan 100 ms worden ingedrukt, maar deze kan worden overschaduwd door een delay(500) .

Implementatie details

millis() vertrouwt meestal op een hardwaretimer die draait op een snelheid die veel hoger is dan 1 kHz. Wanneer millis() wordt aangeroepen, retourneert de implementatie enige waarde, maar je weet niet hoe oud dat eigenlijk is. Het is mogelijk dat de "huidige" milliseconde net is gestart of dat deze direct na die functieaanroep eindigt. Dat betekent dat bij het berekenen van het verschil tussen twee resultaten van millis() , u bijna alles tussen bijna nul en bijna een milliseconde kunt hebben. Gebruik micros() als een hogere precisie nodig is.

Kijkend naar de broncode van elapsedMillis onthult dat het inderdaad millis() intern gebruikt om twee punten in de tijd te vergelijken, dus het lijdt ook aan dit effect. Nogmaals, er is het alternatief verstreken elapsedMicros voor hogere precisie, uit dezelfde bibliotheek.

blinky met vertraging blokkeren ()

Een van de meest eenvoudige manieren om een LED te laten knipperen is: zet het aan, wacht een beetje, schakel het uit, wacht opnieuw en herhaal eindeloos:

// 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
}

Wachten zoals gedaan in het bovenstaande voorbeeld verspilt CPU-cycli, omdat het gewoon in een lus zit te wachten op een bepaald tijdstip om voorbij te gaan. Dat is wat de niet-blokkerende manieren, met behulp van millis() of elapsedMillis , beter doen - in de zin dat ze niet zoveel van de hardware-mogelijkheden verbranden.

Niet-blokkerende blinky met de verstreken Millis-bibliotheek (en klasse)

De elapsedMillis-bibliotheek biedt een klasse met dezelfde naam die de tijd bijhoudt die is verstreken sinds deze is gemaakt of op een bepaalde waarde is ingesteld:

#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
}

U kunt in het voorbeeld zien dat het ledTime object nul is toegewezen toen de LED-pin werd omgeschakeld. Dit is op het eerste gezicht misschien niet verrassend, maar het heeft wel effect als er meer tijdrovende dingen gebeuren:

Overweeg een situatie waarin de vergelijking tussen ledTime en PERIOD na 750 milliseconden wordt gedaan. Als u ledTime op nul ledTime betekent dit dat alle volgende ledTime 250 ms "te laat" zijn. Als PERIOD daarentegen werd afgetrokken van ledTime , zou de LED een korte periode zien en vervolgens blijven knipperen alsof er niets gebeurde.

Niet-blokkerende blinky met millis ()

Dit komt heel dicht in de buurt van een voorbeeld uit de Arduino-documenten :

// 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
}

millis() op deze manier gebruiken - om operaties op een niet-blokkerende manier te timen - is iets dat vrij vaak nodig is, dus overweeg hiervoor de elapsedMillis bibliotheek te gebruiken.

Meet hoe lang iets heeft geduurd met behulp van elapsedMillis en verstreken Micros

#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() {
}

In dit voorbeeld worden een elapsedMillis object en een elapsedMicros object gebruikt om te meten hoe lang iets heeft elapsedMicros , door ze te maken net voordat de expressie die we willen tijd wordt uitgevoerd, en hun waarden achteraf te krijgen. Ze zullen iets andere resultaten vertonen, maar het milliseconde-resultaat zal niet meer dan één milliseconde uitblijven.

Meer dan 1 taak zonder vertraging ()

Als u meer dan 1 taak hebt om herhaaldelijk met verschillende intervallen uit te voeren, gebruikt u dit voorbeeld als uitgangspunt:

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()");
}

Om een andere taak om elke 15 seconden uit te voeren toe te voegen, het uitbreiden van de variabelen intervals en last :

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

Voeg vervolgens een if instructie toe om de nieuwe taak uit te voeren. In dit voorbeeld noemde ik het thirdTask .

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

Declareer ten slotte de functie:

void thirdTask(){
  //your code here
}


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow