Guia CNC Brasil - Tudo sobre CNC, Router, Laser, Torno e 3D Print
ELETRÔNICA / ELÉTRICA => Eletrônica Básica => Microcontroladores => Tópico iniciado por: Smarley em 08 de Fevereiro de 2009, 00:53
-
Olá!
Fiz um programa com conversor ad para ler uma temperatura.
O sensor que estou usando é o LM35, mas estou com problemas...
O LM35 libera 0,32V digamos.
Mas o meu PIC le e mostra 32 e a cada 10 segundos por exemplo, da um salto para 35 ou 36 e volta para os 32. Mas no LM35 está sempre 0,32V.
Isso ocorre também quando ligo o pino ao terra.
Fica marcando 0, ai derrepente salta para 4 ou 5...
O programa que fiz foi esse:
long int valor;
int32 val32;
void main()
{
lcd_init();
setup_adc_ports(AN0_AN1_AN3);
setup_adc(ADC_CLOCK_INTERNAL);
setup_psp(PSP_DISABLED);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);;
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
set_adc_channel(0);
while(true)
{
valor=read_adc();
if(valor) valor += 1;
val32=(valor*4+((int32)valor*113)/128)/10;
printf(lcd_putc,"\f Temp.=%luC",val32);
delay_ms(200);
}
}
Eu dividi por 10 para mostrar a temperatura em graus.
Porque será que está dando esse problema?
O PIC que eu uso é o 16F877A.
Obrigado!
-
sem dúvidas que este programa é em C ... mas qual o compilador?
se for possível colocar parte do esquema acho ajudaria a lhe ajudar. ;)
abrax!
-
Eae cara!
Estou usando o PCW, CCS Compiler.
#include "C:\Program Files\PICC\PICC\secador.h"
#define LCD_ENABLE_PIN PIN_B0
#define LCD_RS_PIN PIN_B1
#define LCD_RW_PIN PIN_B2
#define LCD_TYPE 2
#include <lcd.c>
long int valor;
int32 val32,tempmax=120,tempmin=115,almax=130,almin=105;
int x;
static boolean y;
void main()
{
lcd_init();
setup_adc_ports(AN0_AN1_AN3);
setup_adc(ADC_CLOCK_INTERNAL);
setup_psp(PSP_DISABLED);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);;
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
set_adc_channel(0);
delay_ms(200);
x=0;
y=0;
while(true)
{
valor=read_adc();
if(valor) valor += 1;
val32=(valor*4+((int32)valor*113)/128)/10;
printf(lcd_putc,"\f Temp.=%luC\nMax=%lu Min=%lu",val32,tempmax,tempmin);
delay_ms(200);
if((val32>almax)&&(y==0))
{
output_high(PIN_C2);
printf(lcd_putc,"\f TEMPERATURA\n MAXIMA!");
delay_ms(5000);
output_low(PIN_C2);
y=1;
}
if((val32<almin)&&(y==0))
{
output_high(PIN_C2);
printf(lcd_putc,"\f TEMPERATURA\n MINIMA!");
delay_ms(5000);
output_low(PIN_C2);
y=1;
}
if(val32>tempmax)
{
while(input(PIN_D6)!=0)
{
output_high(PIN_C0);
y=0;
}
output_low(PIN_C0);
}
if(val32<tempmin)
{
while(input(PIN_D7)!=0)
{
output_high(PIN_C1);
y=0;
}
output_low(PIN_C1);
}
if(input(PIN_D0)&&x==0)
{
while(input(PIN_D0))
{
printf(lcd_putc, "\fAlterar temp.\nmax. para: %luC", tempmax);
delay_ms(200);
if(input(PIN_D1))
{
tempmax=tempmax+1;
}
if(input(PIN_D2))
{
tempmax=tempmax-1;
}
x=1;
}
}
if(input(PIN_D0)&&x==1)
{
while(input(PIN_D0))
{
printf(lcd_putc, "\fAlterar temp.\nmin. para: %luC", tempmin);
delay_ms(200);
if(input(PIN_D1))
{
tempmin=tempmin+1;
}
if(input(PIN_D2))
{
tempmin=tempmin-1;
}
x=2;
}
}
if(input(PIN_D0)&&x==2)
{
while(input(PIN_D0))
{
printf(lcd_putc, "\fAlterar alarme\nmax. para: %luC", almax);
delay_ms(200);
if(input(PIN_D1))
{
almax=almax+1;
}
if(input(PIN_D2))
{
almax=almax-1;
}
x=3;
}
}
if(input(PIN_D0)&&x==3)
{
while(input(PIN_D0))
{
printf(lcd_putc, "\fAlterar alarme\nmin. para: %luC", almin);
delay_ms(200);
if(input(PIN_D1))
{
almin=almin+1;
}
if(input(PIN_D2))
{
almin=almin-1;
}
x=0;
}
}
}
}
Esse é o programa completo.
Eu não tenho o esquema elétrico, mas tenho proteus.
É bem simples...
Ali onde tem um potenciometro no pino A0 é onde vai o sensor...
Eu achei que seria erro no meu programa, mas é o único jeito que sei fazer conversão.
A, eu só sei programar em C.
Abraço!
-
tu não definiu no cabeçalho a resolução do conversor AD ...
#deviceadc=XX;
adicione e veja o que acontece. :)
abrax!
-
Eu esqueci de postar o cabeçalho:
#include <16F877A.h>
#device adc=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES XT //Crystal osc <= 4mhz
#FUSES PUT //Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES WRT_50% //Lower half of Program Memory is Write Protected
#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
Ta la emcima ele...
-
bom .. na primeira vez que tu colocasse o programa no cabeçalho não consta esta linha ... e outro detalhe .. nao coloca o ; que eu coloquei ali ... e tenta iniciar com resolução de 8 bits primeiro ...
abrax!
-
bom carinha .. tem algo errado ainda no primeiro firm completo .. os fuses tb não estou vendo-os ... outra coisa .. tu fez os cálculos de tempo mínimos de aquisição de sinal?Seguiu passo a passo as explicações do livro do Fábio?
qqer coisa .. tamos aí ..
abrax!
-
Passei para 8bit, mas tive que multiplicar o valor por 4 para mostrar certo no LCD.
sobre o tempo de aquisição eu vou colocar um delay de 50ms antes do valor=read_adc(); e depois...
Vamos ver o que acontece.
Abraço!
-
Vou substrair 1 também, para o valor ficar certo.
Porque ele está marcando sempre 1 para mais do que entra...
-
*subtrair
-
Deu o mesmo problema...
Agora eu vou fazer assim, vou voltar com o programa anterior e multiplicar a tensão de saída do LM35 por 3 eu acho...
Assim eu diminuo o erro de leitura.
Ai depois é só eu dividir este valor por 3.
Vamos ver se da certo...
-
Aqui está o esquema que eu vou fazer...
Eu não tenho uma fonte simétrica +12V, -12V para usar.
Então vou tentar fazer assim, usando o terra como alimentação negativa para o TL072.
Não sei se vai funcionar...
Abraço!
-
Eu não tenho uma fonte simétrica +12V, -12V para usar.
Use uma fonte de pc
-
Certo!
Porque sem a alimentação negativa ele não funciona...
Acabei de comprovar o que ja suspeitava.
Aquele meu esquema para amplificar ali está correto?
-
Consegui fazer funcionar melhor...
Multipliquei a saída por 3 para depois dividir no programa...
Assim ele só da um erro de vez enquando de 1 grau.
Este termometro vai ser usado até 150graus então eu não posso multiplicar por mais do que 3 vezes para não passar do 5V na entrada do PIC.
Eu vou fazer um para usar em casa, e vou multiplicar a saída 9 ou 10 vezes porque não vai passar de 50 graus...
vlw pela ajuda!
Abraço!
-
Uma coisa que eu não tentei ainda foi trocar a porta do PIC, usar outra no lugar da A0.
Vou fazer este teste para ver se o problema continua ou não...
-
Troquei a porta do PIC mas o problema continua...
Eu pensei agora e achei uma maneira de amenizar o problema.
Fiz 5 leituras e uma média.
Assim a variação ficou em torno de 0,2 0,3 graus.
Eu não consegui fazer mais que 6 leituras porque ele da erro.
Com 7 leituras ele diz, "Out of ROM, a segment or the program is too large MAIN".
Eu não se se é a função MAIN que está grande e dividindo ela daria para fazer ou é que está acabando a rom mesmo...
eu acho que não pois com 6 leituras ele ocupa 23% da RAM e 45% da ROM.
Vou tentar repartir o programa...
-
Consegui,
foi só fazer 5 leituras em uma função, mais 5 em outra.
E depois fazer a média das duas na MAIN.
Acho que assim eu diminuo ainda mais o erro...
Agora está com 24% da RAM e 63% da ROM...
Ja que o PIC vai só fazer isso, não tem porque deixar memória sobrando...
-
Caro amigo.
Já tive problema parecido com o que está ocorrendo contigo, mas eu usava um sinal de 4-20mA proveniente de um sensor analógico, para resolver o problema fiz duas coisas.
1º fiz uma linearização do sinal de entrada para o PIC.
2º coloquei usei tensão de referencia para o PIC, assim trabalhei com sinais de no máximo 2,5V, com resolução de 10bits.
procure sempre usar fonte chaveada para o PIC ou então fontes de bancada profissionais, que apresentam baixíssimo ripple, já tive muito problema com PIC por utilizar fontes indevidas.
Com essas duas opções que apresentei, eu obtive um ótimo resultado em minha aplicação.
Att.