Hola, quería ver si alguien me podía ayudar. Estoy intentando leer la frecuencia de una onda cuadrada, para ello he escrito éste código:
//________________________________________________________________________________
int ICP=8;
//Contador de desbordamientos
volatile long contador_overflow;
//Flancos de subida
unsigned int flanco_subida;
//Definimos la frecuencia
volatile long frecuencia;
void setup()
{
Serial.begin(9600);
pinMode(ICP, INPUT);
}
//Rutina de Servicio de Interrupción del contador de desbordamientos
ISR(TIMER1_OVF_vect)
{
contador_overflow++;
}
//Subrutina de Servicio de Interrupción de captura del Timer1
ISR(TIMER1_CAPT_vect)
{
/**/
if (ICP) //si hay nivel alto
{
//Un nuevo flanco de subida significa fin de periodo
frecuencia=16000000/(abs(ICR1-flanco_subida)+contador_overflow*0xFF);
// Recojo el tiempo para medida del nuevo pulso
flanco_subida=ICR1;
/*Reseteamos contador de desbordamientos*/
contador_overflow=0;
monitoriza();
}
}
/*Funcion que muestra por pantalla la frecuencia*/
void monitoriza(){
Serial.println();
Serial.print("LA FRECUENCIA ES ");
Serial.print(frecuencia);
Serial.println(" Hz");
}
int main(void)
{
//Modo normal
TCCR1A=0;
//Habilitamos overflow e input capture interrupts
TIMSK1=0x21;
/*Noise canceller, sin prescaler, detecta flanco de subida*/
TCCR1B=0xC1;
//habilitamos interrupciones globales
sei();
for (;;)
{
//bucle cerrado de funcionamiento continuo
}
}
//________________________________________________________________________________
Pero cuando introduzco por el pin8 digital la señal periódica cuadrada que quiero medir, el monitor serie no muestra los resultados y no sé qué pasa.
yo tengo un codigo para eso que me escribio nickgammon gran codigo y a frecuencias de 1khz es super exacto probado con gnerador de señales y oscilloscopio si me dejas buscarlo te lo paso
/ Frequency timer
// Author: Nick Gammon
// Date: 10th February 2012
volatile boolean first;
volatile boolean triggered;
volatile unsigned long overflowCount;
volatile unsigned long startTime;
volatile unsigned long finishTime;
// here on rising edge
void isr ()
{
unsigned int counter = TCNT1; // quickly save it
// wait until we noticed last one
if (triggered)
return;
if (first)
{
startTime = (overflowCount << 16) + counter;
first = false;
return;
}
finishTime = (overflowCount << 16) + counter;
triggered = true;
detachInterrupt(0);
} // end of isr
// timer overflows (every 65536 counts)
ISR (TIMER1_OVF_vect)
{
overflowCount++;
} // end of TIMER1_OVF_vect
void prepareForInterrupts ()
{
// get ready for next time
EIFR = _BV (INTF0); // clear flag for interrupt 0
first = true;
triggered = false; // re-arm for next time
attachInterrupt(0, isr, RISING);
} // end of prepareForInterrupts
void setup () {
Serial.begin(115200);
Serial.println("Frequency Counter");
// reset Timer 1
TCCR1A = 0;
TCCR1B = 0;
// Timer 1 - interrupt on overflow
TIMSK1 = _BV (TOIE1); // enable Timer1 Interrupt
// zero it
TCNT1 = 0;
// start Timer 1
TCCR1B = _BV (CS20); // no prescaling
// set up for interrupts
prepareForInterrupts ();
} // end of setup
void loop ()
{
if (!triggered)
return;
unsigned long elapsedTime = finishTime - startTime;
float freq = 1.0 / ((float (elapsedTime) * 62.5e-9)); // each tick is 62.5 nS
Serial.print ("Took: ");
Serial.print (elapsedTime);
Serial.print (" counts. ");
Serial.print ("Frequency: ");
Serial.print (freq);
Serial.println (" Hz. ");
// so we can read it
delay (500);
prepareForInterrupts ();
} // end of loop
mira si te sirve este codigo lo escribio nick para una idea que tenia y basado en el datasheet del controlador, es increible podes casi llegar a 99,000 khz con este amigo pero ya genera un error
Interesante código...
tengo una duda.... que tipo de señal es capaz de medir, y que pin hay que usar de entrada?
imagino que señales cuadradas de 5v...
Lisergio:
Interesante código...
tengo una duda.... que tipo de señal es capaz de medir, y que pin hay que usar de entrada?
imagino que señales cuadradas de 5v...
gracias..
pues lo he probado con varios tipos de frecuencia no solo cuadradas, y la entrada utiliza los pines de interuptores de la tarjeta
Hola a todos, yo tambien estoy utilizando ese codigo para capturar la frecuencia de una señal de entrada procedente de un mando de RC. La lectura de la frecuencia Is perfect!! (62,5 Hz), pero cuando hago la inversa para obtener el periodo parece que no mide bien los tiempos, me da un periodo T=20ms, cuando deberia ser de 16 ms, sabeis porq puede ser eso??.
No he trabajado nunca con Timer's supongo que no sera muy complicado pero la verdad es que stoy un poco verde. Estoy leyendo mucho para ver si lo acabo de entender bien y adquiero la capacidad de poder razonar en su forma de utilizacion.
Perdona, pero yo no he abierto 2,3 o 4 post, solo abri uno preguntando como se podia cambiar la frecuencia del pwm Y como tambien estoy tratando de ver la frecuencia de entrada de la señal para comprobar la periocidad de la señal y buscando por el foro o la red me salen estos post y pues pregunte aqui tambien.
Y nose a quien te refieres con lo de "York", si hay algun miembro del foro que tenga el mismo avatar que yo y que haya preguntado lo mismo puede ser. Pero vuelvo a repetir que no he abierto varios post preguntando lo mismo.
Siento si te a molestado algo, no es mi intencion molestar, solo intentar aprender un poco mas los entresijos de los timer's de arduino que es con lo que estoy atascado en estos momentos.
Bueno, he estado haciendo mediciones y con este código leo correctamente 62.5Hz
// Frequency timer
// Author: Nick Gammon
// Date: 10th February 2012
// Input: Pin D2
volatile boolean first;
volatile boolean triggered;
volatile unsigned long overflowCount;
volatile unsigned long startTime;
volatile unsigned long finishTime;
// here on rising edge
void isr ()
{
unsigned int counter = TCNT1; // quickly save it
// wait until we noticed last one
if (triggered)
return;
if (first)
{
startTime = (overflowCount << 16) + counter;
first = false;
return;
}
finishTime = (overflowCount << 16) + counter;
triggered = true;
detachInterrupt(0);
} // end of isr
// timer overflows (every 65536 counts)
ISR (TIMER1_OVF_vect)
{
overflowCount++;
} // end of TIMER1_OVF_vect
void prepareForInterrupts ()
{
// get ready for next time
EIFR = bit (INTF0); // clear flag for interrupt 0
first = true;
triggered = false; // re-arm for next time
attachInterrupt(0, isr, RISING);
} // end of prepareForInterrupts
void setup ()
{
Serial.begin(9600);
Serial.println("Frequency Counter");
// reset Timer 1
TCCR1A = 0;
TCCR1B = 0;
// Timer 1 - interrupt on overflow
TIMSK1 = bit (TOIE1); // enable Timer1 Interrupt
// zero it
TCNT1 = 0;
overflowCount = 0;
// start Timer 1
TCCR1B = bit (CS10); // no prescaling
// set up for interrupts
prepareForInterrupts ();
} // end of setup
void loop ()
{
if (!triggered)
return;
unsigned long elapsedTime = finishTime - startTime;
float freq = F_CPU / float (elapsedTime); // each tick is 62.5 nS at 16 MHz
Serial.print ("Took: ");
Serial.print (elapsedTime);
Serial.print (" counts. ");
Serial.print ("Frequency: ");
Serial.print (freq);
Serial.println (" Hz. ");
// so we can read it
delay (500);
prepareForInterrupts ();
} // end of loop