Estou tentando encontrar os cruzamentos zero de uma onda senoidal para transformar a onda senoidal em uma onda quadrada. O único problema é que a onda senoidal é barulhenta, então estou recebendo muitas passagens de jitter e falso zero.
Alguém pode recomendar qualquer psuedocode simples ou materiais relevantes? Até agora eu tenho algo parecido com isto:
if (sample[i]>0 && sample[i+1]<0) || (sample[i]<0 && sample[i+1]>0)
Alguém pode recomendar um método mais robusto?
Respostas:
Você pode tentar passar com baixa frequência o sinal de entrada para obter passagens de zero mais suaves (ou até mesmo passar com banda se tiver uma boa idéia da localização da frequência da onda senoidal). O risco é que, se as informações precisas da fase da amostra forem essenciais para o seu aplicativo, o atraso adicional do filtro possa ser um problema.
Outra abordagem: em vez de tentar transformar a onda senoidal em uma onda quadrada, que tal fazer um oscilador independente de onda quadrada se alinhar em fase / frequência com a onda senoidal? Isso pode ser feito com um loop de fase bloqueada .
fonte
O que você mostrou certamente é um detector de cruzamento zero. Lembre-se de algumas coisas que podem melhorar sua situação:
Se você tiver ruído fora da faixa do seu sinal (o que é quase certamente o caso, já que sua entrada é um tom puro), você poderá melhorar a relação sinal / ruído aplicando um filtro passa-banda ao redor do sinal de interesse . A largura da banda passante do filtro deve ser escolhida com base na precisão com que você conhece a frequência senoidal a priori . Ao reduzir a quantidade de ruído presente no sinusóide, o número de cruzamentos de zero falsos e seu jitter sobre os tempos de cruzamento corretos serão reduzidos.
Com relação ao detector de cruzamento zero, você pode adicionar alguma histerese ao processo. Isso impediria a geração de cruzamentos extra espúrios medidos em torno do instante correto do cruzamento. Adicionar histerese ao detector pode ser algo como isto:
Efetivamente, você adiciona algum estado ao seu detector de cruzamento zero. Se você acredita que o sinal de entrada tem um valor positivo, é necessário que o sinal caia abaixo de um valor limite escolhido
-T
para declarar uma passagem zero real. Da mesma forma, você precisa que o sinal volte acima do limiteT
para declarar que o sinal voltou a ser positivo novamente.Você pode escolher os limites para o que quiser, mas para um sinal equilibrado como um senoide, faz sentido que eles sejam simétricos em relação a zero. Essa abordagem pode ajudar a fornecer uma saída com aparência mais limpa, mas adicionará algum atraso de tempo devido ao fato de você estar realmente medindo cruzamentos de limiar diferentes de zero em vez de cruzamentos de zero.
Como as pichenettes sugeriram em sua resposta, um loop de fase bloqueada seria provavelmente o melhor caminho a seguir, pois uma PLL faz exatamente o que você está tentando fazer. Em resumo, você executa um gerador de onda quadrada que funciona paralelamente ao sinusóide de entrada. O PLL faz medições periódicas de fase no sinusóide e depois filtra esse fluxo de medições para direcionar a frequência instantânea do gerador de ondas quadradas. Em algum momento, o loop travará (espero), momento em que a onda quadrada deve ser travada em frequência e fase com o sinusóide da entrada (com alguma quantidade de erro, é claro; nada em engenharia é perfeito).
fonte
T
. Significado em vez de&& (sample[i - 1] > -T) && (sample[i] < -T))
, use&& (sample[i - 1] >= -T) && (sample[i] < -T))
. Isso precisa ser aplicado às instruçõesif
eelse if
.Eu tenho uma boa experiência com um método muito simples para encontrar as mudanças de sinal no sinal às vezes:
média / mediana de cada cluster, esta é sua alteração de sinal
correlação com a função step no ponto previsto por 4
No meu caso 5 e 6, não aumente a precisão do método. Você pode diminuir o sinal com ruído e ver se isso ajuda.
fonte
Eu sei que essa pergunta é bastante antiga, mas tive que implementar o cruzamento de zero recentemente. Eu implementei o que Dan sugeriu e estou bastante satisfeito com o resultado. Heres meu código python, se alguém estiver interessado. Eu não sou realmente um programador elegante, por favor, tenha paciência comigo.
Nota: meu código não detecta sinais e usa um pouco de conhecimento a priori de uma frequência-alvo para determinar o limite de tempo. Esse limite é usado para agrupar o cruzamento múltiplo (pontos de cores diferentes na imagem) a partir do qual o mais próximo à mediana dos grupos é selecionado (cruzes azuis na imagem).
fonte