Como melhorar precisão do pic

Software e Hardware para uC PIC

Moderadores: andre_luis, 51, guest2003, Renie

Como melhorar precisão do pic

Mensagempor rosiley » 05 Jul 2015 20:15

Boa noite pessoal, estou com dificuldades em acertar a precisão do meu projeto.

Estou usando como base do meu projeto o livro "CRIAÇÃO DE SISTEMAS SUPERVISÓRIOS EM MICROSOFT VISUAL C# 2010 EXPRESS - CONCEITOS BÁSICOS, VISUALIZAÇÃO E CONTROLES". Estou o compilador CCS C, só que não consigo realizar a leitura dos valores com precisão apesar de estar utilizando um processador de 12 bits e ao mesmo tempo não tenho a informação em tempo real no aplicativo e tem mais eu preciso que os valores sejam informado com o sinal (.) pois alguns dos valores são representados em milivolts, segue abaixo o código para a análise de voces.
Informo tambem que estou utilizando uma referencia de 5volts.

cpp code
#include<18F4553.h>           //Inclui arquivo header do PIC 18F4553
#device ADC = 12 //Define 12 bits para o resultado da conversão AD
#use delay (clock=20000000) /*Definição da frequência do cristal para cálculo
..dos delays*/
#fuses HS, NOWDT, PUT,BROWNOUT, NOLVP //Configuração dos bits de controle

//Definições para a comunicação serial
#use RS232 (Baud=9600, enable = PIN_C5, xmit = PIN_C6, rcv = PIN_C7)
#include <2432.c>
#include <DS1307.c>
//#include <RS485.c>

//variáveis para armazenamento da conversão

int32 AN; // AN
int32 AN1; // AN1
int32 AN4; // AN4
int32 AN5; // AN5
int32 AN6; // AN6
int32 AN7; // AN7
int32 AN8; // AN8

int display = 0; //variáveis de controle para o display de leds

/******************************************************************************
variáveis de controle:
temperatura;
agua;
cont = controle de índice para recepção serial;
tempo = informação de tempo em 2 segundos
*******************************************************************************/
int temperatura = 0, agua=0, cont=0, tempo=0;

int1 tmp = 0; /*variável de controle de tempo em 2 segundos para
alterarção das informações no LCD*/
int rec[5]; //Variável de recepção de dados pela serial

#INT_RDA //Diretiva de identficação p/ int. pela recepção serial
void rec_serial() //Funçõa de tratamento da recepção de dados
{
rec[cont] = getc(); /*Lê o dado vindo pela serial e o armazena em
rec na posição (índice) informado por cont*/

if (rec[cont] == 0x0D) //Verifica se o dado recebido é igual a CR (0x0D)
{
//Liga O Display de Leds
if (rec[0]=='L') //Verifica se os primeiros caracteres são 'L'
{
display = 1; //controle do display de leds = 1
output_bit(PIN_D0,display); //Liga o display conectado ao pino RD0
}

//Desliga o display de Leds
if (rec[0]=='D') //Verifica se os primeiros caracteres são 'D'
{
display = 0; //controle do display de leds = 0
output_bit(PIN_D0,Display); //Desliga o display conectado ao pino RD0
}

/*Após recebido todos os dados da serial, faz a limpeza de toda a
variável rec e retorna o controle de índices cont em 0*/
for(cont = 0; cont < 5; cont++) rec[cont] = '\0';
cont = 0;
}
else
/*Se ainda não foram recebidos todos os dados de controle, incrementa
a variável de índice cont*/
cont++;
}

#INT_TIMER0 //Diretiva de indetificação da int. do Timer 0

void PiscaLED()
{
static boolean PiscaLed; //para piscar o led.
static int contador; //para contar o tempo de 1/2 segundo.
set_timer0(61-get_timer0());
contador++;
if(contador == 64) //Se contou 64 (1/2 segundo).
{
contador=0; //zera contagem.
PiscaLed = !PiscaLed; //Inverte bit;
output_bit(pin_C0, PiscaLed); //Liga/desliga LED.
}
}

void Trata_t0() //Função para tratamento do Timer 0
{
tempo++; //Incrementa a variável tempo a cada 25ms
if (tempo >= 80) //Se tempo >= 80 <=> 2 segundos?
{
tmp = 1; //Variável de controle de tempo 2 seg vai para 1
tempo = 0; //Retorna a variável tempo em 0
}
SET_TIMER0(61); //Retorna o valor inicial ao Timer 0
}

//Formato do protocolo = AN0:0000:TMP:0000:00000000
void escreve_serial() //Função de envio do protocolo para a serial
{
printf("AN0:%04lu",AN * 5000/4095); //Envia dados de conversão A/D
printf(":"); //Controle do protocolo
printf("AN1:%04lu",AN1 * 5000/4095); //Envia dados de conversão A/D
printf(":"); //Controle do protocolo
printf("AN4:%04lu",AN4 * 5000/4095); //Envia dados de conversão A/D
printf(":"); //Controle do protocolo
printf("AN5:%04lu",AN5 * 5000/4095); //Envia dados de conversão A/D
printf(":"); //Controle do protocolo
printf("AN6:%04lu",AN6 * 5000/4095); //Envia dados de conversão A/D
printf(":"); //Controle do protocolo
printf("AN7:%04lu",AN7 * 24000/4095); //Envia dados de conversão A/D
printf(":"); //Controle do protocolo
printf("AN8:%04lu",AN8 * 5000/4095); //Envia dados de conversão A/D
printf(":"); //Controle do protocolo
/******************************************************************************
Envia dados referentes ao circuito de aquecimento, ventoinha e leds
0: desligado
1: ligado
******************************************************************************/
printf("%d%d00%d\r\n",agua, temperatura, display);

}

void main() //Função principal
{
//Configura as entradas analógicas AN0 a AN8
SETUP_ADC_PORTS(AN0_TO_AN8|VREF_VREF); //Utiliza o clock interno para tempo de aquisição
//Utiliza o clock externo para tempo de aquisição
SETUP_ADC(ADC_CLOCK_DIV_32);
//Habilita interrupção global
Enable_Interrupts(GLOBAL);
//Habilita interrupção por recepção de dados na serial
Enable_Interrupts(INT_RDA);
//Habilita interrupção pelo overflow do Timer 0
ENABLE_INTERRUPTS(INT_TIMER0);
/*Configura Timer 0 para incremento pelo ciclo de máquina
Prescaler de 1:256 e modo de operação em 8 bits*/
SETUP_TIMER_0(RTCC_INTERNAL | RTCC_DIV_256 | RTCC_8_BIT);
//Inicia o Timer 0 com o valor 61 - Interrupção a cada 25ms
SET_TIMER0(61);


output_D(0x00); //Faz toda a porta D = 0

display = input_state(PIN_D0); //armazena em display o estado do pino RD0

/*Faz a limpeza de toda a variável rec e faz o controle de índices cont em 0*/
for(cont = 0; cont < 5; cont++) rec[cont] = '\0';
cont = 0;

while(true) //Loop principal
{
if (!input(PIN_B4)) //Se chave conectada ao pino RB3 for pressionada
{
agua = 1; //Faz controle da detecção de água = 1
}
else
{
agua = 0; //Faz controle da detecção de água = 0
}

SET_ADC_CHANNEL(0); //Configura o canal de leitura 0
delay_us(100); //Tempo de ajuste do canal (necessário)
AN = READ_ADC(); //Faz a conversão AD e a salva na variável ad0

SET_ADC_CHANNEL(1); //Configura o canal de leitura 1
delay_us(100); //Tempo de ajuste do canal (necessário)
AN1 = READ_ADC(); //Faz a conversão AD e a salva na variável ad0

SET_ADC_CHANNEL(4); //Configura o canal de leitura 4
delay_us(100); //Tempo de ajuste do canal (necessário)
AN4 = READ_ADC(); //Faz a conversão AD e a salva na variável ad0

SET_ADC_CHANNEL(5); //Configura o canal de leitura 5
delay_us(100); //Tempo de ajuste do canal (necessário)
AN5 = READ_ADC(); //Faz a conversão AD e a salva na variável ad0

SET_ADC_CHANNEL(6); //Configura o canal de leitura 6
delay_us(100); //Tempo de ajuste do canal (necessário)
AN6 = READ_ADC(); //Faz a conversão AD e a salva na variável ad0

SET_ADC_CHANNEL(7); //Configura o canal de leitura 7
delay_us(20); //Tempo de ajuste do canal (necessário)
AN7 = READ_ADC(); //Faz a conversão AD e a salva na variável ad0

SET_ADC_CHANNEL(8); //Configura o canal de leitura 8
delay_us(20); //Tempo de ajuste do canal (necessário)
AN8 = READ_ADC(); //Faz a conversão AD e a salva na variável ad0


if (AN4>=200) //Se tempint >= 200 (aprox. 25 graus)
{
temperatura = 1; //Faz controle da temperatura = 1
}

if (AN4<=170) //Se tempint <= 170 (aprox. 20 graus)
{
temperatura = 0; //Faz controle da temperatura = 0;
}

escreve_serial(); //Envia dados pela serial

delay_ms(300); //Atraso de 100ms
}
}
Editado pela última vez por andre_luis em 05 Jul 2015 22:46, em um total de 1 vez.
Razão: inserido tags
rosiley
Nibble
 
Mensagens: 51
Registrado em: 01 Jul 2008 19:38
Localização: rio das ostras

Re: Como melhorar precisão do pic

Mensagempor xultz » 05 Jul 2015 20:39

Se possível, cole o código usando as tags Code, ou cola teu código no site codeviewer.org e coloca o endereço aqui, porque analisar código sem indentação é osso.
98% das vezes estou certo, e não estou nem aí pros outros 3%.
Avatar do usuário
xultz
Dword
 
Mensagens: 3001
Registrado em: 13 Out 2006 18:41
Localização: Curitiba

Re: Como melhorar precisão do pic

Mensagempor EvandrPic » 05 Jul 2015 22:11

Conversor AD de 12 bits...
rosiley escreveu:... apesar de estar utilizando um processador de 12 bits...
EvandrPic
Dword
 
Mensagens: 2116
Registrado em: 31 Mar 2010 15:05

Re: Como melhorar precisão do pic

Mensagempor andre_luis » 05 Jul 2015 22:51

Que valores estão aparcendo ?
"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

Re: Como melhorar precisão do pic

Mensagempor EDSONCAN » 06 Jul 2015 08:20

Vamos la,

Se o seu ruido não vem de problemas de pcb ou dos CI operacionais de entrada que da para ver com o osciloscópio, aumenta os delays e usa uma referencia de tensão externa para o AD estabilizada em temperatura, cuidado com o GND, separe o digital do analógico sempre.

Em controle de processo se trabalha por varredura, ou seja, tem que completar um ciclo de leitura e ação dentro de um determinado tempo e se prioriza alguma tarefas em função de outras, para isso se usa núcleos de tempo real, seu programa é linear, portanto vai ter limitações, quando quiser colocar mais coisas funcionando.

Eu não uso getc, recebo por int na serial, evita que dois caracteres sejam transmitidos e o sistema não pegue devido a algum processo que demore.

Abraços
EDSONCAN
Word
 
Mensagens: 876
Registrado em: 11 Out 2006 14:11

Re: Como melhorar precisão do pic

Mensagempor rosiley » 06 Jul 2015 09:12

Bom dia.

Peço desculpas pelo erro em postar o código.

Consegui resolver o problema da precisão em partes, os valores abaixo de 4.5 volts aparecem beleza sem problema algum mas quando o valor ultrapassa os 4.5 volts ele fica marcando os mesmos 4.5 v estou utilizando referencia externa de 5 volts ajustado em 4.997 mv. Pois precisarei utilizar toda a escala do processador pois um dos sensores tem o seu fundo de escala em 5v.

Outro problema é que utilizando o hyperterminal para verificar o funcionamento o mesmo hora ou outra aparece caracteres que não condiz com o valor a ser mostrado.
rosiley
Nibble
 
Mensagens: 51
Registrado em: 01 Jul 2008 19:38
Localização: rio das ostras

Re: Como melhorar precisão do pic

Mensagempor andre_luis » 06 Jul 2015 12:53

Poderia postar aqui o diagrama esquematico do circuito ?
"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

Re: Como melhorar precisão do pic

Mensagempor ze » 06 Jul 2015 16:12

chutar pode?
chute 1...
experimente fazer
Código: Selecionar todos
(AN*5000)/4095;

onde está
Código: Selecionar todos
AN * 5000/4095

a não ser que int32 seja o mesmo que float

chute 2...
Com relação ao hyperterminal, pode ser que a interrupt do led esteja zoando o barraco

Agora sério... para ad de 12 bis e medir sinal bem baixo, suas referências (+5, gnd) deve ter um layout bem feito além de ter boa estabilidade e precisão. P.ex. não aconselho usar o +5 da alimentação do mc e etc. Mas isso vc ainda vai sentir na pele. Por hora nada a ver com seu problema...
Avatar do usuário
ze
Dword
 
Mensagens: 1655
Registrado em: 05 Jun 2007 14:32

Re: Como melhorar precisão do pic

Mensagempor rosiley » 06 Jul 2015 16:58

ze escreveu:chutar pode?
chute 1...
experimente fazer
Código: Selecionar todos
(AN*5000)/4095;

onde está
Código: Selecionar todos
AN * 5000/4095

a não ser que int32 seja o mesmo que float

chute 2...
Com relação ao hyperterminal, pode ser que a interrupt do led esteja zoando o barraco

Agora sério... para ad de 12 bis e medir sinal bem baixo, suas referências (+5, gnd) deve ter um layout bem feito além de ter boa estabilidade e precisão. P.ex. não aconselho usar o +5 da alimentação do mc e etc. Mas isso vc ainda vai sentir na pele. Por hora nada a ver com seu problema...


Amigo boa tarde.

Verifiquei o circuito utilizando as suas observações e que por sinal me ajudar a enxergar o problema.
Retirei a tensão de referência dos 5v e coloquei diretamente na alimentação principal de cara a precisão e os sinais estranhos desapareceram, tendo uma leitura homogenea e estavel, retirei tambem tambem os leds que fazem a monitoração dos dados enviados e recebidos, a velocidade de recepção aumentou em muito.

Agora vou partir para a confecção de um circuito de referencia com boa estabilidade.

Obrigado pela ajuda, vou fazer os testes e verificar se está tudo do jeito que quero e posto o resultado aqui.
rosiley
Nibble
 
Mensagens: 51
Registrado em: 01 Jul 2008 19:38
Localização: rio das ostras

Re: Como melhorar precisão do pic

Mensagempor rosiley » 29 Jul 2015 19:58

Boa noite pessoal, volto aqui mais uma vez para pedir a ajuda a vocês.

É o seguinte, fiz as modificações no meu código com as instruções de vocês mas me deparei com um problema que não consigo resolver ou não consigo entender, montei todo o circuito na pci que mandei fabricar e funciona perfeitamente mais só que os valores do meu adc está variando muito, encontrei um código em outro fórum mas não entendi como fazer. Segue parte do código abaixo

Código: Selecionar todos
#include <18F4520.h>
#device adc=10

float Media,sinal,sinal2,OFFSET=1.71;

float conversao(){

   Media = 0;
   for(y=0;y<=38;y++){
            delay_us(100);
            Media = Media + read_adc();         
       }
   sinal = (media / 38);     
   sinal2 = (sinal*5.0)/1023;
   return ((sinal2-OFFSET)*8);
rosiley
Nibble
 
Mensagens: 51
Registrado em: 01 Jul 2008 19:38
Localização: rio das ostras

Re: Como melhorar precisão do pic

Mensagempor ze » 30 Jul 2015 12:27

Se só entender lhe basta, então tentemos...O código faz a média de 38 leituras. De fato é melhor fazer media de numeros base 2 por ser binário. No caso 32 e não precisa ser float pois o valor da conversão é int. Algo assim...
Código: Selecionar todos
unsigned int conversao()
{
unsigned char y;
unsigned int media=0;
for (y=0;y<32;y++) {media+=adcread();delay(xxx);}
return media/32;
}

e no programa principal
Código: Selecionar todos
float sinal2;
sinal2 = (conversao()*5.0)/1023;

Também acho que não demos muita bola ao último parágrafo do meu post anterior. Há probabilidade de ser problema de layout. Publique o esquema e o desenho do layout (pra eu copiar seu projeto e ficar milionário... isso foi engraçado? ... sqn)
Avatar do usuário
ze
Dword
 
Mensagens: 1655
Registrado em: 05 Jun 2007 14:32

Re: Como melhorar precisão do pic

Mensagempor rosiley » 30 Jul 2015 12:42

Ze, obrigado pela ajuda.

Agora se isto que estou fazendo vai me deixar milionário, tenho que correr antes que outro fique. rsrsrsrsr
Mais obrigado de novo, vou ler e reler o que você escreveu e aplicar nos testes, como falei anteriormente tudo está funcionando, só me resta mesmo é fazer com que o valor do ad fique estável pois tenho bastante variação, estou usando um lm 324 como amplificador de sinal na simulação via proteus tudo funciona mais na prática tenho essas variações.
rosiley
Nibble
 
Mensagens: 51
Registrado em: 01 Jul 2008 19:38
Localização: rio das ostras

Re: Como melhorar precisão do pic

Mensagempor rosiley » 30 Jul 2015 13:13

Segue anexo o ckt de amplificação do sinal.
Você não está autorizado a ver ou baixar esse anexo.
rosiley
Nibble
 
Mensagens: 51
Registrado em: 01 Jul 2008 19:38
Localização: rio das ostras

Re: Como melhorar precisão do pic

Mensagempor ze » 30 Jul 2015 14:24

seu circuito tá 1/2 estranho. certeza que é assim mesmo? bom... tem algumas variáveis que se devem definir
-que tipo de sinal é? de onde vem? quantos v? mV? uV? é dc, claro.
-qual o valor do ganho - em quantas vezes pretendeu amplificar?
-qual a proposta final do projeto?
-o layout é crítico. aquele gnd p.ex não pode ir pro regulador de voltagem e sim pro pino gnd do mc. O vcc-vdd preferencialmente outro que não seja o mesmo do mc.
-o mc usa ser turrão quando troca de um canal pra outro. Vc deve dar um tempo e as vezes até mesmo deixar as outras entradas como digital pra ler a "analógica do momento"
-etc
Mostre o desenho do layout.
Cogite no futuro migrar para avr. Alguns têm amplificador
Avatar do usuário
ze
Dword
 
Mensagens: 1655
Registrado em: 05 Jun 2007 14:32

Re: Como melhorar precisão do pic

Mensagempor MOR_AL » 30 Jul 2015 16:35

Meu amiguinho. Acho que você está com um problema.
Para poder analisar o circuito:
1 - Quais são os limites de tensão dos sinais fornecidos por J1, pinos 1, 2 e 3?
2 - Quais são os limites de frequência dos mesmos sinais?
3 - Você conhece as impedâncias de saída dos sinais fornecidos por J1, pinos 1, 2 e 3? Quais seriam? Mesmo uma ordem de grandeza bastaria.

Informações adicionais:
1 - O LM324, assim como muitos ou todos os amplificadores operacionais (AO) possuem limitações de tensão máxima comum de entrada. Em outras palavras; a saída não responde (como deveria) se a diferença de tensão entre o sinal e a tensão de alimentação for inferior a um determinado valor. Ex. Vcc ou Vdd = +5V e Vsinal de pico em 4,5V. A diferença é de 0,5V. Acho que para p LM324 essa diferença não pode ser inferior a 1,5V. Pelo menos é o que consta no manual, mas em determinadas condições gerais. Em alguns casos especiais esta diferença não pode ser maior que 2V e em outros casos esta diferença é menor. Mas independente das condições, a tensão de modo comum [(Ventrada positiva + Ventrada negativa) /2] não pode alcançar a tensão de alimentação (Vcc, ou Vdd).
2 - Os AO reais também possuem limitações quanto à faixa de tensão de saída. Para este operacional, a tensão mínima de saída pode ir até 5mV (típico) ou 20mV (máximo). Isso para Vcc = 5V e RL = 10k ohms.
Já a tensão máxima de saída, em boas condições, pois vai depender da corrente de saída, é de no mínimo 1V abaixo de Vcc ou Vdd. Isso quer dizer que, se a sua fonte for de 5V, o AO não DEVE funcionar corretamente com tensões de saída superiores a 4V.
3 - Este AO em especial, possui um circuito para reduzir o consumo da corrente de alimentação. Para isso ele pode funcionar ou em Classe A, ou em Classe B. Vai depender da tensão de saída. Em alguns casos, para prevenir a distorção de Cross-Over, que ocorre com sinais de saída inferiores a 1V, é necessário incluir um resistor da saída ao terra.

4 - Como você está usando um CAD com 12 bits de resolução, este (e muitos AO) não servirão para o seu projeto.
Explico:
Um conversor de 12 bits possui 2 elevado a 12 valores, ou 4096 valores, certo?
Isso quer dizer que, para um sinal que pode variar entre 0V e +5V, você terá degraus mínimos de tensão de 5.000mV / 4096 = 1,2207mV.
1 - O AO não vai possuir esta precisão toda. Teria que usar AO com duas fontes de tensão. Uma positiva e outra negativa para que seu sinal não se aproxime das tensões de alimentação.
2 - A sua tensão de referência teria que ter a precisão referente a uma tensão de meio bit menos significativo, ou 5.000mV / (2 x 4096) = 0,61uV (micro volts). ISSO EM TODA A FAIXA DE TEMPERATURA QUE O CIRCUITO DEVE FUNCIONAR. A própria tensão de referência TERIA que ser EXCELENTE. Não é fácil se obter esta precisão. 4,999.39V <= Vref <= 5,000.61V.

Sinceramente.
Eu não acredito que você precise de toda esta precisão, qualquer que seja este seu circuito. Em outras palavras. Acredito que você poderia reduzir o número de bits do seu CAD. Isso facilitaria, um pouco, a sua vida. Tanto na tensão de referência, como na escolha do AO, como na rapidez do programa.

Finalmente:
1 - Não entendi porque você colocou capacitores diretamente conectados ao seu sinal em J1 (pinos 1, 2 e 3).
2 - Os seus filtros (como R5 e C5) poderiam ser melhorados.
R4 também deveria ter um valor compatível com a impedância de saída dos sinais em J1 (pinos 1, 2 e 3).

São estes os meus comentários.
Bons projetos.
MOR_AL
"Para o triunfo do mal só é preciso que os bons homens não façam nada." Edmund Burke.
"Nunca discutas com pessoas estúpidas. Elas irão te arrastar ao nível delas e vencê-lo por possuir mais experiência em ser ignorante". Mark Twain
Avatar do usuário
MOR_AL
Dword
 
Mensagens: 2934
Registrado em: 19 Out 2006 09:38
Localização: Mangaratiba - RJ

Próximo

Voltar para PIC

Quem está online

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

x