Autor Tema: Precisión timer modo contador  (Leído 175 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado japifer_22

  • PIC18
  • ****
  • Mensajes: 394
Precisión timer modo contador
« en: 03 de Marzo de 2017, 13:30:42 »
Hola compitas. Estoy programando un arduino mega. Y en este caso le estoy dando al timer5 configurado en modo contador y salta a una interrupción. Bueno es aqui mi duda. He estado chequiando el tiempo en que salta cada ves la interrupción en este caso a 2hz.
Al imprimir por pantalla estos tiempo me arroja 500000 luego 499996 y luego 499994. estos tres numero se repiten del mismo orden en el tiempo, siendo que deberías arrojar siempre 500000. Jajajaj a lo mejor estoy siendo muy exagerado por la precisión jaja.
Estoy usando un preescale =256
Cristal =16MHz
Cargo el timer con 34286
Timer de 16 bit
Frecuencia resultante de 2hz

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 5632
Re:Precisión timer modo contador
« Respuesta #1 en: 03 de Marzo de 2017, 13:41:05 »
Y esos numeros que son ¿?, es decir desde donde los sacas ?
Con que estas midiendo el tiempo ?
Cual es el codigo de la interrupcion ?

Desconectado japifer_22

  • PIC18
  • ****
  • Mensajes: 394
Re:Precisión timer modo contador
« Respuesta #2 en: 03 de Marzo de 2017, 13:49:39 »
Los numeros que muestros son el tiempo que salta la interrupcion en micro segundos.
Los datos que puse son para calcular el salto de la interrupción.

El codigo con el que juego
Código: [Seleccionar]

#define ledPin 13
unsigned int timer1_counter;
boolean led = true;
unsigned long tick=0;
unsigned long tiempo=0,temp;

void setup()
{
  pinMode(ledPin, OUTPUT);
  Serial.begin(115200);

  noInterrupts();           // disable interrupts
  TCCR5A = 0;
  TCCR5B = 0;
  // 65536-16MHz/preescaler/frecuencia
  timer1_counter = 34286;
 
  TCNT5 = timer1_counter;   // preload timer
  TCCR5B |= (1 << CS52);    //  prescaler
  TIMSK5 |= (1 << TOIE5);   // enable timer overflow interrupt
  interrupts();             // enable interrupts
}

ISR(TIMER5_OVF_vect)        // interrupt
{
  TCNT5 = timer1_counter;   // preload timer
  led = !led;
  digitalWrite(ledPin, led);
  tiempo = micros()-tick;
  tick = micros();   
}
// the loop routine runs over and over again forever:
void loop() {
    if(temp !=tiempo){
        Serial.println(tiempo);
        temp = tiempo;
    }
}


Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 5632
Re:Precisión timer modo contador
« Respuesta #3 en: 03 de Marzo de 2017, 16:27:21 »
Creo hacer notar que Arduino no esta pensado para esto (me refiero a su comunidad o el entorno dado), si quisieras realmente ir por la precision deberias acercarte mas al microcontrolador y olvidarte un poco de la gran abstracción que te provee arduino.

Como veo decis, que usas el Timer5 para eso. Y micros usa el Timer0.

Como pudiste calcular es correcto el valor , es decir

(2^16 - 34286) * 256 / 16Mhz = 0.5s

Y hasta aca parece perfecto.
El problema esta en como funciona internamente el micro.

Si el timer activa la interrupcion, y por ejemplo esta realizando un salto ( del while del loop principal)  como un JMP que le lleva hasta 4 ciclos, ahi tenemos un desfasaje respecto a otra interrupcion, si ocurre a en el primer ciclo de esta instruccion, seguramente deba terminarla, y luego acceder a la interrupcion.

Acceder a la interrupcion tambien ocupa tiempo, es decir el micro una vez activa la señal de interrupcion debe ir a los vectores de interrupcion, de alli ejecutar el salto incondicional lo cual suma mas ciclos, al entrar a la interrupcion tal ves sea necesario guardar el contexto ( ya no recuerdo bien como se manejan por dentro estos), y finalmente recien comenzar a ejecutar las instrucciones que le dimos.

Pero hay mas, vos estar cargando el timer, que estaba en 0 pero que habian pasado ya varios ciclos desde que se puso en 0, le pones un valor y ocurre que.. esos ciclos que se fueron guardando se borraron al ponerle el nuevo valor.

Sigamoslo complicando un poco mas.

micros() millis() y su flia. Utilizan el TMR0 y su interrupcion, lo interesante es que mientras se atiende una interrupcion la otra debe esperar. Supongamos que ocurre la interrupcion del TMR0 y 3 ciclos mas tarde el de TMR5, El TMR0 supongamos que ocupa 30 ciclos, sale, y recien alli entra al TMR5, esto es un error de la cuenta del TMR5, por que esta ves vas a tambien sobreesrcibir esos ciclos mas.

micros() hasta que llegue desde que ocurrio la interrupcion pasaron vaaarios microsegundos y esos son contados.

Entonces tenemos todas esas fuentes de error y que seguro hay mas. Lo cual es correcto que no te va a coincidir.
Una de las formas de evitar esto o tener un valor mas constante, es usar el Timer en modo CTC ( Aunque no se si se puede obviar la salida, imagino que deberia)

Esto hace que el Timer cuente desde 0 hasta un valor, y cuando ese valor coincida, se resetee solo por hardware y active una interrupcion, es decir vos no cargarias el valor en cada interrupcion, simplemente contarias cuantas ocurrieron, Los valores a cargarlo son parecidos a lo que tenes:

preescale =256
Cristal =16MHz
Cargo el registro OCRnx del timer con el valor (65536 - 34286 - 1) Es decr no el complemento sino lo que debo contar menos 1.
Poner a 0 el timer.
Timer de 16 bit
Frecuencia resultante de 2hz

Lo bueno de este sistema es que vos no tocas nada , solo contas las veces que se activo la interrupcion de comparacion. El unico error que tendrias es al punto de tomar una accion, la cual serian unos cuantos microsegundos.

-------

Finalmente, queres controlar de la forma mas exacta al tiempo?, deberias pensar en ASM y no en C o C++

Desconectado japifer_22

  • PIC18
  • ****
  • Mensajes: 394
Re:Precisión timer modo contador
« Respuesta #4 en: 03 de Marzo de 2017, 20:39:29 »
Tremenda respuesta. Gracias.
La verdad era solo de curioso. Ya que ando jugando con estas tarjetas. tengo la idea controlar unos servos y unos sensores por i2c  para controlar un dron.


 

anything