Escolar Documentos
Profissional Documentos
Cultura Documentos
Brasil
2014
Murilo José de Carvalho
Brasil
2014
C331c Carvalho, Murilo José de
Controle digital de temperatura e pressão em chuveiros
elétricos / Murilo José de Carvalho. -- Bragança Paulista :
IFSP-BRA, 2014.
97f.
CDD 629.8
Murilo José de Carvalho
Brasil
2014
Este trabalho é dedicado à minha família,
que sempre apoiou meus estudos.
Agradecimentos
Ao meu orientador, Prof. Me. Sérgio Ricardo Pacheco pela imensa ajuda, paciência e
empenho dispensados na montagem do projeto e na confecção da monografia.
Ao meu coorientador, Prof. Me. Adilson de Souza Cândido pelo apoio na criação do
algorítimo de controle PID.
Ao Prof. Dr. Luiz Fernando Tibaldi Kurahassi pela enorme ajuda no desenvolvimento
do circuito do potência.
Ao colega de curso Igor Anderson Carvalho de Lima pela doação de alguns componen-
tes eletrônicos utilizados na montagem do projeto.
A todos os colegas, amigos e familiares que tenham contribuído com apoio moral ou
material para a conclusão deste projeto.
“Ando devagar
Porque já tive pressa
E levo esse sorriso
Porque já chorei demais
Hoje me sinto mais forte
Mais feliz, quem sabe
Só levo a certeza
De que muito pouco sei
Ou nada sei
(Tocando em Frente, Almir Sater / Renato Teixeira)
Resumo
O principal objetivo deste trabalho está relacionado com o desenvolvimento de um circuito eletrônico
para o controle digital da pressão da água de entrada e da temperatura em chuveiros elétricos conven-
cionais. Com este propósito, foi utilizado um controlador Proporcional-Integral-Derivativo (controlador
PID) para regular a temperatura da água e um controlador em malha aberta para o ajuste da pressão. Os
resultados demonstraram a viabilidade da solução proposta.
Key-words: Microcontroller. Electric Shower. Temperature Control. Pressure Control. PID Controller.
Lista de ilustrações
A/D Analógico/Digital
DC Direct Current
𝜇C Microcontrolador
MCU Microcontrolador
I/O Input/Output
CI Circuito Integrado
CCP Capture/Compare/PWM
𝐼 2C Inter-Integrated Circuit
USART Universal Synchronous Asynchronous Receiver Transmitter
PC Personal Computer
Hz Unidade de frequência
Kp Ganho proporcional
Ki Ganho Integral
Kd Ganho derivativo
Sumário
1 Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2 Fundamentação Teórica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.1 Sistemas de Controle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.1.1 Sistemas de Controle em Malha Fechada e Malha Aberta . . . . . . . . 20
2.1.2 Controlador PID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.1.3 Ganho Proporcional (Kp) . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.1.4 Ganho Integral (Ki) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.1.5 Ganho Derivativo (Kd) . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.2 Pulse Width Modulation (PWM) . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.3 Controle de Potência por Ângulo de Fase . . . . . . . . . . . . . . . . . . . . . 22
2.4 Filtros Eletrônicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.4.1 Circuito Snubber . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.5 Principais Componentes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.5.1 Microcontroladores . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.5.1.1 A Escolha do Microcontrolador para o Projeto . . . . . . . . 25
2.5.1.2 PIC18F4550 . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.5.1.3 Pinagem . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.5.1.4 Principais Características Elétricas do PIC18F4550 . . . . . . 26
2.5.1.5 Principais Recursos do Microcontrolador Utilizado no Projeto 27
2.5.1.6 Linguagem de Programação e Compilador . . . . . . . . . . 29
2.5.1.7 Kit de Desenvolvimento . . . . . . . . . . . . . . . . . . . . 29
2.5.2 Sensor de Temperatura . . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.5.2.1 Termistor . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2.5.3 Display de Cristal Líquido . . . . . . . . . . . . . . . . . . . . . . . . 30
2.5.3.1 Display de Cristal Líquido de 16X2 . . . . . . . . . . . . . . 31
2.5.4 TRIACS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
2.5.5 Fotoacopladores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
2.5.5.1 Fotoacoplador com Fototransistor . . . . . . . . . . . . . . . 33
2.5.5.2 Fotoacoplador com Fototriac . . . . . . . . . . . . . . . . . . 33
3 Metodologia de Projeto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
3.1 Circuito Detector de Passagem por Zero (Zero-Crossing) . . . . . . . . . . . . 34
3.2 Interface com o Usuário . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
3.2.1 Botões de Ajuste das Configurações . . . . . . . . . . . . . . . . . . . 37
3.2.2 Display de Cristal Líquido . . . . . . . . . . . . . . . . . . . . . . . . 37
3.2.3 Menus do LCD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
3.3 Microcontrolador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
3.3.1 Leitura dos Sinais de Sincronização do Circuito de Zero-Crossing . . . 42
3.3.2 Temporização do PWM do Circuito de Potência . . . . . . . . . . . . . 43
3.3.3 Rotina de Monitoramento . . . . . . . . . . . . . . . . . . . . . . . . . 44
3.3.4 Rotina de Ajuste de Temperatura . . . . . . . . . . . . . . . . . . . . . 45
3.3.5 Rotina de Ajuste de Pressão . . . . . . . . . . . . . . . . . . . . . . . 45
3.3.6 Rotina de Seleção de Favoritos . . . . . . . . . . . . . . . . . . . . . . 45
3.3.7 Rotina de Gravação de Favoritos . . . . . . . . . . . . . . . . . . . . . 45
3.3.8 Leitura do Sensor de Temperatura . . . . . . . . . . . . . . . . . . . . 45
3.3.9 Cálculo da Potência Instantânea . . . . . . . . . . . . . . . . . . . . . 49
3.3.10 Cálculo do Tempo de Banho . . . . . . . . . . . . . . . . . . . . . . . 52
3.3.11 Cálculo do Consumo Elétrico . . . . . . . . . . . . . . . . . . . . . . . 52
3.3.12 Rotina de Ajuste do PID . . . . . . . . . . . . . . . . . . . . . . . . . 53
3.3.13 Rotina de Controle PID . . . . . . . . . . . . . . . . . . . . . . . . . . 53
3.4 Sensor de Temperatura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
3.5 Circuito de Potência . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
3.5.1 Teste do Circuito de Potência . . . . . . . . . . . . . . . . . . . . . . . 57
4 Resultados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
4.1 Estrutura Básica do Software . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
4.2 Montagem do Circuito Lógico em Protoboard . . . . . . . . . . . . . . . . . . 59
4.3 Teste do Controle de Potência por Ângulo de Fase . . . . . . . . . . . . . . . . 59
4.4 Teste do Controle de Pressão . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
4.5 Teste do Controle de Temperatura em Malha Fechada com Lâmpada . . . . . . 62
4.6 Teste Final com Chuveiro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
5 Trabalhos Futuros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
5.1 Aperfeiçoamento do Circuito de Potência . . . . . . . . . . . . . . . . . . . . 64
5.2 Substituição do Sensor de Temperatura . . . . . . . . . . . . . . . . . . . . . . 65
5.3 Aprimoramento da Programação do Microcontrolador . . . . . . . . . . . . . . 65
5.4 Melhoria na Dissipação de Calor dos TRIACS . . . . . . . . . . . . . . . . . . 65
5.5 Conectividade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
6 Conclusão . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
Referências . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
Apêndices 71
Anexos 94
1 Introdução
2 Fundamentação Teórica
Nos sistemas de controle em malha fechada, existe uma comparação entre a saída e a
entrada de referência, utilizando a diferença como meio de controle, sendo esta diferença de-
nominada erro atuante. No controle em malha fechada, o erro atuante realimenta o controlador
com o intuito de acertar a saída do sistema ao valor desejado (OGATA, 2010).
Segundo Ogata (2010), os sistemas de controle em malha aberta são aqueles em que o
sinal de saída não exerce nenhuma ação de controle no sistema, ou seja, o sinal de saída não é
medido nem realimentado para comparação com a entrada.
No controle em malha fechada, a resposta do sistema é relativamente insensível a dis-
túrbios externos e variações internas nos parâmetros do sistema, possibilitando a utilização de
componentes mais imprecisos e baratos do que os utilizados em sistemas de malha aberta.
Contudo, os sistemas em malha aberta são mais simples de serem construídos, pelo fato da es-
tabilidade do sistema ser um problema menos significativo. Desta maneira, para sistemas nos
quais as entradas são conhecidas com antecipação e que são isentos de distúrbios, é conveniente
o uso do controle em malha aberta. Sistemas de controle em malha fechada são mais vantajosos
somente nos casos em que houver distúrbios e/ou alterações não previsíveis nos componentes
do sistema (OGATA, 2010).
Existem diversas equações que podem ser aplicadas no controlador do tipo PID, porém
a Equação (2.1) é a mais comum e que melhor descreve o funcionamento básico do mesmo
(DORF, 2001).
∫︁
d𝑒(𝑡)
𝑢(𝑡) = 𝐾𝑝 · 𝑒(𝑡) + 𝐾𝑖 · 𝑒(𝑡) d𝑡 + 𝐾𝑑 · (2.1)
d𝑡
onde u(t) é o sinal de controle a ser aplicado na planta, e(t) é o sinal de erro, Kp, Ki e Kd são
respectivamente os ganhos proporcional, integral e derivativo, os quais serão apresentados nas
subseções a seguir.
Segundo Instruments (2011), o ganho proporcional é obtido apenas pela diferença entre
o set point e a variável do processo. Este ganho determina a taxa de resposta do controlador. Em
geral quando se aumenta o ganho proporcional, irá aumentar velocidade de resposta no sistema
de controle. Porém se Kp for muito alto, o sistema poderá apresentar oscilações, podendo até
ficar instável.
Este ganho é resultado da soma do erro ao longo do tempo, sendo que sua principal
função é corrigir os erros de regime, ou seja, pequenos desvios entre set point e variável do
processo, que o controle proporcional não consegue eliminar. Altos ganhos da parcela integral
também podem levar o sistema à instabilidade (INSTRUMENTS, 2011).
PWM (Modulação por Largura de Pulso) é um sinal digital com frequência fixa, mas
com largura de pulso variável (MUNIZ, 2009).
Miyadaira (2009) afirma que o PWM consiste em controlar o tempo em que o sinal
permanecerá em nível alto (duty cycle), em um período de tempo predefinido, conforme a Figura
4.
Segundo Muniz (2009), embora o PWM seja um sinal digital, existe um nível DC (ou
valor médio) associado a ele, de modo que pode variar o seu nível DC variando assim a largura
do seu ciclo ativo. Este valor médio é expresso pela equação, a seguir.
∫︁ 𝑇
𝑉𝐷𝐶 = 𝑉 (𝑡) d𝑡 (2.2)
0
Onde, V𝐷𝐶 é a tensão média, T é o período da onda e V(t) a função da tensão no tempo.
Analogamente, os tiristores funcionam como chaves, que são fechadas através de comandos
advindos de outros dispositivos, ou seja, os tiristores não permitem a passagem de corrente sem
que exista um sinal de acionamento no terminal de controle, geralmente conhecido como gate
nos tiristores mais comuns. Os tiristores mais utilizados são o SCR e o TRIAC, sendo que o
SCR é similar a um diodo, onde é permitida a passagem de corrente em apenas um sentido,
sendo que o TRIAC permite a passagem de corrente em ambos os sentidos, atuando assim tanto
no semi-ciclo positivo como no semi-ciclo negativo (MARTINS et al., 2010).
Na Figura 5 pode ser visto um exemplo de controle de potência por ângulo de fase,
comparando-se um disparo de 90o com um disparo de 144o .
Figura 5 – Exemplo de controle de potência por ângulo de fase (MARTINS et al., 2010)
frequência de comutação do tiristor, que caso não sejam atenuados de maneira correta, podem
vir a gerar disparos acidentais do mesmo (BRASIL, 2010).
2.5.1 Microcontroladores
Segundo Souza (2003), dizemos que os microcontroladores são "dotados de uma inteli-
gência programável", pois toda lógica de controle de periféricos (acionamento de LEDs, leitura
de sensores, escrita em LCDs, entre outros) é estruturada na forma de programa e gravada den-
tro do componente. A programação pode ser desenvolvida na linguagem C, Pascal, Assembly,
etc.
2.5.1.2 PIC18F4550
2.5.1.3 Pinagem
O PIC18F4550 possui 40 terminais, sendo que cada terminal pode ser configurado
para mais de uma função. Os únicos terminais que possuem apenas uma função são: 11(Vdd),
32(Vdd), 12(Vss), 31(Vss), 18(Vusb). O restante dos terminais pode ser configurado para vá-
rias aplicações distintas, como barramentos de I/O, conversores A/D, módulos de comunicação
serial e USB, entre outros, sendo cada uma destas aplicações configuradas via programação do
PIC. A seguir a pinagem do PIC18F4550:
∙ Portas de I/O: São terminais que podem ser configurados como entradas ou como saídas,
podendo ler ou enviar sinais lógicos.
∙ Timers: são contadores que podem ser acessados diretamente na memória do microcon-
trolador (MUNIZ, 2009).
No PIC18F4550 existem 4 TIMERS independentes entre si, porém somente o TIMER 0
foi utilizado neste projeto (INC, 2006).
O TIMER 0 é um contador que pode ser configurado para funcionar com 8 bits (0-255) ou
16 bits (0-65535), sendo o incremento da contagem realizado através do ciclo de máquina
ou através de um evento externo pelo terminal T0CKI. Quando o incremento do TIMER
0 é realizado pelo ciclo de máquina, pode ser utilizado um prescale, que nada mais é do
que um divisor de frequência, que determina o número de ciclos de máquina necessário
para incrementar os bits do contador. O prescale pode ser configurado com valores que
sejam potências de 2, em um intervalo de 1 até 256 (MIYADAIRA, 2009; MUNIZ, 2009;
INC, 2006).
O registrador de contagem do TIMER 0, pode ser tanto lido como escrito, isto permite que
a contagem seja iniciada em um valor pré-definido, aumentando assim a precisão quando
o TIMER é utilizado como temporizador (MIYADAIRA, 2009; INC, 2006).
O TIMER 0 também pode ser utilizado como um evento de interrupção de alta ou baixa
prioridade, que é acionada através do overflow na contagem (INC, 2006).
∙ Interrupções:
Para este projeto foram utilizadas duas fontes de interrupção. A primeira trata-se da
interrupção de alta prioridade de mudança de estado no RB0 (INT0) do PIC, para leitura dos
sinais enviados pelo circuito de sincronização com a rede elétrica. A segunda compreende uma
interrupção de baixa prioridade, para o estouro da contagem do TIMER 0, que é diretamente
responsável pelo sinal de PWM que controla o circuito de potência.
Capítulo 2. Fundamentação Teórica 29
∙ Fornecidos 2 tipos de conectores: para uso com protoboard ou barra para ligações com
fios.
2.5.2.1 Termistor
Os termistores são sensores que variam sua resistência elétrica em função da variação
da temperatura. A variação da resistência ocorre de forma lenta e não-linear. Em sua maioria
são fabricados a partir de misturas cerâmicas de óxidos semicondutores, como titânio de bário,
magnésio, níquel, cobalto, titânio, ferro e cobre. Em alguns modelos, o sensor possui um bainha
preenchida com um mineral dielétrico, para isolação da resistência medidora do ambiente de
trabalho (MACIEL, 2012).
A resistência elétrica e a curva de resposta deste tipo de sensor variam para cada mo-
delo. Porém os sensores podem ser basicamente agrupados em dois grandes grupos, sendo eles
os PTCs que variam sua resistência de forma proporcional a varição da temperatura e, os NTCs
que variam a resistência de forma inversamente proporcional.
Os displays de cristal líquido são ótimos quando se deseja exibir uma grande quantidade
de informações oriundas do microcontrolador, pois são relativamente fáceis de trabalhar, além
de apresentarem baixo custo de aquisição. Existem dois tipo de displays de LCD: os de carac-
teres e os gráficos. Nos displays gráficos podem ser exibidas quaisquer tipos de informações,
inclusive imagens e vídeos, porém seu custo é mais elevado e sua programação mais complexa.
Já os displays de caracteres podem exibir os símbolos contidos no código ASCII, além de pos-
suírem um memória RAM, que permite a criação de alguns caracteres especiais. Neste tipo de
display, cada caractere ocupa uma posição na tela, que é definida através do número da coluna
e do número da linha (PEREIRA, 2003; BARBACENA; FLEURY, 1996).
Nos displays de 16X2, os dados e as instruções, que por exemplo, poderiam ser um
caractere da tabela ASCII e a posição de escrita do caractere, respectivamente, são enviados
pelo mesmo barramento, sendo que o controlador do display distingue as informações através
do terminal RS. O display pode tanto receber como enviar dados, este tipo de ação é definida
pelo terminal RW. Para que o microcontrolador do display possa executar uma tarefa, como
por exemplo, leitura de dados ou leitura de instruções, é necessário um pulso no terminal E
(enable), sendo o tempo deste pulso variável entre os fabricantes de displays.
2.5.4 TRIACS
Segundo Maciel (2010):
2.5.5 Fotoacopladores
Um fotoacoplador, nada mais é do que um CI, que possui em seu interior um LED
e algum outro componente que seja fotossensível, como um fototransistor, por exemplo. Sua
principal função é transmitir impulsos elétricos entre dois circuitos sem contato elétrico, por
meio da emissão de luz. Ao se aplicar uma tensão no LED, o mesmo se acende e polariza o
fototransistor. Desta forma o fototransistor conduz corrente pelo segundo circuito, que está iso-
lado eletricamente do primeiro (MACIEL, 2010).
Capítulo 2. Fundamentação Teórica 33
Este tipo de fotoacoplador é mais utilizado quando, parte do circuito utiliza corrente
alternada, pois o fototriac pode conduzir em qualquer sentido. Os fototriacs são muito empre-
gados quando deseja-se acionar um TRIAC de um circuito de potência através de um comando
de um circuito digital. Na Figura 10 está a simbologia de um fotoacoplador com fototriac.
3 Metodologia de Projeto
Este capítulo tem como objetivo mostrar os principais passos para o desenvolvimento
do protótipo. Para uma melhor abordagem, a descrição da montagem será dividida em 5 partes,
sendo elas:
∙ Circuito detector de passagem por zero: responsável pela sincronização do PIC com a
frequência da rede elétrica.
∙ Microcontrolador: responsável pela leitura dos sensores, interface com o usuário e leitura
do circuito de sincronização com a rede elétrica.
Como será detalhado a seguir, o controle de potência é diretamente influenciado pela in-
versão de fase da senoide da rede elétrica, portanto, para um correto funcionamento do circuito
é necessário que seja feita uma sincronização entre os comandos enviados pelo microcontrola-
dor ao circuito de potência e a frequência da rede elétrica.
O diagrama elétrico do circuito detector de passagem por zero pode ser visto na Figura
11. Este diagrama foi baseado no circuito de Fambrini (1999). Seu funcionamento baseia-se
no acionamento de um fotoacoplador pela tensão da rede alternada. No período de tempo em
que a tensão instantânea da rede elétrica for maior que a tensão mínima de acionamento do
fotoacoplador (aproximadamente 1V), o fotoacoplador envia OV (nível lógico 0) para o micro-
controlador e quando a tensão da rede é menor que 1V, o PIC passa a receber aproximadamente
5V (nível lógico 1).
Capítulo 3. Metodologia de Projeto 35
A interface com o usuário é um item de extrema importância para este projeto, pois é
através dela que ocorre a entrada e a saída de informações do microcontrolador. Esta interface
é basicamente constituída por um display de cristal líquido e por um conjunto de três push-
buttons. Na Figura 14 pode ser observado o diagrama elétrico do circuito.
Para ajustes dos set points pelo usuário existem três botões conectados ao microcontro-
lador, sendo a função de cada um explicado, a seguir:
∙ Botão de seleção entre as funções (select): Seu objetivo é alternar entre as funções
de ajuste do 𝜇C a cada toque no botão, também possui uma função especial caso seja
mantido pressionado por mais de 5 segundos, que será explicada mais adiante. Este botão
está ligado ao PORTB1 do PIC.
O display de cristal líquido tem como principal função indicar ao usuário informações
como temperatura d’água, potência elétrica instantânea, consumo elétrico e tempo de banho,
além de interagir com o usuário quando os botões de configuração são acionados, mostrando
instantaneamente quais configurações estão sendo modificadas.
Para este projeto foi utilizado um display com 16 colunas e 2 linhas (16X2). Sua co-
municação com o microcontrolador utiliza 10 portas de I/O do PIC, sendo as oito portas do
PORTD utilizadas para a transmissão de dados, a porta RA4 e RA5 utilizadas para o controle
do terminal RS e enable do LCD, respectivamente. Foi utilizado um resistor de 5K6 para o
ajuste do contraste no display.
Capítulo 3. Metodologia de Projeto 38
A seguir serão explicados todos os menus presentes na programação do PIC, que são
exibidos pelo display de cristal líquido:
∙ Menu principal (Figura 15): Exibe informações de temperatura da água, tempo de ba-
nho, potência elétrica instantânea e consumo elétrico. Todos os outros menus retornam
automaticamente ao menu principal, após um determinado tempo.
∙ Menu de configuração de temperatura (Figura 16): Neste menu o usuário pode confi-
gurar o set point de temperatura, através dos botões de incremento e decremento.
∙ Menu de configuração de pressão (Figura 17): Sua função é receber o set point de
pressão, configurado também, através dos botões de incremento e decremento.
∙ Menu de seleção de favoritos (Figura 18): Sua função é carregar parâmetros de tempe-
ratura e pressão pré-gravados na memória EEPROM pelo usuário. Neste menu o usuário
pode escolher entre 10 configurações favoritas através dos botões de incremento e de-
cremento. Para efetuar o carregamento das configurações é necessário que o botão select
seja pressionado por mais de 5 segundos, até que a mensagem "CARREGANDO..."seja
exibida no display.
∙ Menu de gravação de favoritos (Figura 19): Este é um menu especial, que é acessado
pressionando o botão select na tela inicial por mais de 5 segundos. Neste menu é possível
gravar uma configuração de banho específica, em uma das 10 posições de favoritos, na
memória EEPROM do PIC. A posição de gravação é selecionada através dos botões de
Capítulo 3. Metodologia de Projeto 40
∙ Menu de configuração do algorítimo PID (Figuras 20, 21, 22, 23): Este também é um
menu especial, que é acessado pressionando o botão de incremento e decremento simul-
taneamente, na tela inicial por mais de 5 segundos. Este tipo de configuração é realizado
apenas na calibragem do controlador PID. Neste menu é possível configurar todos os ga-
nhos do controlador PID, além do tempo entre os acionamentos da sub-rotina de controle.
Para selecionar qual ganho do controlador PID será ajustado deve-se pressionar o botão
select. Também é possível gravar as configurações dos ganhos na EEPROM, pressionando
o botão de select por mais de 5 segundos no menu de ajuste do PID.
3.3 Microcontrolador
Para construção do protótipo foi escolhido o PIC18F4550, que já vem embarcado no kit
de desenvolvimento PROTO’n PIC18F4550○ R
, conforme a Figura 24. Neste kit o PIC utiliza-se
de um cristal de 20MHz, para geração do sinal de clock, porém devido a utilização de comu-
nicação USB, internamente no 𝜇C a frequência passou a ser de 48MHz. Foram utilizados 14
terminais de I/O como saídas digitais, 4 terminais como entradas digitais e mais um terminal
como entrada analógica. Também foi utilizada uma interrupção de alta prioridade por mudança
de nível lógico na porta INT0 e, uma interrupção de baixa prioridade para estouro da conta-
gem do TIMER0. A memória EEPROM foi amplamente utilizada, para armazenamento dos set
points favoritos, além dos ajustes dos ganhos do controlador PID.
void YourHighPriorityISRCode(){
periodo = 0;
resistencia = 0;
turbo = 0;
INTCONbits.INT0IF = 0; //Limpa flag de interrupção
}
Como o PWM que controla o circuito de potência é gerado via software, devido a neces-
sidade de sincronizar o sinal de PWM com os pulsos gerados pelo circuito de zero-Crossing, é
necessário dedicar um TIMER exclusivamente para esta temporização. Foi escolhido o TIMER0
para esta função, sendo o controle do PWM efetuado na rotina de tratamento de interrupção,
através do incremento de uma variável de temporização. A interrupção ocorre no estouro da
contagem do TIMER0. Esta interrupção foi configurada como baixa prioridade, para privilegiar
a leitura dos sinais de sincronização enviados pelo circuito de zero-crossing.
void YourLowPriorityISRCode(){
if(periodo<t_off){
resistencia = 0; //Desliga resistencia
}
else{
resistencia = 1; //Liga resistencia
}
if(periodo<t_off_2){
turbo = 0; //Desliga turbo
}
else{
turbo = 1; //Liga turbo
}
periodo++; //Controla a temporização do PWM
relogio++; //Controla a contagem do tempo do relógio
Esta rotina realiza o ajuste do set point de temperatura, através dos botões de incre-
mento e decremento. A rotina de ajuste de temperatura é a primeira rotina da programação,
portanto é acessada pressionando-se o botão select, por aproximadamente 1 segundo na rotina
de monitoramento.
Esta é a segunda rotina na programação do PIC, onde o usuário define o set point de
pressão. Nesta rotina é calculado o duty do circuito de potência do pressurizador, pois como o
controle de pressão é realizado em malha aberta, o duty é diretamente proporcional ao valor do
set point inserido pelo usuário, através dos botões de ajuste.
Nesta função são carregados os set points de temperatura e pressão, que já foram pre-
viamente gravados na memória EEPROM pelo usuário. Esta função é a terceira na ordem de
acesso, ou seja, é acessada pressionando-se o select na função de ajuste de pressão. São dispo-
níveis ao usuário 10 favoritos , sendo que os set points de temperatura ocupam os endereços de
0 até 9 da EEPROM, e os set points de pressão ocupam os endereços de 10 até 19. O usuário
alterna entre as opções de favoritos através dos botões de incremento e decremento e, carrega o
favorito desejado pressionando o botão select por mais de 5 segundos.
várias transformações no valor fornecido pelo conversor A/D do PIC, até que fosse possível
obter o valor de temperatura d’água em graus Celsius. As principais instruções utilizadas na
leitura e no tratamento dos dados são listadas logo abaixo:
∙ Configuração do conversor A/D: Estes comandos tem como função configurar os pa-
râmetros de leitura de acordo com o projeto do circuito e com as especificações de
datasheet. Neste projeto somente foi habilitada a porta AN0 do conversor, pois a única
leitura analógica é a de temperatura. Os bits do registradores de leitura foram justificados
a esquerda, pois desta forma torna-se possível descartar os dois bits menos significativos
(LSB) da leitura, para evitar que ruídos no sensor de temperatura interfiram no processo
de controle.
Após o levantamento da curva de resposta, foi obtida uma equação aproximada por uma
linha de tendências, para o comportamento do sensor em função da temperatura. Esta
equação é exibida, a seguir:
void mede_temp(void){
char m=0;
float res_ntc=0; //Resistencia do ntc
float aux_linear=0, aux_linear1=0; //Auxilia no calculo da temperatura
Nesta rotina, todos os cálculos foram realizados utilizando variáveis do tipo float, para
obter maior precisão nos resultados, porém o resultado final foi truncado e armazenado
numa variável do tipo long int, para possibilitar a exibição do valor da temperatura no
display de cristal líquido, pois a rotina de escrita de numerais no display utiliza um al-
goritmo não compatível com variáveis do tipo float, para a decomposição dos números
maiores que 9 em dígitos individuais, que serão enviados ao LCD.
√︃
𝐴2 ∫︁ 𝜋
𝑉𝑒𝑓 = [𝑠𝑒𝑛(𝜔𝑡)]2 d𝜔𝑡 (3.7)
𝑇 𝑡𝑥
𝑉2
𝑅= (3.9)
𝑃
1272
𝑅= (3.10)
5500
𝑅 = 2, 932545455 Ω (3.11)
Como:
𝑉𝑒𝑓2
𝑃𝑎𝑞 = (3.12)
𝑅
{︂√︂ [︁ (︁ )︁]︁}︂2
𝐴2 𝐴2 𝑠𝑒𝑛(2𝑡𝑥 )
2
− 2𝜋
𝑡𝑥 − 2
𝑃𝑎𝑞 = (3.13)
𝑅
[︁ (︁ )︁]︁
𝐴2 𝐴2 𝑠𝑒𝑛(2𝑡𝑥 )
2
− 2𝜋
𝑡𝑥 − 2
𝑃𝑎𝑞 = (3.14)
𝑅
√
Considerando 𝐴 = 127 · 2, temos que:
√ 2
[︃ √ 2 ]︃
(127· 2) (127· 2) (︁ 𝑠𝑒𝑛(2𝑡𝑥 )
)︁
2
− 2𝜋
𝑡𝑥 − 2
𝑃𝑎𝑞 = (3.15)
2, 932545455
Capítulo 3. Metodologia de Projeto 51
Simplificando: [︁ (︁ )︁]︁
𝑠𝑒𝑛(2𝑡𝑥 )
16129 − 5134 𝑡𝑥 − 2
𝑃𝑎𝑞 = (3.16)
2, 932545455
[︁ (︁ )︁]︁
𝑠𝑒𝑛(2𝑡𝑥 )
5134 𝑡𝑥 − 2
𝑃𝑎𝑞 = 5500 − (3.17)
2, 932545455
4
[︂ (︂ )︂]︂
𝑇 = 256 · + 3 · 10−6 (3.18)
48 · 106
𝜋·𝑇
𝐴𝑚𝑖𝑛 = (3.19)
(1/120)
{︁[︁ (︁ )︁]︁ }︁
𝜋· 256 · 4
48·106
+ 3 · 10−6
𝐴𝑚𝑖𝑛 = (3.20)
(1/120)
void calc_pot(void){
x = 0.0091734505*t_off; //0.0091...é o angulo de disparo minimo
x = 5134*(x-(0.5*sin(2*x)));
x = x/2.932545455; //2.93...é o valor estimado da resistencia em Ohm
PW = 5500 - x;
}
void calc_relogio(void){
segundo_total = (relogio/40137); /*40137 é o valor estimado
da variável relógio para um segundo de contagem*/
hora = segundo_total/3600;
minuto = (segundo_total%3600)/60;
segundo = (segundo_total%3600)%60;
}
Esta também é uma rotina especial, pois para ser acessada é necessário manter os botões
de incremento e decremento pressionados simultaneamente, por mais de 5 segundos, na tela de
monitoramento. Dentro da função de calibragem o botão select seleciona qual ganho será alte-
rado, e os botões de incremento e decremento alteram os valores.
Após alguma alteração nos valores dos ganhos, é possível salvar os mesmos na memória
EEPROM, pressionando-se o botão select na rotina de calibragem por no mínimo 5 segundos,
para que não seja necessário calibrar o controlador toda vez que o PIC for energizado. Os ga-
nhos salvos na EEPROM são automaticamente carregados toda vez que o microcontrolador é
iniciado. Os ganhos ocupam os endereços 20 até 23 da EEPROM.
Para o controle de temperatura da água foi escolhido um controlador PID, que é a es-
tratégia de controle mais recomendada para este tipo de sistema. A Equação 3.22 mostra a
implementação do controlador PID no ambiente digital, onde Kp é o ganho proporcional, Ki o
ganho integral, Kd o ganho derivativo e E(T) é o erro entre set point e a temperatura medida
pelo sensor.
𝑇
∑︁
𝑢(𝑡) = 𝐾𝑝 · 𝐸(𝑇 ) + 𝐾𝑖 · 𝐸(𝑡) + 𝐾𝑑 · [𝐸(𝑇 ) − 𝐸(𝑇 − 1)] (3.22)
𝑡=𝑇 −𝐴
A contribuição integral é aproximada neste trabalho como sendo a somatória dos valo-
res dos erros contidos em todas as 100 posições do vetor. Já o ganho derivativo é obtido pela
subtração do valor do erro atual pelo erro do instante anterior.
void controle(void){
unsigned char pos_erro=0; //Posicao de gravacao do erro
foi utilizado um sensor de temperatura do tipo NTC de 10KΩ. Como o sensor de temperatura
fica situado bem próximo ao aquecedor do chuveiro, que por sua vez é alimentado por tensões
consideravelmente maiores que os 5V utilizados pela alimentação do PIC, fez-se necessário a
utilização de um NTC com bainha isoladora, conforme Figura 27, para evitar possíveis danos
ao circuito lógico causados por sobre-tensões.
∙ Circuito do pressurizador: Este circuito é o mais simples, pelo fato de trabalhar com
correntes baixas em relação a capacidade máxima do TRIAC usado. O circuito é com-
posto basicamente por um TRIAC e um fotoacoplador, que recebe os sinais de aciona-
mento do terminal RC1 do PIC.
∙ Circuito do aquecedor: Este circuito é mais complexo, devido as altas correntes que o
mesmo deve suportar. Neste circuito foram utilizados 6 TRIACS em paralelo, pois como
cada tiristor utilizado suporta até 8A, a utilização de um conjunto com 6 componentes
possibilita trabalhar com até 48A. Também devido às altas correntes de trabalho, foram
necessárias a inclusão de filtros, para evitar o disparo acidental dos tiristores. Foram uti-
lizados um filtro snubber no fotoacoplador, além de um filtro formado por dois indutores
e dois capacitores no conjunto de TRIACS. Este circuito recebe os sinais de acionamento
do terminal RC2 do microcontrolador.
Capítulo 3. Metodologia de Projeto 57
4 Resultados
O protótipo foi desenvolvido e montado em diversas etapas, sendo que ao final de cada
etapa eram efetuados testes no funcionamento, antes de ser dado continuidade ao projeto. Neste
capítulo serão mostrados os principais resultados dos testes realizados no projeto, do começo
até o último teste com o protótipo finalizado. Também serão mostrados os principais problemas
encontrados durante o desenvolvimento e suas respectivas soluções.
Nesta fase do projeto foi criada a estrutura básica da programação para o início do de-
senvolvimento do projeto. Foram criadas rotina de configuração de set points, rotina de exibição
da temperatura da água, além de definição da pinagem a ser utilizada no PIC e botões para con-
figuração de parâmetros. Esta primeira etapa do desenvolvimento foi realizada utilizando o Kit
didático XM118 da EXSTO○ R
mostrado na Figura 30, com o microcontrolador e periféricos já
embutidos.
Durante esta fase não foram encontrados grandes problemas, já que não havia necessi-
dade de se preocupar com o hardware do circuito do projeto, pois os periféricos do kit didático
já eram suficientes para o início do projeto.
Capítulo 4. Resultados 59
O único problema encontrado durante esta montagem foi a utilização do LCD, pois
houve dificuldades para a execução da escrita no mesmo. A solução encontrada foi o aumento
nos delays dos pulsos de enable que o PIC envia ao display, pois a rotina de escrita utilizada
anteriormente à montagem, era projetada para trabalhar em um clock de 20MHz, contudo o
PROTO’n PIC18F4550○ R
utiliza-se de 48MHz. Também foi preciso ajustar o contraste do dis-
play, através da inclusão de um resistor de 5K6 no terminal de ajuste.
O primeiro teste foi realizado utilizando-se o circuito de potência presente em kits di-
dáticos da própria instituição de ensino, e uma lâmpada como carga. Estes testes não foram
satisfatórios, pois o controle de potência se mostrou instável e pouco preciso. As causas do pro-
blema foram erros na programação do PIC, onde a lógica de funcionamento estava invertida,
Capítulo 4. Resultados 60
fazendo com que os tiristores iniciassem conduzindo após a inversão de fase da rede elétrica
e fossem desligados em momentos pré-determinados, sendo que o correto é iniciar os tiristo-
res desligados após a inversão de fase da rede, ligando os mesmos também em um momento
pré-determinado, e aguardando que sejam desligados naturalmente pela passagem por zero da
senóide da rede elétrica.
Como neste projeto o controle de pressão é efetuado em malha aberta através da mani-
pulação da rotação do motor da bomba do pressurizador e não existe sensor de pressão, sendo o
próprio usuário responsável por configurar o nível de pressão d’água desejado, foram realizadas
simulações utilizando-se um ventilador de mesa, que possui um motor do tipo universal, seme-
lhante ao motor do pressurizador, para a demonstração da viabilidade do controle de pressão. A
seguir, na Figura 34, o teste do controle de pressão através da simulação com um ventilador.
Neste teste foi verificada a viabilidade do controle de pressão, pois foi possível controlar
Capítulo 4. Resultados 62
a velocidade de rotação das pás do ventilador com precisão. Não foram encontradas dificuldades
nesta etapa do projeto.
Para efetuar os primeiros testes do controle PID, leitura dinâmica da temperatura e con-
trole de potência, foi desenvolvido um teste para o controle de temperatura, onde o aquecedor
era simulado por uma lâmpada incandescente e a circulação de água pelo movimento do ar
gerado por um ventilador, conforme a Figura 35.
Com esse teste foi possível efetuar ajustes e pré-calibrar o ganhos da rotina de controle
PID, além de eliminar ruídos presentes na leitura de temperatura antes da montagem definitiva
do protótipo, onde alterações no circuito ou na programação do microcontrolador seriam muito
mais complexas de serem efetuadas.
Para validação do protótipo foi utilizado um chuveiro de 127V com 5500W de potência
nominal. Com a inclusão do chuveiro nos testes, foi possível verificar a qualidade e a eficácia
da medição da temperatura da água pelo sensor, o funcionamento do circuito de potência para
altas correntes e controle de temperatura da água em malha fechada. Na Figura 36 pode ser
visto o teste com o chuveiro montado.
Capítulo 4. Resultados 63
Houve dois empecilhos durante esta fase. O primeiro empecilho foi o superaquecimento
do circuito de potência, quando era utilizado o aquecedor do chuveiro na saída de carga. Como
não havia nenhum tipo de dissipador de calor no circuito, foi empregado o uso de ventilação
forçada diretamente sobre os componentes, para que fosse possível a realização dos testes.
5 Trabalhos Futuros
Neste capítulo são apresentadas algumas sugestões de melhorias, que foram analisadas
após o término dos testes e poderiam ser implementadas no projeto.
Durante os testes tanto com lâmpada como com o chuveiro, ficou evidente que a resposta
à varição de temperatura no sensor utilizado no protótipo é muito lenta, prejudicando assim o
controle de temperatura em malha fechada. Seria necessário uma nova pesquisa para encontrar
o sensor ideal para o projeto, que deveria possuir resposta praticamente instantânea a variação
da temperatura, um range de no mínimo 0 a 100 o C, e principalmente possuir isolação elétrica
entre o elemento sensor e o ambiente de medição.
Devido as muitas rotinas e cálculo executados pelo PIC, a memória do mesmo pratica-
mente foi esgotada, impedindo que possam ser implementadas mais funções na programação,
para trabalhos futuros. Trabalhar no limite da memória também impediu que fosse criado um
vetor de 256 posições para o cálculo do controle PID, sendo que o máximo possível para o
projeto atual foi um vetor de 100 posições, desta forma prejudicando a qualidade do controle.
Quando eram exigidas altas correntes no circuito de potência, o mesmo aquecia excessi-
vamente, sendo necessário implementar um dissipador de calor de proporções inaplicáveis para
este tipo de projeto. Porém existe a possibilidade de substituir o conjunto dos seis TRIACS por
apenas um TRIAC de maior capacidade de corrente e inserir este TRIAC no interior do próprio
chuveiro, fazendo com que a água funcione como dissipador de calor. Esta alteração seria de
grande eficiência, já que á água dissiparia o calor com mais rapidez do que qualquer outro tipo
de dissipador, além de gerar economia de energia, pois o calor dissipado pelo TRIAC serviria
para preaquecer a água.
5.5 Conectividade
6 Conclusão
Ao final dos testes foi possível verificar a viabilidade do projeto, pois o controle PID
de temperatura mostrou-se eficaz, conseguindo estabilizar a temperatura no set point desejado,
com um erro de ±1 o C em aproximadamente 30 segundos, conforme pode ser observado no
gráfico da Figura 38 .
Outro fator importante, que também viabiliza o projeto é o baixo custo de produção,
principalmente se for considerada uma montagem em escala industrial, realizada por equipa-
mentos automatizados.
Este projeto gera um item de conforto adicional nos chuveiros, pois possibilita a repro-
dução de uma determinada condição de banho quantas vezes forem desejadas, além de livrar o
usuário da tarefa de controlar a temperatura e a vazão d’água.
68
Referências
BRASIL, T. A. do. Implementação e construção de uma bancada para testes térmicos para
dispositivos semicondutores de potência. , 2010. Disponível em: <http://www.monografias-
.poli.ufrj.br/monografias/monopoli10000501.pdf>. Acesso em: 11/06/2014. Citado na página
24.
FAIRCHILD. 6-PIN DIP RANDOM-PHASE: Optoisolators triac driver output. [S.l.], 2002.
Disponível em: <http://pdf.datasheetcatalog.com/datasheet/fairchild/MOC3021-M.pdf>.
Acesso em: 16/09/2013. Nenhuma citação no texto.
FAIRCHILD. BC337/338: Switching and amplifier applications. [S.l.], 2002. Disponível em:
<http://pdf.datasheetcatalog.com/datasheet/fairchild/BC337.pdf>. Acesso em: 31/03/2014.
Nenhuma citação no texto.
FAIRCHILD. 6-PIN DIP RANDOM-PHASE: Optoisolators triac drivers (600 volt peak).
[S.l.], 2004. Disponível em: <http://www.farnell.com/datasheets/301912.pdf>. Acesso em:
22/09/2014. Citado 2 vezes nas páginas 9 e 64.
MOTOROLA. 6-PIN DIP Random-Phase: Optoisolators triac driver output. [S.l.], 1995.
Disponível em: <http://www.datasheetcatalog.org/datasheet/motorola/MOC3021.pdf>.
Acesso em: 08/05/2013. Nenhuma citação no texto.
NISE, N. S. Engenharia de Sistemas de Controle. 3. ed. Rio de Janeiro: LTC - Livros Técnicos
e Científicos Editora S.A., 2002. Citado na página 20.
OGATA, K. Engenharia de Controle Moderno. 5. ed. São Paulo: Pearson Prentice Hall, 2010.
Citado na página 20.
Referências 70
RADIO, S. Quick Start Guide: PROTO’n PIC 18F4550 Dev. Board. [S.l.], 2013. Disponível
em: <http://smartradio.com.br/pic/PROTOn/Manual%20PROTOn.pdf>. Acesso em:
20/09/2013. Citado 5 vezes nas páginas 8, 9, 29, 42 e 96.
SIEMENS. Phase Control IC: Tca 785. [S.l.], 1994. Disponível em: <http://www-
.datasheetcatalog.org/datasheet/infineon/1-tca785.pdf>. Acesso em: 08/03/2013. Nenhuma
citação no texto.
SOUZA, D. J. de. Desbravando o PIC: ampliado e atualizado para o PIC 16F628A. 6. ed. São
Paulo: Érica, 2003. Citado 2 vezes nas páginas 24 e 27.
APÊNDICE A
void YourHighPriorityISRCode();
void YourLowPriorityISRCode();
void Board_Init (void);
#if defined(PROGRAMMABLE_WITH_USB_HID_BOOTLOADER)
#define REMAPPED_RESET_VECTOR_ADDRESS 0x1000
#define REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS 0x1008
#define REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS 0x1018
#if defined
(PROGRAMMABLE_WITH_USB_HID_BOOTLOADER)||defined
(PROGRAMMABLE_WITH_USB_MCHPUSB_BOOTLOADER)
extern void _startup (void); //See c018i.c in your C18 compiler dir
#pragma code REMAPPED_RESET_VECTOR = REMAPPED_RESET_VECTOR_ADDRESS
void _reset (void)
{
_asm goto _startup _endasm
}
#endif
#pragma code REMAPPED_HIGH_INTERRUPT_VECTOR = REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS
void Remapped_High_ISR (void)
{
_asm goto YourHighPriorityISRCode _endasm
}
#pragma code REMAPPED_LOW_INTERRUPT_VECTOR = REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS
void Remapped_Low_ISR (void)
{
_asm goto YourLowPriorityISRCode _endasm
}
#if defined
(PROGRAMMABLE_WITH_USB_HID_BOOTLOADER)||defined
(PROGRAMMABLE_WITH_USB_MCHPUSB_BOOTLOADER)
#endif
#pragma code
//------------ C O N F I G U R A T I O N B I T S ---------------------------
#pragma config PLLDIV = 5 // (20 MHz crystal on PICDEM FS USB board)
#pragma config CPUDIV = OSC1_PLL2
#pragma config USBDIV = 2 // Clock source from 96MHz PLL/2
#pragma config FOSC = HSPLL_HS
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#pragma config PWRT = ON
#pragma config BOR = OFF
#pragma config BORV = 3
#pragma config VREGEN = ON //USB Voltage Regulator
#pragma config WDT = OFF
#pragma config WDTPS = 32768
#pragma config MCLRE = ON
#pragma config LPT1OSC = OFF
#pragma config PBADEN = OFF
#pragma config STVREN = ON
#pragma config LVP = OFF
#pragma config XINST = OFF // Extended Instruction Set
#pragma config CP0 = OFF
#pragma config CP1 = OFF
#pragma config CPB = OFF
#pragma config WRT0 = OFF
#pragma config WRT1 = OFF
#pragma config WRTB = OFF // Boot Block Write Protection
#pragma config WRTC = OFF
#pragma config EBTR0 = OFF
#pragma config EBTR1 = OFF
#pragma config EBTRB = OFF
if(periodo<t_off_2){
turbo = 0; //Desliga turbo
}
else{
turbo = 1; //Liga turbo
}
periodo++; //Controla a temporização do PWM
relogio++; //Controla a contagem do tempo do relógio
//FUNÇÃO PRINCIPAL
void main(){
TRISA = 0b001111;
PORTA = 0;
TRISD = 0;
PORTD = 0;
TRISE = 0;
PORTE = 0;
TRISC = 0;
PORTC = 0;
TRISB = 255;
INTCON2bits.RBPU = 1; //Desabilta o pull up do PORTB
//Configuração do Timer 0
T0CONbits.T08BIT = 1 ; //8 bits
T0CONbits.T0CS = 0; //Incremento do timer 0 se da pelo ciclo de máquina
T0CONbits.PSA = 1; //Escalonador desabiltado
T0CONbits.TMR0ON = 1; //Habilita o timer 0
//Inicializa LCD
RS = 0;
escreve_lcd(0x38); //8 Vias de dados e duas linhas de 16 caracteres
escreve_lcd(0x06); //Cursor se desloca automaticamente para a direita
escreve_lcd(0x0C); //Ativa o display e inicia o cursor no canto superior esquerdo
Delay10KTCYx(10);
//Configuração do ADC
ADCON1 = 0b001110; //Habilta AN0
ADCON2 = 0b00000110; //Justificado a esquerda /\ TAD = 0 /\ FOSC/64
ADCON0 = 0b00000001; //Habilta o conversor AD e entrada AN0
//Configuração da EEPROM
EECON1bits.WREN = 1; //Configura EECON1 para escrita na EEPROM
//Inicialização
inicializacao(); //Exibe a versao do firmware
leitura_pid(); /*Carrega os ganhos (kp, ki, kd e atraso)
do controlador PID gravados na EEPROM*/
//Loop infinito
while(1){
switch(sel){
case(0): monitoramento();
break;
case(1): set_temp();
break;
case(2): set_pressao();
break;
case(3): seleciona_favorito();
break;
default: sel=0;
break;
}
}
}
//-------------------------------------------------------------------------------
////FUNÇÃO PRINCIPAL DE LEITURA E CONTROLE DA TEMPERATURA
void monitoramento(void){
escreve_rom_lcd(" ", 16, 0, 0); //Limpa a linha 1 do LCD
escreve_rom_lcd(" ", 16, 1, 0); //Limpa a linha 2 do LCD
while(PORTBbits.RB1==0){}; //Aguarda soltar o botão
while(sel==0){
mede_temp(); //Medição e calculo da temperatura
if(conta_controle>atraso_controle){ //Atraso para chamar a rotina PID
controle();
conta_controle = 0;
}
conta_controle++;
calc_relogio(); //Efetua o calculo do tempo de banho
if(minuto != minuto_ant){ //Verifica a transições dos minutos
calc_consumo(); //Calcula o consumo do banho
minuto_ant = minuto;
}
lcd_temp(); //Exibe a temperatura no LCD
lcd_pot(); //Exibe a pot. inst. no LCD
lcd_relogio(); //Exibe o tempo de banho no LCD
lcd_consumo(); //Exibe o consumo no LCD
//-------------------------------------------------------------------------------
////FUNÇÃO DE AJUSTE DA TEMPERATURA PELO USUÁRIO ATRAVÉS DO TECLADO
void set_temp(void){
escreve_rom_lcd("AJUSTE TEMP ", 16, 0, 0);
escreve_rom_lcd(" ", 16, 1, 0); //Limpa a linha 2 do LCD
while(PORTBbits.RB1==0){}; //Aguarda soltar o botao
retorna = 0; //Variavel de controle do retorno automatico
while(sel==1){
if(retorna == 30){ //Retorna auto. para a MONITORAMENTO
sel = 0;
return; //Retorna para a funçao MONITORAMENTO
}
retorna++;
if(PORTBbits.RB2==0 && temp<100){ //Incrementa a temp
temp++;
retorna = 0;
bip(1, 20);
}
if(PORTBbits.RB3==0 && temp>0){ //Decrementa a temp
temp--;
retorna = 0;
bip(1, 20);
}
t[0] = temp/100 + 0x30; //Centena
t[1] = (temp%100)/10 + 0x30; //Dezena
t[2] = temp %10 + 0x30; //Unidade
t[3] = 0xDF; //º
t[4] = 0x43; //C
escreve_ram_lcd(t, 5, 1, 0);
//-------------------------------------------------------------------------------
////FUNÇÃO DE AJUSTE DA PRESSAO PELO USUÁRIO ATRAVÉS DO TECLADO
void set_pressao (void){
escreve_rom_lcd("AJUSTE PRESSAO ", 16, 0, 0);
escreve_rom_lcd(" ", 16, 1, 0); //Limpa a linha 2 do LCD
while(PORTBbits.RB1==0){}; //Aguarda soltar o botão
retorna = 0; //Variavel de controle do retorno automatico
while(sel==2){
if(retorna == 30){ //Retorna auto. para a MONITORAMENTO
sel = 0;
return; //Retorna para a funçao MONITORAMENTO
}
retorna++;
if(PORTBbits.RB2==0 && pressao<100){ //Incrementa pressao
pressao++;
retorna = 0;
bip(1, 20);
}
if(PORTBbits.RB3==0 && pressao>0){ //Decrementa pressao
pressao--;
retorna = 0;
bip(1, 20);
}
t_off_2 = 343 - ((pressao*343)/100); //Calcula o duty
if(t_off_2>300){ //Limita a potencia minima entregue a pressurizador
t_off_2 = 343;
}
p[0] = pressao/100 + 0x30; //Centena
p[1] = (pressao%100)/10 + 0x30; //Dezena
p[2] = pressao%10 + 0x30; //Unidade
p[3] = 0x9C; //Espaço
p[4] = 0X25; //Simbolo de %
escreve_ram_lcd(p, 5, 1, 0);
if(PORTBbits.RB1==0){ //Aciona a rotina de leitura de fav.
sel++;
bip(2, 120);
return;
}
}
}
//--------------------------------------------------------------------------------
////ALGORITMO DE CONTROLE PID DE TEMPERATURA EM MALHA FECHADA
void controle(void){
unsigned char pos_erro=0; //Posicao de gravacao do erro
erro = temp - sensor_temp; //Calc. do erro
memo_erro[e] = erro; //Grava o erro no vetor
integral_erro = 0;
for(pos_erro=0; pos_erro<100; pos_erro++){ //Calcula int. do erro
integral_erro = integral_erro + memo_erro[pos_erro];
}
if(e>0){ //Calcula a derivada do erro
derivada_erro = memo_erro[e] - memo_erro[e-1];
}
else{
derivada_erro = memo_erro[e] - memo_erro[99];
}
//-------------------------------------------------------------------------------
////FUNÇÃO DE SELEÇÃO DOS FAVORITOS PRÉ-GRAVADOS PELO USUÁRIO
void seleciona_favorito(void){
retorna = 0; //Variavel de controle do retorno automatico
escreve_rom_lcd("SELECIONA FAV ", 16, 0, 0);
escreve_rom_lcd("(T= ) (P= )", 16, 1, 0);
while(PORTBbits.RB1==0){}; //Aguarda soltar o botão
while(sel==3){
if(retorna == 50){ //Retorna auto. para a MONITORAMENTO
sel = 0;
return; //Retorna para a funçao MONITORAMENTO
}
retorna++;
bip(1, 200);
bip(1, 200);
bip(1, 1000);
//-------------------------------------------------------------------------------
////FUNÇÃO DE GRAVAÇÃO DOS FAVORITOS NA EEPROM
void grava_favorito(void){
retorna = 0; //Variavel de controle do retorno automatico
escreve_rom_lcd("GRAVAR NO FAV ", 16, 0, 0);
escreve_rom_lcd("(T= ) (P= )", 16, 1, 0);
while(PORTBbits.RB1==0){}; //Aguarda soltar o botao
while(1){
if(retorna == 30){ //Retorna auto. para a MONITORAMENTO
escreve_rom_lcd(" ", 16, 0, 0); //Limpa a linha 1 do LCD
escreve_rom_lcd(" ", 16, 1, 0); //Limpa a linha 2 do LCD
sel = 0;
return; //Retorna para a funçao MONITORAMENTO
}
retorna++;
//-------------------------------------------------------------------------------
////FUNÇÃO DE AJUSTE DO PID
void ajuste_pid(void){
retorna = 0; //Variavel de controle do retorno automatico
escreve_rom_lcd(" ", 16, 0, 0); //Limpa a linha 1 do LCD
escreve_rom_lcd(" ", 16, 1, 0); //Limpa a linha 2 do LCD
while(PORTBbits.RB2==0 || PORTBbits.RB3==0){}; //Aguarda soltar o botão
while(1){
if(retorna == 30){ //Retorna auto. para a MONITORAMENTO
escreve_rom_lcd(" ", 16, 0, 0); //Limpa a linha 1 do LCD
escreve_rom_lcd(" ", 16, 1, 0); //Limpa a linha 2 do LCD
sel = 0;
return; //Retorna para a funçao MONITORAMENTO
}
retorna++;
if(PORTBbits.RB1==0){
retorna = 0;
conta=0;
while((PORTBbits.RB1==0) && (conta<250)){ //Conta o tempo de botao acionado
conta++;
Delay10KTCYx(12); //Atraso de 1 ms
}
if(conta>=100){ //Verfica se atingiu o tempo minimo
grava_pid(); //Grava os ganhos na EEPROM
bip(5, 1000);
escreve_rom_lcd(" ", 16, 0, 0); //Limpa a linha 1 do LCD
escreve_rom_lcd(" ", 16, 1, 0); //Limpa a linha 2 do LCD
return;
}
else{
if(sel_pid<3){ //Seleciona qual ganho sera ajustado
}
}
else{
sel_pid = 0;
}
bip(2, 120);
}
}
if(sel_pid == 0){ //Ajusta o ganho KP
escreve_rom_lcd("KP ", 16, 0, 0);
pid_lcd = kp;
}
if(sel_pid == 1){ //Ajusta o ganho KI
escreve_rom_lcd("KI ", 16, 0, 0);
pid_lcd = ki;
}
if(sel_pid == 2){ //Ajusta o ganho KD
escreve_rom_lcd("KD ", 16, 0, 0);
pid_lcd = kd;
}
if(sel_pid == 3){ //Ajusta o atraso no controle PID
escreve_rom_lcd("Periodo Control.", 16, 0, 0);
pid_lcd = atraso_controle;
}
}
}
//-------------------------------------------------------------------------------
////MEDICAO DA TEMPERATURA
void mede_temp(void){
char m=0;
float res_ntc=0; //Resistencia do ntc
float aux_linear=0, aux_linear1=0; //Auxilia no calculo da temperatura
//-------------------------------------------------------------------------------
////ACIONAMENTO DO BIP
void bip(unsigned char n_vezes, unsigned int atraso_adicional){
unsigned int b=0;
//-------------------------------------------------------------------------------
////EXIBE A VERSAO DO FIRMWARE AO INICIAIR O SISTEMA
void inicializacao(void){
escreve_rom_lcd(" ", 16, 0, 0);
escreve_rom_lcd(" ", 16, 1, 0);
escreve_rom_lcd("CHUVEIRO DIGITAL", 16, 0, 0);
escreve_rom_lcd("REV. 24 ", 16, 1, 0);
bip(5, 1000);
escreve_rom_lcd(" ", 16, 0, 0);
escreve_rom_lcd(" ", 16, 1, 0);
}
//------------------------------------------------------------------------------
////EXIBE NO LCD A TEMPERATURA DA ÁGUA
void lcd_temp(void){
s_temp[0] = (sensor_temp/100) + 0x30; //Centena
s_temp[1] = (sensor_temp%100)/10 + 0x30; //Dezena
s_temp[2] = sensor_temp%10 + 0x30; //Unidade
s_temp[3] = 0xDF; //º
s_temp[4] = 0x43; //C
escreve_ram_lcd(s_temp, 5, 1, 0);
}
//-------------------------------------------------------------------------------
////EXIBE NO LCD A POTENCIA INSTANTANEA CONSUMIDA PELA RESISTENCIA
void lcd_pot(void){
calc_pot(); //Calcula a potencia instantanea
pot[0] = PW/1000 + 0x30; //Milhar
pot[1] = (PW%1000)/100 + 0x30; //Centena
pot[2] = (PW%100)/10 + 0x30; //Dezena
pot[3] = (PW%10) + 0x30; //Unidade
pot[4] = 0x57; //W
escreve_ram_lcd(pot, 5, 0, 11);
}
//------------------------------------------------------------------------------
////CALCULO DA POTENCIA CONSUMIDA PELA RESISTENCIA
void calc_pot(void){
x = 0.0091734505*t_off; //0.0091...é o angulo de disparo minimo
x = 5134*(x-(0.5*sin(2*x)));
x = x/2.932545455; //2.93...é o valor estimado da resistencia em Ohm
PW = 5500 - x;
}
//--------------------------------------------------------------------------------
/////EXIBE O TEMPO DE BANHO
void lcd_relogio(void){
relogio_banho[0] = hora/10 + 0X30;
relogio_banho[1] = hora%10 + 0X30;
relogio_banho[2] = 0X3A; //:
relogio_banho[3] = minuto/10 + 0X30;
relogio_banho[4] = minuto%10 + 0X30;
relogio_banho[5] = 0X3A; //:
relogio_banho[6] = segundo/10 + 0X30;
relogio_banho[7] = segundo%10 + 0X30;
escreve_ram_lcd(relogio_banho, 8, 0, 0);
}
//-------------------------------------------------------------------------------
////CALCULO DO TEMPO DE BANHO
void calc_relogio(void){
segundo_total = (relogio/40137); /*40137 é o valor estimado
da variável relógio para um segundo de contagem*/
hora = segundo_total/3600;
minuto = (segundo_total%3600)/60;
segundo = (segundo_total%3600)%60;
}
//-------------------------------------------------------------------------------
////CALCULA O CONSUMO
void calc_consumo (void){
calc_pot(); //Amostra a potencia instantanea
consumo = consumo + (PW/60); /*A pot. inst. é dividida por 60,
pois a amostragem é feita a cada 1 minuto*/
}
//-------------------------------------------------------------------------------
////EXIBE O CONSUMO NO LCD
void lcd_consumo(void){
cons[0] = (consumo/10000) + 0x30;
cons[1] = (consumo%10000)/1000 + 0x30;
cons[2] = 0x2E; // ponto
cons[3] = (consumo%1000)/100 + 0x30;
cons[4] = (consumo%100)/10 + 0x30;
cons[5] = 0x6B; // k
cons[6] = 0x57; // W
cons[7] = 0x2F; // /
cons[8] = 0x68; // h
escreve_ram_lcd(cons, 9, 1, 7);
}
//-------------------------------------------------------------------------------
////ESCRITA DE NUMEROS NO LCD
void escreve_ram_lcd(const char *string, char tamanho, char linha, char coluna){
char i;
coluna = coluna & 0x0F; //Preserva apenas o 4 bits de LSB
if (linha == 0){
coluna = coluna +0x80; //linha 0
}
else{
coluna = coluna+0xC0; //linha 1
}
RS = 0; //Habilita o LCD para comandos
display = coluna; //Informa a posicao de escrita
enable = 1;
Delay10KTCYx(10);
enable = 0;
RS = 1; //Habilita o LCD para dados
for(i=0; i<tamanho; i++){ //Envia os caracteres
escreve_lcd (string[i]);
}
}
//------------------------------------------------------------------------------
////ESCRITA DE PALAVRAS NO LCD
void escreve_rom_lcd(const rom char *string, char tamanho, char linha, char coluna){
char i;
coluna = coluna & 0x0F; //Preserva apenas o 4 bits de LSB
if (linha == 0){
coluna = coluna +0x80; //linha 0
}
else{
coluna = coluna+0xC0; //linha 1
}
RS = 0; //Habilita o LCD para comandos
display = coluna; //Informa a posicao de escrita
enable = 1;
Delay10KTCYx(10);
enable = 0;
RS = 1; //Habilita o LCD para dados
for(i=0; i<tamanho; i++){ //Envia os caracteres
escreve_lcd (string[i]);
}
}
//-------------------------------------------------------------------------------
////ESCRITA DOS CARACTERES NO LCD
void escreve_lcd(char caractere){
display = caractere;
enable = 1;
Delay10KTCYx(10);
enable = 0;
}
//-------------------------------------------------------------------------------
//LEITURA DO ADC
return (ADC);
}
//-------------------------------------------------------------------------------
////ESCRITA DE FAVORITOS NA EEPROM
void write_eeprom(void){
escreve_rom_lcd("GRAVANDO... ", 16, 0, 0);
EEADR = fav; //Configura o endereço de escrita
EEDATA = temp;
INTCONbits.GIEH = 0; //Desabilita as interrupções de alta prioridade
INTCONbits.GIEL = 0; //Desabilita as interrupções de baixa prioridade
EECON2 = 0X55; //Senha de escrita na EEPROM
EECON2 = 0XAA;
EECON1bits.WR = 1; //Inicia a escrita na EEPROM
while(EECON1bits.WR){}; //Aguarda o término da última escrita
EEADR = EEADR+10; //Incrementa o endereço da EEPROM
EEDATA = pressao;
EECON2 = 0X55; //Senha de escrita na EEPROM
EECON2 = 0XAA;
EECON1bits.WR = 1; //Inicia a escrita na EEPROM
while(EECON1bits.WR){}; //Aguarda o término da última escrita
INTCONbits.GIEH = 1; //Habilita as interrupções de alta prioridade
INTCONbits.GIEL = 1; //Habilita as interrupções de baixa prioridade
PIR2bits.EEIF = 0; //Limpa o flag de interrupção da EEPROM
}
//-------------------------------------------------------------------------------
////lEITURA DE FAVORITOS NA EEPROM
void read_eeprom(unsigned char adress){
EEADR = adress; //Endereço de leitura da EEPROM
EECON1bits.RD = 1; //Leitura dos dados
temp_fav = EEDATA;
EEADR = adress+10; //Endereço de leitura da EEPROM
EECON1bits.RD = 1; //Leitura dos dados
pressao_fav = EEDATA;
}
//-------------------------------------------------------------------------------
////GRAVACAO DO PID NA EEPROM
void grava_pid(void){
escreve_rom_lcd("GRAVANDO... ", 16, 0, 0);
EEADR = 20; //Configura o endereço de escrita
EEDATA = kp;
INTCONbits.GIEH = 0; //Desabilita as interrupções de alta prioridade
INTCONbits.GIEL = 0; //Desabilita as interrupções de baixa prioridade
EECON2 = 0X55; //Senha de escrita na EEPROM
EECON2 = 0XAA;
EECON1bits.WR = 1; //Inicia a escrita na EEPROM
while(EECON1bits.WR){}; //Aguarda o término da última escrita
EEADR = 21; //Configura o endereço de escrita
EEDATA = ki;
EECON2 = 0X55; //Senha de escrita na EEPROM
EECON2 = 0XAA;
EECON1bits.WR = 1; //Inicia a escrita na EEPROM
while(EECON1bits.WR){}; //Aguarda o término da última escrita
EEADR = 22; //Configura o endereço de escrita
EEDATA = kd;
EECON2 = 0X55; //Senha de escrita na EEPROM
EECON2 = 0XAA;
EECON1bits.WR = 1; //Inicia a escrita na EEPROM
while(EECON1bits.WR){}; //Aguarda o término da última escrita
EEADR = 23; //Configura o endereço de escrita
EEDATA = atraso_controle;
EECON2 = 0X55; //Senha de escrita na EEPROM
EECON2 = 0XAA;
EECON1bits.WR = 1; //Inicia a escrita na EEPROM
while(EECON1bits.WR){}; //Aguarda o término da última escrita
INTCONbits.GIEH = 1; //Habilita as interrupções de alta prioridade
INTCONbits.GIEL = 1; //Habilita as interrupções de baixa prioridade
PIR2bits.EEIF = 0; //Limpa o flag de interrupção da EEPROM
}
//-------------------------------------------------------------------------------
////LEITURA DO PID PRE-CONFIGURADO
void leitura_pid(void){
EEADR = 20; //Endereço de leitura da EEPROM
EECON1bits.RD = 1; //Leitura da EEPROM
kp = EEDATA;
EEADR = 21; //Endereço de leitura da EEPROM
EECON1bits.RD = 1; //Leitura da EEPROM
ki = EEDATA;
EEADR = 22; //Endereço de leitura da EEPROM
EECON1bits.RD = 1; //Leitura da EEPROM
kd = EEDATA;
EEADR = 23; //Endereço de leitura da EEPROM
EECON1bits.RD = 1; //Leitura da EEPROM
atraso_controle = EEDATA;
}
88
APÊNDICE B
APÊNDICE C
APÊNDICE D
ANEXO A