You are on page 1of 43

UNIVERSIDADE FEDERAL DO ESPÍRITO SANTO

CENTRO TECNOLÓGICO
DEPARTAMENTO DE ENGENHARIA ELÉTRICA
PROJETO DE GRADUAÇÃO

COMUNICAÇÃO SERIAL PC – PLOTTER
ESTUDO E UTILIZAÇÃO DO MICROCONTROLADOR
PIC16F877

SERGIO PAZZINI DA SILVA MATOS

VITÓRIA – ES
FEVEREIRO/2007
SERGIO PAZZINI DA SILVA MATOS

COMUNICAÇÃO SERIAL PC – PLOTTER
ESTUDO E UTILIZAÇÃO DO MICROCONTROLADOR
PIC16F877

Parte manuscrita do Projeto de Graduação
do aluno Sergio Pazzini da Silva Matos,
apresentado ao Departamento de
Engenharia Elétrica do Centro
Tecnológico da Universidade Federal do
Espírito Santo, para obtenção do grau de
Engenheiro Eletricista.

VITÓRIA – ES
FEVEREIRO/2007
SERGIO PAZZINI DA SILVA MATOS

COMUNICAÇÃO SERIAL PC – PLOTTER
ESTUDO E UTILIZAÇÃO DO MICROCONTROLADOR
PIC16F877

COMISSÃO EXAMINADORA:

___________________________________
Prof. Dr. Paulo Faria Santos Amaral
Orientador

___________________________________
Prof. Dr. Teodiano Freire Bastos Filho
Examinador

___________________________________
Eng. Rodrigo Thompson Vargas
Examinador

Vitória - ES, 26, fevereiro, 2007
DEDICATÓRIA

Aos meus pais, Cyro e Letícia.

i
AGRADECIMENTOS

Agradeço a Eric Clapton, U2 e Metallica pela grande compreensão e
companhia na realização deste projeto. Agradeço aos amigos que, por muitas vezes fui
ausente, mas o motivo disto está sendo apresentado aqui.
Ao meu orientador, Paulo Amaral, por ter-me permitido realizar este projeto e
pela ajuda e apoio durante todo o tempo.
Agradeço especialmente a Rogério Costa Pacheco Neto e Paulo Franklin
Raskin Ferrua, companheiros de laboratório nesta reta final. O apoio deles foi
essencial, principalmente nos momentos nos quais nada funcionava. Grandes amigos.
Agradeço aos meus pais pela paciência e apoio em todos estes anos de
estudos. Sem eles isto não seria possível.

ii
LISTA DE FIGURAS

Figura 1 - Diagrama do sistema. ....................................................................................7
Figura 2 - Diagrama de blocos do sistema.....................................................................8
Figura 3 - A plotter HP Draft Pro 7570A. ...................................................................11
Figura 4 - Detalhes dos motores da plotter. .................................................................12
Figura 5 - O circuito de comunicação serial. ...............................................................13
Figura 6 – Esquema do circuito. ..................................................................................14
Figura 7 - O PIC...........................................................................................................15
Figura 8 - HCTL2016. .................................................................................................16
Figura 9 - Esquema da ligação serial. ..........................................................................17
Figura 10 - O L298. .....................................................................................................18
Figura 11 - Diagrama de blocos da ponte H dupla L298.............................................18

iii
LISTA DE TABELA

Tabela 1 - Comandos implementados no projeto. .......................................................25
Tabela 2 - Resultados para o Motor 1, que puxa o papel. ...........................................27
Tabela 3 - Resultados para o Motor 2, que movimenta a pena. ..................................27

iv
SUMÁRIO

DEDICATÓRIA........................................................................................................... I
AGRADECIMENTOS .............................................................................................. II
LISTA DE FIGURAS ............................................................................................... III
LISTA DE TABELA ................................................................................................ IV
SUMÁRIO ................................................................................................................... V
RESUMO ................................................................................................................... VI
INTRODUÇÃO ............................................................................................................7
1 OS ELEMENTOS DO PROJETO .................................................................9
1.1 O Microcontrolador ............................................................................................9
1.2 A Plotter ............................................................................................................10
2 O CIRCUITO DO CONTROLADOR .........................................................13
2.1 O PIC ................................................................................................................15
2.2 Os Chips de Encoder .........................................................................................16
2.3 O Chip MAX232...............................................................................................17
2.4 O L298 ..............................................................................................................17
3 A PROGRAMAÇÃO .....................................................................................19
3.1 Programando o PIC ...........................................................................................19
3.2 Funcionamento do programa ............................................................................19
3.2.1 Mudando os parâmetros do PID..............................................................22
3.2.2 As interrupções ........................................................................................24
3.2.2.1 A interrupção de Timer 0 ...........................................................24
3.2.2.2 A interrupção de recepção pela porta serial ...............................24
3.3 Resumo dos comandos ......................................................................................25
3.4 Comandos interessantes ....................................................................................25
4 RESULTADOS OBTIDOS............................................................................27
5 CONSIDERAÇÕES FINAIS.........................................................................28
APÊNDICE A .............................................................................................................29
REFERÊNCIAS BIBLIOGRÁFICAS.....................................................................40

v
RESUMO

Este trabalho constitui na elaboração de uma placa microcontrolada que
realize uma comunicação serial com o PC e controle os motores de uma plotter. Na
mesma placa foi projetado um circuito de medição das posições dos motores, fechando
a malha para o controle através de um algoritmo PID. A porta serial do circuito tem
como função enviar e receber dados sobre as posições dos motores a serem
controlados.
Este projeto deverá ser mais uma opção para experiências de laboratório da
disciplina de Microprocessadores I da Universidade Federal do Espírito Santo.

vi
7

INTRODUÇÃO

Um trabalho de conclusão de curso pressupõe a utilização dos conceitos e
habilidade adquiridos no mesmo.
O curso de Engenharia Elétrica proporciona ao aluno a aquisição de conteúdos e
o desenvolvimento de habilidades que possibilitam a elaboração de trabalhos práticos
onde ficam evidenciadas as possibilidades desta área de conhecimento que é a
Engenharia Elétrica.
Motivado por estes dois itens: Elaborar um trabalho de conclusão de curso e a
utilização prática dos conceitos e habilidades adquiridos, surge o objeto deste projeto:
Utilizar um microcontrolador para que, via PC, os motores da plotter existente no
laboratório de Microeletrônica do Departamento de Engenharia Elétrica da UFES
sejam acionados. O diagrama abaixo mostra um esquema do sistema como um todo.

Motores
Comunicação
Serial

Placa
microcontrolada
Relé

Figura 1 - Diagrama do sistema.

Para a execução deste projeto foram utilizados conceitos de microcontroladores,
motores CC, sensores, teorias de controle de malha fechada, controladores PID e
linguagem de programação, que foram adquiridos durante este curso. Sendo assim, o
objetivo do projeto se constitui da seguinte maneira:
Substituir toda a parte eletrônica de uma plotter por uma placa
microcontrolada que se comunique via porta serial com o PC, implementando os
comandos dos motores da plotter, usando ponte H com PWM. Será implementado um
8

controlador PID para estes motores que também terão codificadores óticos de posição
visando um controle de malha fechada. E o diagrama de blocos do sistema é
apresentado na figura 2.

Figura 2 - Diagrama de blocos do sistema.

O projeto foi subdividido em etapas descritas nos capítulos deste relatório:
• Uma pesquisa bibliográfica sobre microcontroladores e, especialmente o
microcontrolador PIC 16F877, que está resumidamente apresentada no
capítulo 1, intitulado “Os Elementos do Projeto”. Ainda neste capítulo
são apresentados alguns dados sobre a plotter.
• Montagem da placa para a comunicação serial entre o PC e o PIC cujos
principais circuitos estão apresentados no capítulo 2: “O Circuito de
Comunicação Serial”;
• A programação em linguagem C utilizada para programar o PIC,
apresentadas no capítulo 3, intitulado “Programando o PIC”;
• E no capítulo 4, os resultados obtidos.
Este trabalho apresenta também as considerações finais sobre o projeto:
Resultados, problemas apresentados, possibilidades de outros estudos.
9

1 OS ELEMENTOS DO PROJETO

1.1 O Microcontrolador
Um microcontrolador é uma espécie de microprocessador programável, em um
chip otimizado para controlar dispositivos eletrônicos. Possui memória e interface de
entradas e saídas E/S(I/O) integrados, enfatizando a auto-suficiência, em contraste com
um microprocessador de propósito geral, o mesmo tipo usado nos PCs, que requer
chips adicionais para prover as funções necessárias.
Estes equipamentos são conhecidos como Sistemas Embutidos, do inglês
Embedded System, pois o microcontrolador é embutido dentro de um sistema fechado
e com funções bem específicas. Em geral, estes sistemas exigem um controle preciso
do tempo, pois trabalham em tempo real. A capacidade de processamento e de
memória variam de acordo com a aplicação, podendo ser um simples relógio ou um
equipamento industrial complexo que envolve até uma camada de sistema operacional
executando sobre o microcontrolador.
Os microcontroladores são componentes utilizados em muitos tipos de
equipamentos eletrônicos, sendo a grande maioria entre os chips vendidos. Cerca de
50% são controladores "simples", outros 20% são processadores de sinais digitais
(DSPs) mais especializados. Os microcontroladores podem ser encontrados em
máquinas de lavar, forno de microondas, telefones, etc [12].
As principais vantagens dos microcontroladores são:
• Baixo custo e consumo;
• Portátil;
• Poucos componentes (elimina necessidade de componentes externos);
• Reconfiguração por software;
• Curto tempo para desenvolvimento (time-to-make).
Os PIC (PICmicro) são uma família de microcontroladores fabricados pela
Microchip Technology, que processam dados de 8 bits (recentemente foi lançada uma
família de 16 bits com prefixo 24F) com extensa variedade de modelos e periféricos
internos, com arquitetura Harvard e conjunto de instruções RISC (conjuntos de 35
10

instruções e de 76 instruções), com recursos de programação por Memória Flash,
E2PROM e OTP. Os microcontroladores PIC têm famílias com núcleos de
processamento de 12 bits, 14 bits e 16 bits e trabalham em velocidades de 0kHz (ou
CC) a 48MHz, usando ciclo de instrução mínimo de 4 períodos de clock, o que
permite uma velocidade de no máximo 10 MIPS (Milhões de Instruções Por Segundo).
Há o reconhecimento de interrupções tanto externas como de periféricos internos.
Funcionam com tensões de alimentação de 2 a 6V e os modelos possuem
encapsulamento de 6 a 100 pinos em diversos formatos (SOT23, DIP, SOIC, TQFP,
etc).
Neste projeto utilizamos um microcontrolador da família PIC, pelo fato de ser
bastante poderoso e já ter sido estudado durante o curso de Engenharia Elétrica. Seu
modelo é o PIC 16F877 e tem as seguintes características [3]:
• 40 pinos, o que possibilita a montagem de um hardware capaz de
interagir com diversos recursos e funções ao mesmo tempo;
• Via de programação com 14 bits e 35 instruções;
• 33 portas configuráveis como entrada ou saída;
• Memória de programação E2PROM FLASH, permitindo a gravação
rápida do programa diversas vezes no mesmo chip, sem a necessidade
de apagá-lo por meio de luz ultravioleta;
• Memória de programa com 8kwords, com capacidade de escrita e
leitura pelo próprio código interno;
• Memória E2PROM (não-volátil) interna com 256 bytes;
• Memória RAM com 368 bytes;
• Comunicações seriais: SPI, I2C e USART;
• Dois módulos CCP: Capture, Compare e PWM.

1.2 A Plotter
É o objeto principal deste trabalho. A plotter HP Draft Pro modelo 7570A se
encontra no laboratório de microprocessadores da Universidade Federal do Espírito
Santo.
11

Uma plotter é uma impressora destinada a imprimir desenhos em grandes
dimensões, com elevada qualidade e rigor como, por exemplo, plantas arquitetônicas e
mapas cartográficos.
Primeiramente destinada à impressão de desenhos vetoriais, atualmente
encontram-se em avançado estado de evolução, permitindo impressão de imagens em
grande formato com qualidade fotográfica [11].
Possui uma série de comandos padronizados para realização de diversas
funções, tais como desenhar arcos, linhas cheias, linhas tracejadas, caracteres,
preenchimento de polígonos, entre outros. Neste projeto vamos nos concentrar em
alguns de seus comandos mais básicos. A plotter utilizada neste projeto se apresenta na
figura 3.

Figura 3 - A plotter HP Draft Pro 7570A.

A visualização de seus motores é apresentada na figura 4 abaixo, onde se pode
ver o motor que puxa o papel na parte de cima, com o cilindro que move o papel, e o
motor que move a pena, que se desloca por meio de uma grande correia, ao longo do
eixo cilíndrico.
12

Figura 4 - Detalhes dos motores da plotter.

HPGL é a linguagem de controle primária das impressoras usada pelas plotters
da Hewlett-Packard. HPGL significa Hewlett-Packard Graphics Language (Linguagem
Gráfica da Hewlett-Packard), e mais tarde se tornou padrão para quase todas as
plotters.
Esta linguagem é formada por uma série de duas letras, seguida por parâmetros
opcionais. Por exemplo, um arco pode ser desenhado em uma página através do
seguinte comando: AA100,100,50;
Isto significa Arc Absolute (Arco Absoluto) e seus parâmetros definem o centro
do arco em 100,100 no seu sistema de coordenadas, com um ângulo inicial de 50 graus
anti-horário. Seu sistema de coordenadas foi baseado na menor unidade que estes
equipamentos podem suportar, e foi setado em 25μm.
Para este projeto, foi definida uma linguagem específica para o controle dos
motores, que será explicada com detalhes mais à frente.
13

2 O CIRCUITO DO CONTROLADOR

A comunicação serial entre o PC e a Plotter e o controle dos motores foram
realizados por meio de um circuito eletrônico construído em uma placa universal,
contendo um microcontrolador PIC 16F877 da Microchip®, um chip L298 que
contém duas pontes H para acionamento dos dois motores DC de 12 V da Plotter, dois
chips de encoder HCTL2016, um flip flop para dividir o clock para os chips de
encoder, um chip MAX232 para comunicação serial, um oscilador de 16MHz, além de
diodos, resistores, leds, capacitores e conectores. O circuito eletrônico construído está
apresentado na figura 5 e seu esquema é apresentado na figura 6.
O circuito é alimentado com tensões de 5V para os chips e 12V para os motores
e as pontes H do LM298, e possui as seguintes funcionalidades:
• Led indicador de alimentação;
• Led acionável pelo circuito;
• Comunicação com o PC através da porta serial;
• Controlar a direção de movimentação dos motores;
• Alterar o estado lógico de alguns pinos do PIC;
• Ler o estado lógico de alguns pinos do PIC.

Figura 5 - O circuito de comunicação serial.
14

Figura 6 – Esquema do circuito.
15

2.1 O PIC
O PIC é o elemento principal do circuito. A comunicação entre o PC e o PIC é
feita por um programa escrito em PICC e gravado na memória do PIC. Este programa
é chamado firmware, e recebe os dados enviados pelo PC através da porta serial,
interpreta-os, e executa os comandos correspondentes no PIC. A sua pinagem é
apresentada na figura 7 a seguir.

Figura 7 - O PIC.

São utilizados os dois pinos de CCP no modo PWM para a movimentação dos
motores através da ponte H (chip L298). Para que estes pinos funcionem corretamente,
é preciso que o timer 2 seja configurado, definindo a freqüência do sinal PWM [2].
A ponte H é acionada pelos pinos RB1, RB2, RB4 e RB5 do PIC que fazem a
função de comandar o sentido de giro dos motores. E os pinos CCP (RC1 e RC2)
ligados aos pinos de Enable da ponte irão funcionar como reguladores de velocidade
com a qual os motores irão girar.
Os chips de encoder possuem um barramento de 8 bits no qual a palavra
incrementada ou decrementada relativa aos encoders dos motores é lida pelo PIC
através da sua porta paralela, que correspondem aos pinos RD0, RD1, RD2, RD3,
RD4, RD5, RD6 e RD7.
16

Os pinos RC7 e RC6 são utilizados, respectivamente, como receptor e
transmissor da comunicação serial do PIC. Estes pinos são conectados ao chip
MAX232 que faz a interface com a porta serial do PC. Este chip será descrito melhor
mais à frente.

2.2 Os Chips de Encoder
O HCTL2016 é um circuito integrado que executa as funções de decodificador
em quadratura, contador e interface com o barramento. Este chip possui dois canais
(CHA e CHB) para a entrada do sinal em quadratura, e um barramento de 8 bits de
saída do sinal decodificado. Neste projeto, foram utilizados dois chips HCTL2016,
apresentados na figura 8, operando em 8MHz, sendo necessária a utilização de um flip
flop para a divisão do clock proveniente do oscilador de 16MHz [5].
Os pinos CHA e CHB são ligados aos sinais em quadratura provenientes dos
encoders dos motores, e os pinos D0 a D7 são conectados aos pinos RD0 a RD7 do
PIC. Como são utilizados dois destes chips, este barramento de 8 bits do PIC é
compartilhado pelos dois chips, porém, através de comandos via software, estes chips
nunca irão enviar seus dados pelo barramento ao mesmo tempo.

Figura 8 - HCTL2016.
17

2.3 O Chip MAX232
O chip MAX232 é um transmissor/receptor duplo que inclui um gerador
capacitivo de tensão para fornecer níveis de tensão EIA-232 (-15V a +15V) a partir de
uma única fonte de 5V. Cada receptor converte as entradas EIA-232 aos níveis de 5V
TTL/CMOS. Cada transmissor converte níveis de entrada TTL/CMOS nos níveis EIA-
232 [6].
Para este projeto foi utilizada apenas uma das duas vias de RX/TX do
MAX232 conectado aos pinos RC6 e RC7 do PIC, transmissor e receptor,
respectivamente. O esquema da ligação do PC com a placa é mostrado na figura 9.

Figura 9 - Esquema da ligação serial.

2.4 O L298
O circuito integrado L298, apresentado na figura 10, é um driver duplo de alta
tensão e alta corrente projetado para aceitar níveis lógicos TTL e comandar cargas
indutivas como relés, solenóides, motores CC e de passo. Os dois pinos de Enable
permitem habilitar e desabilitar o dispositivo independentemente dos sinais de entrada.
Possui o emissor dos transistores ligados ao pino de SENSE onde, acoplando-se um
resistor externo, pode-se obter uma tensão proporcional à corrente drenada por cada
ponte. Devido a sua alta corrente, o chip foi montado sobre um dissipador térmico,
para evitar aquecimento excessivo [7].
18

Figura 10 - O L298.

Com os pinos de entradas e Enable ligados ao PIC, é possível acionar os
motores que estão conectados aos pinos de saída do L298, possibilitando o controle da
direção de giro, a partir dos pinos de entrada, e o controle da tensão fornecida para
cada motor, a partir dos pinos de Enable conectados aos pinos de PWM do PIC que
fazem o chaveamento dos transistores do chip que controlam a tensão de saída. O
diagrama de blocos do L298 é mostrado na figura 11.

Figura 11 - Diagrama de blocos da ponte H dupla L298.
19

3 A PROGRAMAÇÃO

3.1 Programando o PIC
Para que a comunicação serial e o acionamento dos motores funcionem, é
preciso que o PIC seja programado com um software adequado, elaborado em uma
linguagem robusta e eficiente. Neste projeto, foi utilizada a Linguagem C para
construir o software a ser carregado no PIC.

3.2 Funcionamento do programa
A execução do programa é feita basicamente através de interrupções, que
serão explicadas mais à frente. O programa fica em um loop infinito e, quando
acontece uma interrupção, ocorre um “desvio” para realizar a função definida pela
interrupção. Assim que as funções terminam, o programa volta ao loop infinito,
esperando uma nova interrupção.
O programa possui várias funções para que ele seja executado de modo mais
eficaz. As funções pid_m1() e pid_m2() são análogas, cada uma para cada motor da
plotter, e calcula o ciclo de trabalho (duty cicle) dos pwms do PIC a partir das
posições atuais e desejadas (no caso, chamadas referências no software) e os termos
proporcional, integral e derivativo dos motores. O trecho do programa com o código
da função pid_m1() é descrito abaixo.
void pid_m1()
{
u0_m1 = (signed long int)(p_ref_m1)-p_atual_m1;
vpid_m1.ypid = (signed int32)kp_m1 * u0_m1;
if (!saturated_m1)
{
integral_m1 +=(signed int32)u0_m1;
if (integral_m1 < -30000) integral_m1=-30000;
else
if (integral_m1 > 30000) integral_m1=30000;
}
vpid_m1.ypid+= (signed int32)ki_m1*integral_m1;
vpid_m1.ypid+= (signed int32)kd_m1*(u0_m1-u1_m1);
20
if (vpid_m1.ypid<-8388607) vpid_m1.ypid= -8388607;
else
if (vpid_m1.ypid>8388607) vpid_m1.ypid=8388607;
vpid_m1.b[0]=vpid_m1.b[1];
vpid_m1.b[1]=vpid_m1.b[2];
ypwm_m1= vpid_m1.i[0];
u1_m1 = u0_m1;
saturated_m1 = 0;
if (ypwm_m1 > 0) ypwm_m1=ypwm_m1+500;
else if (ypwm_m1 < 0) ypwm_m1=ypwm_m1-500;
if(ypwm_m1 > 1000)
{
ypwm_m1 = 1000;
saturated_m1 = 1;
}
else if(ypwm_m1 < -1000)
{
ypwm_m1 = -1000;
saturated_m1 = 1;
}
if (ypwm_m1 >0)
{
output_high(PIN_B2);
output_low(PIN_B1);
}
else if (ypwm_m1 <0)
{
output_high(PIN_B1);
output_low(PIN_B2);
ypwm_m1=-ypwm_m1;
}
set_pwm1_duty(ypwm_m1);
}

Pode-se observar também um trecho desta função onde a variável ypwm_m1
é incrementada ou decrementada de um fator de 500. Isto se deve ao fato de que,
durante a execução do projeto, foi verificado que os motores possuem uma zona morta
e não conseguem se mover, ficando frouxos, até que esta variável esteja em torno de
21

500. Deste modo, foi necessário introduzir este offset para o melhor funcionamento
dos motores.
Como se pode observar na parte final do código, quando a variável ypwm_m1
é maior que zero, o motor m1 gira em uma direção (direção de incremento do
encoder). Quando ypwm_m1 é menor que zero, o motor gira na direção contrária
(direção de decremento do encoder).
É necessário também ler as posições dos encoders dos motores, e para isto as
funções zera_hctl(), zera_hctl2(), le_hctl() e le_hctl2() foram elaboradas. Toda vez
que o programa é iniciado as funções zera_hctl() e zera_hctl2() são executadas para
que os valores dos encoders dos motores sejam iniciados com zero. O código da
função zera_hctl() é apresentado abaixo.
void zera_hctl()
{
// coloca oe do hctl2016 em 1
output_high(PIN_A1);
// coloca SEL do hctl2016 em 0
output_low(PIN_A0);
// coloca Reset do hctl2016 em 1
output_high(PIN_A2);
output_low(PIN_A2);
delay_us(1);
output_high(PIN_A2);
p_atual_m1=0;
}

Durante o programa é preciso atualizar as posições dos motores, e as funções
le_hctl() e le_hctl2() têm tal objetivo. Abaixo pode-se ver o código da função
le_hctl().
void le_hctl()
{
signed long int p_at1;
// para inibir atualização SEL=0 e OE=0 por mais de 1 tclk
output_low(PIN_A1); // SEL já é zero, coloca OE em 0
delay_us(2);
// portd tem o high byte
22
p_at1=input_D();
output_high(PIN_A0); //SEL=1 low byte
delay_us(1);
p_at1=(p_at1<<8) + input_D();
p_atual_m1=p_at1;
output_high(PIN_A1); //volta OE para 1
delay_us(1);
output_low(PIN_A0); // volta SEL para 0
}

A função rs232_envia() é responsável pelo envio das posições atuais dos
motores via porta serial, para o PC e sua rotina é apresentada abaixo. Seu código é
mostrado abaixo.
void rs232_envia()
{
le_hctl();
printf("%Ld\n\r", p_atual_m1);
le_hctl2();
printf("%Ld\n\r", p_atual_m2);
}

3.2.1 Mudando os parâmetros do PID
Foi criada uma rotina para fazer o ajuste dos parâmetros do PID enquanto o
circuito estivesse ligado, para evitar que o PIC fosse regravado toda vez que um
parâmetro fosse mudado. Esta rotina foi implementada dentro da interrupção da porta
serial, que será apresentada mais à frente.
O código desta rotina está apresentado logo abaixo.
if (dados[x] == 0x2b) { x = 0;
a = a*10;
}
if (dados[x] == 0x2d) { x = 0;
a = a/10;
}
if (dados[x] == 0x61) { x = 0;
kp_m1 = kp_m1+a;
kp_m2 = kp_m2+a;
23
}
if (dados[x] == 0x62) { x = 0;
kp_m1 = kp_m1-a;
kp_m2 = kp_m2-a;
}
if (dados[x] == 0x63) { x = 0;
ki_m1 = ki_m1+a;
ki_m2 = ki_m2+a;
}
if (dados[x] == 0x64) { x = 0;
ki_m1 = ki_m2-a;
ki_m2 = ki_m2-a;
}
if (dados[x] == 0x65) { x = 0;
kd_m1 = kd_m1+a;
kd_m2 = kd_m2+a;
}
if (dados[x] == 0x66) { x = 0;
kd_m1 = kd_m1-a;
kd_m2 = kd_m2-a;
}
O ajuste é feito somando ou subtraindo um valor múltiplo de dez, que é
definido pressionando as teclas “+” para multiplicar o valor por dez, e “-“ para dividir
este valor por dez.
Com este valor correto, o próximo passo é ajustar o parâmetro do PID. O
parâmetro proporcional é incrementado pressionando-se a tecla “a”, e decrementado
pressionando-se a tecla “b”. Analogamente, o parâmetro integral é incrementado ou
decrementado pressionando-se as teclas “c” e “d”, respectivamente. Por fim, o
parâmetro derivativo utiliza as teclas “e” e “f” para incrementar ou decrementar seu
valor. Todos os comandos estão resumidos mais à frente.
Vale lembrar que nesta rotina os parâmetros dos dois motores são ajustados ao
mesmo tempo. Para o ajuste neste projeto, foi desconectado um motor e feito o ajuste
para o outro motor que permaneceu conectado.
24

3.2.2 As interrupções
As principais funções deste programa são executadas através das interrupções
de Timer 0 e de recepção pela porta serial.

3.2.2.1 A interrupção de Timer 0
Esta interrupção sempre acontece quando o contador Timer 0 estoura, ou seja,
sempre que ele passar de 0xFF para 0x00. A cada estouro deste contador a variável
conta é incrementada. No momento em que a variável conta chega a 5, as funções
le_hctl(), le_hctl2(), pid_m1() e pid_m2() são executadas, e a variável conta é zerada,
recomeçando o ciclo. Cada ciclo dura aproximadamente 10ms e seu código é
apresentado abaixo.
#int_timer0
void contador() {
conta++;
if (conta == 5) {
le_hctl();
le_hctl2();
pid_m1();
pid_m2();
conta=0;
}
}

3.2.2.2 A interrupção de recepção pela porta serial
Esta interrupção acontece quando um dado é recebido pela porta serial. Este
projeto foi concebido com duas formas de receber dados, por caracteres digitados no
teclado ou por envio dos dados através de um programa em Assembly.
Estes dados recebidos pelo software são analisados e, se o primeiro caractere
recebido for o caractere “r”, o programa reconhece a entrada de dados pelo teclado e
espera receber mais 6 caracteres. O próximo caractere é a escolha do motor a ser
acionado e os últimos 5 caracteres, em forma de dígitos, definem a posição que o
motor deverá alcançar.
25

Se o primeiro caractere recebido for “s”, o envio de dados está sendo feito
através de um programa em Assembly, e assim o software do PIC saberá que deve
aguardar mais 3 bytes, com o primeiro definindo qual motor será acionado e os dois
últimos, em formato decimal, a posição desejada para o motor. O programa completo
se encontra no apêndice A.

3.3 Resumo dos comandos
Na tabela abaixo é possível ver o resumo de todos os comandos aplicados ao
circuito controlador.

Caractere enviado Comando realizado pelo circuito
Indica o recebimento de dados pelo teclado, aguarda a escolha do motor (“1”
r escolhe o motor 1 e “2” escolhe o motor 2) e em seguida aguarda a posição desejada
(através de cinco caracteres numéricos)
Indica o recebimento de dados pelo programa em Assembly, aguarda a escolha do
s motor (“1” escolhe o motor 1 e “2” escolhe o motor 2) e em seguida aguarda a
posição desejada (através de dois bytes)

a Incrementa o termo proporcional dos motores de um fator “a”

b Decrementa o termo proporcional dos motores de um fator “a”

c Incrementa o termo integral dos motores de um fator “a”

d Decrementa o termo integral dos motores de um fator “a”

e Incrementa o termo derivativo dos motores de um fator “a”

f Decrementa o termo derivativo dos motores de um fator “a”

+ Multiplica o fator “a” por 10

- Divide o fator “a” por 10

Tabela 1 - Comandos implementados no projeto.

3.4 Comandos interessantes
Para aplicações futuras, alguns comandos podem ser implementados ou
melhorados conforme a aplicação que se desejar. Um destes melhoramentos seria a
possibilidade de ajustar os parâmetros do PID independentemente para cada motor,
26

sem a necessidade de desconectar um motor. Isto pode ser feito facilmente mudando a
respectiva rotina sem grandes problemas.
Uma nova implementação é a utilização da pena da plotter, acionando o relé
para levantar ou abaixar a pena, já que toda conexão existe na plotter e é de fácil
manuseio. Este comando não foi implementado neste projeto porquê não foi possível
acionar o relé. Fica a idéia para projetos futuros.
27

4 RESULTADOS OBTIDOS

Foram realizados alguns testes e colhidos valores para análise dos erros,
overshoots, que estão apresentados nas tabelas a seguir, para cada motor.

Pos. Atual M1 Pos. Ref. M1 Pos. Final M1 Erro Overshoot
0 4000 4000 0 0
4000 7000 7000 0 7015
7000 15000 15000 0 15200
15000 5000 5000 0 4930
5000 3000 3000 0 3005
3000 2500 2502 2 2470
2502 0 1 1 -20
Tabela 2 - Resultados para o Motor 1, que puxa o papel.

Pos. Atual M2 Pos. Ref. M2 Pos. Final M2 Erro Overshoot
0 4000 4005 5 4009
4005 7000 7003 3 7004
7003 15000 15002 2 15003
15002 5000 5000 0 4996
5000 3000 2998 -2 2998
2998 2500 2495 -5 2494
2495 0 -1 -1 -1
Tabela 3 - Resultados para o Motor 2, que movimenta a pena.
28

5 CONSIDERAÇÕES FINAIS

O universo de aplicações dos microcontroladores está em grande expansão,
sendo que a maior parcela dessas aplicações é em sistemas embutidos. A expressão
“sistema embutido” se refere ao fato do microcontrolador ser inserido nas aplicações
(produtos) e usado de forma exclusiva por elas. Neste projeto foi possível construir um
sistema de comunicação serial com um PC que possibilitou o acionamento e controle
de motores de uma plotter gerenciados pelo microcontrolador.
O objetivo do projeto foi alcançado, pois é possível controlar a posição dos
motores da plotter, gerenciados pelo PIC. Estes motores se movimentam de forma
independente, definida na programação do PIC, proporcionando curvas e diagonais
mais precisas.
Este projeto reuniu uma gama de conhecimentos adquiridos ao longo do curso
de Engenharia Elétrica, dos quais podemos citar conhecimentos de eletrônica ao
construir a placa, programação, ao elaborar o software, e controle, realizando um
algoritmo PID para comandar de forma eficiente os motores.
O projeto ultrapassou o cronograma previsto no anteprojeto já que a
programação e teste exigiram um tempo maior de utilização do PC que se liga à
plotter, e o mesmo teve de ser compartilhado com alunos que estavam elaborando
outros trabalhos.
Devido a problemas da plotter, como desgaste das peças, motores velhos,
correias e roldanas danificadas, não foi possível realizar o controle ótimo dos motores,
ocorrendo um pequeno desvio algumas vezes quando os motores são acionados.
Porém, isto não impediu a conclusão do projeto de modo satisfatório, e este
equipamento está apto a fazer parte das experiências de laboratório da disciplina
Microprocessadores I, como proposto inicialmente.
29

APÊNDICE A

#include "C:\clp\teste_led.h"
#include <stdlib.h>

int conta;
int x = 0;
int a = 1;
char dados[7],posicao[6];

unsigned char saturated_m1, saturated_m2; // indica que saída do PID esta saturada

signed long int
// posicao atual
p_atual_m1,p_atual_m2,

// posicao desejada
p_ref_m1,p_ref_m2;

signed long int
// current and previous position error
u0_m1,u1_m1,u0_m2,u1_m2,

// PID gain constants
kp_m1,ki_m1,kd_m1,kp_m2,ki_m2,kd_m2,

// duty cycle derivado do cálculo do PID
ypwm_m1,ypwm_m2,pwm1,pwm2;

signed int32 integral_m1,integral_m2; // PID error accumulation

//********************************//
// PID //
//********************************//

union
{
signed int32 ypid;
signed long int i[2];
30
char b[4];
} vpid_m1; // Used to hold result of the PID calculations.

void pid_m1()
{
u0_m1 = (signed long int)(p_ref_m1)-p_atual_m1; // Put position error in
u0.

// Calculate proportional term of
PID

vpid_m1.ypid = (signed int32)kp_m1 * u0_m1;

if (!saturated_m1) // Bypass integration if saturated.
{
integral_m1 +=(signed int32)u0_m1;

if (integral_m1 < -30000) integral_m1=-30000;
else
if (integral_m1 > 30000) integral_m1=30000;

}

vpid_m1.ypid+= (signed int32)ki_m1*integral_m1; // Calculate integral term of PID

vpid_m1.ypid+= (signed int32)kd_m1*(u0_m1-u1_m1); // Calculate differential term of PID

if (vpid_m1.ypid<-8388607) vpid_m1.ypid= -8388607; // If PID result is negative limit result
// to 24-bit value
else
if (vpid_m1.ypid>8388607) vpid_m1.ypid=8388607; // If PID result is positive limit result
// to 24-bit value
vpid_m1.b[0]=vpid_m1.b[1];
vpid_m1.b[1]=vpid_m1.b[2]; // Shift PID result right to get upper
// 16 bits of 24-bit result in
ypwm_m1= vpid_m1.i[0];

u1_m1 = u0_m1; // Save current error in u1
31
saturated_m1 = 0; // Clear saturation flag

if (ypwm_m1 > 0) ypwm_m1=ypwm_m1+500;
else if (ypwm_m1 < 0) ypwm_m1=ypwm_m1-500;

if(ypwm_m1 > 1000)
{
ypwm_m1 = 1000;
saturated_m1 = 1;
}
else if(ypwm_m1 < -1000)
{
ypwm_m1 = -1000;
saturated_m1 = 1;
}

pwm1=ypwm_m1;
if (ypwm_m1 >0)
{
output_high(PIN_B2);
output_low(PIN_B1);
}
else if (ypwm_m1 <0)
{
output_high(PIN_B1);
output_low(PIN_B2);
ypwm_m1=-ypwm_m1;
}
set_pwm1_duty(ypwm_m1);

}

union
{
signed int32 ypid2;
signed long int j[2];
char c[4];
} vpid_m2; // Used to hold result of the PID calculations.
32
void pid_m2()
{
u0_m2 = (signed long int)(p_ref_m2)-p_atual_m2; // Put position error in
u0.

// Calculate proportional term of
PID

vpid_m2.ypid2 = (signed int32)kp_m2 * u0_m2;

if (!saturated_m2) // Bypass integration if saturated.
{
integral_m2 +=(signed int32)u0_m2;

if (integral_m2 < -256000) integral_m2=-256000;
else
if (integral_m2 > 256000) integral_m2=256000;

}

vpid_m2.ypid2+= (signed int32)ki_m2*integral_m2; // Calculate integral term of PID

vpid_m2.ypid2+= (signed int32)kd_m2*(u0_m2-u1_m2); // Calculate differential term of
PID

if (vpid_m2.ypid2<-8388607) vpid_m2.ypid2= -8388607; // If PID result is negative limit result
// to 24-bit value
else
if (vpid_m2.ypid2>8388607) vpid_m2.ypid2= 8388607; // If PID result is positive limit result
// to 24-bit value
vpid_m2.c[0]=vpid_m2.c[1];
vpid_m2.c[1]=vpid_m2.c[2]; // Shift PID result right to get upper
// 16 bits of 24-bit result in
ypwm_m2= vpid_m2.j[0];

u1_m2 = u0_m2; // Save current error in u1

saturated_m2 = 0; // Clear saturation flag
33
if(ypwm_m2 > 800)
{
ypwm_m2 = 800;
saturated_m2 = 1;
}
else if(ypwm_m2 < -800)
{
ypwm_m2 = -800;
saturated_m2 = 1;
}

pwm2=ypwm_m2;
if (ypwm_m2 >0)
{ output_high(PIN_B5);
output_low(PIN_B4);
}
else
{ output_high(PIN_B4);
output_low(PIN_B5);
ypwm_m2=-ypwm_m2;
}
set_pwm2_duty(ypwm_m2);

}

//********************************//
// HCTL2016 //
//********************************//

void zera_hctl()
{
// coloca oe do hctl2016 em 1
output_high(PIN_A1);
// coloca SEL do hctl2016 em 0
output_low(PIN_A0);
// coloca Reset do hctl2016 em 1
output_high(PIN_A2);
output_low(PIN_A2);
delay_us(1);
34
output_high(PIN_A2);
p_atual_m1=0;
}
void le_hctl()
{
signed long int p_at1;
// para inibir atualização SEL=0 e OE=0 por mais de 1 tclk
output_low(PIN_A1); // SEL já é zero, coloca OE em 0
delay_us(2);
// portd tem o high byte
p_at1=input_D();
output_high(PIN_A0); //SEL=1 low byte
delay_us(1);
p_at1=(p_at1<<8) + input_D();
p_atual_m1=p_at1;
output_high(PIN_A1); //volta OE para 1
delay_us(1);
output_low(PIN_A0); // volta SEL para 0
}
void zera_hctl2()
{
// coloca oe do hctl2016-2 em 1
output_high(PIN_A4);
// coloca SEL do hctl2016-2 em 0
output_low(PIN_A3);
// coloca Reset do hctl2016 em 1
output_high(PIN_A2);
output_low(PIN_A2);
delay_us(1);
output_high(PIN_A2);
p_atual_m2=0;
}
void le_hctl2()
{
signed long int p_at2;
// para inibir atualização SEL=0 e OE=0 por mais de 1 tclk
output_low(PIN_A4); // SEL já é zero, coloca OE em 0
delay_us(2);
// portd tem o high byte
35
p_at2=input_D();
output_high(PIN_A3); //SEL=1 low byte
delay_us(1);
p_at2=(p_at2<<8) + input_D();
p_atual_m2=p_at2;
output_high(PIN_A4); //volta OE para 1
delay_us(1);
output_low(PIN_A3); // volta SEL para 0
}

//********************************//
// Recebendo dados //
//********************************//

#INT_RDA
void rs232_recebe()
{
dados[x] = getc();

if (dados[x] == 0x72) { x = 0;
dados[0]=0x72;
}
if (dados[x] == 0x73) { x = 0;
dados[0]=0x73;
}
if (dados[x] == 0x2b) { x = 0;
a = a*10;
}
if (dados[x] == 0x2d) { x = 0;
a = a/10;
}
if (dados[x] == 0x61) { x = 0;
kp_m1 = kp_m1+a;
kp_m2 = kp_m2+a;
}
if (dados[x] == 0x62) { x = 0;
kp_m1 = kp_m1-a;
kp_m2 = kp_m2-a;
}
36
if (dados[x] == 0x63) { x = 0;
ki_m1 = ki_m1+a;
ki_m2 = ki_m2+a;
}
if (dados[x] == 0x64) { x = 0;
ki_m1 = ki_m2-a;
ki_m2 = ki_m2-a;
}
if (dados[x] == 0x65) { x = 0;
kd_m1 = kd_m1+a;
kd_m2 = kd_m2+a;
}
if (dados[x] == 0x66) { x = 0;
kd_m1 = kd_m1-a;
kd_m2 = kd_m2-a;
}

// Recebendo dados do teclado

if (dados[0] == 0x72) x++;
if (x == 7)
{
x = 0;
posicao[0]=dados[2];
posicao[1]=dados[3];
posicao[2]=dados[4];
posicao[3]=dados[5];
posicao[4]=dados[6];
posicao[5] = 0;
if (dados[1] == 0x31)
{
p_ref_m1=atol(posicao);
printf("1 %Ld\n\r", p_ref_m1);
}
else if (dados[1] == 0x32)
{
p_ref_m2=atol(posicao);
printf("2 %Ld\n\r", p_ref_m2);
}
37
else printf("Escolha incorreta do motor\n\r");
}

// Recebendo dados do programa em Assembly

if (dados[0] == 0x73)
{
x++;
if (x == 4)
{
x = 0;
if (dados[1] == 0x31)
{
p_ref_m1=dados[2];
p_ref_m1=(p_ref_m1<<8) + dados[3];
}
else if (dados[1] == 0x32)
{
p_ref_m2=dados[2];
p_ref_m2=(p_ref_m2<<8) + dados[3];
}
else printf("Escolha incorreta do motor\n\r");
}
}
if (input(PIN_B7)) output_low(PIN_B7); // desliga led
else output_high(PIN_B7);
}

//********************************//
// Enviando dados //
//********************************//

void rs232_envia()
{
le_hctl();
printf("%Ld\n\r", p_atual_m1);
le_hctl2();
printf("%Ld\n\r", p_atual_m2);
}
38

#int_timer0
void contador()
{
conta++;
if (conta == 5)
{
le_hctl();
le_hctl2();
pid_m1();
pid_m2();
conta=0;
}
}

//********************************//
// Programa principal //
//********************************//

void main()
{
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_32);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DIV_BY_1, 255,1);
SET_TRIS_A( 0xe0 );
SET_TRIS_B( 0x00 );
SET_TRIS_D( 0xff );
setup_ccp1(CCP_PWM);
setup_ccp2(CCP_PWM);
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
enable_interrupts(INT_TIMER0);
zera_hctl();
zera_hctl2();
putc(0x0c);
39
printf("Projeto de Graduação\n\r");
printf("Aluno Sergio Pazzini da Silva Matos\n\r");
printf("\n\r");

u1_m1=0;
u1_m2=0;
saturated_m1=0;
saturated_m2=0;
integral_m1=0;
integral_m2=0;

// Ganhos do PID

kp_m1=200;
kp_m2=200;
ki_m1=7;
ki_m2=7;
kd_m1=300;
kd_m2=300;

conta=0;
p_ref_m1=0;
p_ref_m2=0;

while (true)
{
rs232_envia();
delay_ms(500);
}
}
40

REFERÊNCIAS BIBLIOGRÁFICAS

[1] DORF, Richard G.; BISHOP, Robert H. Sistemas de Controle Modernos. 8ª ed. Rio de
Janeiro: LTC – Livros Técnicos e Científicos, Editora SA, 2001;

[2] PEREIRA, Fábio. Microcontroladores PIC - Programação em C. 4ª ed. São Paulo:
Editora Érica LTDA, 2005;

[3] SOUZA, David José de; LAVINIA, Nicolás César. Conectando o PIC. 2ª ed. São Paulo:
Editora Érica LTDA, 2005;

[4] Datasheet do microcontrolador PIC 16F87X Disponível: http://www.microchip.com
[capturado em 26/03/2006];

[5] Datasheet do chip HCTL2016 Disponível: http://pdf1.alldatasheet.com/datasheet-
pdf/view/64648/HP/HCTL-2016.html? [capturado em 26/03/2006];

[6] Datasheet do chip MAX232 Disponível: http://www.alldatasheet.com/datasheet-
pdf/pdf/27224/TI/MAX232.html [capturado em 26/03/2006];

[7] Datasheet do chip L298 Disponível: http://www.alldatasheet.com/datasheet-
pdf/pdf/22437/STMICROELECTRONICS/L298.html [capturado em 26/03/2006];

[8] Curso de Linguagem C da Universidade Federal de Minas Gerais, Apostila;

[9] Notas de aula sobre a Linguagem Assembly;

[10] http://www.microchipc.com [acessado em 30/03/2006];

[11] http://pt.wikipedia.org/wiki/Plotter [acessado em 20/01/2006];

[12] http://pt.wikipedia.org/wiki/Microcontrolador [acessado em 01/02/2007].