¿Cómo se mide la frecuencia de la señal en ATmega? En particular, ¿cómo se mide la frecuencia de la señal (senoidal) en ATmega8?
¿Cómo se mide la frecuencia de la señal en ATmega? En particular, ¿cómo se mide la frecuencia de la señal (senoidal) en ATmega8?
Muestra valores usando un ADC con una frecuencia mínima que necesita para que sea dos veces (más es mejor ;-) la frecuencia con la que espera que se encuentre su seno). Luego realice una FFT (consulte aquí también). Dependiendo de la rapidez / frecuencia con la que necesite hacer esto, esto debería ser posible en la familia atmega.
Ese aquí parece realmente impresionante para ser honesto
Suponiendo que solo está interesado en medir la frecuencia de la sinusoidal, diría que la convierta en pulsos de onda cuadrada (por ejemplo, con un optoacoplador) y luego use los temporizadores para medir la onda cuadrada.
Hay varias formas de medir la frecuencia, pero la más precisa es mediante el uso de la unidad de captura de entrada, consulte esta publicación.
Otra alternativa que dará resultados bastante precisos pero no tan precisos como el método anterior es usar el temporizador 1 como una puerta para que el temporizador 0 mida los pulsos en una ventana específica (por ejemplo, 100 ms) y luego use matemáticas para obtener la señal frecuencia. Para hacer esto, configura el temporizador 0 para que use los pulsos de señal externos como fuente de reloj, esto es lo que quiero decir:
// sample for mega88
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/power.h>
#define ENABLE_TIMER1 TCCR1B=(1<<CS11) | (1<<CS10);
#define DISABLE_TIMER1 TCCR1B=0x00;
#define ENABLE_TIMER0 TCCR0B=(1<<CS02) | (1<<CS01) | (1<<CS00);
#define DISABLE_TIMER0 TCCR0B=0x00;
#define RESET_TIMERS TCNT1 = 53036; TCNT0=0x00; timer0_ovf=0; timer1_ovf=0;
volatile unsigned char timer1_ovf;
volatile unsigned int timer0_ovf;
uint32_t frequency;
// Timer 0 overflow interrupt service routine
ISR(TIMER0_OVF_vect)
{
timer0_ovf++; // overfloaw counter , will be used in calculations later
}
// Timer1 overflow interrupt service routine
ISR(TIMER1_OVF_vect)
{
DISABLE_TIMER1
DISABLE_TIMER0
timer1_ovf = 1; // flag that measure has finshed
}
uint32_t measure_frequency(void)
{
RESET_TIMERS
_delay_ms(1);
ENABLE_TIMER1
ENABLE_TIMER0
while(timer1_ovf != 1); // wait for flag
// measure window is 0.1sec, to convert to sec multiply with 10
return (((TCNT0 + (256UL * timer0_ovf)) * 10));
}
void main(void)
{
// Crystal Oscillator division factor: 1
clock_prescale_set(clock_div_1);
// Timer/Counter 0 initialization
// Clock source: T0 pin Rising Edge
// Mode: Normal top=0xFF
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A = (0 << COM0A1) | (0 << COM0A0) | (0 << COM0B1) | (0 << COM0B0) | (0 << WGM01) | (0 << WGM00);
TCCR0B = (0 << WGM02) | (1 << CS02) | (0 << CS01) | (0 << CS00);
TCNT0 = 0x00;
OCR0A = 0x00;
OCR0B = 0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 125,000 kHz
// Mode: Normal top=0xFFFF
// OC1A output: Disconnected
// OC1B output: Disconnected
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer Period: 0,52429 s
// Timer1 Overflow Interrupt: On
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A = (0 << COM1A1) | (0 << COM1A0) | (0 << COM1B1) | (0 << COM1B0) | (0 << WGM11) | (0 << WGM10);
TCCR1B = (0 << ICNC1) | (0 << ICES1) | (0 << WGM13) | (0 << WGM12) | (0 << CS12) | (0 << CS11) | (0 << CS10);
TCNT1 = 53036; // 65536-12500 = 53036 , overflow at 100ms
ICR1H = 0x00;
ICR1L = 0x00;
OCR1AH = 0x00;
OCR1AL = 0x00;
OCR1BH = 0x00;
OCR1BL = 0x00;
// Timer/Counter 0 Interrupt(s) initialization
TIMSK0 = (0 << OCIE0B) | (0 << OCIE0A) | (1 << TOIE0);
// Timer/Counter 1 Interrupt(s) initialization
TIMSK1 = (0 << ICIE1) | (0 << OCIE1B) | (0 << OCIE1A) | (1 << TOIE1);
// Global enable interrupts
sei();
frequency = measure_frequency(); // measure frequency and store to variable
while(1)
{
// Place your code here
}
}
Lea otras preguntas en las etiquetas atmega