Sistema de Acesso Remoto Via Comunicação Serial PDF
Sistema de Acesso Remoto Via Comunicação Serial PDF
Sistema de Acesso Remoto Via Comunicação Serial PDF
1 Introdução ........................................................................................................... 7
1.1 Ensino a distância ................................................................................................... 7
1.2 Inteligência Artificial .............................................................................................. 9
1.3 Controle Clássico e Controle Inteligente .............................................................. 11
1.4 Modelagem de Processos em Sistemas de Controle............................................. 12
1.5 Microcontroladores e Microprocessadores ........................................................... 13
7 Metodologia .................................................................................................... 37
9 Conclusões ....................................................................................................... 85
10 Bibliografia .................................................................................................. 88
Índice de Figuras
Figura 1 : Paradigmas de Inteligência Artificial ..................................................................... 9
Figura 2: Esquema da maquete utilizada no projeto............................................................. 31
Figura 3: Estrutura interna do PIC16F877A ........................................................................ 35
Figura 4: Topologia de um laboratório remoto com Servidor WEB dedicado. .................... 38
Figura 5: Maquete do Sistema Térmico antiga ..................................................................... 41
Figura 6: Arquitetura de comunicação de um laboratório remoto........................................ 48
Figura 7: Esquema de ligação do barramento RS-232C....................................................... 52
Figura 8: Esquema de comunicação através de barramento RS-485.................................... 54
Figura 9: Esquema de ligação de vários PIC´s através de um barramento CAN Bus .......... 55
Figura 10: Diagrama de execução do programa Servidor .................................................... 58
Figura 11: Sequência dos dados enviados pelos controladores ao programa Servidor ........ 61
Figura 12: Protocolo PC Barramento: Pedido de Transmissão ....................................... 64
Figura 13: Protocolo PC Barramento: Envio de Parâmetros ........................................... 64
Figura 14: Servidor esperando por uma conexão. ................................................................ 68
Figura 15: Servidor após receber uma conexão. .................................................................. 69
Figura 16: Sequência dos parâmetros enviados pelo Supervisório ao programa Servidor .. 69
Figura 17: Sequência dos dados enviados pelo programa Servidor ao Supervisório ........... 70
Figura 18: Diagrama do software Supervisório.................................................................... 71
Figura 19: Interface gráfica do Supervisório ........................................................................ 73
Figura 20: Critica de dados realizada pelo Supervisório: Campo digitado incorretamente . 74
Figura 21: Crítica de dados feita pelo Supervisório: Campo em Branco ............................. 74
Figura 22: Tela com todas curvas plotadas. ......................................................................... 75
Figura 23: Tela com apenas a duas curvas sendo plotadas................................................... 76
Figura 24: Interface após sair do experimento ..................................................................... 77
Figura 25: Dados gerados em um experimento. ................................................................... 78
Figura 26: Fluxograma do Cabeçalho Geral......................................................................... 80
Figura 27: Fluxograma do módulo “Controle PID” ............................................................. 84
Figura 28: Arquitetura da Rede Infinet................................................................................. 96
Figura 29: Arquitetura Interna de uma PCU. ....................................................................... 97
Figura 30: Fluxograma da parte inicial do módulo ‘Protocolo’ ........................................... 99
Índice de Tabelas
1 Introdução
O público alvo deste projeto são estudantes cursando disciplinas envolvidas na área
de automação e controle. Estes estudantes realizarão experimentos em casa, no campus
universitário ou em qualquer lugar do mundo com apenas um computador na internet. Os
alunos farão ajustes on-line nos parâmetros de controle e obterão a resposta completa
(gráfica, matemática e dados) do experimento em tempo real por meio do WEB Browser.
A simulação é tão boa quanto for o seu modelo matemático, entretanto a
experimentação tem a vantagem de oferecer ao usuário situações e fenômenos que são
difíceis ou impossíveis de simular. A experimentação remota permite que o uso de
equipamentos caros ou únicos seja compartilhado entre diferentes instituições (eg.
universidades). A filosofia do uso remoto de laboratórios está intimamente ligada ao
controle de sistemas físicos e suas aplicações extrapolam o universo do ensino à distância.
Muitas são as aplicações em outras áreas, como industrial, médica, comercial e
entretenimento.
A idéia principal de um laboratório remoto é usar a World Wide WEB como
plataforma de comunicação e o WEB Browser como sua interface. A internet provê a
plataforma para transmissão de informações enquanto o WEB Browser é o próprio
ambiente para execução do software cliente. O servidor WEB é o intermediário entre o
cliente e o experimento. Nesse sentido, serão estudadas as diversas soluções
computacionais razoáveis com ênfase na interação em tempo real entre o usuário e o
processo. Mais ainda, premissas educacionais e computacionais mínimas associadas à
qualidade de ensino a distância serão investigadas e adotadas neste projeto.
2.1 CLP
2.2 SDCD
2.3 Supervisório
• Quadro sinótico;
• Software de supervisão, também chamado Software Supervisório (SCADA -
Supervisory Control And Data Acquisition System);
• Interface Homem Máquina (IHM).
3.1 RS-232C
3.3 RS-485
configurando, assim, uma rede robusta. Este fator é de suma importância para a integridade
de um sistema.
Hoje em dia, tem-se tomado ciência do problema de interferência nas indústrias, e
tem-se protegido os equipamentos de forma abrangente: pela alimentação, pela
comunicação (RS-485), pelos sensores do campo, enfim, blindando o sistema com todos os
recursos disponíveis. A rede RS-485 permite em alguns casos distâncias de até 1200 metros
entre um terminal e outro.
A taxa de transferência de dados é baixa por se tratar de comunicação serial. Seu
uso em sistemas de automação deve-se ao fato de não exigir equipamentos extras para
conexão de vários elementos (hubs, switches, repetidores etc.). O custo com cabeamento é
baixo. Geralmente, é utilizado para ligação entre CLP’s e módulos de aquisição de sinais.
Outro fator importante para adoção do protocolo RS-485 é a comunicação de um
sistema atual a ser trabalhado com o protocolo RS-232, pois existem no mercado empresas
que fazem conversores RS-232/RS-485. Porém não basta somente esta conversão do
protocolo elétrico, mas também a alteração no programa que acessa a porta serial RS-232,
porque o padrão RS-232 utiliza como modo de operação a transmissão full-duplex e
comunicação ponto a ponto, enquanto que o padrão RS-485 usa como modo de operação a
transmissão half-duplex.
Com a necessidade cada vez maior de redes Fieldbus, implementadas em indústrias,
escritórios e residências, de trocar informações com outras redes, tem-se a necessidade
primeira de se utilizar um conversor de protocolo para grandes distâncias, uma maior
velocidade de comunicação, e uma rede mais robusta (imune aos ruídos eletromagnéticos)
e, para tanto, o protocolo RS-485 é o protocolo elétrico mais utilizado em redes Fieldbus. A
tabela 02 a seguir faz uma comparação entre os padrões RS-232 e RS-485.
Definido o meio físico para a conexão dos equipamentos, deve-se analisar qual
protocolo será utilizado. Para que o sistema seja passível de ampliações futuras, é
importante que se utilizem protocolos abertos.
Diferentemente da interface RS-232 a RS-485 é um tipo de interface serial que
utiliza sinais diferenciais balanceados.
O padrão RS-485 permite compartilhar ao mesmo tempo a transmissão e a recepção
em uma linha balanceada. O intervalo de tensão de modo comum que o driver pode
suportar vai de -7 a + 12 Volts ainda quando ficam em estado de alta impedância.
Onde:
q = mc∆T
d (∆T ) 1 (2)
R= =
d (q) K (3)
q
C= = mc
∆T (4)
T (s) 1
= (5)
Tq ( s ) RCs + 1
À direita temos a sala 5 (1024 cm2) onde está presente um dos secadores. Ela possui
divisões de meia altura que a divide em 3 pequenas salas, com um sensor em cada uma
delas. Esse subsistema da maquete permite verificar se existe grande diferença de
temperatura entre pontos da mesma sala, lembrando que as divisões de meia altura são
apenas “decorativas”.
À esquerda temos a sala 1, menor (608 cm2), que também possui um secador,
podemos verificar a condição de um condicionador de ar muito potente para o tamanho da
sala, e assim poder fazer um controle de uma situação crítica. Vizinha a esta sala existe
outra pequena sala (384 cm2) que possibilita obter os parâmetros da resistência térmica da
madeira usada para a confecção da maquete e assim podermos verificar o quão adiabática
são as paredes de nosso sistema. Com os valores de resistência é possível modelar todo o
sistema, levando em conta que as paredes de todas as salas são de mesmo material.
Cada atuador (secador de cabelo) terá um circuito independente do outro. Circuitos
de potência para acionamento e os chips de controle (microcontroladores – PIC16F877)
serão independentes para cada secador.
Com a independência dos atuadores no controle do sistema será possível fazer a
conexão de cada controlador no barramento que fará a comunicação com o computador
servidor e assim tratá-los como experimentos independentes, já que será possível para o
usuário remoto fazer a comunicação com cada um dos controladores de forma
independente.
Algo a ser observado é que entre todos os periféricos a comunicação é feita através de um
barramento de 8 bits.
Um pouco mais ao centro da figura 3, podemos encontrar ainda o registrador de
status (STATUS reg), onde algumas informações importantes sobre a ULA ficam
armazenadas, e os demais SFRs (Special Function Registers). Na parte superior temos
ainda o contador “de linhas” de programa (Program Counter) e a pilha de 8 níveis (Stack).
Por fim, tem-se ainda os circuitos internos de reset, Power-on Reset (POR), Brown-
Out Reset (BOR), osciladores, Watchdog Timer (WDT) e sistemas de programação. As
demais características do microcontrolador são apresentadas no Apêndice H.
7 Metodologia
possibilite a comunicação com novos experimentos, que venham a ser desenvolvidos, sem
maiores dificuldades.
esta placa através da ref. [4] e [5]. As características procuradas foram encontradas na
referida placa, no entanto, o preço comercial da mesma apresentou-se alto (U$400,
quatrocentos dólares) para o presente projeto.
Outro fator que se apresentou de forma negativa para a implementação da
comunicação direta CAN foi à necessidade de utilizar os microcontroladores da família
PIC18f que são mais caros e difíceis de encontrar.
Após verificar a possibilidade de comunicação direta CAN, investigou-se a outra
forma de comunicação com o PIC que é através de sua porta serial (Interface USART).
Para isso, estudou-se, através da ref. [6] e [7], a forma como o PIC implementa esta
comunicação. Seguindo este mesmo padrão de comunicação, estudou-se a forma como os
PC´s atuais fazem a comunicação através da interface serial. As fontes de documentação
utilizada nesta fase foram alguns sites da internet e, em especial, o livro da ref. [8].
A documentação [8] trata da comunicação, através da porta serial do PC, utilizando
o padrão RS-232 e a linguagem de programação “C”. Porém, como descrito anteriormente,
a linguagem que será utilizada no computador servidor para fazer a comunicação com o
usuário remoto será Java. Sendo assim, uma solução bastante interessante seria fazer
também a comunicação com a porta serial através da linguagem Java, pois teríamos apenas
um programa comunicando tanto com o usuário remoto quanto com o microcontrolador.
Para verificar a possibilidade de fazer a comunicação com a porta serial do PC
através da linguagem Java o conteúdo da ref. [9] foi exaustivamente consultado. A partir
desta referência verificamos que é possível e bastante viável utilizar a linguagem Java para
fazer a comunicação serial. A Sun disponibiliza gratuitamente uma API (Applications
Programming Interface) completa de comunicação com a porta serial, a javax.comm.
Dessa maneira vimos que seria possível fazermos a comunicação serial utilizando o
padrão RS-232 entre o computador servidor e o microntrolador. Porém essa comunicação é
ponto-a-ponto e, assim, a priori permite a conexão de apenas um elemento à porta serial.
Com essa limitação decidimos manter esse padrão de comunicação tanto no computador
servidor como no microcontrolador e então fazer uma conversão de padrões de modo a
construir um barramento que possibilitasse a conexão de vários elementos, ou seja, vários
processos.
controle em sistemas térmicos [22] e que está sendo realizado em paralelo com o
desenvolvido por nós.
tentar abrir a porta COM2 e não mais a COM1. Com isso o programa não teve mais
problema na obtenção da porta para comunicação.
A partir do momento em que os PC´s estavam comunicando observamos que em um
dos PC’s (Sistema Opeacional Windows 98) as mensagens com mais de oito caracteres
eram divididas em mensagens de oito bytes (caracteres) e no outro (Sistema Operacional
Windows 2000) as mensagens eram divididas em 14 caracteres. No entanto, o problema
maior estava no fato de que nem sempre as mensagens do PC com windows 98 eram
divididas em 8 bytes às vezes apareciam mensagens com mais de 8 caracteres.
A questão da diferença no número de bytes em que as mensagens eram divididas
nos PC´s foi identificada como sendo configurações diferentes dos buffers de recepção e
transmissão das portas serias dos diferentes computadores. Porém o fato de que em alguns
momentos, as mensagens não estavam sendo divididas de tamanho fixo não era justificado.
A solução encontrada para não repetir este inconveniente foi configurar o buffer de
recepção do PC com windows 98 no máximo, ou seja, para 14 bytes. Com isso, este PC
passou a dividir as mensagens que recebiam em 14 caracteres de maneira fixa.
8 Resultados Obtidos
Usuαrio Remoto
Barramento no Laboratσrio
Web Server
assim apenas o resultado da operação solicitada pelo cliente. Dessa forma, o processamento
local necessário para o computador do cliente internet é reduzida.
Applets Java facilitam atualizações no software, pois um novo download é efetivado
a cada requisição de leitura do servidor WEB. Conseqüentemente, do ponto de vista do
usuário, nenhuma programação e/ou instalação de softwares é necessária para qualquer
atualização do sistema.
Barramento RS-232C
RX ...
TX ...
Barramento -- CAN
CAN
CAN
CAN
PIC16f877 PIC16f877
Processo 3
Processo 1 Processo 2
Inicia Programa
Servidor
Start
Thread – 1 Start
Dorme
Configura Socket
Evento na de comunicação
serial
Thread – 1
Acorda Não Recebeu
Conexão ?
Não Recebeu
Variável Dados ?
Enviar parâmetros Sim
Habilitada ?
Sim
Envia
Não parâmetros para
Controlador 1 e 2 Terminar
Envia dados para o Sim
Conexão ?
Applet
Não
Grava os dados em
arquivo É primeira vez
Não Sim
que está envia nd o
dados?
Thread – 1 Thread – 1
Dorme Dorme
Como pode ser visto no diagrama anterior, assim que o programa Servidor (Classe
Principal) entra em execução duas classes (Classes Internas), que possuem fluxos de
execução (Threads) independentes, são instanciadas e inicializadas.
Uma das classes (Classe – 1) trata da comunicação do PC com o barramento RS-
232, ou seja, realiza a comunicação bidirecional com os controladores de processo
conectados ao barramento.
A outra classe (Classe – 2) trata da comunicação do PC com o usuário remoto
(Supervisório). Esta, que também possui a característica bidirecional, permite que os dados
do processo sejam enviados para o Supervisório continuamente e que, em qualquer
momento, receba dados de configuração submetidos pelo usuário aos controladores de
processo.
Esta abordagem permite que partes do programa que possuem fluxos de execução
sejam executadas concorrentemente, ou seja, cada thread executa suas rotinas
independentemente de outras. Vale ressaltar que Java é a única, entre as linguagens de
programação de uso geral e popular, que torna as primitivas de concorrência disponíveis
para o programador de aplicativos.
A divisão do programa Servidor em duas threads principais permitiu maior
flexibilidade e eficiência na comunicação, já que o programa trata a comunicação com os
microcontroladores e com o Supervisório de forma independente, dispensando, então,
verificações desnecessárias pela chegada de novos dados que, por ventura, poderiam ter
sido enviados pelo usuário no mesmo barramento. Dessa maneira, o atributo velocidade de
execução das rotinas de recepção e envio de dados permitiu a consistência da característica
real-time do sistema.
As duas subseções a seguir fazem um detalhamento das classes utilizadas na
comunicação PC Servidor barramento e PC Servidor Supervisório
respectivamente.
Para a utilização da porta serial do PC, Java possui uma biblioteca de classes que
permite a programação, em alto nível, para configuração e utilização da mesma, sem ter
que recorrer aos atributos de E/S do Sistema Operacional vigente.
Sempre que o programa principal, Servidor, é executado ele cria uma instância
(Objeto) da Classe Interna – 2 (No código do programa esta classe possui o nome
“Conexão”). Esta classe, logo em sua criação, faz uma varredura pelo sistema com o intuito
de obter todas as portas conhecidas pelo SO. Dentre as portas verificadas o programa,
primeiro procura pelas portas seriais e, então, verifica se entre elas existe a porta “COM2”.
A escolha da porta “COM2” foi feita levando-se em consideração a sua presença na
maioria dos PC’s atuais. A não escolha da porta “COM1” se deve ao fato desta estar, quase
sempre, associada ao mouse do computador.
Encontrada a porta “COM2” o programa tenta obter sua utilização para a
comunicação com o barramento. Caso obtenha sucesso em sua abertura, o programa realiza
a configuração dos parâmetros de transmissão que serão realizados na comunicação. Os
parâmetros definidos foram os seguintes:
1 2 3 4 5
Número do Tempo Tempo Referência Referência
Controlador High Low High Low
6 7 8 9 10
Temperatura Temperatura Temperatura Temperatura Tensão
Sala-1 Sala-2 Sala-3 Ambiente Atuador
Figura 11: Sequência dos dados enviados pelos controladores ao programa Servidor
3
x(216-1), ou seja, 2293 segundos. Vale ressaltar que o campo tempo não é composto por
uma mensagem de 16 bits, mas sim por duas mensagens de 8 bits, já que a transmissão pela
serial foi configurada como tendo 8 bits de dados.
O quarto e quinto campo (Referência) correspondem ao valor de temperatura em
que deseja-se que a temperatura das salas estejam. O bit menos significativo da palavra
referência corresponde a 0,5 ºC.
O sexto, sétimo e oitavo campo correspondem aos valores de temperatura das salas
1, 2 e 3 das respectivas salas controladas pelo microcontrolador. O bit menos significativo
destas palavras corresponde a 0,5 ºC.
O nono campo (Temperatura Ambiente) corresponde à temperatura do ambiente em
que se encontram os atuadores. O bit menos significativo corresponde a 0,5 ºC.
E por fim, o décimo campo (Atuador) corresponde à tensão média a qual estão
submetidos os atuadores (secadores). Cada bit desta palavra corresponde a 1 Volt.
Sempre que um dado chega na porta serial, a thread-1, que faz o tratamento da
comunicação “barramento PC”, encontra-se no estado “dormindo”. Dessa maneira,
como pode ser visto na figura 10, a primeira ação que ocorre é “acordar” esta thread.
Estando a thread-1 “acordada” a mesma obterá os dados, que se encontram disponíveis no
buffer da porta, na seqüência definida pelo protocolo descrito anteriormente.
Assim que termina a etapa anterior os dados encontram-se armazenados em
variáveis do programa. Com o intuito de transmitir um único bloco de dados para o
Supervisório, é feito, então, um empacotamento das variáveis. Este empacotamento faz a
conversão das variáveis do tipo “short” e “byte”, que estão armazenando os dados, para o
tipo “String”. Desta maneira possibilita que as diferentes strings sejam concatenadas
formando uma única string que contenha toda a informação do protocolo “Barramento
PC”.
Após criar o pacote de dados o mesmo é enviado para o usuário remoto, que será
recebido e tratado pelo Supervisório em execução.
1 2
Número Status
Controlador
1 2 3 4 5
Número Status Tipo de Kp Kp
Controlador Controlador High Low
6 7 8 9 10
Ki Ki Kd Kd Tipo de
High Low High Low Referência
11 12 13 14 15
Frequência Frequência Amplitude Amplitude Offset
High Low High Low High
16
Offset
High
O primeiro campo, como no caso do protocolo da figura 12, é o dado que permite
identificar para qual controlador a mensagem está sendo transmitida.
O segundo campo (Status), corresponde à identificação da mensagem, ou seja,
permite à entidade identificar que tipo de mensagem está chegando a ela. Diferentemente
do protocolo da figura 12, este campo, no presente protocolo, tem a função de, também,
informar o momento em que o controlador deve finalizar o controle do processo. A tabela -
03 a seguir mostra os diferentes valores para o campo “Status”, “Tipo Referência”, “Tipo
Controlador” e suas correspondências.
Status Mensagem
00000001 Pedido de transmissão
00000010 Parâmetros sendo enviados
00000100 Finalizar Processo
Como a thread-1 fazia pedido de transmissão aos controladores e a thread-2, assim que
chegavam os dados do applet, transmitia-os para os controladores houve, esporadicamente,
a mistura dos dados devido ao seguinte fato: Quando uma das threads iniciava a
transmissão do protocolo e o Sistema Operacional escalonava o processador para a outra
thread que, por ventura, também iniciava a transmissão do outro protocolo ocorria em uma
situação em que os controladores de processo não conseguiam identificar, obviamente, os
dados que estavam chegando a eles.
Este problema foi solucionado utilizando o conceito de monitores. Java utiliza
monitores para executar sincronizações. Todo objeto com métodos synchronized é um
monitor. O monitor permite que uma thread de cada vez execute um método synchronized
sobre o objeto. Isso é realizado bloqueando o objeto quando o método synchronized é
invocado. Se houver vários métodos synchronized, somente um pode estar atuando em um
objeto de cada vez; todos as outras threads tentando invocar métodos synchronized devem
esperar.
Desta maneira, o método que enviava dados (sendProtocol()) e o que pedia
transmissão (sendPic()) para os controladores foram definidos como métodos
synchronized. Como estes métodos pertenciam a uma mesma classe (Classe Principal) e
também ao mesmo objeto (Objeto único da classe principal) o conceito de monitores foi
aplicado corretamente e, então, o problema foi resolvido com êxito.
No entanto, outros problemas apareceram. Devido à característica full-duplex da
transmissão PC Barramento o programa Servidor foi projetado para atender a está
característica, ou seja, mesmo quando os controladores estivessem transmitindo dados que
seriam tratados pela thread-1 o Servidor poderia transmitir parâmetros para os
controladores através da thread-2. Porém foi identificado que quando os controladores
iniciavam uma transmissão de dados para o PC e, antes que finalizassem a transmissão,
chegassem dados do PC para os mesmos o restante dos dados que deveriam ser
transmitidos para o PC não ocorria. Verificamos se havia falha no software dos
controladores, porém não foi encontrado nada de errado. Acreditamos em falha de
hardware, mas nada confirmado.
A solução encontrada para esta falha foi modificar a característica full-duplex para
half-duplex através do programa Servidor. Nesta nova situação o Servidor não transmite
parâmetros para os controladores enquanto os mesmos estão realizando a transmissão.
O esquema das duas threads foi mantido igualmente e com a mesma necessidade. A
diferença é que neste novo sistema a thread-2 não transmite os parâmetros do applet para
os controladores, mas sim habilita uma variável que permite à thread-1 transmitir os
parâmetros do usuário (applet) para o controladores. Sempre que chega um dado na porta
serial proveniente dos controladores a thread-1 obtém os dados e, antes de fazer um novo
pedido, verifica se a variável que permite a transmissão de parâmetros está habilitada. Caso
verdadeiro a thread-1 inicia a transmissão dos parâmetros para o barramento e, logo após,
desabilita a variável e faz o pedido de transmissão de dados. Caso a variável de controle da
transmissão de parâmetros não esteja habilitada a thread-1 apenas faz o pedido de
transmissão de dados aos controladores.
Vale ressaltar que, na primeira vez em que há o envio de parâmetros (iniciar o
experimento) a transmissão tanto dos parâmetros como do pedido por dados é realizada
pela thread-2 já que não há possibilidade dos controladores estarem transmitindo e, então,
gerando eventos na porta serial de modo que a thread-1 acorde.
Destaca-se que esta nova configuração do programa Servidor não afetou a eficiência
na comunicação, já que o programa continua tratando a comunicação com os controladores
e com o applet de forma independente. Como a taxa de transmissão dos parâmetros é muito
baixa, 16 bytes a cada mudança de configuração realizada pelo usuário, ter alterado o
Servidor para não enviar os parâmetros enquanto os controladores estavam transmitindo
não prejudicou a velocidade do sistema. Até porque a transmissão dos dados dos
controladores para o PC não preenche completamente o tempo disponível para transmissão.
Com soquetes de fluxo, um processo estabelece uma conexão com outro processo.
Enquanto a conexão estiver no ar, os dados fluem entre os processos em fluxos contínuos.
Diz-se que os soquetes de fluxo fornecem um serviço orientado para conexão. O protocolo
utilizado para transmissão é o popular TCP (Transmission Control Protocol) [7].
O primeiro passo no desenvolvimento de um aplicativo Servidor é criar um objeto
ServerSocket com uma chamada ao construtor ServerSocket como abaixo:
Onde ‘porta’ especifica um número inteiro de porta disponível em que o Servidor espera
conexões de clientes, e ‘num’ representa o número máximo de clientes que podem solicitar
conexões ao Servidor. A configuração do programa desenvolvido tem como número de
porta ‘3000’ e número de conexões igual a ‘1’.
Cada conexão de cliente é gerenciada com um objeto Socket. Uma vez que o
ServerSocket foi estabelecido, o Servidor ouve indefinidamente (ou bloqueia) uma tentativa
de se conectar por parte de um cliente. Isso é realizado com uma chamada ao método
accept de ServerSocket, como em:
1 2 3 4 5
Status Número do Tipo de Frequência Amplitude
Controlador Referência
6 7 8 9 10
Offset Tipo de Kp Ki Kd
Controlador
Figura 16: Sequência dos parâmetros enviados pelo Supervisório ao programa Servidor
Estes parâmetros chegam à porta como uma única mensagem que está contida em
uma string de caracteres.
Obtida a string o programa Servidor utiliza uma classe chamada StringTokenizer
que divide a frase em palavras individuais. Ou seja, ela obtém a string recebida do
Supervisório e então a divide em segmentos de strings cada qual correspondendo aos
parâmetros indicados na figura 16. A separação dos parâmetros é possivel ao programa
Assim que os dados chegam dos controladores eles são armazenados em variáveis
do programa. Com o intuito de transmitir um único bloco de dados para o applet, é feito,
então, um empacotamento das variáveis. Este empacotamento faz a conversão das variáveis
do tipo “short” e “byte”, que estão armazenando os dados, para o tipo “String”. Desta
maneira possibilita que as diferentes strings sejam concatenadas formando uma única string
que contenha toda a informação que será enviada para o Supervisório. A seqüência dos
dados montada no pacote segue a mesma indicada na figura 17 abaixo:
1 2 3 4
Número do Tempo Temperatura Temperatura
Controlador Referência Sala-1
5 6 7 8
Temperatura Temperatura Temperatura Tensão
Sala-2 Sala-3 Ambiente Atuador
Figura 17: Sequência dos dados enviados pelo programa Servidor ao Supervisório
Vale ressaltar que a variável tempo, antes de ser convertida para o tipo string, é
multiplicada por 35x10-3, já que o bit menos significativo do campo tempo vale 35ms.
Que tipo
De evento De qual
Pic-1 Controlador são os Pic-2
Ocorreu ?
dados ?
Assim que o usuário define os parâmetros para o experimento os mesmos devem ser
enviados para o Servidor clicando no botão enviar Controlador/Referência. Porém, antes de
serem submetidos, os parâmetros são passados por uma inspeção no intuito de verificar a
validade dos mesmos. Esta crítica de dados é feita no próprio Supervisório, pois assim,
evita-se tráfego na rede de parâmetros que não fazem sentido ao experimento. As figuras 20
e 21 a seguir mostram alguns dos erros que podem ocorrer.
Figura 20: Critica de dados realizada pelo Supervisório: Campo digitado incorretamente
Campo em branco:
Como pode ser visto nas duas figuras anteriores, o usuário tem a possibilidade,
também, de acompanhar a temperatura nas diferentes salas da maquete através da variação
da tonalidade das cores nas respectivas salas.
Quando o botão “Stop Experiment” é clicado, o Supervisório transmite a informação
para o programa Servidor que, por sua vez, transmite a informação para os controladores de
processo indicando que o experimento deve ser parado. A partir de então, a conexão entre
os dois programas é finalizada.
A figura 25, a seguir, mostra uma tela de dados gerados em um experimento obtida pelo
usuário após o encerramento do experimento.
Início
Vetor de Reset
Pula para Início do
Programa
Reset
WDT ?
Sim
Inicializa Variáveis
Liga as Interrupções
Limpa WDT
As variáveis da tabela acima são enviadas na seqüência apresentada (ex: pic, status,
tipo_controle, off_lo) do PC para o PIC ou do PIC para o PC (ex: NUMPIC, TEMPO_HI,
SECADOR_2). O detalhamento deste módulo é descrito no Apêndice D.
Antes de se deslocar para uma das quatro opções de ondas disponíveis no sistema
supervisório, o programa pergunta para qual tipo de onda o usuário deseja ir (Senoide,
Quadrada, Triangular ou Degrau) e de acordo com o valor passado do computador pelo
usuário (tecla das opções de ondas na tela do supervisório) ao microcontrolador o programa
desloca para uma subrotina determinada pelos valores binários atribuídos ao byte Onda_ref:
Onda Quadrada:
Ts = 498 µs + 1114 µs = 1612 µs
Fs = 620 Hz
PIC 2
Ts = N Conversões + LOOP do Controle PID + LOOP da Onda Desejada
4 Conversões = X = 4 * (T Adequação _ do _ capacitor + T Conversão + T Re ligamento _ do _ capacitor )
X = 4 * (40 + 12 * T AD + 2 * T AD ) , onde:
T AD = 32 / F OSC e F OSC → Freqüência do Oscilador Externo.
X = 664 µs
Onda Quadrada:
Ts = 664 µs + 1164 µs = 1828 µs
Fs = 547 Hz
Onda Quadrada:
Ts = 498 µs + 1114 µs = 1778 µs
Fs = 562 Hz
9 Conclusões
10 Bibliografia
__CONFIG _CP_OFF & _CPD_OFF & _DEBUG_OFF & _LVP_OFF & _WRT_OFF & _BODEN_OFF &
_PWRTE_ON & _WDT_ON & _XT_OSC
;**************************************
;* DEFINIÇÃO DAS VARIÁVEIS INTERNAS DO PIC *
;**************************************
; O ARQUIVO DE DEFINIÇÕES DO PIC UTILIZADO DEVE SER REFERENCIADO PARA QUE
; OS NOMES DEFINIDOS PELA MICROCHIP POSSAM SER UTILIZADOS, SEM A NECESSIDADE
; DE REDIGITAÇÃO.
;**************************************
;* DEFINIÇÃO DOS BANCOS DE RAM *
;**************************************
; OS PSEUDOS-COMANDOS "BANK0" E "BANK1", AQUI DEFINIDOS, AJUDAM A COMUTAR
; ENTRE OS BANCOS DE MEMÓRIA.
;**************************************
;* DEFINIÇÃO DAS VARIÁVEIS *
;**************************************
; ESTE BLOCO DE VARIÁVEIS ESTÁ LOCALIZADO NO FINAL DO BANCO 0, A PARTIR
; DO ENDEREÇO 0X70, POIS ESTA LOCALIZAÇÃO É ACESSADA DE QUALQUER BANCO,
; FACILITANDO A OPERAÇÃO COM AS VARIÁVEIS AQUI LOCALIZADAS.
ENDC
;**************************************
;* VETOR DE RESET DO MICROCONTROLADOR *
;**************************************
; POSIÇÃO INICIAL PARA EXECUÇÃO DO PROGRAMA
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *******
;* VETOR DE INTERRUPÇÃO DO MICROCONTROLADOR *
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *******
; POSIÇÃO DE DESVIO DO PROGRAMA QUANDO UMA INTERRUPÇÃO ACONTECE
SALVA_CONTEXTO
MOVWF W_TEMP ; COPIA W PARA W_TEMP
SWAPF STATUS,W
MOVWF STATUS_TEMP ; COPIA STATUS PARA STATUS_TEMP
MOVF PCLATH,W ; MOVE PCLATH PARA O REGISTRADOR W
MOVWF PCLATH_TEMP ; COPIA W PARA PCLATH_TEMP
;**************************************
;* FIM DA ROTINA DE INTERRUPÇÃO *
;**************************************
; RESTAURAR OS VALORES DE "W" E "STATUS" ANTES DE RETORNAR.
SAI_INTERRUPCAO
MOVF PCLATH_TEMP,W
MOVWF PCLATH ; COPIA PCLATH_TEMP PARA PCLATH
SWAPF STATUS_TEMP,W
MOVWF STATUS ; COPIA STATUS_TEMP PARA STATUS
SWAPF W_TEMP,F
SWAPF W_TEMP,W ; COPIA W_TEMP PARA W
RETFIE ; RETORNA DA INTERRUPÇÃO
CHEGOU_DADO
BANK0
MOVF RCREG,W ; COLOCA EM REG W O DADO QUE CHEGOU
MOVLW D'5'
MOVWF PORTD
BANK1
BTFSS TXSTA,TRMT ; O BUFFER DE TX ESTÁ VAZIO ?
GOTO $-1 ; NÃO - AGUARDA ESVAZIAR
BANK0
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * **********
;* CONFIGURAÇÕES INICIAIS DE HARDWARE E SOFTWARE *
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * **********
; NESTA ROTINA SÃO INICIALIZADAS AS PORTAS DE I/O DO MICROCONTROLADOR E AS
; CONFIGURAÇÕES DOS REGISTRADORES ESPECIAIS (SFR). A ROTINA INICIALIZA A
; MÁQUINA E AGUARDA O ESTOURO DO WDT.
CONFIG
CLRF PORTD ; LIMPA PORTA D
CLRF PORTC ; LIMPA PORTA C
BANK1 ; SELECIONA BANCO 1 DA RAM
MOVLW B'01111111'
MOVWF TRISC ; CONFIGURA O I/O DO PORTC
MOVLW B'10000000'
MOVWF TRISD ; CONFIGURA O I/O DO PORTC
MOVLW B'00100100'
MOVWF TXSTA ; CONFIGURA USART
; HABILITA TX
; MODO ASSINCRONO
; TRANSMISSÃO DE 8 BITS
; HIGH SPEED BAUD RATE
MOVLW D'23'
MOVWF SPBRG ; ACERTA BAUD RATE -->9600bps
MOVLW B'11000000'
MOVWF INTCON ; CONFIGURA INTERRUPÇÕES
MOVLW B'00100000'
MOVLW B'01111111'
MOVWF PORTD ; COLOCA O VALOR O1111111 NO PORTD
MOVLW B'10010000'
MOVWF RCSTA ; CONFIGURA USART
; HABILITA RX
; RECEPÇÃO DE 8 BITS
; RECEPÇÃO CONTINUA
; DESABILITA ADDRESS DETECT
BANK1
MOVLW B'11011011'
MOVWF OPTION_REG ; CONFIGURA OPTIONS
; DESABILITA PULL-UPS
; INTERRUPÇÃO NA BORDA DE SUBIDA DO RB0
; O TMR0 SERÁ INCREMENTADO PELO CICLO DE
; MÁQUINA
; O PRESCALER SERÁ APLICADO AO WDT
; O WDT - SERÁ NA RAZÃO DE 1:8 E O TIMER 1:1
BANK0
;*********************************************************
; * AS INSTRUÇÕES A SEGUIR FAZEM COM QUE O PROGRAMA TRAVE QUANDO *
; * HOUVER UM RESET OU POWER-UP, MAS PASSE DIRETO SE O RESET FOR POR WDT. *
; * DESTA FORMA, SEMPRE QUE O PIC É LIGADO, O PROGRAMA TRAVA, AGUARDA *
; * UM ESTOURO DE WDT E COMEÇA NOVAMENTE. ISTO EVITA PROBLEMAS NO *
; * START-UP DO PIC. *
;******************************************************** *
;*******************************************************
;* INICIALIZAÇÃO DA RAM *
;*******************************************************
; ESTA ROTINA IRÁ LIMPAR TODA A RAM DO BANCO 0, INDO DE 0x20 A 0x70.
; EM SEGUIDA, AS VARIÁVEIS DE RAM DO PROGRAMA SÃO INICIALIZADAAS.
MOVLW 0X20
MOVWF FSR ; APONTA O ENDEREÇAMENTO INDIRETO PARA
; A PRIMEIRA POSIÇÃO DA RAM
LIMPA_RAM
CLRF INDF ; LIMPA A POSIÇÃO
INCF FSR,F ; IMCREMENTA O PONTEIRO P/ A PRÓX. POS.
INCF FSR,W
XORLW 0X80 ; COMPARA O PONTEIRO COM A ÚLT. POS. + 1
BTFSS STATUS,Z ; JÁ LIMPOU TODAS AS POSIÇÕES ?
GOTO LIMPA_RAM ; NÃO – LIMPA A PRÓXIMA POSIÇÃO
; SIM
;********************************
;* LOOP PRINCIPAL *
;********************************
LOOP
CLRWDT ; LIMPA WDT PARA NÃO ESTOURAR (NAO
; HAVER RESET)
;*********************************
;* FIM DO PROGRAMA *
;*********************************
Interrupção
Salva Contexto
INT Não
USART? Fim Interrupção
Sim
Chegou Dado
Zera
Conta- Sim É a primeira vez que
dores de chega algum dado ?
Tempo
Não
Recebe do PC o valor da
É o primeiro Sim
variável pic e incrementa Fim Interrupção
dado a receber ?
o contador de dados
Não
Sim
Rebebe do PC o É para Incrementa
É o segundo Não
valor da variável transmitir contador de
dado a receber ? ? dados
STATUS
Não
Sim
Fim Interrupção
Zera o
contador
Este é o PIC que Não Fim Interrupção
Dado deve transmitir ?
Sim
Zera TMR0 e
contador de 0,25 s.
Contagem
Do fluxograma acima, vê-se que esta rotina só ocorre quando há comunicação (envio e
recebimento de dados). Em seqüência são tratadas as variáveis ‘pic’ e ‘STATUS’ solicitando
a transmissão ou recepção de dados pelo microcontrolador. A parte descontínua na figura 30
indica a continuidade do módulo Protocolo. A continuidade é representada na figura abaixo.
depois solicita os demais PICs do sistema (nunca ao mesmo tempo – evitar erros de
transmissão) a fazerem suas transmissões e operações de controle. O que determina se o PIC
deve transmitir ou não ao computador é o valor da variável Status (memória RAM) que após
setado possibilita tal transmissão. Para evitar que os microcontroladores fiquem enviando
inúmeros dados repetidos e desnecessários, criou-se uma sub-rotina utilizando o timer 0 que
realiza a contagem de 0,25s e depois desloca-se para a rotina Protocolo onde ocorre a
transmissão dos dados. Mesmo porque o Ploter do supervisório só apresenta diferença de um
dado para outro com aproximadamente 0,5s (projeto no software desenvolvido em Java).
Dentre as variáveis enviadas do PIC ao PC há uma certa peculiaridade relacionada às
variáveis TEMP_SALA1, TEMP_SALA2, TEMP_SALA3 e TEMP_SALA4 enviadas dos
PICs ao computador. O microcontrolador 1 que possui a variável NUMPIC constante e igual a
1 envia na verdade TEMP_SALA1_LO (variável da sala em que têm um dos atuadores
(secadores) → necessidade de bytes LO e HI para tratamento da variável no controle PID),
TEMP_SALA2, o valor zero e TEMP_EXT_1, respectivamente. Enquanto que o
microcontrolador 2 que possui a variável NUMPIC constante e igual a 2 envia ao PC
TEMP_SALA3, TEMP_SALA4, TEMP_SALA5_LO (variável da sala em que têm um dos
atuadores → necessidade de bytes LO e HI para tratamento da variável na rotina de controle
PID) e TEMP_EXT_2. Estas variáveis de temperatura das salas representam exatamente o
número em que elas foram mostradas na figura 06 da maquete.
Da linha descontínua da segunda parte do protocolo segue a recepção dos valores
enviados do computador aos microcontroladores. Antes de receber qualquer valor, os PIC’s
verificam se o valor enviado é para eles mesmo, através da conferência do valor da variável
‘pic’, evitando assim que valores de variáveis de outros PICs sejam atribuídos de forma
equivocada a eles, e incrementam o contador para recebimento das próximas variáveis
enviadas pelo computador. Esta terceira parte do módulo do protocolo pode ser vista na figura
32.
Limpa
registrador de
É o terceiro Sim Este é o PIC que Não
recepção do PIC
dado a receber ? deve receber ? e incrementa
Sim
contador
Não
Limpa
Não registrador de
É o quarto Sim Este é o PIC que
recepção do PIC
dado a receber ? deve receber ? e incrementa
Sim
contador
Não
Limpa
Não registrador de
É o quinto Sim Este é o PIC que
recepção do PIC
dado a receber ? deve receber ? e incrementa
Sim contador
Não
Limpa
Não registrador de
É o sexto Sim Este é o PIC que
recepção do PIC
dado a receber ? deve receber ? e incrementa
Sim contador
Não
Limpa
Não registrador de
É o sétimo Sim Este é o PIC que
recepção do PIC
dado a receber ? deve receber ? e incrementa
Sim
contador
Não
Limpa
Não registrador de
É o oitavo Sim Este é o PIC que
recepção do PIC
dado a receber ? deve receber ? e incrementa
Sim
contador
Não
Limpa
Não registrador de
É o nono Sim Este é o PIC que
recepção do PIC
dado a receber ? deve receber ? e incrementa
Sim contador
Não
dados recebidos pelo PIC para que possa se reiniciar o processo novamente. Estas
informações podem ser verificadas na figura 33 abaixo.
Limpa
Não registrador de
É o décimo Sim Este é o PIC que recepção do PIC
dado a receber ? deve receber ? e incrementa
Sim contador
Não
Limpa
Não registrador de
É o décimo 1º Sim Este é o PIC que
recepção do PIC
dado a receber ? deve receber ? e incrementa
Sim
contador
Não
Limpa
Não registrador de
É o décimo 2º Sim Este é o PIC que
recepção do PIC
dado a receber ? deve receber ? e incrementa
Sim
contador
Não
Limpa
Não registrador de
É o décimo 3º Sim Este é o PIC que
recepção do PIC
dado a receber ? deve receber ? e incrementa
Sim contador
Não
Limpa
Não registrador de
É o décimo quarto Sim Este é o PIC que recepção do PIC
dado a receber ? deve receber ? e incrementa
Sim contador
Não
Limpa
Não registrador de
É o décimo quinto Sim Este é o PIC que
recepção do PIC
dado a receber ? deve receber ? e incrementa
Sim
contador
Não
Limpa
Não registrador de
É o décimo sexto Sim Este é o PIC que
recepção do PIC
dado a receber ? deve receber ? e incrementa
Sim contador
Não
Fim Interrupção
Zera timer de
contagem de
É para
Sim parar o Não
tempo e espera
reiniciar o sistema
processo ?
Nesta subrotina do programa principal, através dos dados enviados pelo usuário
(amplitude, freqüência e offset), criou-se a onda quadrada que possui os eixos Tempo X
Amplitude, da seguinte forma:
A cada meio período (T_sobre2) o valor da onda de referência é alterado na subrotina
‘MUDA_REF’. Nesta subrotina ocorre a comparação entre o valor da referência e os níveis
alto e baixo da onda. Caso o valor de referência seja igual ao nível alto, por exemplo, a
subrotina chama outra subrotina (neste caso REF_BAIXO), onde é a atribuído o valor de
referência Referência = Offset - Amplitude/2. Se por outro lado o valor de referência
seja igual ao nível baixo, subrotina chama outra subrotina (neste caso REF_ALTO), onde é a
atribuído o valor de referência Referência = Offset + Amplitude/2. O fluxograma do
módulo Onda Quadrada é apresentado na figura 34 abaixo
Algo de novo nesta onda é a contagem de um tempo auxiliar para facilitar a montagem
da onda triangular. As equações de formação da onda triangular são as seguintes:
• N_periodo = TEMPO / T
• time = TEMPO – (N_periodo*T )
Neste tipo de onda o usuário só informa o valor de amplitude que deseja e a rotina
quando chamada atribui o valor enviado pelo usuário a referência provocando um degrau de
amplitude como se vê na figura abaixo.
Principais características
Organização da memória
Como foi dito anteriormente, existem três blocos de memória nos PIC´s: programa,
dados e EEPROM. Os dispositivos PIC16F87XA possuem um contador de programa de 13
bits capaz de endereçar um espaço de memória de 8Kx14 bits. Dois endereços desta memória
de programa são reservados para duas tarefas importantes: o endereço “0x0000”, para “reset”
e o endereço “0x0004” para interrupções.
A memória de dados é particionada em 4 “bancos” de 128 bytes que contém dois tipos de
registradores classificados de acordo com sua utilização: registradores de uso geral e
registradores para funções especiais. O acesso a estes “bancos” é feita através da escrita nos
bits 5 e 6 do registrador “STATUS”.
A memória de dados EEPROM pode ser lida e escrita durante a operação do PIC. Está
memória pode ser apagada eletricamente e regravada (gravada com gravadores específicos ou
pelo sistema).
Estas operações são feitas usando apenas um byte desta memória. Uma escrita
ocasiona uma operação para apagar e então escrever o novo valor, não causando nenhum
impacto sobre o dispositivo, diferentemente de uma escrita na memória de programa. A
memória de dados EEPROM mostra-se bastante útil, portanto, para armazenar resultados
mesmo quando o dispositivo está sem alimentação (desligado).
Estes registradores são usados pela CPU e pelos módulos periféricos para controlar o
dispositivo para que o mesmo opere da forma desejada. Implementados como memória RAM
estática, podem ser classificados em dois tipos: “core” (CPU) e periféricos. A seguir são
citados os principais registradores SFR:
Os registradores a seguir também são SFR, mas são utilizados para uso das portas de
E/S do PIC:
• TRISA, TRISB, TRISC, TRISD e TRISE: usados para configurar os pinos das portas:
PORTA, PORTB, PORTC, PORTD e PORTE; respectivamente como entrada (1) ou
saída (0).
• Os registradores PORT, por sua vez, contêm os dados as serem enviados pelo PIC
quando configurados como saída ou os dados a serem recebidos quando configurados
como entrada.
import java.util.*;
import javax.comm.*;
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.text.DecimalFormat;
public sc()
{
super( "Servidor Térmico" );
Container c = getContentPane();
}
}
);
c.add( enter, BorderLayout.NORTH );
display = new JTextArea();
c.add( new JScrollPane( display ),
BorderLayout.CENTER );
setSize(300, 150 );
show();
}
public synchronized void sendProtocol(byte Pic,byte funcao)
{
try
{
dataOutputStream_Pic.writeByte(Pic);
display.append("Destino PIC: " + String.valueOf(Pic)+ "\n");
dataOutputStream_Pic.writeByte(funcao);
display.append("Status: " + String.valueOf(funcao)+ "\n");
//Tipo de controle
dataOutputStream_Pic.writeByte(tipoCont_B);
display.append("Tipo Controle: " + String.valueOf(tipoCont_B)+ "\n");
//Propriedades da referência
dataOutputStream_Pic.writeShort(fre1_S);
display.append("Frequência: " + String.valueOf(fre1_S)+ "\n");
dataOutputStream_Pic.writeShort(amp1_S);
display.append("Amplitude: " + String.valueOf(amp1_S)+ "\n");
dataOutputStream_Pic.writeShort(ofs1_S);
display.append("Offset: " + String.valueOf(ofs1_S)+ "\n");
}
catch (IOException e)
{
display.append("Erro ao enviar dados para o PIC");
}
}
private void sendApp(String s)
{
try
{
dataOutputStream_App.writeUTF( s );
dataOutputStream_App.flush();
display.append("Dados enviado para o Applet \n \n" + s + "\n");
}
catch (IOException cnfex)
{
display.append("\n Erro ao enviar dados para o Applet");
}
}
private synchronized void sendPic(byte pic)
{
try
{
dataOutputStream_Pic.writeByte(pic);
dataOutputStream_Pic.writeByte(PICTRA);
display.append("Pedido de Transmissão ao Pic: " +String.valueOf(pic)+ "\n");
display.append("Status Pic: " +String.valueOf(PICTRA)+ "\n");
//display.append("Dado enviado: " +getBits(dado)+ "\n");
}
//catch (NumberFormatException x)
//{}
catch (IOException e)
{
display.append("Erro ao fazer pedido de transmissão ao Pic: " + String.valueOf(pic) + "\n");
}
}
private void rodaconexao()
{
conexao = new Conexao();
rodaservidor = new rodaServidor();
}
public static void main( String args[] )
{
sc app = new sc();
app.addWindowListener(
new WindowAdapter() {
public void windowClosing( WindowEvent e )
{
System.exit( 0 );
}
}
);
app.rodaconexao();
}
/************************************************************************
Descrição: "Conexão" classe interna que faz toda a programação necessária
para obter, abrir, enviar e receber dados pela porta serial.
************************************************************************/
CommPortIdentifier portId;
Enumeration portList;
SerialPort serialPort;
Thread readThread;
int numBytes;
public Conexao()
{
portList = CommPortIdentifier.getPortIdentifiers(); //Retorna todas as portas conhecidas pelo sistema
while (portList.hasMoreElements()) //em uma vetor (Enumeration) de CommPortIdentifiers
{
portId = (CommPortIdentifier) portList.nextElement();
if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) // Verifica se a porta é do tipo serial
{
if (portId.getName().equals("COM2")) //Verifica se a porta serial é a COM2
{
abrePorta();
}
}
}
}
private void abrePorta() //Abre a porta serial
{
try
{
serialPort = (SerialPort) portId.open("Comunicação com PIC", 2000);
catch (TooManyListenersException e)
{
display.append("Erro ao tentar definir ouvinte de eventos da serial!");
}
}
catch (IOException e)
{
display.append("Erro na obtenção dos Streams!");
}
}
public void run()
{
try
{
Thread.sleep(20000); //Coloca o programa (Thread) para dormir
//Fica aguardando enventos, na porta serial ou na Interface com usuário
}
catch (InterruptedException e)
{}
}
public void empacota()
{
double TempoPic_D = TempoPic_S*35*0.001; // Corrige o tempo para segundos
float Sala1Pic_I,Sala2Pic_I,Sala3Pic_I,TambPic_I;
if (Sala1Pic_B < ZERO)
{
Sala1Pic_I = (127 -Sala1Pic_B)/2;
}
else
{
Sala1Pic_I = (Sala1Pic_B)/2;
}
if (Sala2Pic_B < ZERO)
{
Sala2Pic_I = (127 -Sala2Pic_B)/2;
}
else
{
Sala2Pic_I = (Sala2Pic_B)/2;
}
public void serialEvent(SerialPortEvent event) //Método chamado quando ocorre eventos na porta serial
{
switch(event.getEventType())
{
case SerialPortEvent.BI: //Break interrupt
case SerialPortEvent.OE: //Overrun error
case SerialPortEvent.FE: //Framing error
case SerialPortEvent.PE: //Parity error
case SerialPortEvent.CD: //Carrier detect
case SerialPortEvent.CTS: //Clear to send
case SerialPortEvent.DSR: //Data set ready
case SerialPortEvent.RI: //Ring indicator
case SerialPortEvent.OUTPUT_BUFFER_EMPTY: //Output buffer is empty
break;
case SerialPortEvent.DATA_AVAILABLE: //Data available at the serial port
try
{
numPic_B = dataInputStream_Pic.readByte();
display.append("1-Numero do Pic: "+String.valueOf(numPic_B)+"\n");
if (numPic_B == Pic_1 || numPic_B == Pic_2)// Este parametro está sendo colocado devido a um ruido
que aparece quando
//liga o pic com o software executando. Neste caso aparece um dado com valor
//zero na porta!
{
TempoPic_S = dataInputStream_Pic.readShort();
display.append("2e3-Tempo: "+String.valueOf(TempoPic_S)+"\n");
RefPic_S = dataInputStream_Pic.readShort();
display.append("4e5-Referência: "+String.valueOf(RefPic_S)+"\n");
Sala1Pic_B = dataInputStream_Pic.readByte();
display.append("6-Sala1: "+String.valueOf(Sala1Pic_B)+"\n");
Sala2Pic_B = dataInputStream_Pic.readByte();
display.append("7-Sala2: "+String.valueOf(Sala2Pic_B)+"\n");
Sala3Pic_B = dataInputStream_Pic.readByte();
display.append("8-Sala3: "+String.valueOf(Sala3Pic_B)+"\n");
TambPic_B = dataInputStream_Pic.readByte();
display.append("9-Temp. Amb: "+String.valueOf(TambPic_B)+"\n");
AtuPic_S = dataInputStream_Pic.readShort();
display.append("10e11-Atuador: "+String.valueOf(AtuPic_S)+"\n");
sendProtocol(Pic_1,PARAR);
sendProtocol(Pic_2,PARAR);
}
else
sendProtocol(numCont_B,PICREC);
Bprotocol = false;
}
if (Istatus == 1)
{
empacota();
sendApp(Pacote);
gravar_arquivo(Pacote);
if (numPic_B == Pic_1)
{
sendPic(Pic_2);
}
else
{
sendPic(Pic_1);
}
}
}
}
catch (EOFException eof)
{
display.append("Erro ao receber bytes \"Short\" do PIC-Fim de Fluxo!");
}
catch (IOException e)
{}
break;
}
}
} //Fim da classe interna "Conexão".
/******************************************************************************
Descrição: "rodaServidor" classe interna que faz toda a programação necessária
para obter a conexao e enviar e receber dados para o usuário remoto (applet).
*******************************************************************************/
public rodaServidor()
{
esperaConexao = new Thread(this);
esperaConexao.start();
}
do
{
try
{
message = dataInputStream_App.readUTF();
StringTokenizer tokens = new StringTokenizer(message);
Istatus = Integer.parseInt(tokens.nextToken());
//Propriedades do controlador 1
float p1 = Float.parseFloat(tokens.nextToken());
p1_S = Util.FloatShort(p1);
float i1 = Float.parseFloat(tokens.nextToken());
i1_S = Util.FloatShort(i1);
float d1 = Float.parseFloat(tokens.nextToken());
d1_S = Util.FloatShort(d1);
// pertencem ao controlador 1;
if (numCont_B == Pic_1)
{
sendProtocol(Pic_1,PICREC);
}
else
{
sendProtocol(Pic_2,PICREC); //Na primeira vez em que enviar dados para o pic1 e pic2
PrimeiroPedido = false; // deve-se fazer o pedido de transmissão ao pic1
sendPic(Pic_1); //A partir deste momento não é mais necessário pois
//assim que os dados chegarem pela serial será feito
// os novos pedidos (No método que trata os eventos
//da serial.
}
}
else
{
Bprotocol = true; //Variável que abilita a transmissão dos dados para o pic
}
}
catch (IOException cnfex)
{
display.append("Erro de I/O ao ler dado do usuário remoto");
}
}
while (!message.equals("0 0 0 0 0 0 0 0 0 0"));
}
catch (IOException io)
{
display.append("Erro de I/O");
io.printStackTrace();
}
}
} //Fim do construtor rodaServidor
} //Fim da classe interna rodaServidor
} //Fim da classe principal "sc"
P = new JRadioButton("Prop.",false);
P.addItemListener(rbclasse);
PI = new JRadioButton("Prop. Int.", false);
PI.addItemListener(rbclasse);
Pcontrolador1.add(P);
Pcontrolador1.add(PI);
Pcontrolador1.add(TFki);
Pcontrolador1.add(TFkd);
//--------------------------------Fim-Painel-Controlador----------------------
//--------------------------------Painel_Referencia 1 e 2---------------------------
Preferencia1 = new JPanel();
Preferencia1.setLayout(new GridLayout(1,6));
RBdegrau = new JRadioButton("Step", false);
RBquadrada = new JRadioButton("Square", true);
RBdegrau.addItemListener(rbclasse);
RBquadrada.addItemListener(rbclasse);
Preferencia1.add(RBdegrau);
Preferencia1.add(RBquadrada);
TFfrequencia = new JTextField();
TFamplitude = new JTextField();
TFoffset = new JTextField();
Preferencia1.add(TFfrequencia);
Preferencia1.add(TFamplitude);
Preferencia1.add(TFoffset);
BenviarRef = new JButton("Send reference 1");
BenviarRef.setEnabled(false);
BenviarRef.addActionListener(rbclasse);
Preferencia1.add(BenviarRef);
Preferencia2.setLayout(new GridLayout(1,6));
//---------------------------------Fim-Painel-Referencia----------------------
//---------------------------------Painel-Fun‡oes-----------------------------
Pfuncoes = new JPanel();
Pfuncoes.setLayout(new GridLayout(1,3));
Biniciar = new JButton("Start Experiment");
Biniciar.setEnabled(false);
Biniciar.addActionListener(rbclasse);
Pfuncoes.add(Biniciar);
Bparar = new JButton("Stop Experiment");
Bparar.setEnabled(false);
Bparar.addActionListener(rbclasse);
Pfuncoes.add(Bparar);
Bsair = new JButton("Finish");
Bsair.addActionListener(rbclasse);
Pfuncoes.add(Bsair);
//-----------------------------------Fim-Painel-Funcoes-----------------------
//--------------------Painel lado esquerdo da regiao Sul-----------------------
Lcontrole2.setHorizontalAlignment(SwingConstants.CENTER);
Pcontrole12 = new JPanel();
Pcontrole12.setLayout(new GridLayout(1,2));
Pcontrole12.add(Lcontrole1);
Pcontrole12.add(Lcontrole2);
PsulEsq.add(Pcontrole12);
//CBsala6.setHorizontalAlignment(SwingConstants.CENTER);
CBsala6.addItemListener(rbclasse);
Psala36 = new JPanel();
Psala36.setLayout(new GridLayout(1,2));
Psala36.add(CBsala3);
Psala36.add(CBsala6);
PsulEsq.add(Psala36);
//----------------------------Fim-painel-Sul esquerdo--------------------------
Container c = getContentPane();
titulo = new TituloPanel(logo1);
JPanel Pnorte = new JPanel();
Pnorte.setLayout(new BorderLayout());
Pnorte.add(titulo,BorderLayout.NORTH);
painel0 = new JPanel();
painel0.setLayout(new GridLayout(7,1));
painel0.add(new JLabel("Define Controller"));
painel0.add(Pcontrolador1);
painel0.add(Pcontrolador2);
painel0.add(new JLabel("Define reference"));
painel0.add(Preferencia1);
painel0.add(Preferencia2);
painel0.add(Pfuncoes);
Pnorte.add(painel0,BorderLayout.SOUTH);
c.add(Pnorte,BorderLayout.NORTH);
p_v_completo = new JPanel();
p_v_completo.setLayout(new GridLayout(1,3));
p_v_completo.add(PsulEsq);
maqReal = new Maquete(logo2);
setSize(820,980);
}
if( enviar_1)
{
sendData("0 0 0 0 0 0 0 0 0 0");
enviar_1=false;
}
//try
//{
//input.close();
//output.close();
//client.close();
//}
///catch (IOException io) {
//JOptionPane.showMessageDialog(null,"Houve um erro ao fechar a conexão!",
//"ERRO!", JOptionPane.ERROR_MESSAGE);
//io.printStackTrace();
//}
}
}
if( e.getSource() == RBtriangular)
{
TFamplitude.setEditable(true);
TFoffset.setEditable(true);
TFfrequencia.setEditable(true);
}
// }
// }
if( e.getSource() == CBtempAmb1)
{
if( e.getStateChange() == ItemEvent.SELECTED)
{
showPlots[4] =true;
DPnivel.graficos(showPlots);
}
else
{
showPlots[4] =false;
DPnivel.graficos(showPlots);
}
}
if( e.getSource() == CBatuador1)
{
if( e.getStateChange() == ItemEvent.SELECTED)
{
showPlots[5] =true;
DPatuador.graficos(showPlots);
}
else
{
showPlots[5] =false;
DPatuador.graficos(showPlots);
}
}
if( e.getSource() == CBreferencia2)
{
if( e.getStateChange() == ItemEvent.SELECTED)
{
showPlots[6] =true;
DPnivel.graficos(showPlots);
}
else
{
showPlots[6] =false;
DPnivel.graficos(showPlots);
}
}
if( e.getSource() == CBsala4)
{
if( e.getStateChange() == ItemEvent.SELECTED)
{
showPlots[7] =true;
DPnivel.graficos(showPlots);
}
else
{
showPlots[7] =false;
DPnivel.graficos(showPlots);
}
}
if( e.getSource() == CBsala5)
{
if( e.getStateChange() == ItemEvent.SELECTED)
{
showPlots[8] =true;
DPnivel.graficos(showPlots);
}
else
{
showPlots[8] =false;
DPnivel.graficos(showPlots);
}
}
if( e.getSource() == CBsala6)
{
if( e.getStateChange() == ItemEvent.SELECTED)
{
showPlots[9] =true;
DPnivel.graficos(showPlots);
}
else
{
showPlots[9] =false;
DPnivel.graficos(showPlots);
}
}
if( e.getSource() == CBtempAmb2)
{
if( e.getStateChange() == ItemEvent.SELECTED)
{
showPlots[10] =true;
DPnivel.graficos(showPlots);
}
else
{
showPlots[10] =false;
DPnivel.graficos(showPlots);
}
}
if( e.getSource() == CBatuador2)
{
if( e.getStateChange() == ItemEvent.SELECTED)
{
showPlots[11] =true;
DPatuador.graficos(showPlots);
}
else
{
showPlots[11] =false;
DPatuador.graficos(showPlots);
}
}
}
//-----------Fim do bloco que configura quais curvas serão plotadas----------------
{
sendData("0 0 0 0 0 0 0 0 0 0");
// StringIniciar = "2";
enviar_1=false;
execucao = false;
BenviarRef.setEnabled(false);
BenviarRef2.setEnabled(false);
BenviarCon2.setEnabled(false);
BenviarCon.setEnabled(false);
}
{
Scont2 ="1 " + Skp2 + " " + Ski2 + " " + Skd2;
BenviarRef.setEnabled(true);
}
if(PI.isSelected())
if(!Util.campoVazio(Skp2,"Kp") && Util.campoCorreto(Skp2,"Kp"))
if(!Util.campoVazio(Ski2,"Ki") && Util.campoCorreto(Ski2,"Ki"))
{
Scont2 ="1 " + Skp2 + " " + Ski2 + " 0";
BenviarRef.setEnabled(true);
}
if(execucao)
sendData(StringIniciar + " 2 " + Ref2 + " " + Scont2);
}
if( e.getSource() == BenviarRef2)
{
String Samp2 = TFamplitude.getText();
String Sfre2 = TFfrequencia.getText();
String Soff2 = TFoffset.getText();
if(RBdegrau.isSelected())
if(!Util.campoVazio(Samp2,"Amplitude") && Util.campoCorreto(Samp2,"Amplitude"))
{
Ref2 = "8 0 " + Samp2 + " 0";
Biniciar.setEnabled(true);
}
if(RBsenoide.isSelected())
if(!Util.campoVazio(Sfre2,"Frequencia") && Util.campoCorreto(Sfre2,"Frequencia"))
if(!Util.campoVazio(Samp2,"Amplitude") && Util.campoCorreto(Samp2,"Amplitude"))
if(!Util.campoVazio(Soff2,"Offset") && Util.campoCorreto(Soff2,"Offset"))
{
Ref2 = "1 " + Sfre2 + " " + Samp2 + " " + Soff2;
Biniciar.setEnabled(true);
}
if(RBquadrada.isSelected())
if(!Util.campoVazio(Sfre2,"Frequencia") && Util.campoCorreto(Sfre2,"Frequencia"))
if(!Util.campoVazio(Samp2,"Amplitude") && Util.campoCorreto(Samp2,"Amplitude"))
if(!Util.campoVazio(Soff2,"Offset") && Util.campoCorreto(Soff2,"Offset"))
{
Ref2 = "2 " + Sfre2 + " " + Samp2 + " " + Soff2;
Biniciar.setEnabled(true);
}
if(RBtriangular.isSelected())
if(!Util.campoVazio(Sfre2,"Frequencia") && Util.campoCorreto(Sfre2,"Frequencia"))
if(!Util.campoVazio(Samp2,"Amplitude") && Util.campoCorreto(Samp2,"Amplitude"))
if(!Util.campoVazio(Soff2,"Offset") && Util.campoCorreto(Soff2,"Offset"))
{
Ref2 = "4 " + Sfre2 + " " + Samp2 + " " + Soff2;
Biniciar.setEnabled(true);
}
if(execucao)
{
sendData(StringIniciar + " 2 " + Ref2 + " " + Scont2);
Biniciar.setEnabled(false);
}
}
}//---------------------------- Fim dos eventos de ação "actionPerformed"--------------------------------------
}// Fim da classe interna rbClasse
} // Fim da classe principal
**********************************Arquivo DefinePanel.java********************************
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.text.*;
import java.util.*;
g.drawString("120",36,79);
g.drawString("160",36,47);
g.drawString("200",36,15);
}
g.drawLine(58,170,740,170); //Eixo x
g.drawLine(60,10,60,172); //EIXO y
g.drawString("Seconds",380,200);
if((!seg_tela))
{
g.drawString("20",87,186);
g.drawString("40",121,186);
g.drawString("60",155,186);
g.drawString("80",189,186);
g.drawString("100",220,186);
g.drawString("120",254,186);
g.drawString("140",288,186);
g.drawString("160",322,186);
g.drawString("180",356,186);
g.drawString("200",390,186);
g.drawString("220",424,186);
g.drawString("240",458,186);
g.drawString("260",492,186);
g.drawString("280",526,186);
g.drawString("300",560,186);
g.drawString("320",594,186);
g.drawString("340",628,186);
g.drawString("360",662,186);
g.drawString("380",696,186);
g.drawString("400",730,186);
}
else
{
g.drawString("420",84,186);
g.drawString("440",118,186);
g.drawString("460",152,186);
g.drawString("480",186,186);
g.drawString("500",220,186);
g.drawString("520",254,186);
g.drawString("540",288,186);
g.drawString("560",322,186);
g.drawString("580",356,186);
g.drawString("600",390,186);
g.drawString("620",424,186);
g.drawString("640",458,186);
g.drawString("660",492,186);
g.drawString("680",526,186);
g.drawString("700",560,186);
g.drawString("720",594,186);
g.drawString("740",628,186);
g.drawString("760",662,186);
g.drawString("780",696,186);
g.drawString("800",730,186);
}
{
if ((permissao) && (!painel1))
{
if (showPlots[5])
{
g.setColor(Color.red);
g.drawPolyline(t_Pic1,a_Pic1,v);
}
if (showPlots[11])
{
g.setColor(Color.yellow);
g.drawPolyline(t_Pic2,a_Pic2,u);
}
}
}
}
public void graficos(boolean show[])
{
showPlots = show;
this.repaint();
}
public void desenha2(String s)
{
try
{
permissao = true;
if(!s.equals("NOVO GRAFICO"))
{
StringTokenizer tokens = new StringTokenizer(s);
if ((tempo<400) && (seg_tela)) //Caso o tempo de um dos Pics chegue aos 400 s (segunda tela) e o outro
{ // posteriormente não, então o outro (o atrasado) só plotará quando seu
// seu tempo chegar aos 400 segundos.
if (numPic == Pic_2)
{
BplotaPic_2 = false;
}
else
{
BplotaPic_1 = false;
}
}
else
{
BplotaPic_2 = true;
BplotaPic_1 = true;
}
if (tempo >= 400) //if numero
{
tempo -= 400;
seg_tela = true; // Habilita a segunda tela
}
if ((seg_tela) && (!v_zerado1)) // Se está na segunda tela e o v ainda não foi zerado então zera-o.
{ // Vale ressaltar que esta definição assegura que o v será zerado
// apenas uma vez. Ele não pode ser zerado no if numero 1 pois
// após 400 segundos aquela definição sempre será verdadeira
v = 0;
u = 0;
v_zerado1 = true;
}
s3_Pic2[i]=0;
ta_Pic2[i]=0;
a_Pic2[i]=0;
}
v = 0;
u = 0;
seg_tela = false;
v_zerado1 = false;
}
}
catch(NumberFormatException nfe)
{
JOptionPane.showMessageDialog(null, "Dado com Erro !", "Dado com Erro !",
JOptionPane.ERROR_MESSAGE);
}
}
}
***********************************Arquivo Maquete.java*******************************
import java.awt.*;
import javax.swing.*;
import java.util.*;
import java.text.DecimalFormat;
//Segurança para que os parametros das cores não esteja fora dos limites
if (Isala1>100)
{
Isala1 = 100;
}
if (Isala2>100)
{
Isala2 = 100;
}
if (Isala3>100)
{
Isala3 = 100;
}
if (Isala4>100)
{
Isala4 = 100;
}
if (Isala5>100)
{
Isala5 = 100;
}
if (ItempAmb1>100)
{
ItempAmb1 = 100;
}
if (ItempAmb2>100)
{
ItempAmb2 = 100;
}
//--------------------------------------------------------------------
g.setColor(new Color(255,(int)(250-2.5*Isala2),0));
g.fillRect(c1x+2,c1y+2,c2x-c1x-2,c2y-c1y-2); //Sala 2
g.setColor(new Color(255,(int)(250-2.5*Isala1),0));
g.fillRect(c1x+2,c2y+2,c2x-c1x-2,H-c1y-c2y+10-2);//Sala 1
g.setColor(new Color(255,(int)(250-2.5*Isala3),0));
g.fillRect(c2x+2,c1y+2,c4x-c2x-2,c3y-c1y-2);//Sala 3
g.setColor(new Color(255,(int)(250-2.5*Isala4),0));
g.fillRect(c4x+2,c1y+2,c4x-c2x-2,c3y-c1y-2);//Sala 4
g.setColor(new Color(255,(int)(250-2.5*Isala5),0));
g.fillRect(c2x+2,c1y+c3y-c1y+2,2*(c4x-c2x-1),H-c1y-c3y+10-2); //Sala 5
g.setColor(new Color(255,(int)(250-2.5*ItempAmb2),0));
g.fillRect(7,H-c1y+12,W-3,c1y-7); //Sala ambiente inferior
g.fillRect(c4x+c4x-c2x+2,c1y+2,W-(c4x+c4x-c2x)+2,H-(c1y+7));
g.setColor(new Color(255,(int)(250-2.5*ItempAmb1),0));
g.fillRect(7,7,W-3,c1y-8); // Sala ambiente superior
g.fillRect(7,7,c1x-7,H-c1y+3);
g.setColor(Color.black);
g.setFont(new Font("Serif",Font.PLAIN,12));
g.drawString("Sala-2",((c1x+c2x)/2)-15,((c1x+c2x)/2)-20);
g.drawString(Ssala2+"ºC",((c1x+c2x)/2)-20,((c1x+c2x)/2)-8);
g.drawString("Sala-1",((c1x+c2x)/2)-13,((H-c1y+c2y+10)/2)-5);
g.drawString(Ssala1+"ºC",((c1x+c2x)/2)-17,((H-c1y+c2y+10)/2)+7);
g.drawString("Sala-3",((c4x+c2x)/2)-13,((c1y+c3y)/2)-5);
g.drawString(Ssala3+"ºC",((c4x+c2x)/2)-17,((c1y+c3y)/2)+7);
g.drawString("Sala-4",((3*c4x-c2x)/2)-13,((c1y+c3y)/2)-5);
g.drawString(Ssala4+"ºC",((3*c4x-c2x)/2)-17,((c1y+c3y)/2)+7);
g.drawString("Sala-5",c4x-16,((H-c1y+c3y+10)/2)-5);
g.drawString(Ssala5+"ºC",c4x-20,((H-c1y+c3y+10)/2)+7);
g.drawString("Temperatura Ambiente 1",(W/2)-50,22);
g.drawString(StempAmb1+"ºC",(W/2)-10,34);
g.drawString("Temperatura Ambiente 2",(W/2)-50,H-14);
g.drawString(StempAmb2+"ºC",(W/2)-10,H-2);
}
}
public void desenha(String s)
{
if(!s.equals("NOVO GRAFICO"))
{
StringTokenizer tokens = new StringTokenizer(s);
String Snum = tokens.nextToken();
String temp = tokens.nextToken();
temp = tokens.nextToken();
Bnum = Integer.parseInt(Snum);
if (Bnum==Pic_1)
{
Ssala1 = tokens.nextToken();
Ssala2 = tokens.nextToken();
Ssala6 = tokens.nextToken();
StempAmb1 = tokens.nextToken();
Isala1 = Float.parseFloat(Ssala1);
Isala2 = Float.parseFloat(Ssala2);
Isala6 = Float.parseFloat(Ssala6);
ItempAmb1 = Float.parseFloat(StempAmb1);
}
else
{
Ssala3 = tokens.nextToken();
Ssala4 = tokens.nextToken();
Ssala5 = tokens.nextToken();
StempAmb2 = tokens.nextToken();
Isala3 = Float.parseFloat(Ssala3);
Isala4 = Float.parseFloat(Ssala4);
Isala5 = Float.parseFloat(Ssala5);
ItempAmb2 = Float.parseFloat(StempAmb2);
}
this.repaint();
}
}
public Dimension getPreferredSize()
{
return new Dimension(400,180);
}
}
************************************Arquivo Útil.Java************************************
import javax.swing.*;
import java.text.DecimalFormat;
try
{
emprestimo = Float.parseFloat(s);
return(true);
}
catch(NumberFormatException nfe)
{
JOptionPane.showMessageDialog(null, S2+ " Digitado incorretamente !",
"Dado com Erro !",
JOptionPane.ERROR_MESSAGE);
return(false);
}
}
public static short FloatShort(float f)
{
f = f*100;
if (f>32767)
{
return(32767);
}
else
{
short i = (short) Math.floor(f);
return(i);
}
}
public static short trataTemp(float f)
{
f = f*2;
if (f>255)
{
return(255);
}
else
{
short i = (short) Math.floor(f);
return(i);
}
}
//O método a seguir converte a frequencia dada pelo usuário na
//metade do período desta frequencia. Além disso, o valor é multiplicado
// por (1/0,035) de modo que cada bit do resultado corresponda a 35 ms.
//Este procedimento foi criado para facilitar a programação da onde de referencia
//no PIC.
}
*********************************TituloPanel.java**********************************
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;