Arduino: ¿mejor resolución de microsegundos que micros ()?

11

La documentación de micros () señala que el valor de retorno siempre será un múltiplo de 4.

¿Hay alguna forma de obtener un clic de microsegundos de mayor resolución, preferiblemente hasta el nivel de 1 microsegundo?

Es aceptable bajar al nivel de AVR.

    
pregunta Mark Harrison

3 respuestas

9

Sí, dependiendo de la velocidad de reloj básica de tu Arduino. Por ejemplo, aquí están las frecuencias de entrada del contador / temporizador y los períodos posteriores a la escala previa, para el contador / temporizador 2 de ATMega2560, y una velocidad de reloj básica de 16MHz. El temporizador ha incorporado opciones de valor "preescalador" que determinan la frecuencia / período, que se muestra en esta tabla:

    TCCR2B bits 2-0    Prescaler    Freq [KHz], Period [usec] after prescale
          0x0          (TC stopped)      --         --
          0x1                1        16000.        0.0625
          0x2                8         2000.        0.500
          0x3               32          500.        2.000
          0x4               64          250.        4.000
          0x5              128          125.        8.000
          0x6              256           62.5      16.000
          0x7             1024           15.625    64.000

Para una mejor resolución de temporización, utiliza un valor llamado TCNT2. Hay un contador integrado que va de 0 a 255 porque el temporizador es de 8 bits. Cuando el contador alcanza el valor asignado por TCNT2, se dispara una interrupción. Esta interrupción se llama TIMER2_OVF_vect.

dada esta información, la tasa de interrupción resultante sería: 16 MHz / (prescaler * (255 - TCNT2))

Podría hacer que el temporizador se ejecute a 16MHz completos (62.5nSec), aunque es mucho más rápido de lo que necesita; 2 MHz con un recuento inicial de (255-2) le daría una tasa de interrupción de 1 MHz. Divide eso por 2 en tu ISR:

extern uint32_t MicroSecClock = 0;

ISR(TIMER2_OVF_vect) {// this is a built in function that gets called when the timer gets to the overflow counter number
  static uint_8 count;            // interrupt counter

  if( (++count & 0x01) == 0 )     // bump the interrupt counter
    ++MicroSecClock;              // & count uSec every other time.

  digitalWrite(53,toggle);// pin 53 is arbitrary
  TCNT2 = 253;                    // this tells the timer when to trigger the interrupt. when the counter gets to 253 out of 255(because the timer is 8 bit) the timmer will trigger an interrupt
  TIFR2 = 0x00;                   // clear timer overflow flag
};

La hoja de datos de su MCU es el recurso básico; este artículo le dará (¡y me dio!) una buen comienzo.

    
respondido por el JRobert
4

Mark, decidí escribir un nuevo conjunto de funciones, basado en el Arduino Atmega328 Timer2, y usando interrupciones de desbordamiento, para obtener una precisión de 0.5us. Mi código está disponible para descargar y utilizar aquí:

enlace

Aquí hay una breve descripción: "Escribí un" libary "para obtener una precisión de 0.5us en una función de reemplazo de" micros () ", de modo que puedo obtener resultados repetibles al leer una señal PWM o PPM, hasta 1us. Busqué en todo Internet y no pude encontrar algo comparable (o que era fácil de usar, y mantenía la capacidad de Arduino para escribir señales PWM a través de Servo Libary), así que creo que esta es mi primera contribución importante al mundo de Arduino y Radio Control ".

    
respondido por el Gabriel Staples
3

Si se puede bajar al nivel de AVR (como mencionó en su pregunta), puede configurar un temporizador e incluso obtener los tictacs del reloj del AVR.

Debe consultar la hoja de datos de su AVR porque difiere dentro de las diferentes ATMegas y ATTinys. Pero el procedimiento es siempre el mismo. Lo que debes hacer es:

  • decida qué prescaler va a usar (por ejemplo, establézcalo en 1, es decir, sin preescalado si desea la velocidad real del reloj de la CPU), consulte la documentación de TCCR
  • configure una interrupción por desbordamiento del temporizador, un controlador de interrupciones y active las interrupciones a nivel mundial
  • activar el temporizador en el registro de control de temporizador / contador TCCR

De esta forma puede obtener las marcas exactas del registro del temporizador, sin embargo, debe contar los desbordamientos manualmente. Esto es lo más preciso posible por la tecnología.

Aquí hay un código de ejemplo para el AT90S2313 obsoleto, pero te da buenos consejos sobre qué hacer básicamente:

/* uC: AT90S2313 */
#include <avr/io.h>
#include <avr/interrupt.h>

int main(void)
{
  // set up timer 0
  TCCR0 = (1<<CS01); // Prescaler 8

  // enable overflow interrupt
  TIMSK |= (1<<TOIE0);

  // activate interrupts
  sei();

  while(1)
  {
     /* Do whatever you like */
  }
}


ISR (TIMER0_OVF_vect)
{    
   /*
      This gets called everytime there in an overflow in the timer register  
   */
}
    
respondido por el FeeJai

Lea otras preguntas en las etiquetas