Buscar..


Sintaxis

  • millis largos sin firmar ()

  • micros largos sin firmar ()

  • retraso de vacío (milisegundos largos sin firmar)

  • void delayMicroseconds (microsegundos largos sin firmar)

  • Consulte el encabezado elapsedMillis para los constructores y operadores de esa clase. En breve:

    • elapsedMillis elapsedMillisObject; crea un objeto para realizar un seguimiento del tiempo desde que se creó o desde algún otro punto de tiempo establecido explícitamente
    • elapsedMillisObject = 0; restablecer el tiempo seguido por el objeto a "desde ahora"
    • sin signo long deltaT = elapsedMillisObject; nos deja mirar el tiempo seguido
    • elapsedMillisObject + = y - = funcionan como se esperaba

Observaciones

Bloqueo contra código no bloqueante

Para bocetos muy simples, escribir código de bloqueo usando delay() y delayMicroseconds() puede ser apropiado. Cuando las cosas se vuelven más complejas, el uso de estas funciones puede tener algunos inconvenientes. Algunos de estos son:

  • Perder el tiempo de la CPU: es posible que los bocetos más complejos necesiten la CPU para otra cosa mientras esperan que termine el período de parpadeo del LED.
  • retrasos inesperados: cuando se llama a delay() en subrutinas que obviamente no se llaman, por ejemplo, en las bibliotecas que incluye.
  • eventos faltantes que ocurren durante el retraso y no son manejados por un manejador de interrupciones, por ejemplo, al presionar un botón de sondeo: un botón puede presionarse por 100 ms, pero esto puede estar sombreado por un delay(500) .

Detalles de implementacion

millis() generalmente se basa en un temporizador de hardware que se ejecuta a una velocidad que es mucho mayor que 1 kHz. Cuando se llama a millis() , la implementación devuelve algún valor, pero no se sabe qué edad tiene realmente. Es posible que el milisegundo "actual" haya comenzado, o que termine justo después de esa llamada de función. Eso significa que, al calcular la diferencia entre dos resultados de millis() , puede estar desconectado entre casi cero y casi un milisegundo. Use micros() si se necesita mayor precisión.

Al examinar el código fuente de elapsedMillis revela que, efectivamente, utiliza millis() internamente para comparar dos puntos en el tiempo, por lo que también sufre este efecto. Una vez más, hay la alternativa de elapsedMicros para una mayor precisión, desde la misma biblioteca.

bloqueando blinky con retraso ()

Una de las formas más directas de hacer que parpadee un LED es: enciéndalo, espere un poco, apáguelo, espere de nuevo y repita sin cesar:

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

Sin embargo, esperar como se hace en el ejemplo anterior desperdicia los ciclos de la CPU, ya que simplemente permanece allí en un bucle esperando que pase un cierto punto en el tiempo. Eso es lo que hacen mejor las formas de no bloqueo, utilizando millis() o elapsedMillis , en el sentido de que no queman la mayor parte de las capacidades del hardware.

Blinky sin bloqueo con la librería elapsedMillis (y clase)

La biblioteca elapsedMillis proporciona una clase con el mismo nombre que realiza un seguimiento del tiempo transcurrido desde que se creó o se estableció en un determinado valor:

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

Puede ver en el ejemplo que al objeto ledTime se le asigna un cero cuando se ledTime el pin LED. Esto puede no ser sorprendente a primera vista, pero tiene un efecto si suceden cosas que consumen más tiempo:

Considere una situación en la que la comparación entre ledTime y PERIOD se realiza después de 750 milisegundos. Luego, establecer ledTime en cero significa que todas las siguientes operaciones de conmutación tendrán un retraso de 250 ms. Si, por el contrario, el PERIOD se resta de ledTime , el LED verá un período corto y luego continuará parpadeando como si no hubiera pasado nada.

Blinky sin bloqueo con milis ()

Esto está muy cerca de un ejemplo de la documentación de 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
}

El uso de millis() de esta manera (para elapsedMillis las operaciones de manera no bloqueante) es algo que se necesita con bastante frecuencia, así que considere usar la biblioteca de elapsedMillis para esto.

Mida cuánto tiempo tomó algo, utilizando elapsedMillis y 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() {
}

En este ejemplo, un objeto elapsedMillis y un objeto elapsedMicros se utilizan para medir cuánto tiempo tardó algo, al crearlos justo antes de que se ejecute la expresión que queremos medir y obtener sus valores posteriormente. Mostrarán resultados ligeramente diferentes, pero el resultado de milisegundos no se desactivará en más de un milisegundo.

Más de 1 tarea sin demora ()

Si tiene más de 1 tarea para ejecutar repetidamente en diferentes intervalos, use este ejemplo como punto de partida:

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

Para agregar otra tarea para ejecutar cada 15 segundos, extienda los intervals las variables y last :

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

Luego agrega una sentencia if para ejecutar la nueva tarea. En este ejemplo, lo nombré thirdTask .

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

Finalmente declarar la función:

void thirdTask(){
  //your code here
}


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow