LCPaula DISSPRT
LCPaula DISSPRT
LCPaula DISSPRT
i
RELÉ DIGITAL PARA PROTEÇÃO CONTRA SOBRECORRENTE E
de Uberlândia como parte dos requisitos para obtenção do título de Mestre em Engenharia
Elétrica.
______________________________
ii
DEDICATÓRIA
iii
AGRADECIMENTOS
disposição diante das inúmeras dificuldades que surgiram durante esta nossa caminhada.
Aos meus irmãos e sobrinho por sempre me motivarem a concluir este trabalho
Aos meus amigos e sócios Charles e Wagner por me motivarem e ainda por me
Aos meus amigos Felipe, Luis Marcelo e Renato pela força e pela pronta
Aos meus colegas e amigos do laboratório pelas ajudas e dicas que sempre
Aos meus grandes amigos que colaboraram para a conclusão deste trabalho
iv
RESUMO
Este trabalho apresenta uma solução para o monitoramento em tempo real das
correntes de um motor de indução juntamente com proteção contra sobre correntes, com curva
tecnologia digital para proteção contra sobrecorrente para motores de indução capaz de
funcionamento.
carga. Com a reprogramação deste relé inteligente, facilmente um mesmo dispositivo pode ser
utilizado para controlar motores de diferentes potências ou carga nominal. Assim pode-se
v
ABSTRACT
protection and online monitoring of induction motor operation, able to replace with some
It allows real time monitoring of induction machine currents and over current
protection, with programmable current x time characteristic. The typical current x time
thermal relay curve can be easily programmed in this device and both the curve and setting
The device has a network communication interface for remote control and
operation monitoring in a remote PC. Due to the programmable characteristic, the hardware
can be used for different ranges of motor sizes and rated powers.
The work shows details of design and programming, and presents experimental
vi
Sumário
RESUMO .............................................................................................................................. v
ABSTRACT ........................................................................................................................... vi
1.4 Contribuições.......................................................................................................... 7
vii
Capítulo 3 - Microcontroladores........................................................................................... 29
viii
4.3.3 Módulo de controle do teclado .................................................................. 63
7.1 Conclusões............................................................................................................ 94
ix
Lista de Figuras
Figura 2.5 –Fluxo magnético resultante de cada fase em instante distintos ........................... 17
x
Figura 4.2 – Protocolo de comunicação típico para RS-232 e RS-485 .................................. 49
Figura 4.6 – Fluxograma da rotina para configuração local (modo ajuste) ............................ 60
Figura 6.3 – Corrente do motor no momento da aplicação de sua carga nominal .................. 88
Figura 6.4 – Curva de resposta contra sobre corrente programada no protótipo .................... 92
xi
Lista de Tabelas
xii
Lista de Abreviaturas
universal)
EEPROM: Electrical Eraser Programmable Read Only Memory (memória não volátil
xiii
1
Capítulo 1 - Introdução
1.1 Motivações
controlar todos os equipamentos industriais a partir de uma sala única, comumente chamada
de “sala de controle”.
seja feito a partir de uma única sala pode ser resumido em poucas palavras: basta pensar nos
benefícios trazidos para uma empresa caso fosse possível que um único funcionário pudesse
ser responsável pela monitoração e controle de vários equipamentos fabris ao mesmo tempo
sem precisar sair de sua poltrona, ou seja, este trabalhador seria capaz de ligar ou desligar
controles que, além de serem mais “inteligentes” (agora microcontrolados), ocupassem menos
espaço nas salas de controle. Estas novas técnicas de controle podem ser instaladas próximo
ao equipamento que se deseja controlar e sua comunicação com a sala de controle pode ser
feita através de uma rede local, facilitando assim a manutenção e instalação dos mesmos.
no mercado da microeletrônica os antigos CLPs passaram por uma profunda modificação sob
deixaram de ser equipamentos de bancadas que ocupavam toda uma sala. Outra vantagem
seria a comunicação com o computador central que agora pode gerenciar vários CLPs ao
controladores, isto se deve a vários motivos, dentre os quais se podem ressaltar o fato de que o
atuação e monitoramento.
soluções eletrônicas para todo tipo de problema, mesmo os mais simples. Com este intuito, foi
analisada a necessidade atual da automação industrial. Depois de uma breve pesquisa sobre os
que um relé microcontrolado, que atue e proteja ao mesmo tempo os motores trifásicos, está
em falta ou está presente com um preço ainda muito elevado para aplicação no mercado
nacional.
bimetálico, relé este que possibilita apenas uma proteção do equipamento e não uma boa
noção de como está o histórico de funcionamento deste motor. Esta idéia se aplica a
3
acionamentos de motores que ainda é, em sua maioria, realizado com contatores, mas é
nacional novo e barato, que seja capaz de não apenas monitorar e proteger, mas também atuar
sobre um motor de indução trifásico. O produto final também deverá ser hábil de trabalhar
Toda esta análise e estudo ajudaram para que a idéia ganhasse as motivações e
importâncias necessárias para ser implementada aqui, visto que os outros dispositivos
equivalentes existentes no mercado atual, se comparado ao que está sendo proposto, são
1.2 Objetivos
o mercado nacional, assim como as informações de como este protótipo pôde ser
com a linguagem de programação orientada a objeto Delphi, este software será desenvolvido
software são:
• Informa em tempo real ao usuário caso haja uma sobrecarga no motor ou qualquer
• Informa ao usuário a corrente RMS que o motor está consumindo, podendo assim
desligar um equipamento remotamente, mas, na maioria dos equipamentos com este nome,
não passa de uma simples chave que pode ou não informar seu estado atual, isto é, se ele está
ou não ligado.
relés inteligentes, porém poucos possuem todas as características a que se propõe este
5
trabalho, além do que, os que as possuem, são produtos muito mais caros do que se deseja
desligar, sem se preocupar em responder qual é a corrente atual que o equipamento ligado está
corrente, o relé utilizado para acionar a carga normalmente é um relé bimetálico, que não
passa de uma proteção limitada, pois não há como se saber, de uma sala de controle, se o
motor protegido por este relé está ou não com problemas, pois a única informação que se
este encargo para um fusível rearmável ou até mesmo o tradicional relé bimetálico. Assim,
estas linhas de produtos apenas informam qual o histórico da corrente de carga, mas não
desenvolvido para criar um dispositivo capaz de ser programado através de entradas com
níveis lógicos de 0 e 1. Com relação ao protótipo proposto aqui este relé tem a vantagem da
monitoração das tensões, mas não é capaz de ser programado para reproduzir uma curva sobre
tipo de controlador, este equipamento possui saídas de até 10A e entradas para informações
6
lógicas 0 ou 1, isto é, pode-se executar uma programação para que ele ligue caso uma
determinada entrada estiver em nível lógico ligado (1) ou para ele desligar se a entrada mudar
de desligada (0) para ligada (1). Várias combinações são possíveis e este equipamento já
iluminações, esteiras rolantes entre outros. Mas para o controle de motores não é como o
proposto aqui, pois não há uma entrada de um conversor analógico digital para monitorar as
correntes e, portanto, não é capaz de proteger um motor contra sobre correntes [18].
utilizado para controlar motores e máquinas em geral na indústria, como novamente ele não
possui características para o monitoramento de corrente, por isto não possibilita a proteção
ainda da marca Siemens, dois outros relés valem a pena serem apresentados. O primeiro é
apenas um relé térmico para proteção contra sobrecarga, já o segundo é um relé inteligente,
bastante parecido com a proposta deste trabalho salvo pelo fato dele não possuir um display
ou comando para programação local. Apesar disto o SIMOCODE-DP, como é chamado este
relé inteligente, é capaz de se comunicar com um PC e monitorar as correntes das três fases
do motor. Por não possuir um display LCD este equipamento possui um tamanho bastante
deste protótipo, visto que se trata de um produto caro em um mercado de poucos fabricantes.
Ainda por se tratar de um produto cujo mercado é favorável e poucas empresas estão
1.4 Contribuições
esteja dentro das especificações de carga do equipamento. Por este motivo pode ser
se fizer necessário.
Outra contribuição que merece ser ressaltada aqui seria o fato de esta proposta
criar um relé inteligente de tal modo que seja possível programá-lo em tempo real, isto é,
enquanto o processo estiver em andamento (o relé estiver monitorando uma carga) pode-se
alterar sua curva de resposta sem que haja qualquer interferência na operação da carga
monitorada.
entendimento, para possibilitar que futuros trabalhos sejam implementados a partir dele. A
máquinas de indução para possibilitar o seu controle de partida. Por isto este capítulo
8
métodos mais utilizados para proteção de sobrecarga e finalmente uma proposta para
fluxogramas dos módulos mais importantes e ainda uma análise sobre o equipamento
proposto;
resultados dos testes feitos em laboratório. Este item apresenta uma discussão sobre a
indução; o tipo de partida utilizado durante os testes práticos; as curvas de sobrecarga que o
motor pode suportar bem como sua corrente nominal; os métodos de proteção existentes e
microcontrolador interno, que seja capaz de monitorar as correntes de fase do motor e ainda
atuar de acordo uma programação específica para cada motor. A programação deste relé
inteligente irá proteger o motor contra sobrecarga. O estudo sobre motores elétricos que será
visto neste capítulo será bastante objetivo, para que se possa entender o funcionamento básico
são sem dúvida alguma os mais utilizados na indústria atualmente. Embora o motor de
indução seja, talvez, o mais simples de todos os motores sob o ponto de vista de operação e
trabalho, foi utilizado um motor de indução trifásico de baixa potência, por isto será visto aqui
de rotor bobinado têm um rotor semelhante ao do estator, isto é, possuem três enrolamentos
11
isolados distribuídos ao longo da periferia do rotor cujas fases estão deslocadas de 120º no
espaço. A ligação com o exterior da máquina faz-se através de três anéis e escovas aos quais
regulação de velocidade.
ferro no qual se encontram condutores ligados na periferia do rotor através de dois anéis que
fecham um curto entre si. Esta construção tem um elevado nível de robustez, um baixo peso
bem como um reduzido momento de inércia e, no conjunto, é talvez a máquina mais barata.
simples no aspecto construtivo. Outra característica que faz com que o motor de gaiola de
esquilo seja largamente utilizado é o fato de possuir uma operação quase isenta de
velocidade fixa e é cada vez mais utilizada também em acionamentos de velocidade ajustável,
apesar das dificuldades de controle que apresenta. A Figura 2.1 representa o corte
esquemático de uma máquina de indução, onde abc são as correntes das fases entrando e.a'b'c'
alternada e por isto não requer nenhuma elaboração adicional, já o núcleo do rotor de um
são fundidos ou são enrolados paralelamente ao eixo em ranhuras existentes no núcleo. Nota-
se que os condutores não precisam ser isolados do núcleo, pois as correntes induzidas no rotor
12
fundido [1].
curto-circuitados em cada terminal por anéis terminais contínuos – daí o nome de “gaiola de
esquilo”. Caso os rotores sejam maiores, os anéis são soldados aos condutores em vez de
serem moldados na construção. Um detalhe construtivo deste tipo de motor é que as barras
nem sempre são paralelas ao eixo do rotor, mas podem ser deslocadas ou colocadas segundo
um pequeno ângulo em relação a ele para produzir um conjugado mais uniforme e diminuir o
diversas ranhuras, usualmente isolados do núcleo de ferro. Estes motores podem ser ligados
associadas à fase A para um par de pólos. De modo similar, a bobina bb’ representa as
estator trifásico é dito como conectado em estrela, por exemplo, as extremidades abc em curto
é, fase A ligada em a e a’, fase B ligada em b e b’ e fase C ligada em c e c’, é dito que o motor
está conectado em triângulo. O desenho esquemático dos tipos de ligações estrela e triângulo
síncrona pode ser produzido por qualquer grupo polifásico de enrolamentos cujos eixos
mesmo número de fases e se as correntes que circulam através dos enrolamentos também
deslocamento de 90°, assim seria produzido um campo girante constante desde que as
120° elétricos no espaço e pelos quais circulem correntes defasadas também de 120° no
tempo. Somente com este pré-requisito será possível produzir um campo magnético de
armadura de uma máquina trifásica, assim pode-se considerar a mesma curva para as
presente nos três enrolamentos. Para facilitar a análise deste gráfico, o deslocamento no tempo
das correntes, no eixo horizontal, está em graus proporcional a cada instante, isto facilita a
análise da curva senoidal para cada fase e também simplifica a verificação da defasagem entre
Para entender melhor como é formado este campo magnético resultante girante
deve-se calcular o campo magnético gerado por cada fase e posteriormente calcular-se o
campo resultante. Então para verificar o giro deste campo resultante deve-se calcular
novamente os campos magnéticos de cada fase só que para um instante diferente do primeiro,
cada fase, para isto será mostrado o que ocorre com o fluxo de cada fase em quatro diferentes
instantes do gráfico da Figura 2.3: 90°; 210°; 330°; 450°. Observe que o instante de 450°
segunda vez que a fase A passa pelo seu ponto de máximo. Este três instantes distintos (90°,
210° e 330°) foram escolhidos devido ao fato de serem os instantes em que cada fase
Uma análise simplificada de como o fluxo magnético é gerado por cada uma
das fases pode ser obtida através da regra da mão direita [1], utilizada para a determinação da
direção e do sentido do fluxo, e através de uma analogia entre fases, para a determinação da
amplitude do fluxo.
A Figura 2.5 mostra o sentido da corrente elétrica gerado por cada uma das
fases nos quatro instantes escolhidos. Pode-se observar na Figura 2.3 que no instante de 90°
(4,17ms) as fases B e C encontram-se com polaridade invertida com relação à fase A, por isto
17
que na Figura 2.5 o sentido da corrente elétrica devido às fases B e C estão invertidas, isto é,
de 90° é mostrado na Figura 2.5 conforme a regra da mão direita, já a amplitude devido a esta
fase é considerada a máxima amplitude de um fluxo magnético gerado por uma única fase
cujo valor é de Fa=Fmax, pois neste instante a fase A encontra-se em sua amplitude máxima
também estão indicados na figura, assim como suas amplitudes que serão iguais entre si em
módulo, cujo módulo vale Fb=Fc=Fmax/2, pois no instante de 90° é exatamente o instante em
que os valores de suas fases encontram-se, em módulo, na metade do seu valor máximo.
120° e suas amplitudes são iguais, o fluxo resultante destas duas componentes será um com
mesma direção e sentido do fluxo magnético gerado pela fase A, cuja amplitude será a metade
da amplitude do fluxo magnético gerado pela fase A. Logo o fluxo magnético resultante das
três fases no instante de 90° terá a mesma direção e sentido do fluxo gerado pela fase A e
Nos demais instantes as análises são as mesmas vistas anteriormente com uma
única diferença: o fluxo magnético resultante das três fases muda de direção. Um detalhe
importante para finalizar a análise do instante de 90° da Figura 2.5 é que independente do
instante em que se fizer a análise do fluxo resultante, seu módulo sempre será o mesmo e irá
valer 50% a mais do valor máximo de um fluxo gerado por uma única fase.
do número de pares de pólos para o qual o enrolamento trifásico foi projetado e da freqüência
120 ⋅ f
NS = Equação 2.1
P
Onde:
• P é o número de pólos;
19
força magneto motriz girante estabelecer um campo magnético girante de mesma velocidade,
rotor, de tal forma que, na presença do campo magnético, se o rotor estiver parado ou girando
com velocidade diferente da síncrona ocorre uma velocidade relativa entre o campo girante e
de fluxo do campo magnético, o que dá origem a tensões e correntes induzidas no rotor. Essas
correntes por sua vez estabelecem o campo magnético do rotor, cuja interação com o campo
enrolamentos e o giro do rotor é uma característica dos motores de indução e, por isto, eles
são classificados como motores assíncronos ou não síncronos, a Figura 2.6 mostra como seria
Conforme foi visto, a velocidade do motor nunca poderá ser igual à do campo
magnético girante, pois se isto ocorresse a corrente induzida seria zero e não se produziriam
20
fluxo magnético nem conjugado. Por isto se diz que ele deve “escorregar” em velocidade a
fim de que se produza conjugado. O que resulta numa diferença de velocidades produzidas
entre a velocidade síncrona do campo magnético girante (Ns) e a velocidade na qual o rotor do
motor gira (Nr) como resultado do conjugado produzido pela interação entre seu campo e o
Ns − Nr f
s= ou N r = N s ⋅ (1 − s ) = 120 ⋅ ⋅ (1 − s ) Equação 2.2
Ns P
Onde:
• P é o número de pólos;
suficiente para produzir o conjugado necessário a vazio. O fator de potência é muito baixo e
em atraso (tipicamente menor que 0,3), pois a corrente que circula pelo estator é utilizada
Quanto maior a carga do motor maior terá que ser o conjugado necessário para
acioná-la, já para se obter um maior conjugado terá que ser maior a diferença de velocidades
21
escorregamento.
rotor reflete-se num aumento da corrente primária do estator, em decorrência disto uma
corrente maior será requerida no estator melhorando assim o fator de potência, que resultará
contra sobrecarga para motores trifásicos e não um estudo das diferentes formas de partida
bem como os métodos para se limitar a corrente de partida, não farão parte desta dissertação
informações detalhadas sobre o assunto, mas sim apenas uma pequena ilustração do tipo de
pequena potência, podem arrancar por ligação direta à rede elétrica sem que se verifiquem
quedas bruscas na tensão de suprimento e sem que se verifique ainda um tempo de partida
prolongado. Foi este o tipo de motor utilizado nos testes relacionados a este trabalho.
botoeira que por sua vez aciona um contator que está ligado ao objeto deste trabalho: o relé
inteligente. O acionamento desta botoeira deu-se através de um comando TTL vindo do relé
inteligente. Este motor foi conectado em triângulo e partida direta, pois como é de pequeno
22
porte não causa nenhum estresse na rede elétrica e por isto não se faz necessário nenhum tipo
de controle de partida.
necessário informar o tempo de partida do motor a ser monitorado e controlado, pois o relé
inteligente precisará desta informação para poder ignorar a corrente lida pelo seu transdutor
é muitas vezes maior que a nominal. A Figura 2.7 mostra a simulação do tempo de partida
típico de um motor a vazio. Note que o tempo de partida é menor do que 250 ms.
23
Já a Figura 2.8 mostra o mesmo motor da Figura 2.7 partindo com carga
nominal, note que o tempo de partida sobe para aproximadamente 350 ms. Mesmo assim, os
motor (denominação que a NBR 5410 sugere para este tipo de dispositivo) devem possuir um
funcionamento normal à plena carga, como foram mostradas nas Figura 2.7 e Figura 2.8. Por
isto, o projeto do circuito de ligação deverá ser dimensionado para suportar as condições de
trifásico de indução tipo gaiola de esquilo, que são utilizados em mais de 90% das aplicações,
Onde:
• In a corrente nominal;
diferença entre as correntes de partida, até 250 ms, com carga nominal, entre 350 ms e 500
solicitada pela carga acionada, o que pode resultar em sobrecarga no circuito de alimentação
sem atuar, a corrente de partida, sendo capaz, portanto, de distinguir o momento de partida do
ultrapassar 15% da corrente nominal o dispositivo de proteção deverá ser capaz de atuar
assunto de proteção dos circuitos de motores, dentre eles o relé térmico de sobrecarga é sem
dúvida nenhuma o mais empregado quando o assunto é a proteção contra sobre corrente.
principal deste trabalho é desenvolver um relé inteligente que consiga atuar de forma
semelhante a um relé térmico, então apenas este tipo de dispositivo será apresentado aqui.
desligar o motor conforme as curvas apresentadas na figura. Estes relés são constituídos
funcionamento está baseado no aquecimento destes dois metais, pois como eles estão
soldados um sobre o outro ao esquentarem devido à sobre corrente na fase um dos metais irá
dilatar mais que o outro, fazendo com que estas lâminas se afastem do contato abrindo o
ambientes superiores às indicadas pela curva de disparo de cada relé bi metálico, recorre-se à
27
A proteção contra curto-circuito deve ficar por conta de outro dispositivo, tal
como um fusível ou um disjuntor magnético. Isto porque o relé bi metálico pode levar um
relé inteligente. A diferença maior entre estes dois dispositivos está associada ao fato de que o
parecido com o diagrama ilustrado pela Figura 2.11. Observe que a idéia seria possibilitar em
primeiro lugar uma interface gráfica e bastante amigável com um PC remoto através de uma
correntes de fase do motor e por fim deseja-se atuar sobre a bobina de um contator utilizando
para comunicação remota, pelo menos uma saída digital para comandar o acionamento do
motor e ainda um conversor analógico digital (ADC) para poder tratar as correntes lidas.
28
térmico são:
do funciomento do objeto de controle, o motor de indução, pode-se agora partir para o estudo
teórico da eletrônica necessária para o desenvolvimento de uma placa que consiga atender aos
requisitos deste trabalho. No próximo capítulo será visto um estudo sobre eletrônica e
Capítulo 3 - Microcontroladores
Ao se analisar este trabalho de uma maneira macro pode-se notar que se trata
de sua aplicação estar totalmente direcionada à engenharia de potência. Este fato faz com que
sobre o microcontrolador PIC utilizado. Todo este conteúdo foi utilizado no desenvolvimento
do protótipo.
integrados (CI), os CIs são componentes eletrônicos que possuem dentro deles inúmeros
resistores, capacitores, diodos e transistores agrupados de tal maneira que são capazes de
com alguns circuitos integrados, por isto algumas noções básicas do funcionamento de
pois ele não interfere de forma ativa no comportamento da corrente elétrica ou da tensão.
resistência à corrente elétrica. A lei de Ohm ilustrada na equação abaixo mostra bem o
V V
V = R ⋅i ⇔ i = ⇔R= Equação 3.1
R i
Onde:
• i: é a corrente elétrica que passa pelo resistor devido esta diferença de potencial.
circuito.
R5
10K
seu conceito foi amplamente utilizado no decorrer deste trabalho. Primeiro com resistores de
31
que é trabalhado quimicamente para se implantar nele características especiais [4]. Aqui será
visto apenas o funcionamento básico do diodo sem explicar como ou porque ele consegue se
“aponta” para o sentido que ele permite a corrente passar e se por algum motivo uma corrente
reversa tentar passar por ele, esta corrente não conseguirá passar no sentido reverso e o diodo
irá reter toda a tensão que estiver tentando produzir esta corrente reversa.
D1
Zenner
5.1V
São vários os tipos de diodos existentes no mercado, mas neste projeto foram
utilizados apenas dois tipos: o diodo simples e o diodo zenner. O zenner é conectado ao
circuito de maneira diferente do diodo simples, ele é utilizado normalmente quando se deseja
limitar uma tensão para evitar que algum outro componente não se queime. Este diodo é
capaz de funcionar, quando polarizado com uma corrente reversa, como um circuito aberto até
a sua tensão nominal, depois que atinge esta tensão ele passa a conduzir corrente para evitar
32
que sua tensão aumente além da sua tensão nominal. Este tipo de diodo é utilizado neste
graças a ele que hoje existem poderosos computadores e os mais variados circuitos
Neste projeto o transistor foi utilizado como uma chave liga desliga e por isto
será apenas apresentada aqui a sua função como chave [4] e [5]. O funcionamento de um
transistor, cuja representação pode ser vista na Figura 3.3, como chave é basicamente ligando-
elétrica que deverá passar por ele deverá ser do pino 2 para o pino 3 e utilizar o pino 1 como
1 Q1
3
aplicada na base (pino 1) de tal forma que uma corrente de base passe pelo transistor então o
transistor irá “abrir” uma passagem de corrente entre o coletor (pino 2) e o emissor (pino 3).
Quando se retirar a corrente de base o transistor irá fechar a passagem de corrente entre o
Deve-se cuidar para que as correntes de base e as correntes que passam entre o
transistor em questão, pois isto iria danificar o transistor e, portanto, iria fazer com que o
utilizado apenas o conhecimento sobre flip-flops e sobre conversor analógico digital além de
computadores e microcontroladores, foi graças a esta ciência que hoje é possível realizar o
controle preciso de vários processos. Na eletrônica digital o que se faz é representar todos os
sinais analógicos e que se deseja controlar em números binários (“0” e “1”). Depois de se
conseguir equacionar o que se deseja dentro da álgebra booleana fica relativamente fácil
É importante ter uma boa noção sobre o latch (circuito base para um Flip-Flop)
estrutura básica dos dispositivos de memória atuais e o conversor foi utilizado neste trabalho
O lacth nand é um Flip-Flop (FF) simples com apenas duas portas NAND. A
característica básica de um lacth seria possuir dois pinos de saída, uma sendo o complemento
da outra em termos de álgebra booleana, isto é, quando uma tiver o valor “1” a outra terá o
valor “0” e vice-versa. Estas saídas são normalmente denominadas como sendo Q e Q .
34
estado alto e por isto possuem a barra em cima do nome, assim se alguém desejar colocar a
saída Q em nível lógico alto deverá colocar a entrada SET em nível lógico baixo mantendo a
entrada CLEAR em nível lógico alto, caso deseje-se colocar a saída em nível lógico baixo
deve-se fazer o oposto. As duas entradas não podem estar ao mesmo tempo no nível lógico
baixo, pois isto seria um comando inválido para este circuito relativamente simples. O circuito
SET 2
1 Q Q
3 SET CLEAR Q
1 1 Q Q
0 1 0 1
2
1 Q 1 0 1 0
CLEAR 3
0 0 inválido
colocando uma porta NAND a mais em cada entrada de comando conseguindo assim um
que é chamada de nibble. Então se agrupando dois nibbles obtém-se uma palavra de 8 bits
denominada byte (observe que seria necessário oito circuitos de lacth como o da Figura 3.4).
E assim por diante pode-se conseguir o circuito com o número de bits que se necessite
porque um ADC é muito mais complexo do que um DAC. Normalmente o ADC utiliza um
O circuito mais tradicional de uma conversão digital analógica seria uma rede
trabalhar basicamente com resistores é fácil de montar na prática pelo fato de possuir apenas
dois valores de resistências: R e 2R. A Figura 3.5 mostra como seria um DAC com esta rede
de apenas 4 bits.
Vref
1
B0 B1 B2 B3 3
+
6 Vout
2
2
2R 2R 2R 2R
4
A B C D
2R R R R R
2R
A entrada deste DAC seria a palavra B de 4 bits, representada na figura por B3,
B2, B1 e B0. O número indicado de cada bit indica a potência que a base dois do número
binário deverá ser o expoente da potência com base 2, isto é, o bit B2 tem valor 2 2 e o bit B3
36
tem valor 2 3 . Assim a palavra B pode variar de 0, quanto todos os bits estiverem com o valor
superposição de fontes, isto é, pode-se analisar separadamente cada bit do circuito e depois
somar a contribuição de cada bit para então chegar ao valor de Vout . Também será necessário
utilizar o teorema de Thévenin, veja referência bibliográfica [7], para encontrar a tensão e a
A análise deste circuito fica mais fácil se for feito do bit mais significativo
primeiro, assim primeiramente será vista a contribuição apenas deste bit ligado à Vref e os
conectado à massa (terra), em paralelo com o 2R do ponto “A” para a massa, logo a
resistência equivalente do ponto “A” para o terra seria 2R//2R=R. Então poderia se somaria
esta resistência com a resistência existente entre os pontos “A” e “B” o que resultaria
Então se repetiria esta mesma análise até chegar ao ponto “D”, que seria um
pouco diferente. No ponto “D” ter-se-ia uma resistência de 2R vinda do ponto “C”, a
resistência de 2R do próprio ponto “D” à massa, o que difere o ponto “D” dos demais pontos,
e ainda o resistor 2R do bit B0 que nesta consideração estaria ligado à Vref . Logo as duas
e a tensão no ponto “D” seria a do divisor de tensão entre os resistores 2R, ligado à Vref , e R
1
ligado à massa. A tensão calculada por este divisor de tensão seria então ⋅ Vref .
3
37
equivalente de Thévenin visto do ponto “D” está ilustrado na Figura 3.6, observe que o Vth é a
1
tensão calculada para cada bit, no caso do bit B3 será ⋅ Vref .
3
7
3
+
6 Vout
2
-
4
Vth
2R/3 R
R 3
Vout = − ⋅ Vth = − ⋅Vth Equação 3.2
2R / 3 2
1
Como a tensão de Thévenin para o caso do bit B3 é ⋅ Vref , a contribuição para
3
a tensão de saída do bit B3 será de − 0,5 ⋅ Vref . Fazendo uma análise análoga para encontrar a
1
tensão de Thévenin para o bit B2 será encontrada uma tensão de ⋅Vref e conseqüentemente a
6
bit menos significativo. Como o teorema da superposição diz que a tensão resultante será a
38
soma das contribuições parciais das tensões encontra-se para o DAC de 4 bits a seguinte
B
Vout = − ⋅Vref Equação 3.3
8
Onde:
de referência utilizada, neste exemplo pode-se notar que o máximo valor seria, em módulo,
potenciômetro ligado a uma tensão Vref jamais seria possível ler o valor exato de Vref , mas
apenas 2(n—1) valores com em passos discretos de 2-(n-1) iniciados em 0 e máximo valor de
2 ( n−1) − 1
Vref , onde n seria o número de bits do seu conversor ADC.
2 ( n−1)
bits seria capaz de ler uma valor aproximado de 99,22% do valor máximo de referência e um
importante que varia entre eles é a velocidade de conversão, esta velocidade de conversão
ciência que será utilizada no trabalho, será visto apenas um ADC típico e seu funcionamento
para explicar como funciona esta conversão, os demais tipos de ADC serão apenas citados e
unidade de controle irá precisar de um sinal de Clock externo para poder sincronizar o envio
da primeira palavra digital ao registrador. Então a cada passo do Clock o ADC verifica se a
nova tensão gerada pelo DAC interno é maior do que a da entrada analógica, quando esta
resposta for verdadeira então o ADC interrompe sua conversão habilitando o sinal EOC.
Alguns tipos de ADC são: ADC de rampa digital, há um contador interno que
irá contar desde 0 até um valor um pouco maior que Va encontrando assim o seu valor; ADC
acordo com o número de bits, pois este verifica do bit mais significativo para o menos
40
significativo se cada um destes bits devem ou não estar ligados; ADC flash, é o de maior
mais caro.
3.3 Microcontroladores
um circuito integrado da eletrônica digital com uma tabela-verdade muito maior que a maioria
dos circuitos integrados e cuja tabela-verdade interna possibilita a execução de várias tarefas
diferentes.
na sua entrada, que são chamados de opcode, em função de sua tabela-verdade interna. Os
opcodes são os valores de entrada da unidade central de processamento (CPU) que foram
previamente programados neste CI e que representam algum tipo de operação, que pode ser
Na verdade é bem mais complexo do que isto, mas esta é uma analogia
bastante interessante de se fazer. Existem vários livros abordando este assunto e alguns deles
estão na referência bibliográfica deste trabalho [6], [8] e [9]. A melhor maneira para verificar
Figura 3.8.
chip conectados de tal forma que tudo execute exatamente os opcodes gravados na memória
de programa, ROM neste caso. No caso dos microcontroladores utilizados ainda há mais um
tipo de memória de dados além da memória RAM, a memória EEPROM. As portas paralelas
interrupções são para melhorar algumas funções, por exemplo, a da comunicação serial. Os
temporizadores podem ser utilizados para a contagem de tempo e assim realizar alguns atrasos
ou esperas por algum evento de um determinado tempo. Os conversores ADC e DAC também
geral também podem ser encontrados nas bibliografias deste trabalho [10] e [11].
direta para ilustrar todo o funcionamento básico do PIC adotado e ainda dar uma noção de
deste microcontrolador.
Este PIC possui 28 pinos, dos quais apenas 22 estão disponíveis para I/O,
foram utilizados 4 pinos da porta RB como barramento de dados, isto é, funcionando como
I/O, e outros 3 pinos desta porta foram utilizados como barramento de controle para o
exceto pelo pino que habilita o teclado. Enquanto que a maioria dos pinos da porta RC
pinos foram utilizados para a comunicação em si e, se for o caso, 1 pino poderá ser utilizado
capazes de fornecer correntes de até 25mA cada, caso seja necessária mais corrente um drive
da placa de circuito impresso que viabilize este projeto será dado início, no próximo capítulo,
O enfoque deste capítulo será mostrar todos os passos para a escolha dos
firmware seria o programa desenvolvido especialmente para uma placa, por exemplo, a BIOS
placa mãe. Já o software é um programa desenvolvido para uma aplicação final, normalmente
firmware não.
Este capítulo está dividido em itens que obedecem a uma ordem cronológica da
componentes básicos de todo o projeto. Posteriormente cada bloco do diagrama será estudado
funcionamento. Por fim será feita a integração entre todos estes blocos criando assim um
Para atender aos requisitos exigidos neste diagrama de blocos foi necessário
fazer um estudo das inúmeras relações entre os custos e os benefícios dos componentes
com a existente nos computadores pessoais, assim foi escolhida a interface USART que é
I/O, pois o dispositivo deverá ler um teclado, comandar um LCD, atuar em pelo menos um
acionamento e ainda portas para comandar um ADC externo, conforme a proposta inicial, ou
80C51 da Intel, por ser mais fácil de programar devido à sua arquitetura CISC. Mas por
posteriormente pelo PIC16F876A, por este último possuir um conversor analógico digital
Outro fator que auxiliou na escolha da família PIC foi o fato de que este tipo de
microcontrolador possui uma memória flash interna suficientemente grande para armazenar
memória não volátil do equipamento, isto porque se deseja que o mesmo “lembre” da sua
necessitava de pouca memória e seria melhor utilizar uma memória que possuísse escrita e
leitura por byte, ou seja, byte a byte a EEPROM pode ser alterada e lida enquanto que a
programa, mas neste caso a idéia é utilizá-las como memória de dados não volátil, assim sua
gravação é feita em tempo de execução e o PIC já possui instruções que facilitam este tipo de
programação.
47
desenvolvimento deste firmware optou-se por dividir estes 256 bytes em 8 blocos de 32 bytes
bloco foram colocados os dados referentes à curva que o relé inteligente deverá obedecer
durante a monitoração do motor configurado. Nada foi implementado nos demais blocos, mas
o desenvolvimento do firmware foi de tal maneira que facilmente pode-se aumentar o número
máximo de pontos da curva de controle do equipamento ou utilizar este vários bytes para
outras aplicações.
Foi exatamente nesta fase do projeto que se desistiu do PIC16F628, pois como
ele não possui um ADC interno seria necessário um externo, até aí tudo estava dentro do
esperado. Mas quando se percebeu que seria necessário um ADC serial externo e quando se
estudou o datasheet de um periférico destes tudo mudou, pois esta programação seria bastante
complicada de se desenvolver.
possui a mesma estrutura de memória interna, o que possibilitou migrar todo o código de
ADC interno de 10 bits com até 5 canais. Em virtude desta troca o projeto ficou com pinos de
uma corrente senoidal cuja freqüência de rede é de 60 Hz, o tempo de aquisição de dados
48
do ADC interno, optou-se por utilizar apenas três canais e utilizar as outras duas entradas
possível. A idéia inicial era utilizar uma rede CAN para esta comunicação, porém seria muito
A vantagem da rede CAN para a rede RS-485 é que pode-se conectar um novo
equipamento na rede em qualquer topologia e sem se preocupar com a fiação, enquanto que a
rede RS-485/422 necessita ser conectada ponto a ponto, não permitindo ramificações. Então a
diferença é na camada física da rede, então tudo que for feito para um poderá ser aproveitado
para o outro padrão bastando substituir a camada física, isto é, a interface elétrica da
sincronismo chamado start bit e um bit de parada denominado de stop bit. Outras variações
podem ser utilizadas, por exemplo, a utilização de um bit de paridade para fazer o controle de
redes com mais de um escravo no caso do padrão RS-485 ou RS-422. A Figura 4.2 ilustra
1 bit de paridade
1 bit de parada
1 Bit de start
8 Bits de dados
RS-485 é que o primeiro necessita de no mínimo três fios (um para transmissão, um para
recepção e um comum de referência) enquanto que no segundo podem ser utilizados apenas
dois fios (ambos são utilizados para a transmissão e recepção) ou RS-422 com quatro fios
deverá ser half duplex, isto é, apenas um dispositivo de cada vez poderá transmitir seus dados,
isto porque existe apenas um canal de dados e não pode ser usado para transmitir e receber
Para evitar que o PC transmita dados ao mesmo tempo que o protótipo e que
ocorra colisão de dados na rede caso ela seja half duplex desenvolveu-se toda a programação
da serial com um protocolo mestre escravo, isto é, quando um equipamento somente transmite
colocadas na rede e seus significados. Para o RS-232 o nível lógico zero é transmitido quando
uma tensão positiva entre 3V e 12V estiver entre os terminais de transmissão e o comum,
analogamente um nível lógico um é quando esta tensão for negativa entre -12V e -3V. Na
recepção de dados os mesmos níveis de tensão devem ser respeitados mudando apenas que a
diferença de tensão estará entre os terminais de recepção e o comum. O padrão RS-485, por
possuir apenas dois fios, trabalha com níveis lógico correspondentes às diferenças de tensão
entres estes dois fios. Se a tensão for positiva então um zero lógico foi transmitido e se for
computadores pessoais atuais, pois eles possuem, normalmente, pelo menos uma porta serial
RS-232. Se for utilizar o RS-485 – que tem a vantagem de atingir maiores distâncias devido
ao fato de transmitir tensões balanceadas sem uma tensão de referência comum – será
MAX232 e o HIN232 para o padrão RS-232 e o DS485 para o padrão RS-485. A escolha por
estes dispositivos foi baseada no baixo custo e por serem fáceis de encontrar.
Para fazer uma interface visual com o usuário local optou-se pela utilização de
um display de cristal líquido de 2 linhas por 16 colunas, pois este LCD é bastante comum e
possui caracteres suficientes para realizar uma boa interface. Visando melhorar ainda a
51
interface de saída de dados foi ligado um LED vermelho indicando se o motor está ligado ou
não.
programação, porém foi preciso utilizar 4 pinos de dados e 3 pinos de controle para realizar
esta comunicação. Gastou-se apenas 4 pinos de dados porque este tipo de LCD pode ser
para “economizar” portas de I/O do PIC e porque já havia 4 pinos no barramento de dados
destinados ao teclado, assim foi compartilhar estes pinos. Fazer funcionar esta interface foi a
parte mais complicada de todo o projeto, isto porque foram desenvolvidas aqui todas as
satisfatória para atender ao que se esperava do projeto. Foi criado um teclado de apenas
quatro teclas: uma para acessar o menu do dispositivo (tecla “Menu”); uma para sinalizar uma
confirmação de dados (Tecla “Ok”); uma para sinalizar um incremento (tecla “Up”); e
Com estas quatro teclas foi possível criar uma boa interface de entrada de
dados tanto para perguntas e confirmações simples quanto para entrada de valores numéricos
pelo usuário. Para “ler” estas teclas foram necessários utilizar 5 pinos do PIC, os mesmos 4
pinos do barramento de dados utilizados na comunicação com o LCD mais 1 pino de controle
motor, caso no final do projeto sobre mais pinos outras aplicações poderão surgir, mas por
de suas correntes.
Uma pequena placa adicional foi utilizada para elevar a corrente do pino do
PIC para uma corrente capaz de acionar um contator, por exemplo. Esta placa utilizará um
PIC16F628, uma vez que este PIC atendia ao requisitos de memória RAM e EEPROM para
os dados e memória FLASH para o firmware e aos requisitos de pinos de I/O. Então foram
Somente quando se concluiu esta parte do trabalho foi que se iniciou o estudo
de como seria a interface com o ADC externo. Como já estava previsto neste projeto,
reservou-se dois pinos de I/O (RA6 e RA7) para a comunicação serial com o ADC externo. A
Vcc
J2
U3
3 Vcc
J4
2 4 6 +
1 DI A 7 - 1
Vcc 3 B 2
Driv er p/ Motor R5 R6 2 DE 1 RS485
RE R0
3
10K 10K
U1 DS485 P1
C3
2 10K 100nF
RA0/AN0
RA1/AN1
VDD RA2/AN2/VREF
RA3/AN3/CMP1
1
RA4/TOCKI/CMP2
RA5/MCLR/Vpp
RA6/OSC2/CLKOUT J3
RA7/OSC1/CLKIN
1
2
RB0/INT RS 3
RB1/Rx/DT R/W 4
RB2/Tx/CK EN 5
RB3/CCP1 6
RB4/PGM 7
RB5 8
Vss RB6/T1OSO/T1CKI/PGC 9
RB7/T1OSI/PGD 10
11
PIC16F628 12
D1 13
14
LCD
S4 S3 S2 S1
externo, o tempo necessário para se programá-lo e o fato de o projeto com o PIC16F628 estar
caminhando para o seu limite em termos de hardware, decidiu-se então trocar este
microcontrolador por outro que já possuísse um conversor analógico digital interno, ou seja, o
PIC16F876A.
54
J1 ADC
Vcc
1
2
3
4
5
C3 100nF
P2 10K
3 1
Vcc 10K
3 1
2
P1
U1
20
2
10K R5
VDD
2 J3
RA0/AN0 3
RA1/AN1 S4 S3 S2 S1 1
4
RA2/AN2/VREF- 5 D1 2
RA3/AN3/VREF+ 6 RS 3
1 RA4/TOCKI 7 R/W 4
MCLR RA5/SS/AN4 EN 5
21 6
9 RB0/INT 22 7
10 OSC1/CLKIN RB1 23 8
OSC2/CLKOUT RB2 24 9
RB3/PGM 25 10
RB4 26 11
RB5 27 12
X1 RB6/PGC 28 13
RB7/PGD 14
11
20 MHz RC0/T1OSO/T1CKI 12 LCD
RC1/T1OSI/CCP2 13
C5 C4 RC2/CCP1 14
RC3/SCK/SCL 15
15 pF 15 pF RC4/SDI/SDA 16
RC5/SDO 17
19 RC6/TX/CK 18
8 Vss RC7/RX/DT U2
Vss
Vcc 4 1 J4
PIC16F876A 2 DI RO 6 +
3 RE A 7 - 1
J2 DE B 2
8 RS485
3 +VCC
2
1 DS485 / MAX485
Driv er p/ Motor
A escolha do novo microcontrolador não foi difícil, pois bastou procurar pelo
e que ainda dispusesse de um ADC interno e mais alguns pinos de I/O para eventuais novas
necessidades.
mas ao utilizá-lo descobriu-se que a disposição da sua memória RAM tornava impossível
utilizar a mesma camada de aplicação da rede serial já desenvolvida, foi assim que se optou
de variáveis.
55
banco 0 da memória RAM, o que possibilita o acesso aos valores das variáveis do banco 0
mesmo estando com os outros bancos selecionados. Isto não ocorre no PIC16F873A.
protótipo do relé inteligente salvo apenas a substituição do componente U2, o DS485, por um
não contava com um conversor RS-485 para RS-232 que seria necessário instalar no PC.
Outra mudança causada pele troca do DS485 pelo HIN232 foi o cabo de comunicação, que
Agora uma breve explicação deste esquemático dará uma idéia de como a placa
funciona. Iniciando com U1, que é o PIC16F876A, ele foi conectado a uma alimentação de
5V (Vcc) e a um cristal de 20MHz – com este cristal o PIC executa uma instrução em apenas
200ns.
disponibilizados pelo PIC. O hardware ligado a este conector deverá limitar a tensão em até
5V para que não queime estas entradas analógicas. Este conector também fornece a tensão de
lembrando que será necessário um amplificador de corrente conhecido como driver para que o
sinal digital seja capaz de acionar um contator, que por sua vez irá acionar o motor.
têm a função da camada física da rede de comunicação serial, isto é, é através deles que os
dados e 3 pinos de controle para que o PIC consiga comunicar-se com o LCD. Ainda estão
disponíveis neste conector dois pinos para a alimentação (Vcc e Gnd) e ainda um pino para o
Os botões S1, S2, S3 e S4 terão as funções das teclas Down, Up, Ok e Menu,
respectivamente. Observe que o pino 6 do PIC – o RA4 – está ligado neste botões e enquanto
ele estiver com um nível lógico “1” (5V) o teclado estará desabilitado e os 4 pinos de dados –
memória flash para armazenar o firmware, uma memória EEPROM para armazenar os dados
para controlar o teclado ficou totalmente independente daquele necessário para controlar o
O módulo que ficou responsável pelo teclado é acionado via varredura pelo
programa principal no seu loop principal, isto é, o teclado não funciona com interrupção, mas
sim por varredura. Já o módulo desenvolvido para controlar o LCD disponibilizou várias
Foi criado um módulo contador de tempo que funciona com interrupção, este
módulo é utilizado para gerar o relógio interno do relé inteligente. Infelizmente para se
conseguir um relógio preciso seria necessário outro cristal conectado diretamente a um pino
específico, mas como não há necessidade de tanta exatidão foi utilizado o próprio oscilador de
20 MHz do microcontrolador para a contagem do tempo. Este contador será utilizado para
ele é controlado remotamente via interrupção serial. Trata-se de um módulo que simplesmente
responde aos comandos remotos de maneira rápida e eficaz. Este módulo utiliza as funções do
Por fim, um módulo capaz de ler os dados do ADC foi desenvolvido de modo a
imprimir no display a corrente lida naquele instante. Este módulo também é executado via
funcionamento de cada um deles para que todo o projeto do equipamento possa ser entendido.
que assim que o PIC é inicializado, o primeiro passo é iniciar os valores das variáveis globais
58
interrupções (serial e do relógio interno) para que este protótipo possa contar o tempo e ainda
isto é, sincronizar a comunicação entre o PIC e o LCD, sem dúvida nenhuma é nesta etapa
que a programação é mais trabalhosa porque o PIC trabalha em tempos de "µs" enquanto que
Loop Principal do
Programa Principal
Início do
Programa
Mostra a
= Ok
mensagem
principal no LCD
Inicializa variáveis
e portas do
Microcontrolador Tecla? = Menu
Módulo ADC
(imprime a
corrente lida) = Up / Down
Rotina de
Inicializa configuração local
Interrupções (modo de ajuste)
(Relógio e Serial) Seleciona o canal do
ADC da corrente
Módulo do escolhida (Up/Down)
Teclado
(Retorna tecla)
Inicializa o
Módulo LCD
(Display)
terá uma repetição eterna e que fará com que o relé inteligente sempre esteja monitorando as
correntes, o teclado e ainda a comunicação serial. O loop principal começa mostrando uma
mensagem padrão na primeira linha do LCD e em seguida faz a leitura de um dos canais do
ADC e mostra o valor da corrente lida de acordo com o que foi configurado na sua memória
59
controle do tempo em que a corrente monitorada está acima da corrente nominal configurada
para o motor em questão não foram tratadas no programa principal e muito menos no loop
neste modo de ajuste o teclado é lido até que uma tecla seja pressionada, caso passe muito
tempo sem que a tecla seja pressionada então a rotina do teclado retorna que nada foi
comando serial, afinal ele está em ajuste, mas recebe os dados normalmente e pode executar o
comando assim que sair deste modo, porém o PC remoto pode achar que o comando não foi
Note que para simplificar o fluxograma não foram colocadas todas as variáveis
capazes de serem alteradas localmente, mas sim apenas o nome da primeira que é o ID do
equipamento a ser ajustado. Este ID é utilizado para saber a qual equipamento da rede está
por exemplo. Esta mudança já permitiria a confirugação de uma rede, pois tanto o firmware
interface para isto não é tão amigável quanto a configuração remota. Exemplos de outras
variáveis são: máxima variação da corrente lida no ADC (chamado de delta); menor valor da
corrente lida no ADC (corrente equivalente se o valor lido no ADC for zero); corrente
nominal do motor; tempo de partida do motor; unidade em que o tempo de partida do motor
e é utilizado apenas para mostrar os resultados de uma maneira local. Depois de se inicializar
o LCD e criar algumas rotinas que facilitam a impressão de caracteres no display ficou muito
mais fácil de se utilizar este módulo, contudo foi aqui empregada a maior parte do tempo em
programação. Inclusive, ao se trocar o PIC utilizado, foi necessário revisar todo este módulo
uma de leitura de dados. Outras variações destas rotinas básicas foram desenvolvidas para
A Tabela 4.1 traz uma descrição básica de cada pino do LCD. Dos 7 pinos
Dados
Descrição Modo RS R/W
(Hexa)
Liga (sem cursor) 0 0 0C
Display
Desliga 0 0 0A / 08
Limpa display com home p/ cursor 0 0 01
Liga 0 0 0E
Desliga 0 0 0C
Desloca p/ Esquerda 0 0 10
Controle do Cursor Desloca p/ Direita 0 0 14
Cursor Home 0 0 02
Cursor piscante 0 0 0D
Cursor com alternância 0 0 0F
Sentido de deslocamento do cursor Para a esquerda 0 0 04
ao entrar caractere Para a direita 0 0 06
Deslocamento da mensagem ao Para a esquerda 0 0 07
entrar caractere Para a direita 0 0 05
Deslocamento da mensagem sem Para a esquerda 0 0 18
entrada de caractere Para a direita 0 0 1C
Primeira linha 0 0 80
Endereço da primeira posição
Segunda linha 0 0 C0
descritos na A Tabela 4.1 traz uma descrição básica de cada pino do LCD. Dos 7 pinos
Tabela 4.2, para enviar comandos com apenas 4 bits (nibble) de dados é
necessário enviar primeiro o nibble mais significativo depois o menos significativo. Por
63
exemplo, para enviar o comando liga display sem cursor (0x0C) deve-se enviar primeiro o
implementados na prática basta consultar o Anexo A . Neste anexo encontra-se o código fonte
compilado de todo o firmware, lembrando que a linguagem utilizada para esta programação
é necessário entender bem este circuito para compreender como ele foi programado.
• R5 é o resistor de pull-up;
Vcc
R5
10K
1
D1 Pino de Controle
S1
1
Pino de Dados
teclado foi programado pelo sistema de varredura, isto é, o loop principal fica monitorando o
computadores pessoais.
sempre com nível lógico “1” (+5V). Nesta condição pode-se notar que o diodo jamais irá
conduzir, pois a tensão de 5V é a mais alta tensão presente no circuito e, por isto, será
impossível que o diodo seja polarizado diretamente a ponto de haver uma diferença de tensão
direta de +0,7V. Como jamais passará corrente pelo diodo, o botão poderá ser pressionado
que não alterará a tensão que estará presente nos pinos de dados, ou barramento de dados.
Assim, os pinos de dados poderão estar sendo utilizados para acessar outros dispositivos, no
caso o LCD.
colocar o pino de controle em nível lógico “0” (0V). Quando o pino de controle estiver com
“informações” contidas nos pinos de dados poderão sofrer alterações vindas desta conexão
física.
Início da
Rotina que lê a tecla
pressionada
Para ler a tecla propriamente dita deve-se colocar nível lógico “1” no pino de
dados que está conectado à tecla que será lida, isto é feito através da habilitação dos resistores
de pull-up internos da própria porta (veja a Figura 4.8). Em seguida aguarda-se algum tempo
para estabilizar as tensões e eliminar os ruídos e então é feita a leitura da porta para verificar
as teclas que estão pressionadas. Caso seja lido um nível lógico “1” a tecla não foi
pressionada, mas caso seja lido um nível lógico “0” a tecla está pressionada.
feito um filtro dos bits do barramento de dados zerando os valores dos outros pinos da porta (a
porta do PIC possui 8 pinos ou 8 bits) e posteriormente é negado o valor destes pinos, para
que o bit fique com o valor “1” somente se a tecla for pressionada, o que facilita a utilização
lógica no meio do programa, pois “1” está associado à verdadeiro e “0” à falso.
Observe que se o pino lido estiver em nível lógico “0” significa que está
diferente do que foi colocado nele através dos resistores de pull-up, isto indica que houve uma
66
interferência do hardware externo, ou seja, o botão foi pressionado. Esta interferência ocorre
devido à passagem de corrente pelo botão pressionado e pelo diodo diretamente polarizado,
dados será de aproximadamente 0,7V, tensão esta que indica um nível lógico “0” e não “1”.
simples possível, observe a Figura 4.9 para entendê-la melhor. Se não houver tecla
pressionada a varredura passa pelo módulo do teclado somente verificando se deve responder
a algum comando serial. Já se houver tecla pressionada, o relé irá guardar apenas a última
tecla pressionada, isto é, mesmo que sejam pressionadas mais de uma tecla simultaneamente
apenas a última ficará gravada na variável que indica a tecla pressionada. É praticamente
impossível soltar as teclas no mesmo instante, pois o tempo que o PIC executa uma instrução
inteligente estiver sendo ajustado no módulo local, isto é, caso alguém esteja configurando o
relé inteligente localmente. A Figura 4.10 mostra a outra forma de leitura do teclado
Note que de acordo com este segundo fluxograma o relé inteligente não espera
que a tecla pressionada seja solta, isto faz com que se a tecla for mantida pressionada pelo
usuário do equipamento por muito tempo o módulo irá acreditar que a tecla foi pressionada
várias vezes, por isto no modo de ajuste deve-se ter bastante cuidado ao se pressionar o
teclado. Também é importante notar que se nenhuma tecla for pressionada por muito tempo,
aqui configurado 7s, o relé inteligente irá acreditar que o usuário não mais irá configurar o
equipamento e, conseqüentemente, irá sair do modo de ajuste, o que evita que este protótipo
Início do
Módulo do Teclado
(ajuste)
Salva tecla
Inicia contador de Tempo
pressionada na
tempo (7s) acabou?
variável
Sim
Timer2 do microcontrolador. Este contador de tempo interno foi programado para gerar
interrupções de 1ms, isto é, ele foi programado para gerar mil interrupções por segundo.
Esta contagem de tempo possui um erro, como toda medição, mas para esta
aplicação o erro é desprezível, porém para criar um relógio não, pois teria um atraso por dia
que poderia ser significativo. Este erro não foi levantado porque não é devido ao cálculo, que
está exatamente correto, mas devido às variações do cristal de 20 MHz utilizado, por isto
verificar o tempo de sobre corrente do motor. Este controle simplesmente conta o tempo que a
sobre corrente está no motor e verifica se este tempo está dentro do tempo programado para
este motor. Caso este tempo seja ultrapassado o relé inteligente irá desligar o motor e gerar
interrupção do relógio interno do protótipo é que, com toda a certeza, o motor será desligado
Este módulo é sem dúvida nenhuma o módulo mais complexo que foi
desenvolvido neste protótipo, apesar do módulo do LCD ter sido mais trabalhoso e mais
módulo do teclado, pois é o único lugar do firmware que sempre está em execução, já que o
loop principal pode ficar sem ser chamado se alguém ficar segurando uma tecla pressionada.
simplesmente copia estes dados para um buffer na memória RAM do microcontrolador, uma
vez que esta cópia tenha sido completada um flag irá indicar que os dados poderão ser
tratados. Então no módulo do teclado uma rotina que verifica este flag e trata os dados, se for
Já rotina que trata os dados é responsável por executar o comando enviado pelo
PC remoto e ainda responder que este comando foi executado corretamente. No instante em
que o relé está tratando os dados recebidos ele poderá estar: copiando dados para a EEPROM
3 bytes com as 3 correntes de fase; 3 bytes com o horário do relógio interno (segundo, minuto
EEPROM ou lidos; 1 byte com o número de bytes do pacote (48 ou 0x30). Caso haja o
recebimento de um byte a mais ou a menos ou caso algum byte de controle seja diferente dos
70
histórico.
a execução do loop principal. Sempre que o programa passa pelo loop principal as correntes
são lidas pelo ADC do microcontrolador, mas se por algum motivo o loop principal for
interrompido – pode ser porque alguém travou o teclado ou porque alguém esteja acessando o
modo de ajuste – o equipamento não estará atualizando o valor da corrente, o que pode
resultar numa tomada de decisão errada diante de uma possível corrente antiga.
Início do
Módulo do ADC
<3
Calcula o valor da
Testa Incrementa um
corrente lida no =3
Contador? contador
ADC
Mostra corrente do
canal selecionado Fim do Módulo
no LCD
O fluxograma mostra que inicialmente este módulo irá verificar qual dos três
canais está selecionado para ser mostrado no LCD, em seguida irá ler as correntes do ADC
deixando por último a corrente do canal que deverá ser mostrado no display. Todas as
71
O byte lido no ADC representa o valor lido de cada corrente, mas para que este
valor seja mostrado no LCD será necessário realizar um cálculo de acordo com uma reta que
poderá ser configurada pelo usuário. Esta configuração possibilitará a conexão deste
em si não faz parte do relé digital, mas sim é um periférico necessário e pode ser de qualquer
natureza desde que seja uma função linear. O protótipo aceita a configuração desta reta
∆ ⋅ I lido + I zero
I Calc = Equação 4.1
256
Onde:
• Izero é o valor proporcional da corrente mínima, quando o valor lido no ADC é zero
(byte);
Com esta função de transferência qualquer transdutor linear pode ser conectado
na entrada do ADC do relé inteligente sem problema algum, isto faz com que o equipamento
possa trocar de transdutor sem que seja necessário fazer qualquer tipo de adaptação. A única
limitação é a da entrada analógica que não pode receber tensões acima de 5 V e, por ser usado
72
um ADC de 8 bits, maiores do que 0,02 V (5 V dividido por 256) para que seja perceptível ao
conversor analógico.
analógico ser capaz de medir, o ganho do transdutor, ou sensor, utilizado deverá ser
requisitos iniciais deste trabalho. Com a placa e os componentes eletrônicos utilizados aqui
poderiam ser agregadas neste relé inteligente e serão citadas no capítulo final deste trabalho
em DC como foi implementado, isto possibilita uma resposta mais rápida a qualquer mudança
um pequeno atraso devido ao capacitor utilizado para encontrar o valor médio da onda AC. A
Figura 4.12 mostra como deve ser o circuito conectado ao canal analógico do PIC.
73
R R
R R R/2
Sinal AC Entrada do ADC
1
Zenner
7
C 5.1V
3 3
+ +
6 6
2 2
- -
4
Figura 4.12 – Esquemático do retificador de precisão que converte o sinal AC em DC
tensão de 0,7V dos diodos tradicionais, pois este circuito é um retificador de precisão. Na
seqüência, o sinal é convertido em DC para simplificar o algoritmo utilizado, que agora não
precisará calcular o valor da tensão média que é proporcional à corrente média do motor.
este protótipo. Esta próxima etapa é bastante enriquecedora, pois a partir dela que se alcançará
controle do protótipo do relé inteligente proposto neste trabalho e mostrará também como este
programa é capaz de monitorar e atuar sobre o protótipo. Também será visto aqui todas as
e como ele foi implementado seguido por alguns fluxogramas e explicação funcional. Para
finalizar o capítulo haverá uma apresentação dos resultados e uma discussão sobre a eficiência
implementação do protótipo, por isto ele ficou bastante simples e sem uma visão de software
final, isto é, sem os devidos cuidados que se deve ter com um software comercial.
em Delphi, é acessar uma das portas serial do computador pessoal e comunicar-se com o
protótipo do relé inteligente através do padrão serial RS-232 e, com isto, ser capaz de
programar este equipamento de uma maneira bem mais simples do que a programação local,
pois o PC conta com vários recursos que o equipamento desenvolvido não possui.
programada somente via PC, pois seria muito complicado desenvolver uma interface para esta
programação local utilizando-se apenas das 4 teclas disponíveis no protótipo, além ainda da
dificuldade que seria de se entrar os dados corretamente com apenas estas teclas.
75
limitação que não é problema devido ao fato de que a idéia inicial deste trabalho é
A implementação deste software precisou ser feita em paralelo com boa parte
disponíveis no PC ficaria mais fácil conferir e depurar os dados gravados na EEPROM do relé
Contudo, para que a comunicação fosse possível o primeiro grande desafio foi
elaborar um protocolo de comunicação que funcionasse e fosse de certa forma seguro quanto
a perda de dados ou bytes. O protocolo segue a idéia mostrada no fluxograma da Figura 5.1.
conseguissem "falar" a mesma língua, o pacote de comunicação deveria seguir uma regra, esta
Alguns detalhes devem ser levados em conta para que o pacote seja válido, o
byte "Relé" foi previsto para o caso de se desejar plugar o relé digital a uma rede que utilize o
byte deve conter os bits 1, 2, 4 e 5 sempre zerados para que o comando seja válido e o bit 0
informa se o motor está ou não ligado naquele momento ou, dependendo do bit 3, se é para
ligar ou desligar o motor. Maiores detalhes sobre o funcionamento e valores válidos para cada
byte da Tabela 5.1 podem ser vistos nos anexos deste trabalho.
das funções do equipamento. Foi feita uma tela no programa capaz de mostrar todos os bytes
gravados no bloco da EEPROM que se desejava acessar, com isto era possível verificar se os
capaz de gravar e verificar as configurações principais do relé. Com este módulo pronto,
que tudo já estava funcionando. Para finalizar o projeto funcional do software foi
implementada uma tela no programa que possibilita a entrada dos dados da curva de operação
configurações e traz alguns valores padrões, tais como ID do relé a ser comunicado 255, bloco
de memória da EEPROM igual ao bloco 1, corrente nominal do motor igual à 5A entre outros.
trabalho para o monitoramento do relé inteligente, observe que praticamente todos os dados
configuráveis variam de 0 até 255, pois são os valores que cabem em um byte da EEPROM
do PIC. Note também que os blocos da memória EEPROM variam de 1 até 8, conforme já foi
visto anteriormente. Observe que o bloco 1 está relacionado com a configuração do relé, por
78
“1.Configurações” do programa.
A Figura 5.3 já mostra um exemplo de curva que pode ser programada no relé
inteligente utilizando este programa, note ainda que o bloco de memória seja automaticamente
selecionado para o bloco 2, local onde fica armazenada a curva na memória EEPROM do
PIC.
enquanto que na mesma linha na coluna do “Tempo (s)” deve-se programar o tempo máximo
que a corrente citada nesta linha pode ser fornecida ao motor. Assim um ponto é definido no
79
gráfico ao lado desta tabela, a interpolação linear de todos os pontos programados na tabela
resposta do relé é de 16, este valor é suficiente para se montar uma boa curva de resposta se
grupo a unidade dos tempos é de centésimos de segundos e por isto pode varia de 0,00s até
80
2,55s (limite determinado pelo valor máximo de um byte). Já no segundo grupo a unidade dos
tempos é de segundos, logo podem variar de 0s até 255s, somente valores inteiro.
Além das limitações nos preenchimentos dos tempos máximos que cada sobre
corrente pode passar pelo motor antes do relé inteligente desligar há também uma limitação
para os valores das sobre correntes. A sobrecorrente cadastrada na curva de operação não
deve ser maior do que a corrente máxima configurada para o ADC, pois assim o relé não será
capaz de monitorá-la. O software também não permite que se cadastre uma corrente menor do
que a corrente nominal do motor, pois senão o motor mal partiria e já seria desligado.
alterações devido à conversão do valor para um valor inteiro compatível no ADC de 8 bits,
por isto muitas vezes os valores lidos no protótipo não são os mesmos que foram gravados ou
A Figura 5.4 mostra a janela que se abre caso o botão “Definições das
Curvas...” seja pressionado. Nesta janela pode-se selecionar uma curva já gravada no PC para
enviá-la ao equipamento ou salvar a curva que acabou de ser digitada na pasta “2.Curva de
Resposta”. Com esta facilidade consegue-se gerar várias curvas que simulem qualquer relé
comunicação é gerado na pasta “4.Histórico”, conforme pode ser observado na Figura 5.5.
Este histórico pode ser apagado sempre que o usuário desejar e informa se
houve algum erro de comunicação, erro ao gravar a EEPROM interna ou ainda alerta de sobre
corrente. Porém este histórico não foi implementado para ser gerado pelo protótipo do
hardware, mas sim apenas pelo software. Por este motivo o histórico não é descarregado via
atual do protótipo.
foram detectadas pelo equipamento, então para visualizar melhor a descrição dos erros
ocorridos pode-se clicar com o botão direito e selecionar a opção “Visualizar toda
descrição...” sobre a linha que se deseja verificar ou então dar um duplo clique nesta linha. A
Figura 5.6 mostra uma mensagem com toda a descrição para que se possa ler toda a
mensagem, observe que neste exemplo todos os possíveis erros de uma comunicação foram
notar que algumas das configurações são globais, por exemplo, o bloco de memória, a opção
Estes comandos são globais e podem ser enviados ao equipamento juntamente com a opção
a opção “Automático” e configurar a opção de intervalo de acordo com o computador que está
sendo utilizado. Com isto o programa irá ficar comunicando com o relé e levantando um
Outro detalhe que poder ser ressaltado é o fato de o programa utilizar as cores
para chamar a atenção do usuário dependendo do tipo de alerta. Por exemplo, se o motor
estiver ligado a cor azul irá aparecer no escrito “Motor Ligado” se estiver apenas desligado a
cor é um preto, mas caso tenha sido desligado devido a uma sobre corrente a cor é o vermelho
ótimo desempenho, pois ficou pequeno (menor que 1MB) e roda muito bem em qualquer
Time Out estava pequeno demais para máquinas mais lentas – algo em torno de um segundo.
Por este motivo foi necessário aumentar este tempo em até 5 vezes.
RS-485, assim caso resolva-se instalar um conversor de RS-232 para RS-485 na saída da
porta do PC não será necessário realizar nenhum tipo de alteração no software, mas no
protótipo sim já que ele foi montado com o MAX232 ou HIN232. A menos que se instale no
protótipo também um conversor RS-232 para RS-485. Um detalhe é que este conversor
84
deverá possuir o chamado SDC (Send Data Control), um circuito capaz de detectar
trabalho que, além de possuir uma interface amigável, facilita o aprendizado e o manuseio do
equipamento.
a aprovação do projeto como um todo, alguns dos resultados encontrados nos testes podem ser
deste motor obedeçam às curvas programadas pelo software de configuração, o qual foi
da sobre corrente de acordo com uma curva previamente definida, assim o que foi feito nesta
parte do trabalho resumiu-se em apenas configurar algumas curvas e verificar como foi o
permita durante a partida que uma sobre corrente qualquer seja absorvida pelo motor. Graças
a esta programação é que o relé inteligente permite que o motor parta, pois se não houvesse
esta configuração o relé iria desligar o motor logo que o ele fosse ligado, pois a corrente de
segundo até 255 segundos, que é o limite de um byte. Esta faixa de valores permite atender à
todos os motores de indução, pois dificilmente um motor levará mais do que 10 segundos para
laboratório durante sua partida sem carga, note que o tempo de partida nesta condição ficou
O mesmo motor da Figura 6.1 leva agora cerca de 300 ms para partir com
carga nominal. É importante notar que o tempo de partida depende também da condição de
carga de partida e por isto deve-se levar em conta a carga de partida para se programar o
funcionamento não estava correto, então foi necessário realizar algumas alterações no
bastou colocar uma condição que ignorava a sobre corrente se o tempo de partida ainda não
tivesse se esgotado.
verificar como o relé se comportava durante o seu funcionamento normal, isto é, deixou-se o
motor funcionando com sua corrente nominal por uma hora. Este teste visou verificar se o relé
conseguiria monitorar a corrente e manter o motor ligado até que recebesse um comando para
desligá-lo. Para tanto foi necessário mantê-lo a uma corrente de até 15% da corrente nominal,
porque a curva programada no relé somente iniciava o desligamento do motor a partir deste
valor.
corrente do motor ficasse abaixo da curva programada, assim o equipamento foi validado por
ter conseguido ligar e desligar o motor através de um comando remoto, via PC, ou um
funcionamento do motor a vazio e seu funcionamento com carga nominal. Este momento foi
utilizado várias vezes para confirmação do funcionamento do relé digital. No primeiro ensaio
buscava-se verificar se o relé funcinaria corretamente durante uma transição brusca do valor
diferentes correntes como sendo uma sobre corrente que deveria ser desligada em um
determinado tempo.
89
Para facilitar os testes foi programado no relé que a sua corrente nominal era a
da sua operação a vazio e a sua corrente nominal como sendo a primeira sobrecorrente que
deveria o relé deveria desligar com tempo de programação de 5 segundos. Agora a Figura 6.3
passou a ser “entendida” pelo relé inteligente como momento de transição de sua operação
passava os tempos programados para esta sobre corrente, vários tempos diferentes foram
experimentados.
uma maneira simulada porque existe no laboratório meios para monitorar tempos abaixo de 1
segundo com precisão. Novamente para realizar os testes no laboratório foram feitas algumas
partida de 2 s, uma corrente igual á corrente à vazio da máquina como sendo uma sobre
corrente que deve ser cortada em 3 s e então foi verificado que 5 s após ter se ligado o motor o
Com estes testes notou-se que o relé inteligente respeitou o tempo de partida e
passou a verificar as sobre correntes somente após este tempo ter se passado, assim o
equipamento atendeu a uma das suas principais características: monitorar a sobre corrente
monitoramento das correntes. Como o foco deste trabalho esteve sempre voltado ao
desenvolvimento do relé digital o sensor a ser empregado poderia ser qualquer um, pois o relé
foi projetado para se adaptar ao sensor como poderá ver observado a seguir no item que se
foi programado para ser totalmente configurável pelo usuário em uma função de transferência
linear qualquer. Assim o equipamento tornou-se extremamente aberto e pronto para atender a
todos os casos.
retificada que representasse uma corrente equivalente a que estava passando pelo motor
naquele instante. Esta corrente pôde ser monitorada pelo PC remoto sem maiores problemas.
arredondamentos dos cálculos envolvidos bem como o fato do conversor analógico digital
utilizado ter sido de apenas 8 bits, apesar de o PIC possuir capacidade para um conversor de
até 10 bits. Este erro não representou um problema porque ele era inferior a 1,0% do fundo de
O erro citado acima não foi significativo para o controle da sobre corrente do
diversos motores com diversas amplitudes de correntes, um problema foi gerado por se dar
91
esta solução de medição. O problema que surge é que um circuito de retificação com precisão
e um circuito de proteção para garantir que a tensão de entrada na porta do canal do ADC do
Outro problema, mas não muito crítico é que o tempo de resposta do relé
inteligente agora está limitado ao tempo de resposta da tensão retificada que indica o valor da
corrente medida. Como esta tensão teve que ser retificada, um capacitor foi colocado no
elevada for utilizado haverá a vantagem de se conseguir mais estabilidade no valor medido da
corrente, mas em contrapartida o tempo de resposta do relé inteligente será menor porque a
foi desenvolvido para executar respostas a partir de 1 centésimo de segundo. Como o período
forma de onda da corrente elétrica medida antes de se tomar uma decisão, o que é bastante
momento mesmo com o motor ligado, graças a esta facilidade este protótipo poderá atender a
indução sem que se precise trocar a proteção, mas sim apenas a sua programação.
92
para verificar se o protótipo era capaz de desligar o motor caso o tempo de sobre corrente
medido por ele fosse maior que o tempo nele configurado, porém todas as situações testadas
aqui foram simulações e não o funcionamento real em campo, mas foi suficiente para validar
o relé inteligente.
curva da Figura 6.4. Observe que para correntes acima de 10A, o que representa 200% da
corrente nominal, foi programado para o relé inteligente desligar em 3 segundos. Os valores
de corrente acima de 200% praticamente têm os tempos de resposta próximos, pois não há
como abaixar muito mais do que 0,5s o tempo de resposta devido ao que foi citado
anteriormente.
pois ele conseguiu desligar o equipamento com precisão para todos os tempos pedidos acima
de 1 segundo. Para tempos abaixo deste valor já não foi possível avaliá-lo, pois´era
Pode-se dizer que o relé inteligente desenvolvido neste trabalho pode ser capaz
de simular as diversas curvas dos relés bimetálicos existentes no mercado atual sem maiores
problemas, no capítulo seguinte será feita uma análise destes resultados e propostos alguns
Pode-se notar que este trabalho abrange diversas áreas da engenharia elétrica,
das quais vale citar: eletrônica básica; eletrônica de potência; eletrônica digital; máquinas
máquinas elétricas, mas como o relé inteligente não está preocupado em controlar a partida do
motor e muito menos com o controle da velocidade da máquina, acabou-se investindo mais
elétrico.
engenharia elétrica, ele também possibilitou unir as diversas áreas citadas acima. Fato este
engenharia pode e deve ser mais explorada em seus cursos, pois se não fosse por esta
7.1 Conclusões
mercado pouco explorado pela indústria brasileira. Este nicho precisaria receber mais atenção
envolvido, não ficou muito alto comparado com o que existe no mercado para a proteção de
motores contra a sobre corrente. Este seria outro fator que poderia atrair a atenção de alguns
95
nacional.
neste protótipo seria o fato de que não existem muitos equipamentos nacionais com as
ótimo controle de partida para os motores de indução, isto pode ser feito utilizando o próprio
PIC deste trabalho sem que seja necessário realizar grandes mudanças no hardware ou
firmware.
Pode-se ainda utilizar os outros 8 pinos de I/O que sobraram para controlar
vários motores em paralelo, visto que este microcontrolador trabalha em 200ns de ciclo de
instrução e o seu ADC interno consegue realizar uma conversão em menos de 100µs. Para
tanto bastaria incluir um circuito integrado multiplexador na entrada dos pinos do ADC, por
canais analógicos e ainda sobrariam 7 pinos, dos quais apenas um seria utilizado para acionar
um outro motor.
Outra sugestão seria reduzir o custo deste trabalho retirando o display de cristal
líquido, pois a interface com o PC é muito mais simples e pode ser utilizada em seu lugar,
96
assim constrói-se um equipamento mais barato (menos da metade do preço de um com LCD)
Diversos trabalhos podem ser originados a partir deste estudo, cada variação na
aplicação ou novidade geraria um trabalho novo, utilizar uma rede CAN ou Ethernet (TCP/IP)
no lugar da serial, uma rede USB ou ainda uma conexão bluetooth para manter o equipamento
Referências Bibliográficas
[1] Kosow, Irving I. – Máquinas Elétricas e Transformadores. 2ª. Edição, 1979. Editora
[3] Guia EM da NBR 5410. Capítulo 5 – Proteção contra sobre correntes e Capítulo 7 –
[4] Millman, Jacob e Halkias, Christos C. Eletrônica – Volume 1. 2ª. Edição, 1981. Editora
[5] Millman, Jacob e Halkias, Christos C. Eletrônica – Volume 2. 2ª. Edição, 1981. Editora
[6] Tocci, Ronald J. e Widmer, Neal S. Sistemas Digitais – Princípios e Aplicações. 8ª.
[7] Hayt Jr., William H. e Kemmerly, Jack E. Análise de Circuitos em Engenharia. 1ª.
[8] Gimenez, Salvador R. – Microcontroladores 8051. 1ª. Edição, 2002. Editora Pearson
[9] Silva Júnior, Vidal Pereira da – Aplicações Práticas do Microcontrolador 8051. 5ª.
[16] ARTIGO: Fernandes, José Manuel e Paula, Leonardo Costa – On-line Control Systems
maintenance testing of multifuncition digital relays. Plup and Paper Industry Technical
Conference, 2004.
Bibliográficas recomendadas
[19] Toro, Vincent Del – Fundamentos de Máquinas Elétricas, LTC Livros Técnicos e
Edição, 1994. Editora LTC – Livros Técnicos e Científicos. Rio de Janeiro, RJ.
;************************************************************************************************
; PROJETO DE UM RELÉ INTELIGENTE
; CARACTERÍSTICAS:
; ESTE PROTÓTIPO POSSUI UM DISPLAY LCD 16x2, 4 BOTÕES PARA UMA PROGRAMAÇÃO LOCAL, 3 ENTRADAS
; ANALÓGICAS PARA LEITURA DAS CORRENTES DE UM MOTOR DE INDUÇÃO TRIFÁSICO, 1 SAÍDA TTL PARA
; LIGAR OU DESLIGAR O MESMO MOTOR, 1 PORTA SERIAL RS232 PARA PROGRAMAÇÃO REMOTA.
; ELABORADO POR:
; ENG. LEONARDO COSTA DE PAULA
; ORIENTADO POR:
; DR. DARIZON ALVES DE ANDRADE - UFU
; INICIADO EM: 29/07/03
; Arquivo: Main.asm
;************************************************************************************************
PROCESSOR 16F876A
; RADIX HEX
#INCLUDE <P16F876A.INC>
#INCLUDE <D:\PROJETOS\PIC\UTILS\MACROS.INC>
#INCLUDE <MAIN.INC>
ORG 0X00
; GOTO R_INICIO_TST
GOTO R_INICIO
;================================================================================================
; Tratamento das Interrupções
;================================================================================================
ORG 0X04
GOTO R_INTERRUPCOES
;================================================================================================
; ATENÇÃO!!! ÁREA RESERVADA PARA AS MENSAGENS (POIS O ENDEREÇO MÁXIMO É 255!!!)
MSG_INICIO
RETLW D'5' ; TAMANHO DA MENSAGEM
RETLW 'R'
RETLW 'E'
RETLW 'L'
RETLW 'E'
RETLW ' '
MSG_MOTOR
RETLW D'6'
RETLW 'L'
RETLW 'I'
RETLW 'G'
RETLW 'A'
RETLW 'R'
RETLW '?'
MSG_CONFIRMA
RETLW D'15' ; TAMANHO DA MENSAGEM
RETLW 'O'
RETLW 'K'
RETLW ' '
RETLW 'P'
RETLW '/'
RETLW ' '
RETLW 'C'
RETLW 'O'
RETLW 'N'
RETLW 'F'
RETLW 'I'
RETLW 'R'
RETLW 'M'
RETLW 'A'
101
RETLW 'R'
MSG_ID
RETLW D'7' ; TAMANHO DA MENSAGEM
RETLW 'R'
RETLW 'E'
RETLW 'L'
RETLW 'E'
RETLW ' '
RETLW 'I'
RETLW 'D'
MSG_DELTA
RETLW D'9' ; TAMANHO DA MENSAGEM
RETLW 'A'
RETLW 'M'
RETLW 'P'
RETLW 'L'
RETLW 'I'
RETLW 'T'
RETLW 'U'
RETLW 'D'
RETLW 'E'
MSG_MENOR
RETLW D'8' ; TAMANHO DA MENSAGEM
RETLW 'I'
RETLW ' '
RETLW 'M'
RETLW 'I'
RETLW 'N'
RETLW 'I'
RETLW 'M'
RETLW 'O'
MSG_NOMINAL
RETLW D'9' ; TAMANHO DA MENSAGEM
RETLW 'I'
RETLW ' '
RETLW 'N'
RETLW 'O'
RETLW 'M'
RETLW 'I'
RETLW 'N'
RETLW 'A'
RETLW 'L'
MSG_PARTIDA
RETLW D'7' ; TAMANHO DA MENSAGEM
RETLW 'P'
RETLW 'A'
RETLW 'R'
RETLW 'T'
RETLW 'I'
RETLW 'D'
RETLW 'A'
MSG_UNIDADE
RETLW D'14' ; TAMANHO DA MENSAGEM
RETLW 'T'
RETLW 'E'
RETLW 'M'
RETLW 'P'
RETLW 'O'
RETLW ' '
RETLW '1'
RETLW '='
RETLW 'c'
RETLW 's'
RETLW '/'
RETLW '2'
RETLW '='
RETLW 's'
MSG_I_UNIDADE
RETLW D'12' ; TAMANHO DA MENSAGEM
RETLW 'I'
RETLW ' '
RETLW 'x'
RETLW ' '
RETLW '1'
RETLW '/'
RETLW '1'
102
RETLW '0'
RETLW '/'
RETLW '1'
RETLW '0'
RETLW '0'
;================================================================================================
; AS INTERRUPÇÕES VIERAM PARA CÁ PARA SOBRAR MAIS ESPAÇO PARA AS MENSAGENS (STACK 1)
R_INTERRUPCOES
MOVWF V_W_TEMP ; Salva W e STATUS
MOVF STATUS, W
MOVWF V_S_TEMP
MOVF FSR, W
MOVWF V_FSR_TEMP
CLRF STATUS ; VAI PARA O BANK 0
INT_SER
GOTO R_SERIAL_RX ; DENTRO DESTA ROTINA HÁ UM "GOTO INT_FIM"
INT_TMR2
GOTO R_TIMER2 ; DENTRO DESTA ROTINA HÁ UM "GOTO INT_FIM"
INT_FIM
MOVF V_FSR_TEMP, W
MOVWF FSR
MOVF V_S_TEMP, W
MOVWF STATUS
SWAPF V_W_TEMP, F
SWAPF V_W_TEMP, W ; RECUPERA W SEM ALTERAR O STATUS (MOVF ALTERA O STATUS!)
RETFIE
;================================================================================================
; ROTINA UTILIZADA PARA TESTES GERAIS DO PIC (DEBUG)
R_INICIO_TST
CLRF STATUS
MOVLW K_PORTA
MOVWF PORTA
MOVLW K_PORTB
MOVWF PORTB
MOVLW K_PORTC
MOVWF PORTC
; MOVLW K_INTCON
; MOVWF INTCON
; MOVLW K_ADCON0
; MOVWF ADCON0
; MOVLW K_T2CON ; BANK 0
; MOVWF T2CON
CLRF STATUS
R_TST_LOOP
MOVLW 0X00
BTFSC PORTB, 7
GOTO R_TST_SET
CLRF PORTB
GOTO R_TST_LOOP
R_TST_SET
MOVLW 0XFF
MOVWF PORTB
GOTO R_TST_LOOP
;================================================================================================
103
; ROTINAS GERAIS PARA ACESSO AOS PERIFÉRICOS OU ROTINAS MATEMÁTICAS
;================================================================================================
;------------------------------------------------------------------------------------------------
; ROTINA QUE MULTIPLICA UM BYTE POR OUTRO
; ENTRADA: V_NUM1 E V_NUM2 = BYTES A SEREM MULTIPLICADOS
; SAÍDA: V_NUM4,V_NUM3 = WORD RESPOSTA (V_NUM4 É O MAIS SIGNIFICATIVO)
; AFETA: W; STATUS; V_NUM1; V_NUM2; V_NUM3; V_NUM4; V_NUM5; V_NUM6
; CHAMA: NADA (STACK: 1)
;------------------------------------------------------------------------------------------------
R_MUL8
CLRF V_NUM3
CLRF V_NUM4
CLRF V_NUM5 ; INICIA VARIÁVEIS LOCAIS
MOVLW 0X08
MOVWF V_NUM6 ; INICIA CONTADOR
R_MUL_LOOP
RRF V_NUM1, F
BTFSS STATUS, C
GOTO R_MUL_PULA ; COMO ERA UM BIT ZERO, NÃO PRECISA SOMAR!
MOVF V_NUM2, W
ADDWF V_NUM3, F ; SOMA PARTE BAIXA
BTFSS STATUS, C
GOTO R_MUL_CONT ; NÃO PRECISOU AJUSTAR PARTE ALTA
INCF V_NUM4, F
R_MUL_CONT
MOVF V_NUM5, W
ADDWF V_NUM4, F ; SOMA PARTE ALTA
R_MUL_PULA
RLF V_NUM2, F ; SEMPRE CHEGA AQUI COM C = 0!
RLF V_NUM5, F ; MULTIPLICA POR 2 (PREPARA PARA TESTAR PRÓXIMO
BIT!)
DECFSZ V_NUM6
GOTO R_MUL_LOOP ; ATÉ PASSAR POR TODOS OS BITS
RETURN
;------------------------------------------------------------------------------------------------
; ROTINA QUE DIVIDE UMA WORD POR UM BYTE
; ENTRADA: V_NUM,V_NUM1 = DIVIDENDO; V_NUM2 = DIVISOR
; SAÍDA: V_NUM5,V_NUM4 = QUOCIENTE; V_NUM3 = RESTO
; AFETA: W; STATUS; V_NUM; V_NUM1; V_NUM3; V_NUM4; V_NUM5; V_NUM6
; CHAMA: NADA (STACK: 1)
;------------------------------------------------------------------------------------------------
R_DIV8
CLRF V_NUM3
CLRF V_NUM4
CLRF V_NUM5 ; INICIA VARIÁVEIS LOCAIS
MOVLW 0X10
MOVWF V_NUM6 ; INICIA CONTADOR
R_DIV_LOOP
RLF V_NUM1, F
RLF V_NUM, F
RLF V_NUM3, F ; V_NUM3 <- BIT MAIS SIGNIFICATIVO
BTFSC STATUS, C
GOTO R_DIV_CY ; SE DEU CARRY, SUBTRAI E GRAVA RESTO!
MOVF V_NUM2, W
SUBWF V_NUM3, W
BTFSS STATUS, C
GOTO R_DIV_NEG ; RESULTADO DA SUBTRAÇÃO FOI NEGATIVO!
GOTO R_DIV_POS
R_DIV_CY
MOVF V_NUM2, W
SUBWF V_NUM3, W
BSF STATUS, C ; GARANTE INCREMENTO DO QUOCIENTE
R_DIV_POS
MOVWF V_NUM3 ; GUARDA RESULTADO, POIS A SUBTRAÇÃO FOI POSITIVA
R_DIV_NEG
RLF V_NUM4 ; AJUSTA O QUOCIENTE
RLF V_NUM5 ; AJUSTA O QUOCIENTE
DECFSZ V_NUM6
GOTO R_DIV_LOOP ; ATÉ PASSAR POR TODOS OS BITS
RETURN
104
;------------------------------------------------------------------------------------------------
; ROTINA QUE CONVERTE UM NUMERO DE BINÁRIO PARA BCD
; ENTRADA: W = NÚMERO EM BINÁRIO DE 0 ATÉ 99
; SAÍDA: W = NÚMERO EM BCD
; AFETA: W; STATUS; V_NUM; V_NUM1; V_NUM2; *V_NUM3; *V_NUM4; *V_NUM5; *V_NUM6
; CHAMA: R_DIV8 (STACK: 2)
;------------------------------------------------------------------------------------------------
R_BIN_TO_BCD
MOVWF V_NUM1
CLRF V_NUM ; PARTE ALTA DA WORD É NULA
M_MOVLF V_NUM2, D'10'
CALL R_DIV8
SWAPF V_NUM4, W
IORWF V_NUM3, W
RETURN
;------------------------------------------------------------------------------------------------
; ROTINA QUE CONVERTE UM NUMERO BCD PARA BINÁRIO
; ENTRADA: W = NÚMERO EM BCD
; SAÍDA: W = NÚMERO EM BINÁRIO
; AFETA: W; STATUS; V_NUM1; V_NUM2; V_NUM3
; CHAMA: NADA (STACK: 1)
;------------------------------------------------------------------------------------------------
R_BCD_TO_BIN
MOVWF V_NUM1 ; SALVA BYTE A SER CONVERTIDO
ANDLW 0X0F
MOVWF V_NUM3 ; SALVA PARTE BAIXA DO BCD
SWAPF V_NUM1, W
ANDLW 0X0F
MOVWF V_NUM1 ; SALVA PARTE ALTA DO BCD
BCF STATUS, C
RLF V_NUM1, F ; MULTIPLICA PARTE ALTA POR 2
RLF V_NUM1, W ; MULTIPLICA PARTE ALTA POR 4 E COLOCA EM W
MOVWF V_NUM2
RLF V_NUM2, W ; MULTIPLICA A PARTE ALTA POR 8 E COLOCA EM W
ADDWF V_NUM1, W ; SOMA PARTE ALTA X 8 COM PARTE ALTA X 2 = PARTE ALTA X (8 + 2)
ADDWF V_NUM3, W ; W = 10x(PARTE ALTA) + PARTE BAIXA = BINÁRIO DO BCD
RETURN
;------------------------------------------------------------------------------------------------
; ROTINA QUE LÊ VALOR DO ADC
; ENTRADA: W = CANAL SELECIONADO (0..4)
; SAÍDA: W = ADRESH = BYTE COM OS 8 BITS MAIS SIGNIFICATIVO DO VALOR CONVERTIDO
; AFETA: ADRESH; ADRESL; V_W_AUX; W
; CHAMA: NADA
;------------------------------------------------------------------------------------------------
R_ADC_READ
MOVWF V_W_AUX
MOVLW B'11000111'
ANDWF ADCON0, F ; ZERA O CANAL
RLF V_W_AUX, F
RLF V_W_AUX, F
RLF V_W_AUX, F ; POSICIONA O BIT ZERO NA TERCEIRA POSIÇÃO!
MOVF V_W_AUX, W
IORWF ADCON0, F ; SELECIONA O CANAL A SER LIDO
MOVLW 0X01
CALL R_DELAY ; PEQUENO ATRASO PARA ESTABILIZAR O SINAL DO NOVO CANAL
MOVF ADRESH, W
;------------------------------------------------------------------------------------------------
; ROTINA QUE LÊ A EEPROM INTERNA
105
; ENTRADA: EEADR = ENDEREÇO A SER LIDO
; SAÍDA: W = BYTE LIDO
; AFETA: W; STATUS; EECON1; EEDATA; EEADR
; CHAMA: NADA (STACK: 1)
;------------------------------------------------------------------------------------------------
R_EE_READ
BSF STATUS, RP0
BSF STATUS, RP1 ; APONTA PARA VARIÁVEIS NO BANK 3
;------------------------------------------------------------------------------------------------
; ROTINA QUE ESCREVE NA EEPROM INTERNA E VERIFICA SE A ESCRITA FOI CORRETA
; ENTRADA: EEADR = ENDEREÇO A SER ESCRITO, EEDATA = BYTE A SER ESCRITO
; SAÍDA: Z = 0 SE OK
; AFETA: W; STATUS; EECON1; EECON2
; CHAMA: NADA (STACK: 1)
;------------------------------------------------------------------------------------------------
R_EE_WRITE
BSF STATUS, RP0
BSF STATUS, RP1 ; APONTA PARA VARIÁVEIS NO BANK 3
BTFSC EECON1, WR
GOTO $-1 ; ESPERA PELA CONCLUSÃO DA ESCRITA P/
VERIFICAÇÃO
;------------------------------------------------------------------------------------------------
; ROTINA QUE LÊ A MEMÓRIA FLASH INTERNA
; ENTRADA: EEADR, EEADRH = ENDEREÇO A SER LIDO (BANK = 2 SELECIONADO)
; SAÍDA: W = BYTE LIDO = EEDATA (BANK = 2), EEDATH = 6 BITS RESTANTES (BANK = 2)
; AFETA: W; STATUS; EECON1; EEDATA; EEDATH
; CHAMA: NADA (STACK 1)
;------------------------------------------------------------------------------------------------
R_FLASH_READ
BSF STATUS, RP0 ; MUDA O BANCO 3
RETURN
;------------------------------------------------------------------------------------------------
; ROTINA LIGA O MOTOR E PREPARA VARIÁVEIS
; ENTRADA: NENHUMA
; SAÍDAS: V_FAIXA; V_PARTIDA; V_SER_FLAG SÃO ATUALIZADOS
106
; AFETA: W; STATUS
; CHAMA: R_EE_READ (STACK: 2)
;------------------------------------------------------------------------------------------------
R_LIGA_MOTOR
BTFSC P_MOTOR
GOTO R_L_MOTOR_FIM ; IGNORA COMANDO PORQUE O MOTOR JÁ ESTÁ LIGADO!
CLRF V_SER_FLAG ; DESLIGA O ALARME ATUAL
M_EE_READ E_PARTIDA
MOVWF V_PARTIDA ; INICIA CONTADOR DO TEMPO DE PARTIDA
M_EE_READ E_UNIDADE
MOVWF V_FAIXA ; PEGA A UNIDADE DA PARTIDA
BSF P_MOTOR
R_L_MOTOR_FIM
RETURN
;------------------------------------------------------------------------------------------------
; ROTINA QUE TRATA A INTERRUPÇÃO DO TIMER2
; ENTRADA: V_1MS; V_10MS; V_SEG; V_MIN; V_HOR; V_DIA; V_SEM
; SAÍDAS: V_1MS; V_10MS; V_SEG; V_MIN; V_HOR; V_DIA; V_SEM SÃO ATUALIZADAS
; AFETA: W; STATUS; V_1MS; V_10MS; V_SEG; V_MIN; V_HOR; V_DIA; V_SEM
; CHAMA: NADA (STACK: 1)
;------------------------------------------------------------------------------------------------
R_TIMER2
BCF PIR1, TMR2IF ; PREPARA PARA NOVA INTERRUPÇÃO
INCF V_MS, F
MOVLW D'10'
XORWF V_MS, W ; VERIFICA SE JÁ CHEGOU
M_JNZ R_TMR2_OK ; AINDA NÃO CHEGOU EM ZERO
CLRF V_MS
R_TRM2_CS
BTFSC B_1CS ; TESTA SE DEVE INCREMENTAR CONTADOR DE SOBRECORRENTE
BSF B_INC_TEMP ; PREPARA FLAG QUE AVISA PARA INCREMENTAR O
TEMPO E TESTAR
INCF V_CS, F
MOVLW D'100'
XORWF V_CS, W ; VERIFICA SE JÁ CHEGOU
M_JNZ R_TMR2_OK
CLRF V_CS
MOVF V_TEC_TEMPO, F
BTFSS STATUS, Z ; CASO JÁ ESTEJA EM ZERO, IGNORE PRÓXIMO COMANDO
DECF V_TEC_TEMPO, F
R_TRM2_TEC_OK
MOVF V_PARTIDA, F ; VERIFICA SE O TEMPO DE PARTIDA É ZERO
M_JZ R_TRM2_S
BTFSC B_1S_P ; TESTA SE DEVE DECREMENTAR A PARTIDA
DECF V_PARTIDA, F
R_TRM2_S
BTFSC B_1S ; TESTA SE DEVE INCREMENTAR CONTADOR DE SOBRECORRENTE
BSF B_INC_TEMP ; PREPARA FLAG QUE AVISA PARA INCREMENTAR O
TEMPO E TESTA
INCF V_SEG, F
MOVLW D'60'
XORWF V_SEG, W ; VERIFICA SE JÁ CHEGOU
M_JNZ R_TMR2_OK
CLRF V_SEG
R_TMR2_OK
MOVF V_PARTIDA, F ; VERIFICA SE O TEMPO DE PARTIDA ACABOU
M_JZ R_TMR2_FIM ; SAI IGNORANDO A CONTAGEM DE TEMPO
R_TMR2_CONT
BTFSS P_MOTOR ; VERIFICA SE O MOTOR ESTÁ LIGADO
GOTO R_TMR2_FIM ; SAI SE ELE ESTIVER DESLIGADO
BTFSS B_INC_TEMP
GOTO R_TMR2_FIM
BCF B_INC_TEMP ; LIMPA ESTE FLAG
INCF V_TEMPO
MOVF V_TEMPO_MAX, W
SUBWF V_TEMPO, W ; FAZ W = V_TEMPO - W
BTFSS STATUS, C
GOTO R_TMR2_FIM ; ENQUANTO NÃO ESTOURAR O TEMPO TUDO BEM!
M_MOTOR 0 ; DESLIGA O MOTOR (DEVE ESTAR NO BANK 0
OU 2)
BCF B_M_ALERTA ; FLAG PARA AVISAR AO PC DO PROBLEMA
BSF B_M_SOBRE ; FLAG PARA AVISAR AO PC DO PROBLEMA
R_TMR2_FIM
GOTO INT_FIM ; FINALIZA INTERRUPÇÃO
;------------------------------------------------------------------------------------------------
; ROTINA QUE ENVIA UM DADO PELA SERIAL
; ENTRADA: W = BYTE COM O DADO A SER ENVIADO
; SAÍDAS: NENHUMA
; AFETA: TXREG; STATUS;
; CHAMA: NADA (STACK: 1)
;------------------------------------------------------------------------------------------------
R_SERIAL_TX
BTFSS PIR1, TXIF
GOTO $-1 ; TESTA SE O TXREG ESTÁ VAZIO
MOVWF TXREG
RETURN
;------------------------------------------------------------------------------------------------
; ROTINA QUE RECEBE UM DADO PELA SERIAL
; ENTRADA: NENHUMA
; SAÍDAS: [V_SER_PTR] = W = BYTE RECEBIDO OU ERRO; V_SER_OK = SER_COUNT
; AFETA: W; STATUS; FSR; V_SER_PTR; V_SER_OK
; CHAMA: NADA (STACK: 1)
;------------------------------------------------------------------------------------------------
R_SERIAL_RX
BSF STATUS, IRP ; PONTEIRO APONTANDO PARA BANK 2 OU BANK 3
R_SER_RX_PTR
M_MOVLF FSR, SER_INFO
BSF B_ERRO_OVER ; GRAVA O ERRO DE ESTOURO! (PRIMEIRO ERRO
POSSÍVEL!)
R_SER_RX_END
CLRF STATUS
GOTO INT_FIM ; FINALIZA INTERRUPÇÃO
;------------------------------------------------------------------------------------------------
; ROTINA QUE TRATA OS BYTES RECEBIDOS PELA SERIAL
; ENTRADA: NENHUMA
; SAÍDAS: NENHUMA
; AFETA: W; STATUS; FSR; V_SER_PTR; V_SER_OK; *EEADR; *EEADRH; EEDATA
; CHAMA: R_LIGA_MOTOR (2); R_EE_READ; R_EE_WRITE; R_ATUALIZA_EEPROM (STACK: 3)
;------------------------------------------------------------------------------------------------
R_SERIAL
CLRF STATUS ; GARANTE BANK 0
BSF STATUS, IRP ; PONTEIRO PARA O BANK 2 E BANK 3
BSF STATUS, RP1 ; PREPARA PARA LER DADOS DO BANK 2
MOVF V_SER_OK, F
M_JZ R_SER_END
DECFSZ V_SER_OK
GOTO R_SER_END
MOVF V_SER_PTR, W
XORLW SER_END
M_JZ R_SER_TIMEOUT_OK ; TESTA SE OCORREU UMA QUEBRA NA COMUNICAÇÃO (BREAK)
BSF B_ERRO_BREAK ; ESCREVE QUE OCORREU UM ERRO DE QUEBRA DE
COMUNICAÇÃO
R_SER_TIMEOUT_OK
; HÁ DADOS A SEREM TRATADOS PELA SERIAL
MOVLW SER_SIZE
XORWF SER_TAM, W ; TESTA SE O TAMANHO DO PACOTE ESTÁ OK
M_JZ R_SER_TST_OK
BSF B_ERRO_TAM ; ESCREVE QUE OCORREU UM ERRO DE COMANDO
INVÁLIDO
R_SER_TST_OK
MOVLW SER_CMD_TST
ANDWF SER_CMD, W ; FILTRA BITS PARA TESTAR SE O COMANDO É VÁLIDO
M_JZ R_SER_COM_OK
BSF B_ERRO_CMD ; ESCREVE QUE OCORREU UM ERRO DE COMANDO
INVÁLIDO
R_SER_COM_OK
; VERIFICA ID
BSF B_ID_OK ; ACREDITA QUE O PC ESTEJA FALANDO COM ELE (ID
OK!)
M_MOVLF FSR, SER_ID ; APONTA PARA O BYTE DA IDENTIFICAÇÃO
M_EE_READ E_ID
XORWF INDF, W
BTFSS STATUS, Z
BCF B_ID_OK ; SE DIFERENTES ENTÃO ID NOK!
; SE CHEGOU AQUI É PORQUE DEVE ATENDER AO COMANDO, PACOTE SERIAL ESTÁ OK!
BTFSS B_ID_OK
GOTO R_SER_RESP ; SE DIFERENTES ENTÃO NÃO TRATA DADOS
R_SER_EE_WRITE
MOVF INDF, W
MOVWF EEDATA
CALL R_EE_WRITE
M_JNZ R_SER_EE_NOK ; SALTA SE HOUVE ERRO DE ESCRITA NA EEPROM!
R_SER_EE_CONT
BCF STATUS, RP0
BSF STATUS, RP1 ; APONTA PARA VARIÁVEIS DO BANK 2
INCF EEADR, F
INCF FSR, F ; INCREMENTA OS PONTEIROS E CONTINUA A CÓPIA
R_SER_EE_OK
BTFSS B_EE_WR ; TESTA SE FOI UMA LEITURA OU ESCRITA
GOTO R_SER_EE_FIM ; SALTA SE É PARA FAZER UMA ESCRITA
R_SER_EE_NOK
M_MOVLF FSR, SER_INFO ; APONTA PARA O BYTE DE INFORMAÇÃO
BSF B_ERRO_EEPROM ; ESCREVE QUE OCORREU UM ERRO ESCRITA NA EEPROM
R_SER_EE_FIM
BCF STATUS, RP0
BCF STATUS, RP1 ; GARANTE O BANK 0
BTFSS B_MOTOR_SET
GOTO R_SER_MOTOR_READ ; SALTA POIS NÃO DESEJA LIGAR / DESLIGAR O MOTOR
BTFSS B_MOTOR_ON
GOTO R_SER_MOTOR_OFF
M_MOTOR 1 ; LIGA O MOTOR (DEVE ESTAR NO BANK 0 OU 2)
GOTO R_SER_MOTOR_READ
R_SER_MOTOR_OFF
M_MOTOR 0 ; DESLIGA O MOTOR (DEVE ESTAR NO BANK 0 OU 2)
R_SER_MOTOR_READ
BCF B_MOTOR_ON ; CONSIDERA INICIALMENTE A CONDIÇÃO DE
MOTOR DESLIGADO
BTFSS P_MOTOR
GOTO R_SER_MOTOR_OK ; RETORNA INDICANDO QUE O MOTOR ESTÁ DESLIGADO
BSF B_MOTOR_ON ; RETORNA INDICANDO QUE O MOTOR ESTÁ
LIGADO
110
R_SER_MOTOR_OK
; INICIA VERIFICAÇÃO DO HORÁRIO
M_MOVLF FSR, SER_TIME ; APONTA PARA O PRIMEIRO BYTE DO HORÁRIO NO BUFFER SERIAL
BTFSS B_TIME_WR ; SE FOR PARA ATUALIZAR SALTA O GOTO
GOTO R_SER_TIME_READ ; SE FOR PARA APENAS LER O HORÁRIO SALTA
; O PIC DEVE ATUALIZAR SEU HORÁRIO INTERNO
BCF STATUS, RP1 ; APONTA PARA VARIÁVEIS NO BANK 0
CLRF V_MS
CLRF V_CS
MOVF INDF, W
INCF FSR, F
MOVWF V_SEG
MOVF INDF, W
INCF FSR, F
MOVWF V_MIN
MOVF INDF, W
INCF FSR, F
MOVWF V_HOR ; ATUALIZA HORÁRIO DO PIC
GOTO R_SER_RESP
R_SER_TIME_READ
; O PIC DEVE ENVIAR SEU HORÁRIO INTERNO
BCF STATUS, RP1 ; APONTA PARA VARIÁVEIS NO BANK 0
MOVF V_SEG, W
MOVWF INDF
INCF FSR, F
MOVF V_MIN, W
MOVWF INDF
INCF FSR, F
MOVF V_HOR, W
MOVWF INDF
INCF FSR, F ; CARREGA HORÁRIO NO BUFFER SERIAL
R_SER_RESP
BCF STATUS, RP0
BCF STATUS, RP1 ; APONTA PARA VARIÁVEIS NO BANK 0
MOVLW SER_INFO
MOVWF FSR
MOVF V_SER_FLAG, W
IORWF INDF, F
CLRF V_SER_OK
M_MOVLF V_SER_PTR, SER_ID ; INICIALIZA VARIÁVEIS DE CONTROLE DA SERIAL
MOVWF FSR ; APONTA PARA O END. INICIAL DO BUFFER
DA SERIAL
R_SER_LOOP
MOVF INDF, W
CLRF INDF
BTFSS B_ID_OK
GOTO R_SER_LOOP_PULA ; SE DIFERENTES ENTÃO NÃO ENVIA DADOS
R_SER_LOOP_PULA
INCF FSR, F
MOVLW SER_END ; TESTA SE JÁ PASSOU DO END. DO CHECK SUM
XORWF FSR, W
M_JNZ R_SER_LOOP ; ENVIA TODOS OS BYTES ZERANDO O BUFFER
R_SER_END
CLRF STATUS ; RETORNA PARA CONDIÇÃO DE TUDO ZERO
RETURN
;------------------------------------------------------------------------------------------------
; ROTINA QUE CARREGA VARIÁVEIS PRINCIPAIS DA EEPROM PARA A MEMÓRIA RAM (ESPELHO)
; ENTRADA: NENHUMA
; SAÍDAS: NENHUMA
; AFETA: W; STATUS; FSR; V_SER_PTR; V_SER_OK; *EEADR; *EEADRH; EEDATA
; CHAMA: R_EE_READ (STACK: 2)
;------------------------------------------------------------------------------------------------
R_ATUALIZA_EEPROM
M_EE_READ E_DELTA
MOVWF V_DELTA
M_EE_READ E_MENOR
MOVWF V_MENOR
RETURN
111
;************************************************************************************************
; Inicio do Programa Principal
;************************************************************************************************
R_INICIO
CLRF STATUS ; GARANTE BANK = 0
R_INI_LOOP1
CLRF INDF
INCFSZ FSR, F
GOTO R_INI_LOOP1 ; LOOP ATÉ ZERAR TODAS AS VARIAVEIS GLOBAIS
R_MAIN
CALL R_MSG_INICIO ; ESCREVE MSG INICIAL NO LCD
; CALL R_LCD_I ; MOSTRA CORRENTE ATUAL NO LCD
; CALL R_TESTA_I ; VERIFICA SE HÁ SOBRECORRENTE
CALL R_TEC_UP
M_JZ R_MAIN ; ESPERA POR UMA TECLA
;DEBUG!!!
GOTO R_MAIN
;FIM DO DEBUG!!!
R_MAIN_MENU
CALL R_MSG_MOTOR
CALL R_TECLA
BTFSC V_TECLA, TEC_OK
GOTO R_MAIN_MENU_OK ; FOI TECLA OK
BTFSS V_TECLA, TEC_MENU
GOTO R_MAIN_FIM ; CASO CONTRÁRIO VOLTA AO LOOP
; TRATA BOTÃO MENU DENTRO DO MENU LIGA / DESLIGA MOTOR
MOVLW E_ID
CALL R_AJUSTA_EEPROM
MOVLW E_DELTA
CALL R_AJUSTA_EEPROM
MOVLW E_MENOR
CALL R_AJUSTA_EEPROM
MOVLW E_NOMINAL
CALL R_AJUSTA_EEPROM
MOVLW E_PARTIDA
CALL R_AJUSTA_EEPROM
MOVLW E_UNIDADE
CALL R_AJUSTA_EEPROM
MOVLW E_I_UNIDADE
CALL R_AJUSTA_EEPROM
CALL R_ATUALIZA_EEPROM
GOTO R_MAIN_FIM ; POR HORA APENAS SAI!
R_MAIN_MENU_OK
; TRATA BOTÃO OK PARA LIGA / DESLIGA MOTOR
BTFSS P_MOTOR ; VERIFICA SE O MOTOR ESTÁ LIGADO
GOTO R_MAIN_MOT_ON ; SALTA PARA LIGAR O MOTOR, POIS ESTÁ DESLIGADO
M_MOTOR 0
GOTO R_MAIN_FIM
R_MAIN_MOT_ON
; O MOTOR ESTÁ DESLIGADO, DEVE LIGÁ-LO
M_MOTOR 1
GOTO R_MAIN_FIM
R_MAIN_OK
; NADA IMPLEMENTADO PARA ESTA OPÇÃO ATÉ AGORA
R_MAIN_FIM
MOVLW LCD_CLR
CALL R_LCD_CMD
M_WAIT D'100' ; ESPERA UM POUCO ANTES DE CONTINUAR
GOTO R_MAIN
;------------------------------------------------------------------------------------------------
; ROTINA QUE CAUSA UM ATRASO DE APROXIMADAMENTE N x 51,2 us
; ENTRADA: W = N ESPERAS
; SAÍDA: NENHUMA
; AFETA: W; STATUS; TMR0
; CHAMA: NADA (STACK: 1)
;------------------------------------------------------------------------------------------------
113
R_DELAY
SUBLW 0XFF
MOVWF TMR0 ; APROXIMADAMENTE W x 256 x 4/Fosc ~= W x 50 us
INCF TMR0, F ; AJUSTE DA SUBTRAÇÃO
RETURN
;------------------------------------------------------------------------------------------------
; ROTINA QUE CAUSA UM ATRASO DE APROXIMADAMENTE N ms
; ENTRADA: W = N ESPERAS
; SAÍDA: NENHUMA
; AFETA: W; STATUS; V_WAIT; TMR0
; CHAMA: NADA (STACK: 1)
;------------------------------------------------------------------------------------------------
R_WAIT
MOVWF V_WAIT ; CARREGA CONTADOR DE TEMPO
R_WIT_LOOP
MOVLW D'20'
CALL R_DELAY ; APROXIMADAMENTE 20 x 256 x 4/Fosc ~= 1000 us
DECFSZ V_WAIT, F
GOTO R_WIT_LOOP ; REPETE ATÉ PASSAR O TEMPO PEDIDO
RETURN
;------------------------------------------------------------------------------------------------
; ROTINA QUE ESPERA POR UMA TECLA POR UM TEMPO MÁXIMO
; ENTRADA: V_TEC_TEMPO = NÚMERO DE SEGUNDOS QUE DEVE ESPERAR PELA TECLA = 7 SEGUNDOS SE ZERO!
; SAÍDA: V_TECLA = TECLA PRECIONADA
; AFETA: W; STATUS; V_TECLA; V_TEC_TEMPO
; CHAMA: R_TEC_UP (4) (STACK: 5)
;------------------------------------------------------------------------------------------------
R_TECLA
MOVF V_TEC_TEMPO, W
BTFSC STATUS, Z ; VERIFICA SE O TEMPO É ZERO
MOVLW D'7' ; SE FOR ZERO ENTÃO COLOCA O DEFAULT VALOR
MOVWF V_TEC_TEMPO
R_TEC_LOOP
MOVF V_TEC_TEMPO, F
M_JZ R_TEC_FIM ; TESTA SE JÁ ESTOUROU TEMPO DE ESPERA DA TECLA
;------------------------------------------------------------------------------------------------
; ROTINA QUE LÊ ÚLTIMA TECLA PRECIONADA (ESPERA SOLTAR A TECLA SE FOR O CASO)
; ENTRADA: NENHUMA
; SAÍDA: V_TECLA = 0 SE NADA; = TECLA PRECIONADA; STATUS, Z = 0
; AFETA: W; STATUS; V_TECLA
; CHAMA: R_SERIAL (3); R_LE_TEC (1) (STACK: 4)
;------------------------------------------------------------------------------------------------
R_TEC_UP
CLRF V_TECLA ; PRIMEIRAMENTE NENHUMA TECLA PRECIONADA
R_TEC_UP_LOOP
CALL R_SERIAL ; VERIFICA A COMUNICAÇÃO SERIAL
R_TEC_UP_FIM
MOVF V_TECLA,F ; APENAS ATUALIZA STATUS DE ACORDO COM A TECLA
RETURN
114
;------------------------------------------------------------------------------------------------
; ROTINA QUE ESPERA POR UMA TECLA POR UM TEMPO MÁXIMO, MAS NÃO ESPERA SOLTAR A TECLA
; ENTRADA: V_TEC_TEMPO = NÚMERO DE SEGUNDOS QUE DEVE ESPERAR PELA TECLA = 7 SEGUNDOS SE ZERO!
; SAÍDA: V_TECLA = TECLA PRECIONADA
; AFETA: W; STATUS; V_TECLA; V_TEC_TEMPO
; CHAMA: R_LE_TEC; R_WAIT (STACK: 2)
;------------------------------------------------------------------------------------------------
R_TECLA_WAIT
MOVF V_TEC_TEMPO, W
BTFSC STATUS, Z ; VERIFICA SE O TEMPO É ZERO
MOVLW D'7' ; SE FOR ZERO ENTÃO COLOCA O DEFAULT VALOR
MOVWF V_TEC_TEMPO
R_TEC_WIT_LOOP
MOVF V_TEC_TEMPO, F
M_JZ R_TEC_WIT_FIM ; TESTA SE JÁ ESTOUROU TEMPO DE ESPERA DA TECLA
M_WAIT D'100'
CALL R_LE_TEC ; RETORNA Z = 0 SE NADA PRECIONADO
M_JZ R_TEC_WIT_LOOP ; SE NADA TECLADO, SAI IMEDIATAMENTE
MOVWF V_TECLA ; SALVA TECLA PRECIONADA
M_WAIT D'50'
R_TEC_WIT_FIM
CLRF V_TEC_TEMPO
MOVF V_TECLA,F ; APENAS ATUALIZA STATUS DE ACORDO COM A TECLA
RETURN
;------------------------------------------------------------------------------------------------
; ROTINA QUE VERIFICA QUAIS AS TECLAS QUE ESTÃO PRESSIONADAS (NÃO ESPERA SOLTAR TECLA)
; ENTRADA: NENHUMA
; SAÍDAS: W = TECLA PRECIONADA ; Z = 0 SE NÃO E Z = 1 SE SIM
; AFETA: W; TRIS_TEC; STATUS; *TMR0; V_WAIT
; CHAMA: R_WAIT (STACK: 1)
;------------------------------------------------------------------------------------------------
R_LE_TEC
BSF STATUS, RP0 ; BANK 1
BCF OPTION_REG, 7 ; HABILITA PULL UP
BCF STATUS, RP0 ; BANK 0
;------------------------------------------------------------------------------------------------
; ROTINA DE INICIALIZAÇÃO DO LCD
; ENTRADA: NENHUMA
; SAÍDAS: NENHUMA
; AFETA: W; STATUS; V_LCD; *V_WAIT
; CHAMA: R_WAIT; LCD_CMD (STACK: 4)
;------------------------------------------------------------------------------------------------
R_LCD_START
M_CHBK 01
MOVLW TRIS_LCD_OUT
ANDWF TRIS_LCD, F ; CONFIGURA BARRAMENTO DE DADOS COMO OUTPUT
M_CHBK 10
BCF P_RS
BCF P_READ ; GARANTE COMANDO DE ESCRITA DE COMANDOS NO MÓDULO DO LCD
; AGORA O LCD ESTÁ PRONTO PARA COMUNICAR-SE VIA 4 BITS DE DADOS (INICIA PROGRAÇÃO DO LCD)
MOVLW LCD_CFG
CALL R_LCD_CMD
MOVLW LCD_OFF
CALL R_LCD_CMD
MOVLW LCD_ON
CALL R_LCD_CMD
MOVLW LCD_CLR
CALL R_LCD_CMD
MOVLW LCD_CUR_R
CALL R_LCD_CMD
MOVLW LCD_CUR_INPUT
CALL R_LCD_CMD
RETURN
;------------------------------------------------------------------------------------------------
; ROTINA QUE LE UM BYTE DO LCD
; ENTRADA: NENHUMA
; SAÍDAS: V_LCD = BYTE LIDO DO LCD
; AFETA: W; STATUS; TRIS_LCD = INPUT; CTRL_LCD; V_LCD
; CHAMA: NADA (STACK: 1)
;------------------------------------------------------------------------------------------------
R_LCD_READ
BSF P_READ ; CONFIGURA COMO LEITURA
M_CHBK 01
MOVLW TRIS_LCD_IN
IORWF TRIS_LCD, F ; CONFIGURA PORT_LCD COMO INPUT
M_CHBK 10
NOP
NOP
NOP ; ESPERA MAIS DE 500ns PARA MONTAR A ONDA
QUADRADA DO ENABLE
RETURN
116
;------------------------------------------------------------------------------------------------
; ROTINA QUE ESCREVE UM BYTE NO LCD
; ENTRADAS: W = BYTE A SER ESCRITO NO LCD
; SAÍDAS: NENHUMA
; AFETA: STATUS; V_LCD; V_W_AUX
; CHAMA: NADA (STACK: 1)
;------------------------------------------------------------------------------------------------
R_LCD_WRITE
MOVWF V_LCD ; SALVA BYTE A SER ESCRITO
BCF P_READ ; CONFIGURA COMO ESCRITA
M_CHBK 01
MOVLW TRIS_LCD_OUT
ANDWF TRIS_LCD, F ; CONFIGURA PORT_LCD COMO OUTPUT
M_CHBK 10
MOVLW K_NDATA
ANDWF PORT_LCD, F ; ESCREVE ZERO NO BARRAMENTO DE DADOS DO LCD
M_CHBK 01
MOVLW TRIS_LCD_IN
IORWF TRIS_LCD, F ; CONFIGURA PORT_LCD COMO INPUT
M_CHBK 10
;------------------------------------------------------------------------------------------------
; ROTINA QUE ESPERA O LCD FICAR DESOCUPADO
; ENTRADA: NENHUMA
; SAÍDAS: NENHUMA
; AFETA: CTRL_LCD; *W; *STATUS; *TRIS_LCD; *V_LCD
; CHAMA: R_LCD_READ (STACK: 2)
;------------------------------------------------------------------------------------------------
R_LCD_BF
BCF P_RS ; CONFIGURA COMO COMANDO
CALL R_LCD_READ ; LÊ BYTE DE COMANDO DO LCD
BTFSC V_LCD, 7
GOTO R_LCD_BF ; CONTINUA ATÉ O LCD DESOCUPAR!
RETURN
;------------------------------------------------------------------------------------------------
; ROTINA QUE ENVIA UM COMANDO PARA O LCD
; ENTRADA: W = BYTE COM O COMANDO A SER ENVIADO
; SAÍDAS: NENHUMA
; AFETA: STATUS; V_W_AUX; *V_LCD; *TRIS_LCD; *CTRL_LCD
; CHAMA: R_LCD_BF; R_LCD_WRITE (STACK: 3)
;------------------------------------------------------------------------------------------------
117
R_LCD_CMD
MOVWF V_W_AUX ; SALVA COMANDO
CALL R_LCD_BF ; ESPERA O LCD DESOCUPAR
MOVF V_W_AUX, W
CALL R_LCD_WRITE
RETURN
;------------------------------------------------------------------------------------------------
; ROTINA QUE ENVIA UM DADO PARA O LCD
; ENTRADA: W = BYTE COM O DADOS A SER ENVIADO
; SAÍDAS: NENHUMA
; AFETA: STATUS; V_W_AUX; *V_LCD; *TRIS_LCD; *CTRL_LCD
; CHAMA: R_LCD_BF; R_LCD_WRITE (STACK: 3)
;------------------------------------------------------------------------------------------------
R_LCD_CHAR
MOVWF V_W_AUX ; SALVA DADO
CALL R_LCD_BF ; ESPERA O LCD DESOCUPAR
;------------------------------------------------------------------------------------------------
; ROTINA QUE MOSTRA UM BCD NO LCD
; ENTRADA: W = BCD A SER MOSTRADO
; SAÍDAS: NENHUMA
; AFETA: W; STATUS; V_W_AUX; V_NUM1; *V_LCD; *TRIS_LCD; *CTRL_LCD
; CHAMA: R_LCD_BF; R_LCD_WRITE (STACK: 3)
;------------------------------------------------------------------------------------------------
R_LCD_BCD
MOVWF V_W_AUX ; SALVA NUMERO A SER MOSTRADO
ANDLW 0X0F
ADDLW '0' ; CONVERTE NO ASCII EQUIVALENTE
MOVWF V_NUM1 ; SALVA NIBBLE INFERIOR DO BCD
SWAPF V_W_AUX, W ; PEGA NIBBLE SUPERIOR DO BCD
ANDLW 0X0F
ADDLW '0' ; CONVERTE NO ASCII EQUIVALENTE
;------------------------------------------------------------------------------------------------
; ROTINA QUE MOSTRA UM BYTE EM DECIMAL NO LCD
; ENTRADA: W = BYTE COM O DADOS A SER ENVIADO
; SAÍDAS: NENHUMA
; AFETA: W; STATUS; V_NUM; V_NUM1; V_NUM2; V_NUM3; V_NUM4; *V_NUM5; *V_NUM6; V_NUM7
; *V_W_AUX; *V_LCD; *TRIS_LCD; *CTRL_LCD
; CHAMA: R_DIV8; R_LCD_BF; R_LCD_WRITE (STACK: 3)
;------------------------------------------------------------------------------------------------
R_LCD_DECIMAL
CLRF STATUS ; GARANTE BANK 0
MOVWF V_NUM3 ; SALVA DADO
R_LCD_DEC_SHOW
ADDLW '0'
118
MOVWF V_NUM1 ; SALVA DADO EM ASCII
CALL R_LCD_BF ; ESPERA O LCD DESOCUPAR
MOVF V_NUM1, W
BSF P_RS ; CONFIGURA COMO DADO
CALL R_LCD_WRITE
BSF V_NUM7, 4 ; FLAG TEMPORÁRIO PARA INFORMAR QUE DEVE MOSTRAR ZEROS!
R_LCD_DEC_OK
DECF V_NUM7, F
MOVLW 0X03
ANDWF V_NUM7, W
M_JZ R_LCD_DEC_FIM
MOVLW D'10'
BTFSS V_NUM7, 0
GOTO R_LCD_DEC_LOOP
BSF V_NUM7, 4 ; FLAG TEMPORÁRIO PARA INFORMAR QUE DEVE MOSTRAR ZEROS!
MOVLW D'1'
GOTO R_LCD_DEC_LOOP
R_LCD_DEC_FIM
RETURN
;------------------------------------------------------------------------------------------------
; ROTINA QUE ENVIA UMA MENSAGEM PARA O DISPLAY A PARTIR DA POSIÇÃO ATUAL DO CURSOR
; ENTRADA: W = ENDEREÇO DA MENSAGEM (PRIMEIRO BYTE INFORMA O TAMANHO DA MENSAGEM)
; SAÍDAS: NENHUMA
; AFETA: W; STATUS; V_NUM; V_NUM1; *V_W_AUX; *V_LCD; *TRIS_LCD; *CTRL_LCD
; CHAMA: R_LCD_CHAR (STACK: 4)
;------------------------------------------------------------------------------------------------
R_MENSAGEM
MOVWF V_NUM ; GUARDA ENDEREÇO DA MENSAGEM
CALL R_CALL_MSG
MOVWF V_NUM1
R_MSG_LOOP
INCF V_NUM, F
MOVF V_NUM, W
CALL R_CALL_MSG
CALL R_LCD_CHAR
DECFSZ V_NUM1, F
GOTO R_MSG_LOOP
RETURN
;------------------------------------------------------------------------------------------------
; ROTINA QUE ENVIA A MENSAGEM DO LOOP PRINCIPAL NA PRIMEIRA LINHA
; ENTRADA: NENHUMA
; SAÍDAS: NENHUMA
; AFETA: W; STATUS; *V_W_AUX; *V_LCD; *TRIS_LCD; *CTRL_LCD
; *V_NUM; *V_NUM1; *V_NUM2; *V_NUM3; *V_NUM4; *V_NUM5; *V_NUM6
; CHAMA: R_MENSAGEM (5), R_LCD_CHAR; R_LCD_CMD; R_BIN_TO_BCD; R_LCD_BCD (STACK: 5)
;------------------------------------------------------------------------------------------------
R_MSG_INICIO
MOVLW LCD_L0
CALL R_LCD_CMD ; POSICIONA NA PRIMEIRA LINHA
MOVF V_HOR, W
CALL R_BIN_TO_BCD
CALL R_LCD_BCD
MOVLW ':'
CALL R_LCD_CHAR
MOVF V_MIN, W
CALL R_BIN_TO_BCD
CALL R_LCD_BCD
MOVLW ':'
CALL R_LCD_CHAR
MOVF V_SEG, W
CALL R_BIN_TO_BCD
CALL R_LCD_BCD
RETURN
;------------------------------------------------------------------------------------------------
119
; ROTINA QUE ENVIA A MENSAGEM QUE PERGUNTA SE LIGA OU DESLIGA O MOTOR
; ENTRADA: NENHUMA
; SAÍDAS: NENHUMA
; AFETA: W; STATUS; *V_W_AUX; *V_LCD; *TRIS_LCD; *CTRL_LCD; *V_NUM; *V_NUM1
; CHAMA: R_MENSAGEM (5), R_LCD_CHAR; R_LCD_CMD (STACK: 5)
;------------------------------------------------------------------------------------------------
R_MSG_MOTOR
MOVLW LCD_CLR
CALL R_LCD_CMD ; LIMPA O DISPLAY
MOVLW LCD_L1
CALL R_LCD_CMD ; POSICIONA NA SEGUNDA LINHA
MOVLW LCD_L1 + 3
CALL R_LCD_CMD ; POSICIONA NA SEGUNDA LINHA PARA ESCREVER "LIGAR?"
M_SHOW_MSG MSG_MOTOR ; MOSTRA A MENSAGEM PARA LIGAR OU DESLIGAR O MOTOR
R_MSG_MOT_FIM
RETURN
;------------------------------------------------------------------------------------------------
; ROTINA DE INTERFACE PARA AJUSTAR OS VALORES DE CONFIGURAÇÃO NA EEPROM
; ENTRADA: W = ENDEREÇO DA EEPROM A SER AJUSTADO
; SAÍDAS: NENHUMA
; AFETA: W; STATUS; V_NUM2; *V_W_AUX; *V_LCD; *TRIS_LCD; *CTRL_LCD; *V_NUM; *V_NUM1;
; *V_NUM3; *V_NUM4; *V_NUM6; *V_NUM7
; CHAMA: R_MENSAGEM (5), R_TECLA_WAIT (2); R_EE_READ; R_EE_WRITE;
; R_LCD_CHAR (3); R_LCD_CMD; R_LCD_DECIMAL (STACK: 6)
;------------------------------------------------------------------------------------------------
R_AJUSTA_EEPROM
MOVWF V_EE_OP ; SALVA ENDEREÇO DA EEPROM
MOVLW E_ID
XORWF V_EE_OP, W
M_JNZ R_AJT_EE_DELTA
MOVLW MSG_ID
GOTO R_AJT_EE_VALOR
R_AJT_EE_DELTA
MOVLW E_DELTA
XORWF V_EE_OP, W
M_JNZ R_AJT_EE_MENOR
MOVLW MSG_DELTA
GOTO R_AJT_EE_VALOR
R_AJT_EE_MENOR
MOVLW E_MENOR
XORWF V_EE_OP, W
M_JNZ R_AJT_EE_NOMINAL
MOVLW MSG_MENOR
GOTO R_AJT_EE_VALOR
R_AJT_EE_NOMINAL
MOVLW E_NOMINAL
XORWF V_EE_OP, W
M_JNZ R_AJT_EE_PARTIDA
MOVLW MSG_NOMINAL
GOTO R_AJT_EE_VALOR
120
R_AJT_EE_PARTIDA
MOVLW E_PARTIDA
XORWF V_EE_OP, W
M_JNZ R_AJT_EE_UNIDADE
MOVLW MSG_PARTIDA
GOTO R_AJT_EE_VALOR
R_AJT_EE_UNIDADE
MOVLW E_UNIDADE
XORWF V_EE_OP, W
M_JNZ R_AJT_EE_I_UNIDADE
MOVLW MSG_UNIDADE
GOTO R_AJT_EE_VALOR
R_AJT_EE_I_UNIDADE
MOVLW E_I_UNIDADE
XORWF V_EE_OP, W
M_JNZ R_AJT_EE_FIM
MOVLW MSG_I_UNIDADE
GOTO R_AJT_EE_VALOR
R_AJT_EE_VALOR
CALL R_MENSAGEM ; MOSTRA A MENSAGEM EQUIVALENTE
MOVLW ':'
CALL R_LCD_CHAR
CALL R_TECLA_WAIT
BTFSC V_TECLA, TEC_OK
GOTO R_AJT_EE_GRAVA ; FOI TECLA OK
BTFSS V_TECLA, TEC_MENU ; SE FOI MENU OU NADA, ENTÃO SAI
BTFSC STATUS, Z
GOTO R_AJT_EE_FIM ; NADA TECLADO POR MUITO TEMPO, ENTÃO SAI DO LOOP
R_AJT_EE_GRAVA
MOVF V_EE_VALOR, W
BSF STATUS, RP1 ; MUDA PARA O BANCO 2
MOVWF EEDATA
CALL R_EE_WRITE ; CHAMA ROTINA DE ESCRITA DA EEPROM
R_AJT_EE_FIM
RETURN
;------------------------------------------------------------------------------------------------
; ROTINA QUE LÊ AS 3 CORRENTES DE FASES DO ADC E MOSTRA A CORRENTE SELECIONADA NO LCD
; ENTRADA: V_I_PTR = END. DA VARIÁVEL COM O VALOR DA CORRENTE A SER MOSTRADA
; SAÍDAS: NENHUMA
; AFETA: W; STATUS; FSR; V_NUM; V_NUM7; *V_W_AUX; V_LCD; *TRIS_LCD; *CTRL_LCD;
; V_NUM1; V_NUM2; *V_NUM; *V_NUM3; *V_NUM4; *V_NUM5; *V_NUM6
; CHAMA: R_ADC_READ; R_LCD_DECIMAL; R_LCD_CHAR; R_LCD_CMD; R_DIV8; R_MUL8 (STACK: 4)
;------------------------------------------------------------------------------------------------
R_LCD_I
MOVLW LCD_L1
CALL R_LCD_CMD
MOVLW 'I'
121
CALL R_LCD_CHAR
MOVLW V_I1
SUBWF V_I_PTR, W
ADDLW '1' ; DETERMINA A CORRENTE FASE A SER LIDA
CALL R_LCD_CHAR
MOVLW '='
CALL R_LCD_CHAR
M_MOVLF V_NUM1, 3
R_LCD_I_LOOP
BSF STATUS, C
CALL R_I_PTR ; INCREMENTA O PONTEIRO DA CORRENTE ATUAL
MOVF V_I_PTR, W
MOVWF FSR ; GUARDA ENDEREÇO DA FASE ATUAL EM FSR
MOVLW V_I1
SUBWF V_I_PTR, W ; DETERMINA O CORRENTE CANAL A SER LIDO
CALL R_ADC_READ ; LÊ O ADC
MOVWF INDF ; SALVA VALOR ATUAL
DECFSZ V_NUM1
GOTO R_LCD_I_LOOP
MOVLW D'10'
MOVWF V_NUM2 ; PREPARA PARA MOSTRAR A PARTE DECIMAL
MOVF V_NUM3, W ; PEGA PARTE BAIXA
MOVWF V_NUM1
CALL R_MUL8
MOVLW '0'
ADDWF V_NUM4, W ; CONVERTE PARA ASCII
CALL R_LCD_CHAR
MOVLW 'A'
CALL R_LCD_CHAR
MOVLW ' '
CALL R_LCD_CHAR
MOVLW '('
CALL R_LCD_CHAR
MOVF INDF, W
CALL R_LCD_DECIMAL
MOVLW ')'
CALL R_LCD_CHAR
MOVLW ' '
CALL R_LCD_CHAR
CALL R_LCD_CHAR
CALL R_LCD_CHAR
CALL R_LCD_CHAR
CALL R_LCD_CHAR
RETURN
;------------------------------------------------------------------------------------------------
122
; ROTINA QUE INC/DEC PONTEIRO DA CORRENTE
; ENTRADA: V_I_PTR = END. DA VARIÁVEL COM O VALOR DA CORRENTE; C = 1 P/ INCREMENTAR
; SAÍDAS: NENHUMA
; AFETA: W; STATUS; V_I_PTR
; CHAMA: NADA (STACK: 1)
;------------------------------------------------------------------------------------------------
R_I_PTR
M_JC R_I_PTR_INC
DECF V_I_PTR, F
MOVLW V_I1 - 1
XORWF V_I_PTR, W
M_JNZ R_I_PTR_END
MOVLW V_I3
MOVWF V_I_PTR
GOTO R_I_PTR_END
R_I_PTR_INC
INCF V_I_PTR, F
MOVLW V_I3 + 1
XORWF V_I_PTR, W
M_JNZ R_I_PTR_END
MOVLW V_I1
MOVWF V_I_PTR
R_I_PTR_END
RETURN
;------------------------------------------------------------------------------------------------
; ROTINA QUE VERIFICA SE HÁ SOBRECORRENTE
; ENTRADA: V_I_PTR = END. DA VARIÁVEL COM O VALOR DA CORRENTE
; SAÍDAS: V_TEMPO_MAX; V_FAIXA; V_TEMPO SÃO ATUALIZADOS
; AFETA: W; STATUS; V_TEMPO_MAX; V_FAIXA; V_TEMPO
; CHAMA: NADA (STACK: 1)
;------------------------------------------------------------------------------------------------
R_TESTA_I
MOVF V_I_PTR, W ; W = ENDEREÇO DA CORRENTE DA FASE ATUAL
MOVWF FSR ; GUARDA ENDEREÇO
MOVLW K_FAIXA
MOVWF V_NUM ; PREPARA CONTADOR
R_TST_I_LOOP
CALL R_EE_READ
SUBWF INDF, W
BTFSC STATUS, C
GOTO R_TST_I_OK ; HÁ SOBRECORRENTE E LOCALIZOU O SEU TEMPO!
R_TST_I_CLR
; LIMPA TODAS AS VARIÁVEIS INTERNAS (MENOS O FLAG DE SOBRECORRENTE)
CLRF V_TEMPO ; NÃO HÁ SOBRECORRENTE!
CLRF V_TEMPO_MAX
BCF B_1CS
BCF B_1S
BCF B_M_ALERTA ; LIMPA O ALERTA DA VARIÁVEL
GOTO R_TST_I_FIM ; NÃO HÁ SOBRECORRENTE!
R_TST_I_OK
BSF B_M_ALERTA ; FLAG PARA AVISAR AO PC QUE HÁ UM ALERTA NO
MOTOR
R_TST_I_1CS
; OBSERVOU QUE A FAIXA É DE CENTÉSIMOS DE SEGUNDOS
BTFSC B_1CS ; VERIFICA SE A FAIXA ANTERIOR ERA A MESMA
GOTO R_TST_I_FIM
CLRF V_TEMPO ; LIMPA CONTADOR SE A FAIXA MUDOU!
BCF B_1S
BSF B_1CS ; ACIONA O FLAG DA FAIXA
R_TST_I_FIM
RETURN
END
;*************************************************************************************************
; DEFINIÇÕES DAS CONSTANTES
; Arquivo: Main.inc
;*************************************************************************************************
;=================================================================================================
; TIMER2
;=================================================================================================
; CONSTANTES DE INICIALIZAÇÃO
#DEFINE K_TRISA B'11101111' ; SELECIONA COMO I/O (=1 -> INPUT / =0 -> OUTPUT)
#DEFINE K_TRISB B'11110000' ; SELECIONA COMO I/O (=1 -> INPUT / =0 -> OUTPUT)
#DEFINE K_TRISC B'11111110' ; SELECIONA COMO I/O (=1 -> INPUT / =0 -> OUTPUT)
;=================================================================================================
; TECLADO
#DEFINE TEC_MENU 7
#DEFINE TEC_OK 6
#DEFINE TEC_UP 5
#DEFINE TEC_DOWN 4
;=================================================================================================
; LCD MODULE
124
#DEFINE TRIS_LCD TRISB
#DEFINE TRIS_LCD_OUT 0X0F
#DEFINE TRIS_LCD_IN 0XF0 ; CONSTANTES UTILIZADAS PARA CONFIGURAR DIREÇÃO DO I/O
#DEFINE PORT_LCD PORTB
;=================================================================================================
; SERIAL
#DEFINE SER_COUNT 0X10 ; VEZES QUE PASSA PELA LE_TEC E ESPERA PRÓXIMO BYTE
; BUFFER SERIAL
#DEFINE SER_EDATA D'32' ; 32 BYTES DE DADOS DA EEPROM DENTRO DO PACOTE
#DEFINE SER_SIZE D'48' ; TOTAL DE BYTES DE UM PACOTE DE COMUNICAÇÃO
; COMANDOS DA SERIAL
#DEFINE SER_CMD_TST B'00110110' ; TODO COMANDO ENVIADO DEVE TER ESTES BITS ZERADOS
#DEFINE B_TIME_WR SER_CMD, 7 ; BIT RESPONSÁVEL PELA ATUALIZAÇÃO DO HORÁRIO (=1-
>ATUALIZA)
#DEFINE B_EE_WR SER_CMD, 6 ; BIT QUE INFORMA SE DEVE ESCREVER NA EEPROM
#DEFINE B_MOTOR_SET SER_CMD, 3 ; BIT QUE INFORMA SE DEVE ESCREVER O NOVO STATUS DO MOTOR
#DEFINE B_MOTOR_ON SER_CMD, 0 ; BIT QUE INFORMA O STATUS DO MOTOR (LIGADO / DESLIGADO)
;=================================================================================================
; ACIONAMENTO DO MOTOR
;*************************************************************************************************
; VARIÁVEIS DA RAM
;*************************************************************************************************
;-------------------------------------------------------------------------------------------------
; VARIÁVEIS COM ACESSO ATRAVÉS DO BANK 0
; VARIÁVEIS DE CONTROLE
V_TECLA EQU V_BANK0 + 0X00 ; VARIÁVEL DE LEITURA DA TECLA
V_WAIT EQU V_BANK0 + 0X01 ; CONTADOR PARA ATRASO EM ms DA ROTINA R_WAIT
V_LCD EQU V_BANK0 + 0X02 ; BYTE CONTENDO O DADO/COMANDO DO/PARA LCD
V_I_PTR EQU V_BANK0 + 0X03 ; BYTE COM O ENDEREÇO DA CORRENTE MOSTRADA NO LCD
; BYTES PARA AS FUNÇÕES MATEMÁTICAS
V_NUM EQU V_BANK0 + 0X04 ; BYTE UTILIZADO NAS ROTINAS MATEMÁTICAS
V_NUM1 EQU V_BANK0 + 0X05 ; BYTE UTILIZADO NAS ROTINAS MATEMÁTICAS
V_NUM2 EQU V_BANK0 + 0X06 ; BYTE UTILIZADO NAS ROTINAS MATEMÁTICAS
V_NUM3 EQU V_BANK0 + 0X07 ; BYTE UTILIZADO NAS ROTINAS MATEMÁTICAS
V_NUM4 EQU V_BANK0 + 0X08 ; BYTE UTILIZADO NAS ROTINAS MATEMÁTICAS
V_NUM5 EQU V_BANK0 + 0X09 ; BYTE UTILIZADO NAS ROTINAS MATEMÁTICAS
V_NUM6 EQU V_BANK0 + 0X0A ; BYTE UTILIZADO NAS ROTINAS MATEMÁTICAS
V_NUM7 EQU V_BANK0 + 0X0B ; BYTE UTILIZADO NAS ROTINAS MATEMÁTICAS
; BYTES PARA GUARDAR AS ÚLTIMAS LEITURAS DO ADC
V_I1 EQU V_BANK0 + 0X0C ; CORRENTE DA PRIMEIRA FASE DO MOTOR (END.= BASE + 8)
V_I2 EQU V_BANK0 + 0X0D ; CORRENTE DA SEGUNDA FASE DO MOTOR
V_I3 EQU V_BANK0 + 0X0E ; CORRENTE DA TERCEIRA FASE DO MOTOR
; BYTES PARA A CONTAGEM DO TEMPO
V_MS EQU V_BANK0 + 0X0F ; BYTE QUE CONTA MILÉZIMOS DE SEGUNDOS (0..9)
V_CS EQU V_BANK0 + 0X10 ; BYTE QUE CONTA OS CENTÉZIMOS DE SEGUNDOS (0..99)
V_SEG EQU V_BANK0 + 0X11 ; BYTE QUE CONTA OS SEGUNDOS (0..59)
V_MIN EQU V_BANK0 + 0X12 ; BYTE QUE CONTA OS MINUTOS (0..59)
V_HOR EQU V_BANK0 + 0X13 ; BYTE QUE CONTA AS HORAS (0..23)
; BYTES PARA A CONVERSÃO DO ADC
V_DELTA EQU V_BANK0 + 0X14 ; ESPELHO DO E_DELTA
V_MENOR EQU V_BANK0 + 0X15 ; ESPELHO DO E_MENOR
; BYTES PARA A CONTAGEM DE TEMPO
V_PARTIDA EQU V_BANK0 + 0X16 ; CONTADOR DO TEMPO DE PARTIDA DO MOTOR
V_UNIDADE EQU V_BANK0 + 0X17 ; INDICADOR DA UNIDADE DO TEMPO DE PARTIDA DO MOTOR
V_TEMPO_MAX EQU V_BANK0 + 0X18 ; CONTÉM O TEMPO MÁXIMO QUE O RELE DEVE MANTER O MOTOR LIGADO
V_TEMPO EQU V_BANK0 + 0X19 ; CONTÉM A CONTAGEM DE TEMPO (TEMPO QUE JÁ PASSOU)
V_TEC_TEMPO EQU V_BANK0 + 0X1A ; CONTÉM O CONTADOR DE TEMPO PARA A ROTINA DE LEITURA DA TECLA
V_FAIXA EQU V_BANK0 + 0X1B ; CONTÉM O PONTEIRO PARA A FAIXA DA SOBRECORRENTE
; DEFINIÇÕES SOBRE A FAIXA E OS TEMPOS DAS CORRENTES (NIBBLE INF. SÓ DE FLAGS P/ OS CONTADORES)
#DEFINE K_FAIXA D'16' ; NÚMERO DE SOBRECORRENTES CADASTRADAS NA EEPROM
#DEFINE B_1CS_P V_FAIXA, 0 ; INDICA QUE A FAIXA ESTÁ EM CENTÉSIMOS DE SEGUNDOS
(PARTIDA)
#DEFINE B_1S_P V_FAIXA, 1 ; INDICA QUE A FAIXA ESTÁ EM SEGUNDOS (PARTIDA)
#DEFINE B_1CS V_FAIXA, 2 ; INDICA QUE A FAIXA ESTÁ EM CENTÉSIMOS DE SEGUNDOS
#DEFINE B_1S V_FAIXA, 3 ; INDICA QUE A FAIXA ESTÁ EM SEGUNDOS
#DEFINE B_INC_TEMP V_FAIXA, 4 ; INDICA QUE DEVE INCREMENTAR O CONTADOR DE TEMPO
; VARIÁVEIS AUXILIARES DE USO GERAL
V_I_AUX EQU V_BANK0 + 0X1C ; CONTÉM A PARTE BAIXA DO CÁLCULO DA CORRENTE EM R_LCD_I
V_EE_VALOR EQU V_BANK0 + 0X1D ; CONTÉM UM VALOR ESPELHO DA EEPROM UTILIZADO EM R_AJUSTA_EEPROM
V_EE_OP EQU V_BANK0 + 0X1E ; CONTÉM O ENDEREÇO (OPÇÃO DA EEPROM) EM R_AJUSTA_EERPOM
;-------------------------------------------------------------------------------------------------
; VARIÁVEIS COM ACESSO INDEPENDENTE DO BANCO (16 BYTES)
V_W_TEMP EQU V_BANKS + 0x00 ; WREG TEMPORÁRIO PARA INTERRUPÇÕES
V_S_TEMP EQU V_BANKS + 0x01 ; STATUS TEMPORÁRIO PARA INTERRUPÇÕES
V_FSR_TEMP EQU V_BANKS + 0x02 ; FSR TEMPORÁRIO PARA INTERRUPÇÕES
V_W_AUX EQU V_BANKS + 0x03 ; VARIÁVEL AUXILIAR PARA O W (DESTRUÍDO NAS SUBROTINAS)
; VARIÁVEIS GLOBAIS PARA COMUNICAÇÃO SERIAL
V_SER_PTR EQU V_BANKS + 0x04 ; PONTEIRO PARA BUFFER DA SERIAL
V_SER_OK EQU V_BANKS + 0x05 ; CONTADOR PARA TIME OUT DA SERIAL
V_SER_FLAG EQU V_BANKS + 0X06 ; CONTÉM BITS DE STATUS PARA SER ENVIADO AO PC
#DEFINE B_M_ALERTA V_SER_FLAG, 5 ; ESTÁ EM ALERTA DE SOBRECORRENTE
#DEFINE B_M_SOBRE V_SER_FLAG, 6 ; HOUVE UMA SOBRECORRENTE
; BYTES COM FLAGS PARA USO GERAL NAS ROTINAS
V_FLAGS EQU V_BANKS + 0X07 ; FLAGS PARA USO GERAL EM ROTINAS INTERNAS
#DEFINE B_ID_OK V_FLAGS, 0 ; FLAG QUE INDICA SE A COMUNICAÇÃO É COM O RELE (1=SIM)
;*************************************************************************************************
; VARIÁVEIS DA EEPROM
126
;*************************************************************************************************
; 32 BYTES: BUFFER COM O CADASTRO DAS MÁXIMAS CORRENTES (16 x 2 = 32 BYTES USADOS)
; PARA OS PRIMEIROS 16 BYTES (8 CORRENTES) A UNIDADE É 1cs, NAS DEMAIS SERÁ 1s
; AS CORRENTES ESTÃO EM ORDEM DECRESCENTE DE CORRENTE E CRESCENTE DE TEMPO
E_MAX EQU 0X20 ; END. BASE PARA O PRIMEIRO DOS CINCO CADASTROS
E_I_MAX EQU D'0' ; OFFSET PARA A CORRENTE
E_T_MAX EQU D'1' ; OFFSET PARA O TEMPO QUE DEVE ESPERAR ANTES DE DESLIGAR O MOTOR
;*************************************************************************************************
; MACROS
;*************************************************************************************************
;-------------------------------------------------------------------------------------------------
; MACRO PARA ATRASOS
M_DELAY MACRO N
MOVLW N
CALL R_DELAY ; TEMPO EM N x 4 us
ENDM
M_WAIT MACRO N
MOVLW N
CALL R_WAIT ; TEMPO EM N x 1 ms
ENDM
;-------------------------------------------------------------------------------------------------
; MACRO PARA CONTROLE DO MOTOR
;-------------------------------------------------------------------------------------------------
; MACROS PARA O ADC DESTE PROJETO
;-------------------------------------------------------------------------------------------------
; MACROS PARA A EEPROM
;-------------------------------------------------------------------------------------------------
; MACROS PARA A FLASH
;-------------------------------------------------------------------------------------------------
; MACROS PARA O DISPLAY