(info de la configuracion de los registros sacada de Arduino Playground)
Se supone que modificando los registros del Timer 0 de esta manera podria obtener en una de las salidas que maneja este Timer una frecuencia de 31.25 kHz, segun la formula del Datasheet de Atmel
F_phase_correct= (fclock / pres-scaler*510)
Opcion 2) ---> Timer 1
TCCR1A = 0x00;
TCCR1B = 0x11; // Modo Phase-correct , pre-scaler = 1
ICR1 = 214; // valor TOP
con esta opcion se supone que obtendria una frecuencia en una de las salidas que maneja este Timer de 37,38 kHz, segun la formula :
F_phase_correct= (fclock / pres-scaler2ICR1)
(esta info la he sacado de una web que me he encontrado por ahi)
Mira este tutorial de Nick Gammon del Moderador Global de arduino.
Lo que me ocurre con el segundo tutorial es que Nick Gammon dice que su sketch asi funciona y no he logrado que lo haga.
En cambio con el primero no tengo problemas.
Una cosa es setear los timers y sus registros como tu has hecho y otra es prescindir de la ISR correspondiente.
Sin una rutina de interrupción no he logrado que funcionen.
Con el AVR si lo hacía.
Es facil cuando se entiende al 100%.
Puntualmente el tutorial de Gammon a mi me deja como si le faltara algo pero leo los comentarios y pienso que ese algo es que yo no se habilitar determinado registro. No me doy cuenta.
Ahora cuando probé esos ejemplos con una subrutina de interrupción funcionaron sin problemas.
con estas 3 lineas de codigo puestas en el Setup, cambias la frecuencia de arduino del pin 9 a 37 khz.
TCCR1A = 0x00; // modifica el TCCR (timer 1) (pin A) = pin digital 9
TCCR1B = 0x11; // y este modifica el preescalado
ICR1 = 214; //valor maximo de analogwrite modificarlo, tambien modificaria la frecuencia de 37 khz otra cualquiera.
esta modificacion no cambia ningun valor en el timer de arduino que controla el delay. Dejo tambien la formula por si interesa algun cambio.
// Fórmula: Fpwm(KHz) = 16000KHz [clock de la arduino] / (2 * N* ICR1)
Donde ICR1 es el valor maximo de analogWrite y N es el factor de reescalado dentro de estos posibles.
(TCCR1B=0x11 -->N=1; TCCR1B=0x12 -->N=8; TCCR1B=0x13 -->N=64, etc)
Una pregunta al respecto de la frecuencia. Mido en el osciloscopio la fecuencia de la señal de entrada de un mando de RC (freq= 62.5 Hz) con un periodo (T=16ms).
Lo mido o calculo tambien en arduino mediante el capturador de ventos externosdel Timer 1 de Arduino y obtengo la misma frecuencia (62.5 Hz) , hago la inversa para calcular el periodo y es distinto periodo (T= 20ms) , 4 ms más que en el osciloscopio.
Como puede ser eso??.
pego aqui el codigo de captura de frecuencia:
volatile boolean primero;
volatile boolean disparo;
volatile unsigned long overflowCount; // desbordamiento de contador
volatile unsigned long tiempo_inicio; // inicio tiempo
volatile unsigned long tiempo_final; // final tiempo
// here on rising edge
void isr ()
{
unsigned int contador = TCNT1; //(contador de disparos), TCNT1 se va incrementando en 1
// cada vez que salta la imnterrupcion
// wait until we noticed last one
if (disparo)
return;
if (primero)
{
tiempo_inicio = (overflowCount << 16) + contador;
primero = false;
return;
}
tiempo_final = (overflowCount << 16) + contador;
disparo = true;
detachInterrupt(0);
} // end of isr
// timer overflows (every 65536 counts)
ISR (TIMER1_OVF_vect)
{
overflowCount++;
} // end of TIMER1_OVF_vect
void prepareForInterrupts ()
{
EIFR = _BV (INTF0); // (limpia registro para interrupcion 0 , pin 2)
primero = true;
disparo = false; // se `pone a false para la proxima lectura
attachInterrupt(0, isr, RISING);
}
void setup () {
Serial.begin(9600);
Serial.println("Frequency Counter");
// // reset Timer 1
TCCR1A = 0;
TCCR1B = 0;
// // Timer 1 - interrumpir desbordamiento
TIMSK1 = _BV (TOIE1); // Habilita interrupcion Timer 1
TCNT1 = 0;
// // iniciar Timer 1
TCCR1B = _BV (CS20); // no prescaling
prepareForInterrupts ();
}
void loop ()
{
if (!disparo)
return;
unsigned long tiempo_transcurrido = tiempo_final - tiempo_inicio;
float freq = 1.0 / ((float (tiempo_transcurrido) * 62.5e-9)); // each tick is 62.5 nS
float T = 1.0/freq;
Serial.print ("Tiempo inicial : ");
Serial.print (" ");
Serial.println (tiempo_inicio);
Serial.print ("Tiempo final : ");
Serial.print (" ");
Serial.println (tiempo_final);
Serial.print ("Took: ");
Serial.print (" ");
Serial.println (tiempo_transcurrido);
Serial.print ("Frequency: ");
Serial.print (freq);
Serial.println (" Hz. ");
Serial.print ("Periodo: ");
Serial.print (T);
Serial.println (" seg. ");
// Serial.println (" seg. ");
// so we can read it
delay (1000);
prepareForInterrupts ();
} // end of loop
Bueno el problema es mas simple de lo que uno imagina.
Serial.print con los float redondea a 2 decimales, entonces un resultado como 0.016 bien calculado se redondea a 0.02 seg
La solución es que en lugar de calcular T = 1/freq; hagas esto
T = float(tiempo_transcurrido * 62.5e-6); // expresado en mseg
Por si alguien puede ayudarme, necesito generar por ejemplo en el pin 9 una salida de 7,83 Hz (2 decimales) con un 50% de Duty Cicle, y también la misma frecuencia pero con un ancho de pulso del 10%.
Por si alguien puede ayudarme, necesito generar por ejemplo en el pin 9 una salida de 7,83 Hz (2 decimales) con un 50% de Duty Cicle, y también la misma frecuencia pero con un ancho de pulso del 10%.
Teslatronica si con lo expuesto en este hilo no resolviste tu problema entonces no se como?
7.83Hz será dificil de lograr. Tampoco es un valor que tenga un período entero, porque da 1/7.83 = 127.714 milisegundos
raro muy raro.
Deberías haber preguntado en un hilo propio no en uno que tiene 1 año sin movimientos (esto anotalo para la próxima).
Veamos como genero 7.83 hz.. dificil.
Con Timer en modo Compare mach interrupt tienes este cálculo
Valor 1 = 16Mhz/256/7.83=
Valor 1 = 16000000/256/7.83= 7982.12 asi que puedes usar 7982 o 7983. El mas cercano es 7982
OCR1A = 7982; [color=#7e7e7e]// compare match register[/color] [color=#7e7e7e]16MHz/256/2Hz[/color]
#define ledPin 13
void setup()
{
pinMode(ledPin, OUTPUT);
// initialize timer1
noInterrupts(); // deshabilito interrupciones
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 7982; // compare match register 16MHz/256/7.83Hz
TCCR1B |= (1 << WGM12); // CTC mode
TCCR1B |= (1 << CS12); // 256 prescaler
TIMSK1 |= (1 << OCIE1A); // habilito timer compare interrupt
interrupts(); // habilito todas las interrupciones
}
ISR(TIMER1_COMPA_vect) // timer compare interrupt service routine
{
digitalWrite(ledPin, digitalRead(ledPin) ^ 1); // basculo el pin LED a 7.83 aprox
}
void loop()
{
// resto del programa acá...
}