Estoy tratando de encontrar los cruces por cero de una onda sinusoidal para transformar la onda sinusoidal en una onda cuadrada. El único problema es que la onda sinusoidal es ruidosa, por lo que recibo mucha fluctuación de fase y cruces de cero falsos.
¿Alguien puede recomendar algún psuedocódigo simple o materiales relevantes? Hasta ahora tengo algo como esto:
if (sample[i]>0 && sample[i+1]<0) || (sample[i]<0 && sample[i+1]>0)
¿Alguien puede recomendar un método más robusto?
Respuestas:
Puede intentar el filtrado de paso bajo de la señal de entrada para obtener cruces por cero más suaves (o incluso el filtrado de paso de banda si tiene una buena idea de la ubicación de frecuencia de la onda sinusoidal). El riesgo es que si la información de fase precisa de la muestra es esencial para su aplicación, el retraso adicional del filtro podría ser un problema.
Otro enfoque: en lugar de tratar de transformar la onda sinusoidal en una onda cuadrada, ¿qué hay de conseguir que un oscilador de onda cuadrada independiente se alinee en fase / frecuencia con la onda sinusoidal? Esto se puede hacer con un bucle de fase bloqueada .
fuente
Lo que ha mostrado ciertamente es un detector de cruce por cero. Se me ocurren un par de cosas que podrían mejorar su situación:
Si tiene ruido que está fuera de la banda de su señal (lo cual es casi seguro, ya que su entrada es un tono puro), puede mejorar la relación señal / ruido aplicando un filtro de paso de banda alrededor de la señal de interés. . El ancho de banda de paso del filtro debe elegirse en función de la precisión con la que conoce la frecuencia sinusoide a priori . Al reducir la cantidad de ruido presente en la sinusoide, se reducirá el número de cruces falsos a cero y su fluctuación sobre los tiempos de cruce correctos.
Con respecto al detector de cruce por cero en sí mismo, puede agregar algo de histéresis al proceso. Esto evitaría la generación de cruces medidos espurios adicionales alrededor del instante de cruce correcto. Agregar histéresis al detector podría verse así:
Efectivamente, agrega algún estado a su detector de cruce por cero. Si cree que la señal de entrada tiene un valor positivo, necesita que la señal baje por debajo de un valor umbral elegido
-T
para declarar un cruce por cero real. Del mismo modo, necesita que la señal se eleve nuevamente por encima del umbralT
para declarar que la señal ha oscilado nuevamente a positivo.Puede elegir que los umbrales sean lo que desee, pero para una señal balanceada como una sinusoide, tiene sentido que sean simétricos respecto a cero. Este enfoque puede ayudarlo a obtener un resultado más limpio, pero agregará un cierto retraso debido al hecho de que en realidad está midiendo cruces de umbral distintos de cero en lugar de cruces por cero.
Como pichenettes sugirió en su respuesta, un bucle de fase bloqueada probablemente sería la mejor manera de hacerlo, ya que un PLL hace casi exactamente lo que está tratando de hacer. En resumen, ejecuta un generador de onda cuadrada que funciona en paralelo con la sinusoide de entrada. El PLL realiza mediciones periódicas de fase en la sinusoide, luego filtra esa corriente de mediciones para dirigir la frecuencia instantánea del generador de onda cuadrada. En algún momento, el bucle se bloqueará (con suerte), en ese punto la onda cuadrada debe bloquearse en frecuencia y fase con la sinusoide de la entrada (con cierta cantidad de error, por supuesto; nada en ingeniería es perfecto).
fuente
T
. Significado en lugar de&& (sample[i - 1] > -T) && (sample[i] < -T))
, uso&& (sample[i - 1] >= -T) && (sample[i] < -T))
. Esto debe aplicarse a ambosif
yelse if
declaraciones.Tengo buena experiencia con un método muy simple para encontrar los cambios de señal en la señal a veces:
promedio / mediana de cada grupo, este es su cambio de signo
hacer correlación con la función de paso en el punto predicho por 4
En mi caso 5 y 6 no aumentan la precisión del método. Puede oscurecer su señal con ruido y ver si ayuda.
fuente
Sé que esta pregunta es bastante antigua, pero recientemente tuve que implementar el cruce por cero. Implementé la forma en que Dan sugirió y estoy bastante satisfecho con el resultado. Aquí está mi código de Python, si alguien está interesado. No soy realmente un programador elegante, por favor tengan paciencia conmigo.
Nota: mi código no detecta signos y utiliza un poco de conocimiento a priori de una frecuencia objetivo para determinar el umbral de tiempo. Este umbral se usa para agrupar el cruce múltiple (diferentes puntos de color en la imagen) del cual se selecciona el más cercano a la mediana de los grupos (cruces azules en la imagen).
fuente