Problemas na conversão A/D (preciso de velocidade...)

Software e Hardware para uC PIC

Moderadores: andre_luis, 51, guest2003, Renie

Problemas na conversão A/D (preciso de velocidade...)

Mensagempor Fabio_Jerena » 28 Jan 2008 10:32

Eu necessito fazer um coletor de dados, ele deve efetuar leituras periódicas de todos os canais do A/D do PIC 16F877A, porem eu necessito que essas leituras tenham o menor temo possível entre elas, estou programando em C (CCS) e pensei em utilizar a interrupção de final de conversão mas acho que estou "comendo bola", não sei onde estou errando e acho que estou me perdendo em algum conceito simples, vejam estes trechos do programa:


Rotina que efetua a leitura dos canais do AD´s, sendo que ela é disparada por um relógio interno via Timer0:

void efetuar_leitura() // Realiza 8 leituras e armazena num vetor leitura_canais[]
{
int canal_AD;

enable_interrupts(INT_AD);

for (canal_AD=0; canal_AD<=7; canal_AD++)
{
set_adc_channel (canal_AD);
delay_us(10); // Garante a carga do capacitor de amostragem
leitura_canais [canal_AD+1] = read_adc();
controle_leitura=1;
while(controle_leitura) // Trava na rotina até terminar a conversão do A/D
{
}
}

disable_interrupts(INT_AD);
}

Dai minha rotina de tratamento da interrupção é a seguinte:

#inline
void trata_AD()
{
controle_leitura = 0;
ADIF = 0;
}


/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Tratamento da Interrupção Global *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#int_global

void trata_int()
{

#asm
timer: movwf w_tmp //
swapf status,w //
clrf status //
movwf stt_tmp // Salva os registradores especiais (salva o Pclath,
movf pclath,w // necessário para trabalhar em bancos de memória de
movwf pclath_tmp // programa diferentes).
clrf pclath //
#endasm

if (t0if) trata_t0(); // Gera base de tempo interna
if (ADIF) trata_AD(); // Avisa quando foi finalizada a conversão

#asm
movf pclath_tmp,w //
movwf pclath //
swapf stt_tmp,w //
movwf status // Recupera os registradores especias
swapf w_tmp,f //
swapf w_tmp,w //
bcf intcon,2 //
#endasm

}


Mas não funcionou...
Eu não sei se em C o proprio código read_adc() automaticamente já faz isso, eu queria uma rotina que eu gastasse o mínimo tempo possível entre leituras, a idéia era ler todos os canais ao mesmo tempo pois esse conjunto de leituras representa um estado de uma grandeza a ser medida, um grupo de 8 canais deve ser lido de 1 em um minuto aproximadamente.
Agradeço quem souber e puder ajudar!!!
Fábio Jerena
Fabio_Jerena
Nibble
 
Mensagens: 52
Registrado em: 08 Mar 2007 08:59

Mensagempor ze » 28 Jan 2008 10:49

veja um ex. do hitech-c

Código: Selecionar todos
void
adc_read(unsigned char channel)
{

   ADCON0 = (channel << 3) + 0xC1;      // enable ADC, RC osc.
   ADGO = 1;
   while(ADGO)
      continue;   // wait for conversion complete
}


veja 1 trecho do dataxit:

Código: Selecionar todos
The A/D conversion time per bit is defined as TAD. The
A/D conversion requires a minimum 12 TAD per 10-bit
conversion. The source of the A/D conversion clock is
software selected. The seven possible options for TAD
are:
• 2 TOSC
• 4 TOSC
• 8 TOSC
• 16 TOSC
• 32 TOSC
• 64 TOSC
• Internal A/D module RC oscillator (2-6 µs)
For correct A/D conversions, the A/D conversion clock
(TAD) must be selected to ensure a minimum TAD time
of 1.6 µs.


em 1 minuto pode-se fazer milhares de leituras, portanto configure corretamente os ADCS2:ADCS1:ADCS0. analise a seção analog-to-digital converter. É claro, deixe um tempo maior que 1,6uS pra segurança!!!

Ah, o mplab (+ hitech c) me avisou um dia que o tempo de aquisição estava curto se mantivesse meus setups de ADCS. Achei legal...
Avatar do usuário
ze
Dword
 
Mensagens: 1655
Registrado em: 05 Jun 2007 14:32

Mensagempor LeandroPIC » 28 Jan 2008 11:18

VC DEVE CONFIGURAR OS REGISTRADORES DIRETAMENTE, É BEM MELHOR E VC SABE O QUE ESTA FAZENDO, NÃO SELECIONE O CLOCK DO AD INTERNO ESSE É AS VEZES É LENTO, E O MAIS INTORTANTE ABILITE A INT GLOBAL.
Avatar do usuário
LeandroPIC
Byte
 
Mensagens: 163
Registrado em: 06 Jul 2007 12:19

Re: Problemas na conversão A/D (preciso de velocidade...)

Mensagempor andre_luis » 28 Jan 2008 12:25

Eu uso a rotina de A/D do CCS com parametro :

read_adc ( ADC_READ_ONLY )

E uso o proprio ciclo do programa como delay.

+++
"Por maior que seja o buraco em que você se encontra, relaxe, porque ainda não há terra em cima."
Avatar do usuário
andre_luis
Dword
 
Mensagens: 5447
Registrado em: 11 Out 2006 18:27
Localização: Brasil - RJ

Mensagempor Pask » 30 Jan 2008 11:32

Amigo Fábio Jerena, experimente a função abaixo. Não sei se vai fazer o que você quer, mas funciona. A função abaixo é para o compilador da CCS.
Configure o conversor A/D assim:

setup_adc(adc_clock_div_8); //A/D ativado com clock interno de 1:8
setup_adc_ports(all_analog); //todas as entradas analógicas
set_tris_a=(0xff); //todo o porta configurado como entrada

static int16 valor_0,valor_1,valor_2,valor_3,valor_4,valor_5,valor_6,valor_7;
//declaração de 8 variáveis inteiras de 16 bits

void ad_varredura (void){
set_adc_channel(0); //varredura ciclica em nos canais do CAD
delay_us(68);
valor_0=read_adc();

set_adc_channel(1);
delay_us(68);
valor_1=read_adc();

set_adc_channel(2);
delay_us(68);
valor_2=read_adc();

set_adc_channel(3);
delay_us(68);
valor_3=read_adc();

set_adc_channel(4);
delay_us(68);
valor_4=read_adc();

set_adc_channel(5);
delay_us(68);
valor_5=read_adc();

set_adc_channel(6);
delay_us(68);
valor_6=read_adc();

set_adc_channel(7);
delay_us(68);
valor_7=read_adc();
}

Depois que o programa terminar de executar esta função, você usa cada variável valor_x para fazer o que você quiser. Não há necessidade de usar a interrupção do conversor A/D.

Espero ter ajudado.

Té mais...!!!
Pask
Word
 
Mensagens: 600
Registrado em: 22 Dez 2006 19:19

Mensagempor EDSONCAN » 30 Jan 2008 13:08

Não quero se chato, mas se voce esta chaveando os canais AD tem que esperar a leitura se estabilizar antes de ler ou um canal ira influenciar em outro, que eu me lembre o PIC usa somente 1 conversor e um MUX analogico.

Edson
EDSONCAN
Word
 
Mensagens: 876
Registrado em: 11 Out 2006 14:11

Mensagempor Pask » 30 Jan 2008 13:26

Por isso coloquei as rotinas de delay. Para dar tempo do capacitor interno se carregar com a tensão a ser convertida.
Pask
Word
 
Mensagens: 600
Registrado em: 22 Dez 2006 19:19

Mensagempor tcpipchip » 30 Jan 2008 14:58

O certo seria voce usar o SAB80166, que consegue disparar os 8 A/D dele em paralelo :)
Avatar do usuário
tcpipchip
Dword
 
Mensagens: 6560
Registrado em: 11 Out 2006 22:32
Localização: TCPIPCHIPizinho!

Mensagempor ze » 30 Jan 2008 14:58

que tal:
Código: Selecionar todos
unsigned int adc_read(unsigned char channel)
{
   ADCON0 = (channel << 3) + 0xC1;      // enable ADC, RC osc.
   ADGO = 1;
   while(ADGO)
   continue;   // wait for conversion complete
return ADRESH*256 + ADRESL;
}
...
...
unsigned int ad[8]
...
...
void le_tudo(void)
{
unsigned char i;
for (i=0;i<8,i++) {ad[i]=adc_read(i);delay(xxx);} //faça 1 teste com e sem delay, talvez a própria iteração sirva como delay.
}
main()
...
...//setups dos ad´s, etc
for (;;)
{
   ...
   le_tudo(); //depois dessa função terás os valores do ad nos globais ad[7]...ad[0]
   ...
   ...
}   
...
...
Avatar do usuário
ze
Dword
 
Mensagens: 1655
Registrado em: 05 Jun 2007 14:32

Mensagempor EDSONCAN » 30 Jan 2008 19:24

Nao quero se chato novamente, mas
ADCON0 = (channel << 3) + 0xC1; // enable ADC, RC osc.
ADGO = 1;
while(ADGO)

O certo não seria:
le:
chaveia o canal;
delay;
dispara a proxima conversao;
??????
Estava vendo minhas rotinas antigas e dava mais de 100useg na conversao, pode ser exagero, mas funcionava.
EDSONCAN
Word
 
Mensagens: 876
Registrado em: 11 Out 2006 14:11

Mensagempor proex » 30 Jan 2008 20:16

Sim o certo é:

1-Seleciona o canal
2-Dá um tempinho pra estabilizaçao
3-Inicia a conversao
4-Salva o valor lido
5-Seleciona o outro canal
6-Dá um tempinho pra estabilizaçao
7-Inicia a conversao
8-Salva o valor lido

e por ai vai.

Já consegui 4700 leituras por segundo num único canal. Com varios canais essa taxa cai proporcionalmente.

Outro ponto importante, para altas taxas de conversão, a impedância da fonte que esta fornecendo a tensao para as entradas AD, tem que ser baixa, da ordem de 2kohm. Sem isso, nada feito.
proex
Dword
 
Mensagens: 2101
Registrado em: 11 Out 2006 14:05
Localização: São Paulo

Mensagempor andre_luis » 30 Jan 2008 20:48

Poisé....

Como mencionei antes, uma outra possibilidade, é implementar a rotina de conversao a/d de tal modo a eliminar as etapas de delay. Isso pode ser feito colocando trechos do programa principal nas etapas 2 e 6 indicadas pelo proex, ao invéz de puramente loops fechados. Tendo sido o título desse tópico "preciso-de-mais-velocidade" ou coisa parecida, acho que isso poderia ser considerado, se não estiver usando interrupção.

Existe áinda apossibilidade de terminar a conversão antes do tempo, perdendo assim precisao no resultado, mas depende da aplicação.


+++
"Por maior que seja o buraco em que você se encontra, relaxe, porque ainda não há terra em cima."
Avatar do usuário
andre_luis
Dword
 
Mensagens: 5447
Registrado em: 11 Out 2006 18:27
Localização: Brasil - RJ

Mensagempor ze » 31 Jan 2008 06:56

edson tu é um chato com razão! rsrsrsrs
só pra constar: o ex. de ad foi copiado e colado da pasta samples\adc do hitech c. mas eles podem não ter atentado a este detalhe (ninguém é perfeito). tem um produto que usa esta rotina (provavelmente já pelo menos passou perto de 1). no caso do produto especificamente, lê-se 2 vezes o valor do ad (descarta-se 1ª leitura). foi uma idéia da época (onde estavam pra ajudar no milênio passado? rsrsrs).

"Tendo sido o título desse tópico "preciso-de-mais-velocidade" ou coisa parecida, acho que isso poderia ser considerado, se não estiver usando interrupção."

só curiosidade: não há uma menção de ler os ad´s em 1 minuto? pros ad´s isso é uma eternidade!!!!!! pra que + velocidade???

abrç
Avatar do usuário
ze
Dword
 
Mensagens: 1655
Registrado em: 05 Jun 2007 14:32


Voltar para PIC

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante

x