El temporizador de ATtiny13A parece ser muy inexacto, ¿es normal? [cerrado]

2

Escribí este programa de parpadeo para mi ATtiny13A y traté de medir la precisión con un Arduino Uno, pero el temporizador parece ser bastante inexacto. En el ATtiny estoy ejecutando el reloj internal 128KHz y estoy usando los temporizadores para hacer pin0 alto y bajo con una frecuencia de 1Hz .

Aquí está el código ATtiny:

int main(void){

  DDRB = 0;
  TCCR0A = 0;
  PORTB = 0;

  DDRB |= (1 << DDB0);      // pin0 output

  TCCR0A |= (1 << WGM01);   //CTC mode
  TCCR0A |= (1 << COM0A0);  //toggle OC0A on compare match

  TCCR0B |= (1 << CS02) | (1 << CS00); //1024 prescalar
  OCR0A = 124;              //1Hz @ 128KHz internal clock

  while(1){ 
  }

  return 0;
}

En el Arduino, estoy usando interrupciones para medir el tiempo entre cada señal alta / baja. Es un Uno estándar con un cristal externo de 16Mhz. Aquí está el código de Arduino:

unsigned long lastHigh = 0;

void setup() {
  Serial.begin(9600);
  const byte interruptPin = 2;
  attachInterrupt(digitalPinToInterrupt(interruptPin), myISR, CHANGE);
}

void loop() {
}

void myISR(){
  unsigned long temp = micros();    //store it ASAP to minimize delay
  Serial.println(temp - lastHigh);
  lastHigh = temp;
}

He tirado el pin 2 en el Arduino a tierra con una resistencia de 1K, y lo conecté al pin 0 de la ATtiny13A.

Esperaba leer un 1 perfecto entre cada parpadeo, pero aquí están mis lecturas (en microsegundos):

  

1063616 1062696 1063608 1062696 1063636 1062692 1063608 1062680   1063576 1062580 1063512 1062676 1063576 1062660 1063584 1062680   1063580 1062672 1063596 1062700 1063596 1062688 1063604 1062680   1063596 1062612 1063528 1062668 1063580 1062680 1063588 1062684

Como puede ver, el temporizador no solo está apagado durante ~ 60 milisegundos, sino que también tiembla mucho.

Leí en Internet que el reloj interno no es preciso pero no estoy seguro de que ~ 60 ms sea demasiado inexacto o no.

Además de estar fuera, los tiempos también son muy inquietos. Pasan de 106 2 580 a 106 3 680 microsegundos.

Soy bastante inexperto y estoy realmente curioso si este nivel de inexactitud se considera normal o no. Me pareció extraño porque 1000us inquietud hace que las funciones micros() o _delay_us() sean bastante inútiles.

    
pregunta Pouria P

2 respuestas

3

Entonces, estás viendo un + 6% de desviación y ± 0.05% de jitter.

La devación.

No pude encontrar nada en el oscilador interno de 128 kHz, pero el oscilador interno de 4.8 / 9.6 MHz tiene una precisión predeterminada de ± 10% a un voltaje y temperatura específicos. Consulte la sección 18.4.1 (página 119) de la hoja de datos :

Sospechoqueelosciladorde128kHzessimilar,porloquesospechoqueel+6%esin-specparamí.Puedecalibrarelosciladorinternoparaobtenerunamejorprecisión,consultelanotaAVR053deAtmel: Calibración de oscilador RC interno para dispositivos tinyAVR y megaAVR .

También debes ver la forma en que estás usando el temporizador; No tiene un controlador de interrupción definido, así que creo que está causando un restablecimiento suave de la pequeña cuando el temporizador expire. Esto significa que cualquier código de inicialización avr-glibc se volverá a ejecutar, al igual que su código de configuración del temporizador. Esto tomará algunos ciclos y aumentará su tiempo de ciclo, causando una desviación positiva.

Intente configurar un ISR que parpadee, y vea si eso hace una diferencia. O incluso intente un bucle de retardo calibrado en lugar del temporizador.

El jitter.

En cuanto al jitter, ± 0.05% me suena bastante bien. Pero para ser honesto, no estoy seguro de cuán estables son los osciladores RC.

Un sospechoso importante es su println() y la transmisión en serie. println() tiene que hacer un poco de trabajo convirtiendo su número a base-10, y la cantidad exacta de trabajo depende del número que se imprima. Además, la transmisión en serie tiene que sincronizarse con tu computadora y esto puede causar demoras que son semi-aleatorias para tu Arduino.

Intenta almacenar más o menos 20 mediciones en la memoria y solo usa Serial.println() en ellas una vez que todas las mediciones hayan terminado.

Además, no estoy completamente seguro de la precisión de micros() de Arduino. Tal vez hay un problema de precisión allí. Si tiene acceso a un osciloscopio, puede usarlo para medir la frecuencia de salida del diminuto, eliminando el Arduino como una posible fuente de errores.

Actualizar! El consumo de energía del LED influye en el oscilador RC?

¡Ajá, noté un patrón en tu jitter! Está midiendo 106 3 6xx y 106 2 6xx de forma alterna. Así que la mayor parte de su jitter es una variación de 1 ms entre ciclos pares e impares.

Sospecho que esto puede deberse a que está encendiendo un LED, que extrae corriente, lo que afecta la resonancia en el tanque RC utilizado para el oscilador interno. Eso sería interesante.

¿Puedes intentar repetir tu medición original dos veces más, una vez sin el LED y otra vez?

Si quitar el LED hace que el problema desaparezca, es posible que desee utilizar un montón de desacoplamiento en el diminuto, y evitar tener las cargas diminutas en el disco directamente, pero siempre búferlas con transistores. Si la precisión del reloj es lo suficientemente importante para la situación, de todos modos.

    
respondido por el marcelm
1

6% de error suena razonable para un oscilador en chip sin calibrar.

De hecho, las Figuras 19-65 y 19-66 en la página 157 de la hoja de datos indican que la frecuencia ¡El "oscilador de vigilancia de 128 kHz" no se encuentra en ningún lugar cercano a 128 kHz!

Si desea una mayor precisión, debe utilizar como mínimo el oscilador 4.8 / 9.6 "calibrado", y quizás realizar la calibración en cada unidad. Una vez calibrado, se mantendrá dentro de ± 2% por encima de la temperatura y el voltaje (consulte la Tabla 18-2 en la página 119), y puede hacerlo mucho mejor si puede regular uno o ambos parámetros.

    
respondido por el Dave Tweed

Lea otras preguntas en las etiquetas