Página 1 de 1

Problema com ADC - Resolvido

MensagemEnviado: 20 Ago 2009 11:01
por mazzer
Olá a todos.

Estou com um problema e não estou sabendo como resolver.
Acredito que estou fazendo algo nas configurações do ADC.

Durante as leituras acontece de alguma delas vir zerada. (result=0).

Minha rotina de leitura do ADC esta assim:

Código: Selecionar todos
   unsigned int result;

   // Lendo a Potencia Direta
   ADCON0 = ADC_1;
   Delay10TCYx(ADC_DELAY1);
   ADCON0 = ADC_1 | 0x03;
   Delay10TCYx(ADC_DELAY2);      // Delay para estabilização da leitura
   while( BusyADC() );            // Wait for completion
   Delay10TCYx(ADC_DELAY3);
   result = ReadADC();            // Read result


Sendo que
Código: Selecionar todos
ADC_DELAY1 = ADC_DELAY2 = 100
ADC_DELAY3 = 50



Rotina de configuração:
Código: Selecionar todos
   // Configura ADC
   WDTCON = 0x00;         // Default SFR
   ADCON0 = 0x00;         // Ref- = 0, Ref+ = VCC
   ADCON1 = 0b10111110;   // Right, 20TAD, Fosc/64

   WDTCON = 0x10;         // Alternate SFR
   ANCON0 = 0b10000000;   // AN0~AN4 Analogico (1-Digital | 0-Analogico)
   ANCON1 = 0b11100000;   // AN10~AN12 Analogico (1-Digital | 0-Analogico)

   WDTCON = 0x00;         // Default SFR


Já tentei aumentar os delays, mas não tive melhora.

Acontece bem de vez em quando, mas no meu sistema não posso admitir essa falha.

O sinal é proveniente de um amplificador operacional e ele fornece um sinal DC limpo. Quando não ocorre o erro a leitura é bem estabilizada.

As configurações estão feitas exatemente como o datasheet exige.

O PIC em questão é o PIC18F87J50.

Agraceço se alguém tiver alguma sujestão.

Obrigado,
Mazzer

MensagemEnviado: 20 Ago 2009 11:08
por tcpipchip
Dica
Faça uma média de leituras...assim...nao haverá desvio MODAL...

Oi amigo

MensagemEnviado: 20 Ago 2009 11:49
por Vonnilmam
Eu quero tentar ajudar,

No meu caso eu programo em assembler na maioria das vezes, apesar de achar o C e Basic uma linguagem excelente.

Eu utilizo leitura ad também tendo como entrada tenção de 0 até 5v +/- e costumo configurar apenas uma porta (porta,0) como entrada AD e faço a a expanção dos ios analogicos atraves de um 4051, entre cada amostra (canal lido) eu introduzo um delay de 50us, antes da leitura e após a leitura, afim de estabilizar a mesma (se não coloco esses delays tenho um erro de leitura)....é o que eu faço costumeiramente a muitos anos e não tive até agora nenhuma reclamação....

Espero ter ajudado de alguma forma, ok

O seu código parece esta correto em termos de configuração, não consegui ver erros....no seu caso eu faria uma simulação bem simples, experimente colocar um potenciometro na entrada ad diretamente e verifique se o erro ocorre, se não ocorrer, vá eliminando as partes externas do seu hardware por partes até chegar onde esta se manifestando o problema.

Outra coisa que me passou na cabeça agora, o ambiente onde esse sinal esta sendo colhido é "hostil", ou seja esta na rede eletrica pendurado, motores, etc....operacionais são sensiveis e podem captar e amplificar sinais expurios EMI (são picos muito rapidos na alimentação), esperimenta por ultimo colocar um ferrite com 3 voltas de fio cabinho rigido sobre o mesmo (o ferrite pode ser um destes utilizado em entradas de audio - aproximadamente 1cm por 05cm de largura)....

Dá uma atenção na alimentação

MensagemEnviado: 20 Ago 2009 11:58
por mazzer
tcpipchip,

Experimentei fazer média, mas como a leitura de um zero não é correta (ela realmente não existe no sinal analógico), vou acabar colhendo um dado com erro. A média teria que conter grandes amostras para que uma leitura errada não prejudique a média.
Minha dúvida é se isso é normal acontecer, ai eu teria que fazer a média mesmo, ou se é alguma caca no meu sistema.

Vonnilmam,

Realmente ainda não experimentei isolar o circuito digital do analógico, vou experimentar e posto o resultado.

Vonnilmam e tcpipchip, obrigado mesmo pela ajuda

Abraço,
mazzer

MensagemEnviado: 21 Ago 2009 07:28
por ze
o que sai da função readadc()? experimente pegar DIRETO o resultado dos registradores:
result=ADRESH*256+ADRESL;

um ex pra pegar média de 10 leituras
Código: Selecionar todos
unsigned int adc_read(unsigned char ref)
{
unsigned char i;
unsigned int ad;
ad=0;
for (i=0;i<10;i++)
   {
   ADCON0 = ref;  // ref=VREF ou VDD, enable ADC, fosc/64
   asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");// alguns nops resolvem. A única coisa útil do assembler é o "nop". rs
   GODONE=1;
   while(GODONE) continue; // wait for conversion complete
   ad+=(ADRESH*256 + ADRESL);
   }
return ad/10;
}
substitua ref por "0x81| (canal a ser medido)<<2" pro caso de ser 16f676. verifique o dataxit de seu uC como escolher os canais. Aliás prefira lê-lo ao invés de usar rotinas prontas e mastigadas. Verifique se alguma interrupt está a atrapalhar o resultado.

abç

Resolvido

MensagemEnviado: 21 Ago 2009 11:26
por mazzer
Problema resolvido.

Fiz uma interrupção de alta prioridade que eu tinha só ser executada quando nenhuma conversão do adc estivesse em andamento.

lellis,

To fazendo o que vc sugeriu, removi a rotina readadc() e to pegando os dados diretamente.

E como foi sugerido, estou usando média de 8 leituras (mais fácil fazer divisão) como leitura válida.

Com os dois procedimentos acima, resolveu o problema, as leituras agora estão corretas e estáveis.

Obrigado a todos!

Abraço,
Mazzer.