Ir ao conteúdo
  • Cadastre-se

Problemas para rodar aquecedor com temporizador - PIC 16F877


Guilbuss

Posts recomendados

Olá a todos,

Sou iniciante em eletrônica e em projetos com microcontroladores e este é meu primeiro tópico no fórum. Gostaria da ajuda de vocês para resolver um problema no qual realmente "travei", apesar de várias tentativas! É o seguinte:

Elaborei um projeto de um aquecedor integrado a um temporizador utilizando o PIC 16F877A, com objetivo de efetuar aquecimentos progressivos em um sistema (um banho-maria, para ser mais específico), a diferentes tempos. Um exemplo de funcionamento pretendido (T=temperatura e t=tempo): iniciando a uma temperatura de 28°C (T ambiente) o sistema é aquecido até T1 (35°C, por exemplo) e, ao chegar nesse ponto, a temperatura é mantida constante (via controle liga-desliga) durante t1 minutos (15 minutos, por exemplo); ao finalizar esse tempo o sistema passa novamente a ser aquecido até uma segunda temperatura programada (T2, 50°C por exemplo), a qual, uma vez alcançada, é mantida constante por t2 minutos (12 minutos, por exemplo) e assim consecutivamente (limite de 20 set points). O dispositivo lê e mostra a temperatura do sistema ao longo de todo o processo e, ao chegar em um dos setpoints (de temperatura), inicia um temporizador - o qual é mostrado ao lado da temperatura lida. Por enquanto o controle é do tipo liga-desliga sem histerese - o qual pretendo modificar, dentro em breve, para um controle mais preciso.

Bem, até agora consegui elaborar o código e rodar no Proteus sem grandes problemas; porém, ao testar em um protótipo real montado em protoboard sempre acontece uma coisa estranha: ao chegar no setpoint de temperatura (T1, T2, etc, quaisquer que sejam as temperaturas programadas) o sistema aciona o temporizador e começa a contar o tempo (t1,t2, etc), mas nesse ponto imediatamente a leitura de temperatura sofre um incremento de cerca de 2°C sem motivo aparente!. Quando o temporizador é desligado (decorridos t1, t2, etc) e o sistema passa a ser aquecido até a próxima T programada a leitura de temperatura sofre um decréscimo desses mesmos 2°C!. Já tentei alterar a lógica do programa, mas não surtiu efeito. Alguém saberia o porquê desse "salto" na temperatura e como poderia resolver tal problema? Já não consigo mais "enxergar" o que pode estar errado no código...

informações importantes:

- Estou simulando a temperatura via um potenciômetro de 10K (o qual futuramente será devidamente substituído por um sensor, possivelmente um LM35);

- O compilador utilizado é o CCS;

- Na versão mais atual do programa (mostrada abaixo) o TIMER0 é dedicado para a leitura (e apresentação em display LCD) da temperatura e o TIMER1 para o temporizador - ressalto que já utilizei outra lógica, na qual a leitura de temperatura era feita no programa principal (Main)... mesmo assim o problema ocorreu!

Segue o programa completo para avaliação:

include <16F877A.h>

#device adc=10

#fuses NOWDT,XT,PUT

//Declaração de funções

Timer();

Leitura_Temperatura();

Aquisicao_de_Dados();

Alarme();

#use delay(clock=4000000)

#use fast_io(a)

#use fast_io(B)

#use fast_io©

#use fast_io(d)

#use fast_io(e)

#byte porta=0x05

#byte portb=0x06

#byte portc=0x07

#byte portd=0x08

#byte porte=0x09

int i=0, delay=100, debounce1=80, debounce2=40;

long int valor=0, giros=0, ciclos=0, seg=0, min=0;

signed int N=0, M=0, T=0, s=0, setpointTemperatura=0, setpointtempo=0;

signed int Temperaturas[20];

signed int Tempos[20];

float temperatura=0;

#define use_portd_lcd true

#include <lcd.c>

////////////////////////////////////// FUNÇÃO: INTERRUPÇÃO TIMER 1 - TIMER ////////////////////////////////////

#int_TIMER1

void Timer()

{

set_timer1(3036-get_timer1());

ciclos=ciclos+1;

if(ciclos==2)

{seg=seg+1;

ciclos=0;

}

if(seg==60)

{min=min+1;

seg=0;

}

}

////////////////////////////////////// FUNÇÃO: INTERRUPÇÃO TIMER_0 - Temperatura ///////////////////////////////

#int_RTCC

void Leitura_Temperatura()

{

set_timer0(131-get_timer0());

giros=giros+1;

if(giros>=50) // 4000000/(4*32) = 1000000/32 32/1000000 = 0,000032 256-131 = 125

{valor = read_adc(); // 125*0,000032 = 0,004 0,004*25 = 100ms

delay_us(30); // Leitura de temperatura a cada 50 giros = 200 ms

temperatura = valor*0.48828125;

lcd_gotoxy(1,1); printf(lcd_putc,"\fT=%1.0f\xDFC", temperatura);

lcd_gotoxy(11,1); printf(lcd_putc,"%02lu:%02lu", min, seg);

giros=0;

}

}

////////////////////////////////////// FUNÇÃO: AQUISIÇÃO DE DADOS //////////////////////////////////////////

void Aquisicao_de_Dados()

{

/////// 1 - AQUISIÇÃO DE DADOS ///////

//PERÍODOS N//

printf(lcd_putc,"\fDigite N:\n");

delay_ms(1000);

N = 0;

While(N < 20)

{

if (input(pin_b1))

{delay_ms(debounce1);

if (input(pin_b1))

{delay_ms(debounce2);

N = N + 1;

}

}

if (input(pin_b0))

{delay_ms(debounce1);

if (input(pin_b0))

{delay_ms(debounce2);

N = N - 1;

}

}

if (N < 1 || N >= 20) {N = 0;} //limite superior de N tem que bater com tamanhos das matrizes

{delay_ms(10);

printf(lcd_putc,"\f%d segmentos", N+1);

}

if (input(pin_b2))

{delay_ms(debounce1);

if (input(pin_b2))

{delay_ms(debounce2);

} break;

}

}

printf(lcd_putc,"\fN = %d segmentos", N+1);

delay_ms(1000);

//TEMPERATURAS E TEMPO//

M = 0;

while (M <= N)

{

//TEMPERATURA T//

printf(lcd_putc,"\fDigite T%d:\n", M+1);

delay_ms(1000);

T = 0;

While(true)

{

if (input(pin_b1))

{delay_ms(debounce1);

if (input(pin_b1))

{delay_ms(debounce2);

T = T + 1;

}

}

if (input(pin_b0))

{delay_ms(debounce1);

if (input(pin_b0))

{delay_ms(debounce2);

T = T - 1;

}

}

if (T<0 || T>150) {T=0;}

{delay_ms(10);

printf(lcd_putc,"\f%d\xDFC",T);}

if (input(pin_b2))

{delay_ms(debounce1);

if (input(pin_b2))

{delay_ms(debounce2);

} break;

}

}

//TEMPO s//

printf(lcd_putc,"\fDigite t%d\n", M+1);

delay_ms(1000);

s = 0;

While(TRUE)

{

if (input(pin_b1))

{delay_ms(debounce1);

if (input(pin_b1))

{delay_ms(debounce2);

s=s+1;

}

}

if (input(pin_b0))

{delay_ms(debounce1);

if (input(pin_b0))

{delay_ms(debounce2);

s=s-1;

}

}

if (s<0) {s=0;}

delay_ms(10);

printf(lcd_putc,"\f%d minutos", s);

if (input(pin_b2))

{delay_ms(debounce1);

if (input(pin_b2))

{delay_ms(debounce2);

} break;

}

}

printf(lcd_putc,"\fT%d=%d\xDFC \nt%d=%d minutos", M+1, T, M+1, s); // \xDF = ° onde \x é utilizado para caracter especial e DF é

delay_ms(1000); // a representação hexadecimal do código do caracter °

//TRANSFERÊNCIA DOS DADOS PARA AS MATRIZES

Temperaturas[M] = T;

Tempos[M] = s;

M = M + 1;

}

}

////////////////////////////////////// FUNÇÃO: ALARME /////////////////////////////////////////////////////

void Alarme()

{

output_high(PIN_B6);

delay_ms(500);

output_low(PIN_B6);

}

////////////////////////////////////// FUNÇÃO: PRINCIPAL ///////////////////////////////////////////////////

void main()

{

setup_timer_0(RTCC_INTERNAL | RTCC_DIV_32);

setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);

set_timer0(131);

set_timer1(3036);

setup_timer_2(T2_DISABLED,0,1);

setup_comparator(NC_NC_NC_NC);

setup_vref(FALSE);

setup_adc_ports(AN0);

setup_adc(ADC_CLOCK_DIV_8);

set_adc_channel(0); //Seleciona Canal 0 para sensor de Temperatura

enable_interrupts(GLOBAL);

disable_interrupts(INT_RTCC);

disable_interrupts(INT_TIMER1);

set_tris_a(0b11111111);

set_tris_b(0b00001111);

set_tris_c(0b11111111);

set_tris_d(0b11111111);

set_tris_e(0b11111111);

porta=0x0;

portb=0x0;

portc=0x0;

portd=0x0;

porte=0x0;

lcd_init();

delay_ms(20);

delay_ms(200);

output_high(PIN_B7);

Alarme();

output_low(PIN_B7);

printf(lcd_putc,"\fSistema ligado!");

delay_ms(1000);

Aquisicao_de_Dados();

delay_ms(500);

printf(lcd_putc,"\fIniciando...");

delay_ms(1000);

printf(lcd_putc,"\f");

enable_interrupts(INT_RTCC);

delay_ms(500);

while(i<M)

{

setpointTemperatura = Temperaturas;

while(i==0 && temperatura > setpointTemperatura)

{Alarme();

lcd_gotoxy(1,2); printf(lcd_putc,"Temperat. > T1!"); // Verifica se a temperatura inicial do sistema

delay_ms(20); // não é maior do que o primeiro setpoint T[1]!

}

printf(lcd_putc,"\f");

while(temperatura < setpointTemperatura)

{lcd_gotoxy(1,2); printf(lcd_putc,"Aquec. a T%d=%d\xDFC", i+1, Temperaturas);

output_high(pin_b4);

delay_ms(20);

}

printf(lcd_putc,"\f");

output_low(pin_b4);

Alarme();

ciclos=0;

seg=0;

min=0;

enable_interrupts(INT_TIMER1);

delay_ms(10);

setpointtempo = Tempos;

while(min < setpointtempo)

{lcd_gotoxy(1,2); printf(lcd_putc,"T%d=%d\xDFC/t%d=%dmin", i+1, Temperaturas, i+1, Tempos);

delay_ms(10);

if(temperatura < setpointTemperatura)

{output_high(pin_b4);}

else {output_low(pin_b4);}

}

disable_interrupts(INT_TIMER1);

i = i+1;

min=0;

seg=0;

}

disable_interrupts(INT_RTCC);

disable_interrupts(INT_TIMER1);

while(true)

{

printf(lcd_putc,"\fFIM!");

Alarme();

delay_ms(200);

printf(lcd_putc,"\f");

}

}

Link para o comentário
Compartilhar em outros sites

Vamos lá!

Como você informou que testou em um protótipo real, então é importantíssimo que você:

1 - Fotografe a parte da estufa com a indicação clara da localização da fonte de calor, do sensor e as medidas da estufa. Coloque uma régua junto a estufa, antes de fotografar. Acho que pode estar acontecendo um gradiente térmico entre a fonte de calor e o sensor.

2 - Normalmente se utiliza um controle PID para resolver o "overshoot" de temperatura que ocorre.

3 - Como não pratico a linguagem C, você poderia mostrar ou em pseudo-código, ou em fluxograma, o que o firmware faz, mas acho que o problema está nos itens 1 e ou 2.

Em tempo: Você deve incluir o sensor de temperatura para que o loop seja fechado. Explique melhor o uso do tal potenciômetro.

Aguardo retorno.

MOR_AL

Link para o comentário
Compartilhar em outros sites

Vou deixar meu palpite :

Quando voce atinge o set-point, o conversor a/d está sendo alterado de alguma maneira. Com certeza existe uma diminuta mudança na alimentação do potenciômetro, ou do PIC, ou da referencia do a/d do PIC, como um acionamento de LED ou de um relê.

Sugiro melhorar a estabilidade da alimentação, com capacitores literalmente colados nos pinos do PIC, e no potenciômetro, para tentar estabilizar essa leitura.

Para ficar imune a esse tipo de problema, sugiro voce usar um sensor de temperatura com saída digital em vez de analógica, assim você recebe a medida prontinha sem depender de parte analógica.

Paulo

Link para o comentário
Compartilhar em outros sites

Vamos lá!

Como você informou que testou em um protótipo real, então é importantíssimo que você:

1 - Fotografe a parte da estufa com a indicação clara da localização da fonte de calor, do sensor e as medidas da estufa. Coloque uma régua junto a estufa, antes de fotografar. Acho que pode estar acontecendo um gradiente térmico entre a fonte de calor e o sensor.

2 - Normalmente se utiliza um controle PID para resolver o "overshoot" de temperatura que ocorre.

3 - Como não pratico a linguagem C, você poderia mostrar ou em pseudo-código, ou em fluxograma, o que o firmware faz, mas acho que o problema está nos itens 1 e ou 2.

Em tempo: Você deve incluir o sensor de temperatura para que o loop seja fechado. Explique melhor o uso do tal potenciômetro.

Aguardo retorno.

MOR_AL

Na verdade creio ter me expressado mal ao mencionar que se tratava de um protótipo real... o que tenho, na verdade, é o circuíto montado em uma protoboard e o potenciômetro simula o sinal de temperatura - sinal que será fornecido, numa próxima etapa do projeto, por um sensor adequado.

O controle por enquanto é do tipo liga-desliga, mas assim que resolver os problemas atuais pretendo fazer um upgrade no programa para um controle PID. Muito obrigado pelas dicas!

Vou deixar meu palpite :

Quando voce atinge o set-point, o conversor a/d está sendo alterado de alguma maneira. Com certeza existe uma diminuta mudança na alimentação do potenciômetro, ou do PIC, ou da referencia do a/d do PIC, como um acionamento de LED ou de um relê.

Sugiro melhorar a estabilidade da alimentação, com capacitores literalmente colados nos pinos do PIC, e no potenciômetro, para tentar estabilizar essa leitura.

Para ficar imune a esse tipo de problema, sugiro voce usar um sensor de temperatura com saída digital em vez de analógica, assim você recebe a medida prontinha sem depender de parte analógica.

Paulo

Estou desconfiado que é isso mesmo, Paulo! Não mostrei o esquema: há dois leds e um buzzer, os quais são acionados durante o processo para sinalizar mudança nas etapas de aquecimento/temporização... pode ser que isso esteja alterando a leitura do ADC! Outra coisa: não estou utilizando o pino de referência do ADC, está livre.

Pretendo alterar e testar as seguintes modificações:

1) Acoplar os capacitores para estabilizar a alimentação;

2) Utilizar um tensão de referência (também estabilizada) para o ADC do microcontrolador;

3) Retirar os leds e o buzzer do dispositivo, caso a utilização de filtros (capacitores) não resulte em melhora.

Futuramente, caso não verifique melhora utilizando tais estratégias, poderei tentar o sensor analógico que comentaste.

Testarei isso e volto para comentar os resultados, provalvelmente na semana que vem, pois infelizmente meu tempo anda curto...

Outra coisa: qual seria o "tamanho" ideal dos capacitores para estabilizar/filtrar a alimentação? 22nF?

Valeu, muito obrigado!

Guilherme

Link para o comentário
Compartilhar em outros sites

Arquivado

Este tópico foi arquivado e está fechado para 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...

Ebook grátis: Aprenda a ler resistores e capacitores!

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!