Ir ao conteúdo
  • Cadastre-se

Tratar onda quadrada


wBB

Posts recomendados

@aphawk , o objetivo é determinar o PERÍODO deste sinal.

 

Eu tenho este sinal pulsado todo maluco, que está sendo lido através da interrupção externa do meu microcontrolador. A interrupção externa é acionada a cada borda de subida do sinal lido. Porém, por ser todo irregular aquele tempo dos primeiros 500us do período sinal, a história de detectar a borda de subida vai pro espaço. Já a parte do período do sinal em que não há pulsos, pode variar de 100ms a 800ms conforme indicado.

 

O que imaginei foi o seguinte: se no lugar do tempo daquele trem de pulsos maluco eu conseguir substituir por um único pulso de mesma largura, será possível determinar o período bastante aproximado.

 

A variação desse período indicado em azul no gráfico é que me interessa.

Link para o comentário
Compartilhar em outros sites

Mas pra calcular o período não precisa ler os pulsos pra calcular, esse trem de pulsos 1 me parece ser uma saída serial comum, se é uma saída serial bastaria saber qual é a frequência(baudrate) que está sendo transmitido, tipo 9600 bits/s daí teria que calcular em um determinado período quantos bits passaram, bom é uma ideia meio doida(tanto quanto a sua rerere) mas pode dar certo rsrsrs.

 

Quanto ao filtro RC pode funcionar porque ele transforma um monte de pequenos pulsos em um único pulso, daí seria o caso de você pegar o resultado desse filtro e calcular o período dele. Essa é outra ideia maluca, mas também pode dar certo se o filtro ficar muito bem calibrado.

Link para o comentário
Compartilhar em outros sites

@wBB ,

 

Bom, me parece simples, mas talvez haja algum empecilho que eu não saiba ....

 

Que tal você usar a interrupção por borda de descida, e disparar um Timer nessa interrupção ?

 

Aí você fica verificando se o nível do sinal foi para 1, pára o Timer, e determina o tempo decorrido através da contagem de seu Timer !

Se essa contagem do Timer resultar em um tempo menor do que 1 milissegundo, sabemos que este é o período errado a ser medido, ignoramos e esperamos outra descida.

 

Mas se a contagem do Timer ultrapassar o tempo de 1 milissegundo, saberemos que o que está sendo medido é justamente esse tempo que você diz que pode variar entre 100 milissegundos e 800 milissegundos !

 

Basta continuar a contagem do Timer até o sinal subir para nível 1, quando então você faz Stop no timer, e verifica o tempo dele.

 

Depois disso, zere o Timer, e habilite novamente a interrupção por borda de descida, e repete o processo.

 

Paulo

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

@ViniciusKruz não é uma saída serial. É um sinal bem irregular mesmo.

Sobre o filtro RC, ele vai alterar o formato da onda, realmente "unindo" os pequenos pulsos, mas também acaba influenciando o trecho de nível baixo do período (na descarga do capacitor depois do último pulso), o que geraria erro de leitura.

Obrigado.

 

@aphawk essa foi a ideia que tive inicialmente também.

Pergunta de leigo: devido ao excesso de pulsos no trecho de 500us, isso não sobrecarregará o processamento do uC em relação às outras coisas que tenho no programa? Afinal ocorrerá uma série grande de interrupções externas.

 

Obrigado.

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

@wBB ,

 

Não é uma pergunta de leigo não hehhe !

 

Aqui entramos no ramo das suposições :

 

Supondo que o menor periodo entre uma descida e uma subida nesse seu trecho meio doido seja de 10 microsegundos. Supondo um clock máximo no seu PIC de 20 Mhz, temos um ciclo de máquina  mínimo de 5 Mhz , o que daria 5 ciclos de máquina a cada microsegundo, e voce teria em seu programa apenas 50 ciclos de máquina para processamento, o que te obrigaria a usar Assembly para fazer o start do Timer e ficar checando o nível do sinal e rapidamente parar o Timer para cálculo do período. Não sei se seria possível fazer isso em outra linguagem usando um Pic da família 16F.

 

Mas poderia usar um da família 18F e usando o clock mais alto por PLL consegue ganhar no mínimo o dobro de ciclos de máquina, e aí acho que daria para fazer em C.

 

Por outro lado, a temporização de um Timer seria suficiente para determinar o período, mesmo na família 16F.

 

Eu não uso os Pics fazem muitos anos, e posso estar dando palpites errados aqui....  espere por alguém mais especializado neles para te dar a resposta mais correta.

 

O que te digo com certeza é que um AVR rodando a 20 Mhz faria essa tarefa sem problemas, mesmo rodando C.

 

Lembre-se que aqui fiz uma suposição de que o período mínimo enrre uma descida e uma subida seja de 10 microsegundos.

 

Mas imagino que esse problema não seja importante para você... se voce consegue usar dois pinos com interrupção, e programar um deles na desçida e outro na subida, creio que voce consegue determinar o tempo sem dificuldade, pois você não precisa determinar o período exato nos intervalos dentro daquele tempo em que ocorrem essas transições doidas, mas sim quando fica pelo menos 1 milisegundo sem ocorrer uma subida !

 

Olhando por este lado, mesmo rodando a 4 Mhz voce consegue determinar o período que você quer com uma boa precisão.

 

Paulo

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Paulo, obrigado pelas dicas.

Sobre o uso do PLL, infelizmente não posso mudar de microcontrolador, portanto essa não é um opção neste caso. De qualquer forma é bem como você observou, ou seja, não há nenhuma necessidade de saber o que acontece nesses pulsos do trecho de 500us. Portanto o 16F atende, em teoria.

 

Sobre o uso de AVR não sei nem como opinar, pois ainda sou iniciante em microcontroladores, tendo começado justamente por PIC.

 

Minha maior preocupação mesmo é a capacidade de processamento das outras coisas junto com essas interações da interrupção externa. Bom, vou ter que testar e talvez gastar um tempo a mais nisso já que parece ser a única alternativa.

 

Aliás, falando em alternativa, eu disse que queria fazer o tratamento desse sinal com o uC, mas não é obrigatório que seja assim. Só imaginei se seria possível/viável. Poderia ser de outra forma... Por exemplo: para eu conseguir chegar a esse sinal que postei na imagem, já foi através um tratamento de um outro sinal, este sim extremamente irregular e cheio de ruídos, que passou por um desacoplamento, depois por um schmitt trigger, por um diodo zener, além de capacitores de filtro.

 

Se tiver alguma outra sugestão que não seja por microcontrolador, talvez eu pudesse testar.

 

Valeu!

Link para o comentário
Compartilhar em outros sites

@wBB ,

 

Só vejo uma outra alternativa..... poderia usar um mono-estável, mas isso pode alterar um pouco a medida do período.

Não sei qual a precisão de sua medida, mas se por exemplo 0,5 milisegundo de erro for tolerável, voce pode fazer um monoestável acionado pela borda de subida, com tempo de duração da saída em torno de 750 microsegundos. Assim, na primeira subida, já acionaria o monoestável, e quando ele terminasse o pulso, acionaria uma interrupção na descida desse pulso, e o seu programa acionaria o Timer para medir o tempo até que o monoestável acione novamente pela borda de subida, simplesmente monitorando a subida de nível do sinal e parando o Timer quando ocorrer a subida.

 

Terá um erro máximo de cerca de 250 microsegundos ( supondo que o período máximo daquele sinal maluco seja de 500 microsegundos ), mas se o período mínimo a ser medido for de 100 milisegundos, o erro é de 0,25% apenas !

 

Isso facilita bastante o seu programa.

 

Paulo

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Pode ser mesmo uma boa solução.

Realmente a precisão em microsegundos não é necessária. Sabendo a largura aproximada do trem de pulsos, basta que eu considere o tempo de nível alto do monoestável maior que o tempo do trem de pulsos (seja lá qual for esse tempo médio).

 

Vou tentar isso.

Obrigado!

Link para o comentário
Compartilhar em outros sites

@wBB ,

 

Pelo seu desenho, o período aproximado é de 500 microsegundos. Eu pensei em usar um pouco mais que isso, tipo 750  microsegundos. Mas é o que eu te falei acima, se até 1 milissegundo não for significativo, pode colocar o tempo do monoetável tipo 900 ,ice-segundos, e manda pau.

 

Paulo

Link para o comentário
Compartilhar em outros sites

Tive uma ideia agora e em princípio me parece ser bastante simples de resolver:

Usando a interrupção externa, detecto a borda de subida normalmente e, em lugar de tentar tratar o sinal, já sabendo que meu trem de pulso tem, digamos 1ms no máximo, eu coloco esse delay (ou o delay que for necessário) no início da rotina da interrupção externa, de forma que este delay ultrapasse o tempo do trem de pulsos. Dessa forma, a próxima borda de subida detectada será necessariamente o fim do período total, lá no final dos 100/800ms, ou seja, o início do próximo trem de pulsos.

 

Funcionar eu sei que funciona. Só não sei se há algum inconveniente nisso. Você vê algum?

Link para o comentário
Compartilhar em outros sites

@wBB ,

 

Sim, é o mesmo princípio do monoestável, só que feito por software.

 

Na sua rotina de interrupção, você tem de desabilitar a interrupção e sair, esperar os 750 microsegundos, e habilitar novamente a rotina de interrupção, ao mesmo tempo que inicia a contagem de tempo pelo Timer. 

 

Dá certo sim, manda bala !

 

Paulo

Link para o comentário
Compartilhar em outros sites

Paulo, pelo que entendi, você está sugerindo que eu não use delay dentro da rotina de interrupção externa, mas não sei se entendi corretamente o que você sugeriu.

 

O que pensei foi fazer o seguinte (dentro da rotina de interrupção externa):

1- detecta borda de subida;

2- desabilita interrupção externa;

3- captura uma referencia de tempo qualquer numa variável T1, por meio de um timer qualquer;

4- delay de "X" tempo (maior que o trem de pulsos);

5- habilita a interrupção;

 

Na interrupção seguinte, ou seja, na próxima borda de subida, que suponho que será o final do ciclo total, calculo quanto passou de tempo a partir do que foi registrado na variável T1.

 

É isso mesmo ou você sugeriu algo de forma diferente, sem o delay interno da interrupção?

Link para o comentário
Compartilhar em outros sites

@wBB ,

 

Eu não sei se o seu programa aceita ficar parado tanto tempo tratando um delay dentro de uma interrupção.

 

Eu tenho por hábito perder sempre o menor tempo possível dentro de uma interrupção. Se isso não for problema para você, pode sim tratar tudo dentro da própria rotina, conforme você descreveu.

 

Nos microcontroladores Pic e Avr, temos apenas um nível de interrupção. Isto significa que enquanto estamos tratando uma, nenhuma outra pode ocorrer, e como às vezes tenho mais de uma interrupção nos meus projetos, sempre me preocupo em perder o menor tempo possível, usar flags, e tratar tudo por fora. Mas é apenas a força do hábito, ok ?

 

Paulo

Link para o comentário
Compartilhar em outros sites

Sim, agora entendi sua preocupação em relação ao processamento em geral. Eu achei que pelo fato da interrupção externa ser uma rotina independente, mesmo que ela ficasse parada aguardando o término do delay não seria problema para que as demais interrupções continuassem em paralelo (como eu falei, sou leigo, iniciante... testei aqui e fica tudo parado mesmo). Também tenho outras interrupções e esse travamento seria um problema.
Vou implementar uma contagem de tempo auxiliar sem deixar nada travado.

 

Obrigado novamente.

Link para o comentário
Compartilhar em outros sites

@wBB ,

 

Opa, que isso, a finalidade aqui do Fórum é justamente o aprendizado !

 

Na verdade, existe um truque , mas é bem arriscado, e eu só usaria ele se programasse em Assembly e com muito domínio e entendimento de tudo o que possa acontecer de errado no projeto :

 

- Assim que voce entrar na rotina de interrupção, habilite novamente as interrupções !

 

É um processo bem arriscado porque permite encavalar as interrupções uma em cima de outra ! E quase sempre perdemos o controle.

 

E justamente para evitar esse tipo de problema è que sempre preferimos que as rotinas de interrupção sejam o mais curtas possíveis, e sempre sinalizando com o programa principal por meio de flags setados ou resetados. Assim o processamento que consome mais tempo será feito no programa principal, permitindo que outras interrupções continuem acontecendo.

 

E muitas vezes eu também sinalizo de volta para uma rotina de interrupção através de flags manipulados no programa principal !

 

Mas isso, só mesmo com a prática é que você vai entendendo o porquê de algumas coisas, ok ?

 

Paulo

 

Link para o comentário
Compartilhar em outros sites

Visitante
Este tópico está impedido de receber novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...