Ricerca…


Sintassi

  • longless non firmati ()

  • micros lungo non firmato ()

  • ritardo vuoto (millisecondi lunghi senza segno)

  • void delayMicroseconds (microsecondi lunghi non firmati)

  • Vedi l'intestazione di ElisedMillis per costruttori e operatori di quella classe. In breve:

    • elapsedMillis elapsedMillisObject; crea un oggetto per tenere traccia del tempo da quando è stato creato o da qualche altro punto nel tempo esplicitamente impostato
    • elapsedMillisObject = 0; resettare il tempo tracciato dall'oggetto su "da ora"
    • deltaT lungo non firmato = elapsedMillisObject; lasciaci guardare il tempo tracciato
    • elapsedMillisObject + = and - = questi funzionano come previsto

Osservazioni

Blocco contro codice non bloccante

Per schizzi molto semplici, scrivere codice di blocco usando delay() e delayMicroseconds() può essere appropriato. Quando le cose diventano più complesse, l'uso di queste funzioni può avere alcuni inconvenienti. Alcuni di questi sono:

  • Sprecare tempo della CPU: schizzi più complessi potrebbero aver bisogno della CPU per qualcos'altro mentre si attende la fine di un periodo di intermittenza del LED.
  • ritardi imprevisti: quando delay() viene chiamato in subroutine che non sono ovviamente chiamate, ad esempio nelle librerie incluse.
  • eventi mancanti che si verificano durante il ritardo e non vengono gestiti da un gestore di interruzioni, ad esempio la pressione di un pulsante di polling: un pulsante potrebbe essere premuto per 100 ms, ma potrebbe essere ombreggiato da un delay(500) .

Dettagli di implementazione

millis() solito si basa su un timer hardware eseguito a una velocità molto più alta di 1 kHz. Quando viene chiamato millis() , l'implementazione restituisce un valore, ma non si sa quanti anni sia effettivamente. È possibile che il millisecondo "corrente" sia appena iniziato o che termini dopo la chiamata di funzione. Ciò significa che, quando si calcola la differenza tra due risultati da millis() , si può avere un valore compreso tra quasi zero e quasi un millisecondo. Usa micros() se è necessaria una maggiore precisione.

Esaminando il codice sorgente di elapsedMillis rivela che utilizza effettivamente millis() internamente per confrontare due punti nel tempo, quindi soffre anche di questo effetto. Anche in questo caso, esiste l'alternativa elapsedMicros per una maggiore precisione, dalla stessa libreria.

blocco lampeggiante con ritardo ()

Uno dei modi più semplici per far lampeggiare un LED è: accenderlo, attendere un po ', spegnerlo, attendere ancora e ripetere all'infinito:

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

Tuttavia, l'attesa come nell'esempio precedente spreca i cicli della CPU, perché si limita a rimanere in attesa di un determinato punto nel tempo. Questo è quello che i modi non bloccanti, usando millis() o elapsedMillis , fanno meglio - nel senso che non bruciano gran parte delle capacità dell'hardware.

Bloccato non bloccante con la libreria di Mills (e la classe) trascorsa

La libreria ElapsedMillis fornisce una classe con lo stesso nome che tiene traccia del tempo trascorso da quando è stato creato o impostato su un determinato valore:

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

Nell'esempio si può vedere che l'oggetto ledTime è assegnato a zero quando il pin del LED è stato commutato. Questo potrebbe non essere sorprendente a prima vista, ma ha un effetto se stanno accadendo cose che richiedono più tempo:

Si consideri una situazione in cui il confronto tra ledTime e PERIOD viene eseguito dopo 750 millisecondi. Quindi impostare ledTime su zero significa che tutte le successive operazioni di commutazione saranno 250 ms "in ritardo". Se, al contrario, il PERIOD stato sottratto da ledTime , il LED vedrebbe un breve periodo e quindi continua a lampeggiare come se nulla fosse accaduto.

Bloccato non bloccante con millis ()

Questo è molto simile a un esempio dei documenti arduino :

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

L'uso di millis() in questo modo - per operazioni temporali in modo non bloccante - è qualcosa che è necessario abbastanza spesso, quindi considerate di utilizzare la libreria elapsedMillis per questo.

Misurare quanto tempo è durato qualcosa, utilizzando la Millis trascorsa e il Microfono trascorso

#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 questo esempio, un oggetto elapsedMillis e un oggetto elapsedMicros vengono utilizzati per misurare quanto tempo è durato qualcosa, creandoli appena prima dell'esecuzione dell'espressione che vogliamo utilizzare per il tempo e ottenendo successivamente i loro valori. Mostreranno risultati leggermente diversi, ma il risultato del millisecondo non sarà inferiore a più di un millisecondo.

Più di 1 attività senza ritardo ()

Se hai più di 1 compito da eseguire ripetutamente a intervalli diversi, usa questo esempio come punto di partenza:

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

Per aggiungere un'altra attività da eseguire ogni 15 secondi, estendere gli intervals variabili e last :

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

Quindi aggiungere un'istruzione if per eseguire la nuova attività. In questo esempio, l'ho chiamato thirdTask .

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

Alla fine dichiara la funzione:

void thirdTask(){
  //your code here
}


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow