UNIVERSIDADE ESTADUAL PAULISTA
CAMPUS DE SOROCABA
ENGENHARIA DE CONTROLE E AUTOMAÇÃO
Trabalho de Graduação
CONTROLE DE UM ROBÔ MÓVEL ATRAVÉS DE
IMAGEM E COMUNICAÇÃO GPRS
Marcelo Henrique Felippe
Sorocaba - SP
Junho / 2011
2
UNIVERSIDADE ESTADUAL PAULISTA
CAMPUS DE SOROCABA
ENGENHARIA DE CONTROLE E AUTOMAÇÃO
CONTROLE DE UM ROBÔ MÓVEL ATRAVÉS DE
IMAGEM E COMUNICAÇÃO GPRS
Trabalho de Graduação
apresentado à Universidade
Estadual Paulista com o
objetivo de obter o título de
bacharel em Engenheria de
Controle e Automação.
Orientador:
Prof. Dr. Galdenoro Botura Jr.
Marcelo Henrique Felippe
Sorocaba - SP
Junho / 2011
3
UNIVERSIDADE ESTADUAL PAULISTA
CAMPUS DE SOROCABA/IPERÓ
ENGENHARIA DE CONTROLE E AUTOMAÇÃO
MARCELO HENRIQUE FELIPPE
CONTROLE DE UM ROBÔ MÓVEL ATRAVÉS DE
IMAGEM E COMUNICAÇÃO GPRS
Trabalho de Graduação
apresentado à Universidade
Estadual Paulista com o
objetivo de obter o título de
bacharel em Engenheria de
Controle e Automação.
Aprovado em: ___/___/___
BANCA EXAMINADORA
_________________________
Prof. Dr. Galdenoro Botura Jr.
(Orientador)
_________________________
Prof. Dr. Everson Martins
_________________________
Prof. Dr. Luiz Carlos Rosa
4
SUMÁRIO
1- Resumo....................................................................................................... 7
2- Objetivos ..................................................................................................... 8
3- Introdução................................................................................................... 9
4- Metologia .................................................................................................. 12
5- Visão Teórica ........................................................................................... 14
5.1- MICROCONTROLADORES ARM7 .....................................................................................................14 5.1.1-Aplicações do Microcontrolador ARM7 ..................................................................... 14 5.1.2-Características do Núcleo ARM7TDMI-S.................................................................. 15 5.1.3-Estruturação Interna do Núcleo ARM7TDMI-S ......................................................... 16 5.1.4-Pipeline do Núcleo ARM7TDMI-S ............................................................................. 17 5.1.5-Set de Instruções do Núcleo ARM7TDMI-S.............................................................. 17 5.1.6-Registradores do Núcleo ARM7TDMI-S ................................................................... 18 5.1.7-Modo de Trabalho das Variáveis do Núcleo ARM7TDMI-S...................................... 19 5.1.8-LPC2148 da Philips ................................................................................................... 20
5.2-CÂMERA VGA C328........................................................................................................................23 5.2.1-Configuração do dispositivo ...................................................................................... 24 5.2.2-Interface Serial .......................................................................................................... 24
5.3- COMPRESSÃO DE IMAGEM POR JPEG ..............................................................................................32 5.4- COMUNICAÇÃO DE SISTEMAS POR PROTOCOLO TCP/IP...................................................................34 5.5- PROTOCOLO GPRS (GENERAL PACKET RADIO SERVICE) ...............................................................44 5.6- OVERHEAD EM GPRS .....................................................................................................................49 5.7- CONTROLE DE MOTORES CC ...........................................................................................................51 5.8- DISPLAY DE CARACTERES DO TIPO LCD.........................................................................................54 5.9 - ANATOMIA DE ROBÔS MÓVEIS........................................................................................................58
6- Desenvolvimento .................................................................................... 62
6.1- ESPECIFICAÇÃO E PROJETO DO HARDWARE ....................................................................................62 6.2- SOFTWARE DE INTERFACE COM A CÂMERA.....................................................................................63 6.3- SOFTWARE DE MEDIÇÃO DE ATRASOS.............................................................................................64 6.4- SOFTWARE DE INTERFACE COM O VEÍCULO.....................................................................................66 6.5- MAPEAMENTO E UTILIZAÇÃO DOS SINAIS DO CARRO.......................................................................69 6.6- CONCEPÇÃO DO SISTEMA................................................................................................................71 6.7- INICIALIZAÇÃO DOS REGISTRADORES.............................................................................................74
6.7.1- Função de temporização.......................................................................................... 75 6.8- INTERFACE COM O LCD ..................................................................................................................78 6.9- CONFIGURANDO UMA CONEXÃO SOCKET ENTRE CLIENTE E SERVIDOR...........................................81
6.9.1- Interrupção da Porta Serial (UART1) ....................................................................... 86 6.10- ENVIO DE DADOS DO CLIENTE PARA O SERVIDOR..........................................................................88 6.11- SINCRONIZAÇÃO COM A CÂMERA C328 ........................................................................................90 6.12- CONSTRUÇÃO DO VEÍCULO............................................................................................................98
7- Resultados ............................................................................................. 103
7.1- MEDIÇÃO DA LATÊNCIA DA REDE..................................................................................................104 7.2 TAXA DE TRANSMISSÃO..................................................................................................................105
8- Conclusão............................................................................................... 106
9- Referências Bibliográficas .................................................................. 107
ANEXO A- Código fonte do Servidor.............................................................. 109
ANEXO B- Firmware do Robô........................................................................ 116
5
ANEXO C- Código fonte, computador e a câmera via RS232....................... 138
ANEXO D- Características Elétricas da Câmera............................................ 147
ANEXO E- Características elétricas do modem GPRS.................................. 150
ÍNDICE DE FIGURAS FIGURA 1- ROBÔ CANADENSE TELEOPERADO QUE DESARMA BOMBAS....................................................10 FIGURA 2- ROBÔ DE SEGURANÇA CONTROLADO POR CELULAR ...............................................................10 FIGURA 3- MICROCONTROLADOR ARM7 DA FAMÍLIA LPC214X DA PHILIPS ...........................................15 FIGURA 4- DIAGRAMA EM BLOCOS DO NÚCLEO ARM7TDMI-S ...............................................................16 FIGURA 5- PIPELINE...................................................................................................................................17 FIGURA 6- MODO THUMB E MODO ARM. ..................................................................................................18 FIGURA 7- ACUMULADOR (REGISTRADORES DE USUÁRIO). ......................................................................19 FIGURA 8- LITTLE ENDIAN E BIG ENDIAN....................................................................................................20 FIGURA 9- PINAGEM DO LPC2148............................................................................................................21 FIGURA 10- SOM ELPC64 E INTERFACE DE INTEGRAÇÃO.....................................................................22 FIGURA 11- DIAGRAMA DE BLOCOS DA CÂMERA C328.............................................................................23 FIGURA 12- DESCRIÇÃO DOS PINOS DA CÂMERA C328 ...........................................................................24 FIGURA 13- DIAGRAMA EM FUNÇÃO DO TEMPO DE UM ÚNICO BYTE.........................................................25 FIGURA 14- RS-232 E COMANDO DE SINCRONIA......................................................................................25 FIGURA 15- DIAGRAMA DE COMANDOS PARA SINCRONIZAR DISPOSITIVO EXTERNO E A CÂMERA ...........30 FIGURA 16- CONFIGURAR PARÂMETROS...................................................................................................31 FIGURA 17- COMANDO DE CAPTURAR E RECEBER DADOS .......................................................................32 FIGURA 18- ARQUITETURA DO TCP/IP .....................................................................................................37 FIGURA 19- CAMADAS DE INTERNET, TRANSPORTA E APLICAÇÃO ..........................................................40 FIGURA 20- ARQUITETURA DO ETHERNET ................................................................................................41 FIGURA 21- QUADRO NA CAMADA DE INTERFACE COM A REDE. ...............................................................43 FIGURA 22- PACOTE DE DADOS NA CAMADA DE TRANSPORTE. ...............................................................44 FIGURA 23- MÓDULO GSM COM TECNOLOGIA GPRS E SUA COMPATIBILIDADE. ...................................45 FIGURA 24- EVOLUÇÃO DE GSM PARA 3G [4].........................................................................................46 FIGURA 25- REDE GPRS ..........................................................................................................................48 FIGURA 26- HIERARQUIA DO PROCOLO GPRS [8]....................................................................................50 FIGURA 27- POLARIZAÇÃO DE UM TRANSISTOR NPN...............................................................................52 FIGURA 28- REPRESENTAÇÃO SIMPLIFICADA DE UMA PONTE H [10]. ......................................................53 FIGURA 29- REPRESENTAÇÃO DO FUNCIONAMENTO DE UMA PONTE H. ..................................................53 FIGURA 30- DISPLAY DE CARACTERES COM 16 COLUNAS E 2 LINHAS (16X2).........................................54 FIGURA 31- CLASSIFICAÇÃO DE ROBÔS MÓVEIS SEGUNDO A ANATOMIA [A]. ..........................................58 FIGURA 32- EXEMPLO DE ROBÔS AQUÁTICOS ..........................................................................................59 FIGURA 33- ROBÔS COM RODAS. ..............................................................................................................60 FIGURA 34- ROBÔS COM ESTEIRAS...........................................................................................................60 FIGURA 35- ROBÔS COM PERNAS. ............................................................................................................61 FIGURA 36- INTERFACE DO SOFTWARE GERADO EM LINGUAGEM C++ ....................................................63 FIGURA 37- PROGRAMA DE MEDIÇÃO DE ATRASO DE DADOS NA REDE....................................................65 FIGURA 38- DIAGRAMA DE BLOCOS DO PROGRAMA DE MEDIÇÃO. ...........................................................65 FIGURA 39- INTERFACE DE COMANDO REMOTO DO VEÍCULO ...................................................................67 FIGURA 40- PROPRIEDADES DO OBJETO SERVERSOCKET.......................................................................68 FIGURA 41- PROPRIEDADES DO TIMER .....................................................................................................68 FIGURA 42- POLARIZAÇÃO DE UM TRANSISTOR BIPOLAR DE JUNÇÃO (TBJ)............................................70 FIGURA 43- PLACA DE CIRCUITO INTEGRADO COM A PONTE H E SEUS PONTOS DE CONTROLE..............70 FIGURA 44- DIAGRAMA DE BLOCOS DO SISTEMA ......................................................................................71 FIGURA 45- FLUXOGRAMA DO FIRMWARE DO VEÍCULO............................................................................73 FIGURA 46- ESQUEMA DO CIRCUITO DO MICROCONTROLADOR E O DISPLAY...........................................78 FIGURA 47- PLACA DE FENOLITE PERFURADA ...........................................................................................98 FIGURA 48- VISÃO FRONTAL DO ROBÔ ......................................................................................................99 FIGURA 49- VISÃO LATERAL DO ROBÔ ....................................................................................................100 FIGURA 50- VISÃO DE TOPO DO ROBÔ ....................................................................................................101
6
ÍNDICE DE TABELAS
TABELA 1- SET DE COMANDOS ESPECIAIS DA CÂMERA C328............................................................ 26 TABELA 2- BAUDRATE ADMISSÍVEL PELA CÂMERA ............................................................................ 28 TABELA 3- CARACTERES ASCII E COMANDOS DE CONTROLE ........................................................... 55
7
1- Resumo
O uso de robôs vem sendo cada vez mais empregado em tarefas de
risco ou custosas para o ser humano. Apesar dos robôs atuais ainda não
possuírem autonomia suficiente para tomar decisões rápidas e seguras em
alguns casos, eles são muito eficientes quando existe uma interface homem-
máquina para o controle à distância. Nestas condições, o presente trabalho
visa desenvolver o protótipo de um robô controlado remotamente através de
uma rede de telefonia celular com o uso da tecnologia GPRS (General Packet
Radio Service) e por uma interface gráfica programada em um computador
pessoal.
O presente trabalho utiliza-se da aquisição digital de imagens
implementada em microcontrolador ARM7-LPC214x da Philips (família de 32
bits) que irá se comunicar com uma pequena câmera de comunicação serial,
modelo C328 – EV232, e enviar os quadros para uma interface local de
controle do robô, que também irá enviar comandos de controle de seus
motores de locomoção.
8
2- Objetivos
Pretende-se criar um sistema de comunicação remota que permite
ao usuário em um computador pessoal em ambiente Windows controlar, sem
grandes dificuldades, os atuadores de um veículo elétrico e receber, através
deste mesmo sistema, quadros de imagem de uma micro câmera instalada a
bordo do robô. O robô deve realizar a comunicação com o servidor através da
rede de telefonia celular com uma tecnologia acessível e de cobertura
abrangente em território brasileiro.
9
3- Introdução
Com o avanço tecnológico da Internet, verificou-se a possibilidade de
controlar robôs remotamente. Foi na década de 90 que um dos primeiros
projetos utilizando este conceito conseguiu controlar um laboratório de forma
totalmente remota. Desde então, empresas do ramo de exploração e
segurança vêm em busca de soluções que implementem esta estrutura em
robôs móveis de baixo custo e flexíveis o bastante para as mais variadas
atividades de monitoramento de ambientes [1].
Esta área de atuação é cada vez mais viável no cenário brasileiro, que
presencia um desenvolvimento significativo no setor de telecomunicações, não
somente para transmissão de voz, mas também na transmissão de dados na
Internet. O avanço neste setor permite o desenvolvimento de novas tecnologias
que auxiliem na vida e na segurança das pessoas e que não eram possíveis
com conexões de curto alcance. O desenvolvimento de um veículo de
monitoração remota é um exemplo disto.
O estudo de robôs de monitoração remota é de grande importância
para contruibuir com o desenvolvimento de tecnologia brasileira e, também,
pode contribuir com as mais diversas aplicações no país. No ano de 2011, por
exemplo, robôs antibombas foram adquiridos do Canadá, com um custo de
R$860.000,00 cada unidade para melhorar a segurança da sociedade brasileira
[2].
10
Figura 1- Robô canadense teleoperado que desarma bombas
Têm-se, também, como exemplo o robô T-34, produzido pela empresa
japonesa Tmsuk, e controlado por rede móvel e possui câmera, sensores de
calor para identificação de pessoas e um lançador de rede para a imobilização
de intrusos. O robô atinge uma velocidade máxima de 10 km/h e possui um
tamanho reduzido, como é visto na figura 2.
Figura 2- Robô de segurança controlado por celular.
Com base nos fatos descritos, procurou-se criar um veículo
controlado à distância, através de um computador, que receberá comandos de
12
4- Metologia
O desenvolvimento do projeto iniciou-se pelo estudo do protocolo de
comunicação da câmera C328 a ser utilizada. Para isso, obteve-se do site do
fabricante da câmera os folha de dados (datasheet) do produto e analisou-se a
fundo as configurações como tamanho das imagens disponíveis, representação
de cores, taxa de dados (baudrate) e comandos de interface para serem
implementados no microcontrolador.
Para melhor estudo dos procedimentos utilizados na comunicação
com a câmera, foi preciso elaborar um programa em ambiente Windows que
fosse capaz de enviar e receber dados serialmente entre computador e a
câmera. Com isso, têm-se algoritmos quase similares que serão embarcados
no microcontrolador durante o trabalho final.
Em paralelo, o microcontrolador ARM7 foi estudado. O
microcontrolador LPC2148 foi escolhido para o projeto devido a sua
superioridade de memória volátil (32Kbytes) em relação a outros
microcontroladores, além de possuir 45 I/O’s tolerantes a 5V, 6 canais PWM e
duas UART’s.
O compilador escolhido foi o software Keil uVision3 para e geração
do código *.HEX que deve ser descarregado na memória Flash do
microcontrolador através do software Flash-Utilities do fabricante Philips. A
programação do microcontrolador é feita através da porta serial do computador
utilizado, padrão RS232.
Adquirida a experiência e familiaridade com o microcontrolador
adotado, estudou-se a lista de comandos necessária para comunicação serial
com o modem GSM utilizado.
Até o momento, também foram estudadas formas de se acionar
motores de corrente contínua com correntes superiores às fornecidas pela
13
porta do microcontrolador. Assim sendo, foi utilizado um circuito de
acionamento conhecido como “ponte H” para o acionamento dos motores do
veículo.
Para simular a interface do microcontrolador com o display de
caracteres em LCD 16x2 foi usado o software de simulação eletrônica
PROTEUS 7.
14
5- Visão Teórica
O desenvolvimento do trabalho foi focado inicialmente no protocolo
de comunicação da câmera e no estudo da arquitetura do microcontrolador,
pois sem o mesmo não é possível implementar nenhum sistema de controle
remoto para o robô. Esta seção resume os principais tópicos estudados e
desenvolvidos com as respectivas referências bibliográficas.
5.1- Microcontroladores ARM7
O estudo dos microcontroladores ARM7 foi baseado no livro
“Microcontroladores ARM7”, publicado pela editora Érica do autor Daniel
Rodrigues de Souza, (Souza,2006), o livro trata as características da família
LPC213x da Philips, mais especificamente utiliza-se como modelo o
microcontrolador LPC2138, em sua dissertação .Grande parte do estudo pode
ser aplicada ao microcontrolador LPC214x, o qual será utilizado neste projeto,
devido às características da arquitetura interna do microcontrolador, funções
disponíveis, estrutura de barramento, e registradores serem idênticos.
5.1.1-Aplicações do Microcontrolador ARM7
Uma nova abordagem do mercado é disponibilizar produtos com
baixo consumo de energia e alto poder de processamento, para atingir este
objetivo surgiram os microprocessadores ARM que significa Advanced RISC
Machine (Máquina RISC avançada) e RISC significa Reduced Instruction Set
Computer (computador com set de instruções reduzido), o núcleo ARM7 está
disponível em vários microprocessadores de diversos fabricantes como a
Philips, Analog Devices, OKI, entre outros. Neste projeto será utilizado o
microcontrolador ARM7, LPC214x da NXP fundada pela Philips, para isso
escolheu-se o modelo LPC2148. A figura 3 apresenta uma imagem do
microcontrolador ARM7 da família LPC214x da Philips.
15
Figura 3- Microcontrolador ARM7 da família LPC214x da Philips
5.1.2-Características do Núcleo ARM7TDMI-S
O LPC213x utiliza como núcleo o ARM7TDMI-S, parte integrante da
família ARM de processadores de uso geral. Esses processadores oferecem
um alto desempenho, alto poder de processamento e baixo consumo, sendo
uma característica importante para aplicações em que baixo consumo de
energia é fundamental, as características principais do núcleo estão listadas a
seguir:
• Modo Thumb: O modo thumb do ARM7TDMI-S nada mais é do que um
segundo set de instruções com 16 bits que visa economizar memória de
programa.
• Multiplicações longa: A utilização de um hardware dedicado para
multiplicação longa possibilita ao núcleo realizar operações mais
complexas normalmente feitas por um DSP. Com esse hardware é
possível realizar multiplicações de 32 bits por 32 bits, apresentando o
resultado em 64 bits. Ainda esse módulo é capaz de realizar
multiplicação-acumulação (MAC) de 32 bits por 32 bits com resultado de
64 bits.
• Depuração: Uma região do núcleo possui uma extensão de hardware
capaz de realizar uma depuração dentro da aplicação com a utilização
de ferramentas J-link através de porta JTAG.
16
• Embedded ICE : é uma extensão das funções de depuração. Esse
módulo estende as funções de breakpoints (pontos de parada),
visualização de registros e outros pontos do programa, o que torna muito
mais fácil o trabalho de depuração. Esse módulo é acessado pela JTAG
e pode ser operado ou interagir com a ferramenta J-link.
• Alta capacidade de processamento: O núcleo ARM7TDMI-S tem
capacidade de processamento de 0.9 MIPS/MHz (Milhões de instruções
por segundo/ MHz).
5.1.3-Estruturação Interna do Núcleo ARM7TDMI-S
A estruturação interna do núcleo esta representada no diagrama em
blocos da figura 4 podendo assim ser visualizadas diversas partes que compõe
o núcleo ARM7TDMI-S.
Figura 4- Diagrama em blocos do núcleo ARM7TDMI-S
17
5.1.4-Pipeline do Núcleo ARM7TDMI-S
Os processadores ARM7TDMI-S executam as instruções usando
pipeline de três estágios (busca, decodificação e execução). Com o uso do
pipeline a maioria das instruções é executada em um ciclo de máquina.A figura
5 representa o pipeline.
Figura 5- Pipeline.
5.1.5-Set de Instruções do Núcleo ARM7TDMI-S
O ARM7TDMI-S possui dois sets de instruções:
• Instruções ARM: conjunto de instruções em 32 bits.
• Instruções Thumb: conjunto de instruções comprimidos em 16 bits.
Utilizando-se o set de instruções ARM, ganhasse velocidade de
processamento, porém utiliza-se mais memória de programa, já se utilizando
do modo Thumb economiza-se 30% de memória de programa, porém perde-se
em torno de 40% de poder de processamento em relação ao set de instruções
ARM. A figura 6 mostra a operação dos dois sets de instruções do núcleo.
18
Figura 6- Modo Thumb e modo ARM.
Observando a figura 6 fica fácil entender porque as instruções ARM
são mais rápidas do que as instruções Thumb, pois se tem um bloco a menos.
5.1.6-Registradores do Núcleo ARM7TDMI-S
O ARM7TDMI-S tem uma estrutura de load-and-store, ou seja, para
realizar qualquer operação envolvendo variáveis ou registradores devem ser
movidos primeiro em um registrador de usuário (uma espécie de acumulador) e
somente com as variáveis carregadas nos registradores é que se podem fazer
todas as operações como adição, subtração, entre outras.
No acumulador temos 15 registradores. De R0 a R12 são os
registradores de usuário, R13 como Stack Pointer, R14 como Link Register e
R15 como contador de programa, como representado na figura 7.
19
Figura 7- Acumulador (registradores de usuário).
5.1.7-Modo de Trabalho das Variáveis do Núcleo ARM7 TDMI-S
O núcleo ARM7TDMI-S trabalha com dois modos de tratamento de
variáveis, o big endian e little endian, apresentados na figura 8. Quando se
trabalha com o modo little endian, o bit menos significativo está a direita e o
mais significativo está à esquerda, já no modo big endian o bit menos
significativo está à esquerda e o mais significativo está à direita.
Por padrão da Philips, o LPC2xxx trabalha com modo little endian,
que é o mais comum aos microprocessadores e microcontroladores.
20
Figura 8- Little endian e big endian
5.1.8-LPC2148 da Philips
Para o trabalho em questão, como foi mencionado anteriormente,
escolheu usar o microcontrolador LPC2148 por ser de baixo custo comparado
aos DSP’s, mas possuir elevada capacidade de processamento (até 60 MHz)
e, além disso, possuir memória volátil relativamente maior que a maioria dos
microcontroladores encontrados no mercado atualmente. A memória RAM para
este trabalho é de fundamental importância, pois ela precisa ser
suficientemente grande para rodar o programa em execução além de ser capaz
de armazenar um único quadro obtido da câmera para detecção das faixas.
5.1.8.1-Características Gerais do LPC2148
As características principais do LPC2148 foram retiradas do
datasheet do fabricante (LPC2148,2009) e estão apresentadas abaixo:
• Núcleo de 16-bit/32-bit ARM7TDMI-S;
• Alimentação de 3,0V à 3,6V;
• 512Kbytes de memória de programa (Flash);
• 32Kbytes de memória de dados volátil (RAM);
• 21 interrupções externas;
• 45 I/O’s tolerantes a 5V;
• Dois timers ou contadores de eventos externos de 32 bits;
• Unidade PWM com seis saídas;
• Watchdog Timer;
21
• Duas UART’s, sendo uma com todos os pinos de controle
implementados por hardware (CTS, DCD,DSR,DTR,RI e RTS),sendo
compatível para interfacear um modem;
• Dois barramentos CI 2 ;
• Um barramento SPI;
• Um módulo SSP (SPI,4-wire ou Microwire);
• RTC interno;
• Dois conversores A/D de 10 bits com 14 canais cada;
• Um canal de conversão D/A de 10 bits;
• Opera com cristal de 1MHz até 30 MHz ou oscilador externo de 1MHz
até 25 MHz;
• 60 MHz de operação máxima via PLL interno;
• USB 2.0 (única diferença em relação ao LPC2138).
5.1.8.2-Pinagem do LPC2148
Os pinos do LPC2148 foram retirados do datasheet do fabricante
(LPC2148,2009) e estão representados na figura 9.
Figura 9- Pinagem do LPC2148
22
5.1.8.3-Placa SOM eLPC64 da eSysTech
Trata-se de um módulo SOM (System on Module), que consiste de
um PCB de dimensão de meio cartão de crédito (half credit card) que
implementa o núcleo de um sistema microprocessado baseado no ARM7TDMI-
S, o microcontrolador escolhido para compor o módulo foi o LPC2148 da
Philips.
O módulo eLPC64 implementa as funcionalidades essenciais
(microcontrolador, alimentação e clock) de um sistema embarcado, uma
interface padrão disponibiliza os sinais necessários para implementação
específica a cada produto em sua base. Desta forma, podem ser empregados
para fins de engenharia ou para a integração de um produto final. A figura 10
mostra o SOM’s e sua interface.
Figura 10- SOM eLPC64 e interface de integração
Características gerais do módulo:
• Header de 60 pinos (2 linhas de 30 pinos com passo de 0,1”)
• Suporte aos processadores NXP LPC21xx;
• Alimentação externa de 4 a 6 V;
• Cristais para processador até 20 MHz e RTC 32,768kHz;
• Compatível com placa de desenvolvimento eLPC-Main 2122;
23
5.2-Câmera VGA C328
Escolheu-se usar a câmera de comunicação serial fornecida pelo
fabricante chinês COMedia Ltda. A câmera é basicamente composta pelo
sensor de imagem VGA OV7640 e um compressor de imagem para formato
JPEG, reduzindo seu tamanho para melhor envio na forma serial. Com isso, é
possível associar este dispositivo de imagem em uma rede wireless (sem fio),
microcontrolador ou a um PDA. O usuário pode enviar um comando de
snapshot (um quadro estático de imagem) do host para a câmera, então ela
captura um único quadro de imagem, comprime e envia de volta como é
mostrado na figura 11.
Figura 11- Diagrama de blocos da câmera C328
Através do “datasheet” da câmera, foi possível encontrar as suas
características:
• Baixo custo e pouco consumo de energia (60 mA) aliado à imagens
capturadas de alta resolução;
• RS-232: 115.2K bps transferidos em JPEG ou 160x128 em modo
preview (pré-visualização) não comprimido com 8 bits por pixel (bpp) e
amostragem de 0.75~6 quadros por segundo (fps);
• Codificador JPEG para diferentes resoluções;
• Captura imagens na forma 4-gray,16-gray,256-gray,12-bit RGB,16-bit
RGB para modo preview.
• Detecta automaticamente baud rate (traxa de transmissão e recepção)
para fazer conexão com o host (no caso, microcontrolador).
24
5.2.1-Configuração do dispositivo
A câmera C328 é equipada com o sensor OmniVision OV7640/8
VGA que possui uma interface de 8-bits YCbCr. O controlador OV528 é o
controlador que transfere os dados do registrador da câmera para um
dispositivo externo.
Sempre que se desejar adquirir uma imagem da câmera, é preciso
configurá-la inicialmente através de alguns comandos pré-definidos que estão
armazenados na sua memória de programa.
A pinagem do módulo da câmera está descrito na figura 12.
Figura 12- Descrição dos pinos da câmera C328
As especificações elétricas da câmera estão informadas no anexo A
do trabalho.
5.2.2-Interface Serial
Para implementar a câmera com o microcontrolador escolhido ou
qualquer outro dispositivo microprocessado é preciso estudar os comandos
básicos necessários para configurar os parâmetros da câmera e assegurar a
correta sincronia entre câmera e host. Os principais tópicos do protocolo da
câmera estão disponíveis no site do fabricante.
• Diagrama de tempo de um único byte:
25
Um único byte numa transmissão pela RS-232 consiste em um start
bit (bit de início), 8-bits de dados e um stop bit (bit de parada). Um start bit
sempre será nível lógico baixo (0), enquanto um stop bit sempre será nível
lógico alto (1). O bit menos significativo (LSB) é enviado logo após o start
bit. Conferir a figura 13.
Figura 13- Diagrama em função do tempo de um único byte
• Diagrama de tempo para um único comando
Um único comando consiste em 6 bytes enviados pelo protocolo RS-
232. Um exemplo de comando típico é o comando SYNC (sincronia)
representado pela palavra AA0D00000000h como é mostrado na figura 14.
Figura 14- RS-232 e comando de sincronia
26
5.2.2.1-Set de comandos
A câmera C328-7640 suporta um total de 11 comandos para
interface com o microcontrolador. Estes comandos são resumidos na tabela
1.
Tabela 1 - Set de comandos especiais da câmera C328
Se o parâmetro é 0xFF, o comando é um Reset especial onde o firmware responde imediatamente.
• Initial (AA01h) – Comando Início
Este comando é sempre utilizado para configurar a imagem no modo
preview como seu tipo de cor e tamanho. Após receber este comando, o
módulo irá enviar um comando de ACK (tudo correto) para o
microcontrolador se a configuração for bem sucedida. Entretanto, um NACK
(falha) será enviado se algo der errado.
• Color Type (tipo de cor)
A câmera C328 pode suportar 7 tipos diferentes de cor:
27
2-bit Gray Scale 01h
4-bit Gray Scale 02h
8-bit Gray Scale 03h
12-bit Color 05h
16-bit Color 06h
JPEG 07h
• Resolução no modo Preview
O modo de pré-visualização, ou seja, com a imagem não comprimida
pode ser suportado nas seguintes resoluções:
80x60 01h
160x120 03h
• Resolução em JPEG
A câmera também suporta um modo de pré-visualização na forma
comprimida em JPEG com as seguintes resoluções:
80x64 01h
160x128 03h
320x240 05h
640x480 07h
• Get Picture (AA04h)- Comando obter imagem
Com este comando, a câmera pode ser configurada para enviar
imagens com os seguintes tipos:
Snapshot Picture 01h
Preview Picture 02h
JPEG Preview Picture 05h
28
• Snapshot (AA05h)
Com este comando, a câmera armazena um único quadro de
imagem na forma de JPEG em um buffer. Porém também existe uma forma
de dar um comando snapshot na forma não comprimida. Os parâmetros de
snapshot são:
Compressed Picture 00h
Uncompressed Picture 01h
• Set Package Size (AA06h) – Comando tamanho do pacot e
Para o envio de imagens em JPEG é possível enviá-las em etapas
chamadas pacotes. É importante enviar este comando antes de enviar o
comando GetPicture ou Snapshot. Porém, para imagens não comprimidas
não é preciso o uso de pacotes, uma vez que elas são enviadas de forma
inteira para o dispositivo externo. Por padrão o tamanho do pacote é de 64
Kbytes e o maior pacote admissível é 512 Kbytes.
• Set Baudrate (AA07h)
A câmera pode automaticamente detectar o baudrate do comando
recebido pelo dispositivo externo ou pode obedecer ao comando Set
Baudrate com os valores fornecidos pela tabela 2:
Tabela 2- Baudrate admissível pela câmera
29
Onde o valor do baudrate do comando é obedecido pelos divisores
como parâmetros da seguinte forma:
Baudrate = 14.7456MHz / 2 x (2° Divisor + 1) / 2 x (1° Divisor + 1)
• Reset (AA08h) – Comando de reinicio
Este comando apaga toda a configuração dada anteriormente à
câmera.
• SYNC (AA0Dh)
É o primeiro comando necessário para o dispositivo fazer conexão
com a câmera e vice-versa.
• ACK (AA0Eh)
Comando enviado pela câmera para confirmar operação do comando
anterior ou envio dos dados corretamente.
• NAK (AA0Fh)
Comando indicador de que algo na operação deu errado.
5.2.2.2-Diagrama do protocolo de comandos
Para fazer a conexão com o dispositivo externo e enviar um único
quadro de imagem não comprimida (snapshot) são precisos 3 etapas de
comandos: sincronia, configurar parâmetros da imagem e comando de
snapshot.
5.2.2.3-Sincronia
30
Para estabelecer conexão com a câmera é preciso que o dispositivo
externo envie repetidas vezes o comando SYNC (no máximo 60 vezes) até
receber um comando ACK e um comando SYNC da câmera. Então, deve-se
enviar um comando ACK garantido a conexão. Ver diagrama da figura 15.
Figura 15- Diagrama de comandos para sincronizar dispositivo externo e a câmera
5.2.2.4-Configurar parâmetros da imagem
Nesta etapa é preciso configurar o tipo de imagem que se deseja
receber da câmera, além do tipo de cor utilizado e, se preciso, alterar o
baudrate da conexão.
31
Figura 16 - Configurar parâmetros
5.2.2.5-Comando preview
Usado para capturar e receber um quadro pequeno de imagem.
Neste trabalho serão usadas imagens no padrão JPEG, pois seria custoso
para transmitir imagens não comprimidas. Escolheu-se receber imagens
comprimidas que facilitam a transmissão das mesmas.
32
Figura 17- Comando de capturar e receber dados
5.3- Compressão de imagem por JPEG
Dada a necessidade de enviar dados de imagens pela rede GPRS para
que o usuário possa se situar no espaço que se encontra o veículo, a utilização
de algum algoritmo de compressão de imagem se faz necessário. Com isso,
33
tem-se uma redução do tamanho do pacote a ser transferido, redução do
tempo de transferência de cada quadro e, também redução dos custos com a
transmissão.
Exemplificando, tem-se um quadro de imagem obtido pela câmera do
robô com resolução de 640x480, ou seja, ela possui 307.200 pixels. Se cada
pixel usa 24 bits (3 bytes) para a cor verdadeira, uma única imagem pode
requerer 900 kilobytes (364x480x3) de espaço de armazenamento, sem
compressão do arquivo. Quanto maior a resolução, maior o tamanho do
arquivo [3].
Para melhorar a questão de armazenamento, ou transferência destas
informações, a câmera serial adotada já fornece imagens comprimidas em
formato JPEG (Joint Photographic Experts Group). Este formato é amplamente
utilizado para compressão de imagens tal como em recursos multimídia na
Internet, câmeras digitais e computadores.
Durante a compressão, dados que são duplicados ou que não têm
nenhum valor para o reconhecimento pelo olho humano são eliminados ou
salvos em uma forma reduzida, diminuindo o tamanho de um arquivo. Quando
a imagem for editada ou exibida, o processo de compressão será invertido [3].
A compressão JPEG trabalha em três fases principais: Transformação,
Quantificação e Codificação.
• A transformação é a formatação dos dados da imagem que
expressam a variação de cor e brilho. Este passo é preparatório e crítico
para a Quantificação [3].
• Quantificação é o processo que de fato descarta alguns dados
para definir uma imagem menor. A imagem inteira é analisada por áreas
de 8x8 pixels, que compõe blocos de 64 pixels cada. Por um processo
matemático, as variações de cor encontradas nestes blocos são
34
calculadas em uma média, de forma que menos dados são necessários
para expressar os valores no bloco [3].
• Por último, tem-se a codificação que usa um processo
semelhante à compressão reversível aplicada aos dados, com isso os
compacta ainda mais [3].
No caso da compressão por JPEG, é difícil predizer qual será o
tamanho do arquivo depois da compressão, pois dependerá do conteúdo da
imagem, sobretudo da quantia de detalhes capturados. Com isso, quando duas
aplicações trocam imagens pela rede, é preciso que haja uma troca de
informação preliminar do tamanho da imagem que será recebida para que seja
possível realizar a transformação inversa dos dados comprimidos.
5.4- Comunicação de sistemas por protocolo TCP/IP
Quando se trata de comunicação em rede, seja ela por redes
cabeadas ou sem fio, o protocolo TCP/IP é o mais conhecido e utilizado
atualmente no mundo. Isto permite que não apenas computadores “falem a
mesma língua” mas também dispositivos embarcados e mais simples possam
interagir na rede.
Contudo, antes do esclarecimento do protocolo TCP/IP, é preciso
entender o funcionamento da sua referência que foi baseada no modelo OSI
(Open Systems Interconnection).
O modelo OSI possui ao todo 7 camadas. Tais camadas serão
vistas com a menor hierarquia (físico) até a mais “alta” (Aplicativo): Físico,
Vínculo de Dados, Rede, Transporte, Sessão, Apresentação, Aplicativo . [1]
35
Camada Física: camada inferior do modelo OSI que fica responsável pela
transmissão e recepção do fluxo de bits enviados/ recebidos através de um
meio físico. Descreve as interfaces óptica, elétrica, mecânicas e funcionais
para o meio físico e executa os sinais de todas as camadas superiores.
Basicamente, esta camada converte em bits 0s e 1s através da excitação de
um meio de transmissão elétrico, óptico ou eletromagnético e o mesmo ocorre
para a recepção [1].
Camada de Link de Dados: é a camada que fornece erros de transferência de
dados de um nó para outro sobre a camada física. Ela estebelece e finaliza
vínculo lógico entre dois nós, controla tráfego de quadros, transmite/recebe
quadros sequencialmente, fornece/espera confirmação de quadro, cria e
reconhece os limites de um quadro, gerencia o acesso à mídia (autorizando um
nó a usar ou não a mídia física) [4].
Camada de Rede: esta camada controla a operação da sub-rede. Decide que
caminho físico deve levar os dados com base em condições de rede, prioridade
do serviço e outros fatores. Para ser mais claro, a camada de rede associa
endereços lógicos (IP) em endereços físicos (MAC), de forma que cada pacote
consiga chegar corretamente em seu destino. [4]
Camada de transporte : é a camada responsável por pegar os dados enviados
pela camada de sessão (que será abordada em seguida) e dividi-los em
pacotes que serão transmitidos para a camada de Rede. O mesmo princípio
ocorre na recepção, onde a camada de Transporte adquire os pacotes
recebidos da camada de Rede, remonta o dado original e assim o envia para a
camada de Sessão.
A camada de Transporte também inclui o controle de fluxo, ordenação
de pacotes e correção de erros. Para cada pacote recebido existe uma
confirmação de transmissão [4]. Esta camada oferece maior confiabilidade e
eficiência na comunicação, porém a ISO define o protocolo de Transporte para
operar em dois modos: Orientado à conexão e Não orientado à conexão.
36
O protocolo TCP é orientado à conexão é confiável, pois garante a
entrega de um pacote de dados, além da ordenação correta do mesmo.
Contudo, existe o protocolo UDP (User data Protocol) que não garante o envio
e o recebimento de um pacote. Apesar do protocolo UDP não ser confiável, ele
possui algumas vantagens que serão vistas posteriormente [4].
Camada de Sessão : a camada de sessão permite que aplicações em
computadores diferentes estabeleçam uma sessão de comunicação.
Basicamente, esta sessão consegue administrar os recursos da rede
de forma que ela seja aproveitada ao máximo sem ficar desocupada. A camada
de sessão também possibilita dois computadores a restabelecer uma conexão
perdida a partir da última marcação comunicada [4].
Camada de apresentação: a camada de apresentação, como o nome diz,
prepara os dados para serem usados na camada de aplicativo. Os dados
podem ser convertidos da forma que são recebidos na rede para um outro
formato que o aplicativo seja preparado para trabalhar e vice-versa. Por
exemplo, converter código ASCII para BDCDIC, compactação de dados e
criptografia (segurança da informação) [4].
Camada de aplicativo: por último, vem a chamada camada de aplicativo que
serve como interface entre usuários ou processos de aplicativos acessarem os
serviços de rede. Com esta camada é possível acessar remotamente arquivos,
impressoras, criar comunicação entre processos, gerenciar redes e serviços de
diretório [1]. Alguns protocolos utilizados nesta camada são HTTP, SMTP, FTP,
SSH, RTP, Telnet, SIP, RDP, IRC, SNMP, NNTP, POP3, IMAP, BitTorrent,
DNS, Ping, etc.
37
5.4.1- Protocolo TCP/IP
O protocolo TCP (Transmission Control Protocol) é um dos principais
protocolos da camada de Transporte do modelo TCP/IP. O TCP é um protocolo
orientado para a conexão , quer dizer que permite duas ou mais aplicações em
máquinas distintas controlarem o estado da transmissão [5]. Em adição, o
modelo TCP/IP é na verdade um conjunto de protocolos com base, também, no
protocolo IP (Internet Protocol). Alguns outros protocolos que compõe a pilha
TCP/IP seriam, por exemplo, o FTP, HTTP, SMTP e o UDP (utilizado neste
projeto) [6].
Figura 18- Arquitetura do TCP/IP
De acordo com a Figura 18, o protocolo TCP/IP possui quatro
camadas (3 camadas a menos que o modelo OSI). Os programas que
possuem uma comunicação de alto nível utilizam a camada de Aplicação.
Alguns protocolos da camada de Aplicação são o SMTP (para e-mails), o FTP
(para a transferência de arquivos) e o HTTP (navegação web) [6].
5.4.1.1-Camada Aplicação
A camada de aplicação comunica-se com a camada de transporte
através de uma porta. As portas são numeradas de acordo com a aplicação e o
38
tipo de dado utilizado. Por exemplo, uma aplicação de e-mail irá usar o
protocolo SMTP e, por isso, utilizar a porta padrão 25, o protocolo FTP a porta
20 (para transmissão de dados) ou 21 (para transmissão de informações de
controle) e o protocolo HTTP utiliza a porta 80 [6].
5.4.1.2- Camada Transporte
Após realizar a sua função, a camada de Aplicação se comunicará
com a camada subsequente, Transporte. O protocolo mais usado nesta
camada é o TCP. Esta camada é responsável de enviar dados da camada
superior, dividi-los em pacotes e enviá-los para a camada inferior, Internet. Ela
também verifica a integridade do conteúdo dos pacotes e os ordena para a
camada inferior [6].
Na recepção dos dados, na camada de Transporte, o protocolo TCP
afirma que recebeu os dados e, após a checagem de integridade dos dados do
pacote, envia um comando de confirmação para o transmissor, conhecido
como “acknowledge” (“ack”). Na ocorrência do não recebimento desse
comando de confirmação, imediatamente o transmissor irá enviar novamente
os pacotes [6].
5.4.1.3- Camada Internet
É na camada Internet que se tem o protocolo IP (Protocolo de
Internet), que adquire os pacotes recebidos da camada de Transporte e
acrescenta informações de endereçamento virtual chamado IP. O endereço IP
funciona como um destino virtual da máquina para qual o pacote deve ser
enviado [6].
Além de possuírem um endereço virtual, as placas de rede possuem
um endereço físico chamado endereço MAC. Numa rede local, se um
computador A quiser enviar um dado para um computador B, o endereço MAC
pode ser necessário [3]. Enquanto numa rede local descobrir o endereço MAC
39
de um computador é tarefa simples, numa rede global como a Internet isto se
torna difícil [6].
Em todas as redes conectadas à Internet existe um dispositivo ,
chamado roteador, que interliga as redes locais com a rede global. Todo
roteador tem uma tabela contendo as redes conhecidas e também uma
configuração chamada gateway padrão apontando para outro roteador na
Internet. Quando o computador envia um pacote de dados para a Internet, o
roteador conectado à rede primeiro verifica se ele conhece o computador de
destino- em outras palavras, o roteador verifica se o computador de destino
está localizado na mesma rede ou em uma rede que ele conhece a rota. Se ele
não conhecer a rota para o computador de destino, ele enviará o pacote para
seu gateway padrão, que é outro roteador. Este processo é repetido até que o
pacote de dados chegue ao seu destino [6].
O protocolo IP recebe os dados da camada de Transporte
(TCP) e os transforma em datagramas (pacotes sem confirmação de
recebimento). Isto torna o protocolo IP não confiável. Porém, em conjunto com
o protocolo TCP, que realiza a checagem de pacotes, ele se torna um protocolo
confiável.
Cada datagrama IP pode ter no máximo 65.535 bytes, incluindo seu
cabeçalho, que pode usar 20 a 24 bytes, dependendo se um campo chamado
“opções” for usado ou não. Dessa forma, os datagramas IP podem transportar
até 65.515 ou 65.511 bytes de dados. Se o pacote de dados recebidos da
camada de Transporte forem maiores do que 65.515 ou 65.511 bytes, o
protocolo IP fragmentará os pacotes em quantos datagramas forem
necessários [6].
40
Figura 19- Camadas de Internet, Transporta e Aplicação
O datagrama IP pode ter até 65.535 bytes. Isto significa que o campo
de dados do datagrama não tem um tamanho fíxo. Como os datagramas serão
transmitidos pela rede de quadros produzidos pela camada Interface com a
Rede, normalmente o sistema operacional configurará o tamanho do
datagrama IP para ter o tamanho máximo da área de dados do quadro usado
na rede. O tamanho máximo do campo de dados dos quadros que são
transmitidos pela rede é chamado MTU, Maximum Transfer Unit, ou Unidade
de Transferência Máxima [6].
As redes Ethernet podem transportar até 1.500 bytes , ou seja, seu
MTU é de 1.500 bytes, Por isso o sistema operacional configura
automaticamente o protocolo IP para criar datagramas IP com 1.500 bytes em
vez de 65.535 (o que não caberia no quadro) [6]. Similarmente ocorre com o
tamanho máximo do quadro utilizado no modem GSM deste projeto, onde
podem ser transmitidos no máximo 1.500 bytes por vez.
TCP/IP é um conjunto de protocolos que lida com as camadas 3 a 7
do modelo de referência OSI. O Ethernet é um conjunto de protocolos que lida
com as camadas 1 e 2 do modelo de referência OSI – o que significa que o
Ethernet se preocupa com o aspecto físico da transmissão de dados. Por isso
eles se complementam, já que precisamos das sete camadas completas (ou
suas equivalentes) para estabelecer uma conexão de rede.
41
5.4.1.4- Interface de Rede
A camada de mais “baixa” hierarquia do protocolo TCP/IP é a
camada Interface com a Rede. Esta camada recebe os pacotes da camada
Internet e os envia para a rede. O protocolo da camada depende do tipo de
rede adotada, porém, atualmente a maioria dos computadores utilizam a rede
Ethernet (usada também em conexões wireless). Para estas redes é possível
encontrar nesta camada o Controle do Link Lógico (LLC), Controle de Acesso
ao Meio (MAC) e Física. Quadros são os pacotes transmitidos pela rede [6].
Figura 20- Arquitetura do Ethernet
A camada LLC é a responsável por adicionar informações de que
protocolo na camada Internet foi o responsável por gerar os dados. Dessa
forma, durante a recepção de dados da rede, esta camada no computador
receptor tem que saber que protocolo da camada de Internet ele deve entregar
os dados. Esta camada é definida pelo protocolo IEEE 802.2 [6].
A camada de Controle de Acesso ao Meio (MAC) é a responsável
por montar o quadro que será enviado para a rede. Esta camada é responsável
por adicionar o endereço MAC de origem ao destino. Os quadros que são
destinados a outras redes utilizarão o endereço MAC do roteador da rede como
endereço de destino. Esta camada é definida pelo protocolo IEEE 802.3, se
uma rede com cabos estiver sendo usada, ou pelo protocolo IEEE 802.11,se
uma rede sem fio estiver sendo usada [6].
42
A camada Física é responsável por converter o quadro gerado pela
camada MAC em sinais elétricos (se for uma rede cabeada) ou
eletromagnéticos (se for uma rede sem fio). Esta camada é também definida
pelo protocolo IEEE 802.3, se for uma rede com cabos sendo usada, ou pelo
IEEE 802.11, se uma rede sem fio estiver sendo usada [6].
As camadas LLC e MAC adicionam suas informações de cabeçalho
ao datagrama da camada Internet. Portanto, uma estrutura completa de
quadros gerados por essas duas camadas pode ser vista na figura 21.Nota-se
que os cabeçalhos adicionados pelas camadas superiores são vistos como
“dados” pela camada LLC. A mesma coisa acontece com o cabeçalho inserido
pela camada LLC, que será visto como dado pela camada MAC [6].
A camada LLC adiciona um cabeçalho de 3 ou 5 bytes e seus
datagramas têm um tamanho total máximo de 1.500 bytes, deixando um
máximo de 1.497 ou 1.495 bytes para dados. A camada MAC adiciona um
cabeçalho de 22 bytes e um CRC (soma dos dados para identificação de erros)
de quatro bytes ao final do datagrama recebido da camada LLC, formando o
quadro Ethernet. Portanto, o tamanho máximo de um quadro Ethernet é de
1.526 bytes [6].
43
Figura 21- Quadro na camada de interface com a rede.
5.4.2- Protocolo UDP
Enquanto o TCP reordena os pacotes e usa mecanismos de
confirmação de recebimento, o que é desejável na transmissão de dados,
existe um outro protocolo que opera nesta camada que não tem esses
recursos. Este protocolo é o UDP (User Datagram Protocol) [6].
Por essa razão o TCP é considerado um protocolo confiável, quanto
o UDP é considerado um protocolo não confiável. O UDP é tipicamente usado
quando nenhum dado importante está sendo transmitido, como requisições
DNS (Domain Name System). Como o UDP não reordena os pacotes e nem
usa mecanismo de confirmação, ele é mais rápido que o TCP [6].
Quando o UDP é usado, a aplicação que solicita a transmissão será
a responsável por verificar se os dados recebidos estão intactos ou não e
também de reordenar os pacotes recebidos, isto é, a aplicação fará o trabalho
do TCP. O cabeçalho UDP tem oito bytes, enquanto o cabeçalho TCP possui
entre 20 e 24 bytes (dependendo se o campo opções estiver sendo ou não
usado) [6].
44
Figura 22- Pacote de dados na camada de Transporte.
5.5- Protocolo GPRS (General Packet Radio Service)
O Serviço de Rádio de Pacote Geral (GPRS) combina acesso
móvel com Protocolo de Internet para transmissão e recepção de dados. Ele
usa de maneira eficiente o espectro de rádio e permite boa taxa de velocidade.
Oferece aos seus usuários uma maior largura de banda (bandwith) tornando
possível a conexão ininterrupta e de baixo custo para envio de dados tais como
texto, gráfico ou vídeo [7].
GPRS é um serviço baseado em pacotes para conexão wireless
que serve como uma melhoria das redes GSM, CDMA e TDMA (ANSI I36). Ele
aplica o Pacote de Rádio (Packet Radio) para transmitir dados de usuários
entre estações GSM e redes externas. A transmissão é realizada pela
comutação de pacotes que serão enviados separadamente e então montados
na recepção. A tecnologia GPRS permite qualquer aplicação que possui um
endereçamento IP a operar sobre uma conexão celular GSM. Com isso, redes
celulares com GPRS são consideradas extensões wireless das redes de
Internet [7] .
Através desta tecnologia é dada uma operação de inicialização
rápida e conexão contínua com a Internet. Usuários de GPRS são capazes de
conectar através de um APN (Acess Point Name) e ter acesso a muitos
serviços e continuar conectado pagando apenas pelo tráfego de dados, em vez
do tempo de conexão. Uma conexão física dedicada apenas para um único
usuário não é necessária, pois os recursos da rede e a largura de banda é a
apenas usada quando os dados são transmitidos/recebidos. Isto torna a rede
45
altamente eficiente no que tange o uso dos seus recursos de largura de banda.
Com isso, um serviço baseado na tecnologia GPRS deve custar menos, uma
vez que os recursos da rede são compartilhados por vários usuários e não
totalmente dedicada para uma aplicação como ocorre com a Comutação de
Circuitos (circuit-switched) [7].
As conexão por GPRS atinge velocidades de tráfego de dados
entre 14.4 kbit/s até 115 kbit/s e oferece conexão ininterrupta de Internet para
telefones móveis e usuários de computador. A média da taxa média de tráfego
fica em torno de 56 kbit/s. Esse tráfego de dados deu a oportunidade de
usuários participarem de video conferências e interagir com websites
multimídia e aplicações similares usando telefones móveis ou computadores
portáteis [7].
Figura 23 - Módulo GSM com tecnologia GPRS e sua compatibilidade.
GPRS é baseado na comunicação GSM e irá complementar um
serviço existente como o a conexão por comutação de circuitos e o serviço de
mensagens curtas (SMS) [7].
As principais diferenças entre GPRS e GSM são a melhoria em
características como:
• Maior largura de banda (ou maiores velocidades) que pode chegar à
170 kpbs em situações ideias , uma média de 56 kbps na prática, com
relação à 9,6 kpbs da tecnologia GSM .
46
• Conexão contínua com a Internet (“always on-line”).
• Possibilidade de uso de recursos de Internet mais avançados, uma vez
que o tráfego de dados é maior.
• Comutação de pacotes em vez de Comutação de circuitos,
determinando assim uma maior eficiência do espectro de rádio porque
os recursos de rede (banda) são apenas usados quando o dado é
preciso ser enviado.
• A conexão não é mais cobrada pelo tempo de conexão e sim pelo
fluxo de dados. Desta forma, o custo de conexão é relativamente
menor.
• Importante passo para a evolução para o 3G (conexões maiores).
Figura 24- Evolução de GSM para 3G [4].
GSM (Global System for Mobile) – conhecido como 2G (segunda
geração) digital. GSM tem velocidade máxima de dados de 9.6 kbit/s e usa
tecnologia de comutação de circuitos [7].
HSCSD (High Speed Circuit Switched Data) – o primeiro passo até
maiores velocidades de trafego de dados sobre a tecnologia GSM. HSCDC
concentra acima de quatro imeslots (canais) e permite velocidades acima
47
de 64kbit/s (mais usado no mercado corporativo). Contudo, terminais que
surportam HSCSD não estão mais disponíveis. Foram usados inicialmente
em notebooks com um cartão de dados [7].
GPRS – Introduz a tecnologia de Comutação de Pacotes para GSM,
CDMA e TDMA (ANSI-I36) em redes celulares, facilitando a integração com
outros protocolos de pacotes como IP ou X.25. GPRS é o primeiro passo
importante para o caminho do 3G, conhecido mais como 2.5G [7].
EDGE (Enhanced Data for GSM Evolution) – é um passo adiante em
relação ao GPRS. Ele possue velocidades maiores de tráfego de dados
médio próximos de 384 kbit/s através de 8 canais ou 48 kbit/s por canal.
Analistas indicam que as velocidades dentro de construções caem para até
115 kbit/s, mas a tecnologia EDGE será capaz de fornecer em ambiente
aberto conexões de até 450-550 kbit/s. Esta tecnologia diferente da GPRS,
pois possui uma modulação de final diferente que permite um tráfego de
dados muito maior através do ambiente [7].
3G (third generation mobile) – a terceira geração de comunicação
móvel é também referida como IMT-2000, WCDMA e UMTS. IMT-2000
(International Mobile Telecommunications 2000) é a iniciativa do ITU
(International Telecomunications Union) para o serviço que irá provir acesso
por rádio para infraestrutures de comunicação globais, através de satélite e
sistemas terrestres. Possui velocidades muito maiores passando a mais de
2 Mbit/s [7].
5.5.1- Funcionamento da tecnologia GPRS
Para fornecer a tecnologia GPRS para seus clientes, uma operadora
de telefonia celular deve possuir os seguintes componentes básicos em sua
rede [7]:
SGSN: é o nó que funciona em conjunto com a rede GSM e que envia e
recebe pacotes de dado para ou de estações e rastreia os celulares dentro
48
da área de serviço. SGSNs enviam pedidos para Registradores de Locação
(HLRs) para obter perfis de dados GPRS e dectam novas estações GPRS
em determinada área. Também responsável pelo registro de cobrança dos
dados trafegados.
GPRS Tunneling Protocol (GTP) – é um protocolo especializado que
opera entre o SGSN e GGSN e encapsula os pacotes sobre IP. Adiciona
informações de roteamento.
GGSN – é o nó responsável pela interface com a rede pública externa
(PDNs) tais como Internet e X.25 .
Vale lembrar que as a rede possui muito mais funcionalidade, porém
não serão comentados os nós responsáveis pela parte de cobraça dos do
serviço.
Figura 25- Rede GPRS
Apesar de o usuário aparentar uma conexão contínua com a rede,
uma conexão deve ser aberta e fechada para cada troca de dados. A
transmissão de dados em uma rede GPRS requer alguns passos para ser
empreendida [7]:
Acesso à rede: uma vez que uma estação é acionada, o dispositivo
móvel apresenta-se através do envio de um pedido de conexão. O acesso á
rede pode ser alcançado tanto pelo dispositivo móvel ou pela estação fixa.
49
Algumas operadoras requerem alguns procedimentos para permitir o acesso de
determinados usuários tais como:
Registro do usuário que associa o número de identificação do
dispositivo móvel dentro do PDP do usuário (Packet Data Protocol) e o
endereça no PLMN (Public Land Mobile Network).
Autenticação , que assegura a validade do dispositivo na rede GPRS.
Controle de Admissão de Chamada (CAC) que requisita recursos da
rede para determinada qualidade de serviço (QoS) que foi pedida. Se estes
recursos estiverem disponíveis, eles serão reservados.
Roteamento e transferência de dados – uma vez que as estações
móveis transmitem um dado, o roteamento é dado por GSNs através da rede
móvel usando o endereço de destino no cabeçalho da mensagem. Tabelas de
rotas são administradas pelo GSNs utilizando a camada GTP que pode
carregar endereço de deslocamento e funções de mapeamento para converter
um endereço PDN externo (Public Data Network) para um endereço útil para
roteamento dentro das PLMNs. O dado irá sofrer várias transformações de
acordo como viaja pela rede [7].
5.6- Overhead em GPRS
Quando um dado é transmitido por GPRS, vários
protocolos dentre deste tipo de rede adicionam cabeçalhos de controle sobre
este dado. Com isso, a partir de uma taxa de transmissão de dados, têm-se
que nem todos os bytes de um pacote são exclusivamente dados úteis para a
aplicação e, portanto, são conjuntos de dados de controle e dados de
aplicação. A relação de dados de controle com os dados úteis é chamado de
Overhead [8].
50
A tecnologia GPRS possui uma hierarquia composto de várias
camadas. Quando um dado “trafega” entre estas camadas, mais dados de
cabeçalho são incluídos nestes dados para garantir sua integridade (figura 26).
Figura 26- Hierarquia do procolo GPRS [8].
Um exemplo é dado por um pacote IP com 1500 bytes e que inclui
32 bytes de cabeçalho TCP e outros 20 bytes de cabeçalho IP. Então, sobrou-
se 1448 bytes para a aplicação. O overhead é a porcentagem do pacote inteiro
que não é a de dados úteis (payload) [8]:
52/1.500 = 3.47%
Quando o dado chega na camada SNDCP, 4 bytes são
acrescentados sobre os 1.500 bytes do pacote IP. Então, o overhead desta
camada é:
4 / (1.500 + 4) = 0.266%.
O overhead total acumulado da camada de aplicação até a camada
LLC é dado pela equação 2:
(2)
onde ovhabs representa o overhead absoluto por pacote IP e data sizeLLC
informa o número de bytes acomulados na camada LLC, então:
51
O overhead acumulado na camada LLC é de 5,15%. A camada RLC/MAC adiciona 3 bytes para cada bloco de 30 bytes do
pacote. Com isto, o overhead desta camada é de
2/32= 6,25%
O exemplo dado não pode afirmar que estes cálculos serão obedecidos
em qualquer situação, uma vez que o overhead depende também das
configurações feitas em determinada rede. Contudo, sabe-se que a velocidade
de transmissão de dados úteis também depende do overhead, sendo algumas
vezes mais vantajoso utilizar protocolos com cabeçalhos menores, como por
exemplo , o protocolo UDP na comunicação GPRS. A camada UDP possui
apenas 8 bytes de cabeçalho contra 32 bytes do protocolo TCP, sendo em
conexões de baixa velocidade, mais vantajoso a utilização de UDP em vez de
TCP.
5.7- Controle de motores CC
É comum a necessidade do acionamento de motores do tipo CC
através de portas de dispositivos de controle integrados tais como
microcontroladores usados em muitos projetos. Contudo, todos os
microcontroladores conhecidos conseguem fornecer correntes na ordem de
alguns mA para acionamento de portas lógicas ou, no máximo, alimentar um
pequeno dispositivo de luz de baixo consumo (LED). Como para este projeto
também houve a necessidade de amplificar a corrente de saída da porta de
um microcontrolador. Buscou-se um dispositivo que atendesse a capacidade
de amplificar tal potência para acionar motores de pequeno porte
52
encarregados de dar movimento ao veículo controlado. Tais dispositivos são
denominados transistores. Existem vários tipos de transistores, porém para
pequenas potências os componentes bipolares são os mais comuns.
O comportamento básico dos transístores em circuitos eletrônicos
é fazer o controle da passagem de corrente entre o emissor e o coletor através
de uma pequena corrente na base. Para isto é necessário polarizar
corretamente as junções do transístor. Polarizando diretamente a junção base-
emissor e inversamente a junção base-coletor, a corrente de coletor IC passa a
ser controlada pela tensão base-emissor Vbe [9].
Figura 27- Polarização de um transistor NPN.
Com o uso de 4 transistores interligados pode-se fazer o controle de
um motor CC, ou seja, acioná-lo para girar em sentido horário ou anti-
horário de acordo com o par de transistores acionados. Esta distribuição de
chaves lógicas , seja ela composta por transistores ou relés, é chamada de
ponte H.
53
Figura 28- Representação simplificada de uma ponte H [10].
Para que o motor funcione, basta acionar um par de chaves
“diagonalmente opostas”, o que faz com que a corrente elétrica flua no
sentido do maior potencial elétrico para o menor potencial atravessando o
motor e fazendo-o girar. Para inverter a rotação, desliga-se o par de chaves e
aciona-se o outro par de chaves, o que faz com que a corrente siga na
direção oposta nos enrolamentos do motor e, consequentemente, o sentido
da rotação do motor será alterada [10].
Figura 29- Representação do funcionamento de uma ponte H.
54
Para ser mais claro, o acionamento das “chaves” é dado pela
ligação da base de cada transistor com o pino de saída do microcontrolador.
Para isso serão necessários 4 pinos de saída para controlar a direção de um
motor CC. Contudo, em muitos projetos de ponte H existem circuitos lógicos
que impedem o acionamento simultâneo dos 4 transistores e,
consequentemente, o curto-circuito dos mesmos.
5.8- Display de Caracteres do tipo LCD
Em muitos casos, seja em projetos ou produtos finais, é necessário
criar uma interface gráfica que irá exibir os resultados de determinado processo
em sistemas embarcados. O uso de um display de caracteres do tipo LCD é
bastante útil em projetos, uma vez que possibilita o monitoramento de cada
algoritmo criado.
Figura 30- Display de caracteres com 16 colunas e 2 linhas (16x2).
Primeiramente, é preciso dizer que esses displays são pré-
programados para exibir caracteres definidos em sua memória. Esses
caracteres são definidos por um padrão americano denominado ASCII.
Microcontroladores e processadores, além do display de caracteres,
podem entender apenas números, então o código ASCII é uma representação
numérica de um caracter, por exemplo ‘a’ ou ‘@’. Alguns programas em
ambiente windows ainda trabalham com este padrão tais como Notepad e MS
Word (formato opcional). Na tabela 02 pode-se ver todos os caracteres
pertencentes ao padrão ASCII [11].
55
Tabela 3- Caracteres ASCII e comandos de controle
Voltando ao display de caracteres, para colocá-lo em funcionamento,
primeiro precisa-se configurá-lo, ou seja, é preciso dizer ao display como serão
transferidos os dados para ele (8 ou 4 bits), quantas linhas utilizadas, se a
mensagem deve ficar fixa ou rolar, se a escrita será da esquerda para direita
ou da direita para esquerda, ou seja, todas essas configurações são
necessárias antes de escrever qualquer mensagem. Essas informações podem
ser consultadas na datasheet do fabricante [11] .
Outro detalhe importante quando se trabalha com este tipo de display, é
a temporização. Deve-se ter um cuidado especial com este ponto, pois uma
temporização equivocada inviabilizará o funcionamento do mesmo (não
danificará, mas também não funcionará) [11].
Em primeiro lugar, é preciso conhecer a função da pinagem do display
LCD 16x2 [12].
56
• Pinos de dados: D7 - D6 - ...- D1 - D0 (8bits): os pinos de dados são
usados para enviar as palavras de configurações e os dados
(caracteres) [12].
• Pinos de controle: EN (6), RS (4), R/W (5) - o pino EN informa ao display
de LCD quando o dado está pronto para ser lido. O pino RS é usado
para diferenciar se a palavra que foi enviada ao LCD é de configuração
ou caractere [12].
• Pinos de alimentação: Vcc (2) e GND (1) [11].
• Pino de controle de contraste: VO (3) - este pino permite alterar o
contraste do display [12].
• Pinos de iluminação do fundo - backlight: A (16), K (15) - nem todos os
displays possuem iluminação de fundo [12].
Instrução RS R/W D7 D6 D5 D4 D3 D2 D1 D0
Conf. Função 0 0 0 0 1 DL N F 0 0
Descrição: Esta instrução é a mais importante, pois configura o display com relação ao número de bits, número de linhas e tamanho do caractere [11].
DL: 0 => 4 bits ou DL: 1 => 8 bits.
N: 0 => 1 linha ou N: 1 => 2 linhas, para display de 4 linhas, o N: 1.
F: 0 => 5x7 dots ou F: 1 => 5x10 dots.
Normalmente se usa: DL= 1, N=1 e F=0, ou seja,(00111000)b => 38h.
Instrução RS R/W D7 D6 D5 D4 D3 D2 D1 D0
Ctrl do display
0 0 0 0 0 0 1 D C B
57
Descrição : controle do display - D: 0 => off ou D: 1 => on.
controle do cursor - C: 0 => cursor desligado ou C: 1 => cursor ligado.
cursor piscante, mesmo que o cursor esteja desligado, toda a matriz ficará piscando - B: 0 => não piscante ou B: 1 => piscante.
Instrução RS R/W D7 D6 D5 D4 D3 D2 D1 D0
Deslocamento
Cursor 0 0 0 0 0 0 0 1 I/D S
Descrição: este comando controla o deslocamento do cursor
no display de LCD. O cursor pode deslocar da esquerda para direita -
incremento(I/D:1) ou da direita para esquerda - decremento (I/D:0). Além disso,
pode-se configurar o display a função scroll, ou seja, à medida que se escreve
a mensagem vai se deslocando, na realidade o cursor fica sempre parado, para
isso, S:0 scroll desligado e S:1 scroll ligado [12].
Instrução RS R/W D7 D6 D5 D4 D3 D2 D1 D0
Retorno do cursor
0 0 0 0 0 0 0 0 1 0
Descrição: este comando faz o cursor retornar para a primeira
posição do display de LCD [12].
Instrução RS R/W D7 D6 D5 D4 D3 D2 D1 D0
Limpar o display 0 0 0 0 0 0 0 0 0 1
Descrição: Limpa todos os caracteres do display [12].
Instrução RS R/W D7 D6 D5 D4 D3 D2 D1 D0
Posição de escrita de um caractere
0 0 1 x x x x x x x
Descrição: O display de LCD é uma memória SRAM, portanto
antes de enviar um caractere deve-se escolher a posição desejada para
58
escrever, no display de LCD funciona da mesma forma. Além disso, quando
chega no final do display, é necessário a troca de linha, isto também precisa
ser feito [12].
Instrução RS R/W D7 D6 D5 D4 D3 D2 D1 D0
escrita de um caractere no LCD
1 0 x x x x x x x x
Descrição: Os X’s correspondem ao código ASCII do
caractere - por exemplo, o número “0” é 30h, o caractere “A”é 41h, e assim por
diante [12].
5.9 - Anatomia de robôs móveis
Um robô móvel é um dispositivo mecânico montado sobre uma base não
fixa, que age sob o controle de um sistema computacional, equipado com
sensores e atuadores que o permitem interagir com o ambiente [13].
A anatomia dos robôs móveis, sejam eles teleoperados ou autônomos, é
classificada em três modos: aéreos, aquáticos e terrestres. Dentre os robôs
móveis terrestres, podem ser classificados quanto ao seu tipo de locomoção:
rodas, esteiras, pernas. A figura 31 ilustra a classificação de robôs móveis [14].
Figura 31- Classificação de robôs móveis segundo a anatomia [14].
59
Os robôs aéreos geralmente são aeromodelos ou LTAs (Lighter-Than-
Air) equipados com câmeras de vídeo e utilizados para inspeção de grandes
áreas. Os aquáticos, em geral, são plataformas equipadas com propulsores e
balões de ar que permitem ao robô permanecer a alguns metros do fundo do
mar, porém também pode possuir patas (figura 32) [14].
Figura 32- Exemplo de robôs aquáticos
Já os robôs terrestres são os mais populares e podem utilizar três tipos
diferentes de atuadores: rodas, esteiras ou pernas.
Robôs com rodas – são os mais simples, pois nào necessitam de um hardware
tão complexo quanto os robôs com esteiras e pernas, além disso, é fácil transformar
brinquedos em robôs. A principal desvatagem no uso de rodas é que em terrenos
irregulares o desempenho pode não ser satisfatório. Em geral, a roda do robô deve
possuir raio igual ou maior aos obstáculos que ele irá transpor (Figura 33) [14].
60
Figura 33- Robôs com rodas [14].
Robôs com esteiras – são mais utilizados em robôs que atuam em
ambientes irregulares, como por exemplo com solo fofo e pedras. A grende
desvatagem está na dissipação de energia causada pelo movimento de giro da
própria esteira e pelas rodas no seu interior [14].
Figura 34- Robôs com esteiras [14].
Robôs com pernas – Este tipo de robô é utilizado em terrenos
acidentados, com subidas íngremes, ou em ambientes específicos, como por
exemplo, ambientes com escadas. A grande dificuldade deste tipo de robô está
no desenvolvimento do projeto para o controle das pernas, que tem, no
mínimo, dois graus de liberdade. Há também o fator custo deste tipo de projeto,
pois cada atuador utiliza pelo menos dois motores (figura 35) [14].
61
Figura 35- Robôs com pernas [14].
Como o terreno utilizado durante os testes deste projeto é do tipo regular
e plano, foi possível a utilização de um brinquedo com rodas e atuadores para
servir de plataforma do robô teleoperado.
62
6- Desenvolvimento
6.1- Especificação e Projeto do Hardware
Para a realização do projeto, foram usados três aplicações para
compilação do software do servidor e para gerar e gravar o código em
hexadecimal que será executado pelo microcontrolador do veículo. Para isso, o
requisito mínimo de um computador para executar qualquer um dos softwares
de desenvolvimento usados é descrito abaixo:
• Pentium II 400 MHz ou processador mais rápido.
• Microsoft Windows 98, 2000 (SP2), ou XP . Também testado e aprovado em Windows 7 em modo de compatibilidade para Win XP.
• 128 MB RAM.
• 750 MB de espaço mínimo em disco rígido (HD).
• Leitor de CD-ROM.
• Monitor de 256 cores e com resolução mínima de 800x600.
• Mouse
Os requisitos de hardware que dizem respeito ao veículo controlado são
descritos abaixo:
• Câmera de baixo consumo e de comunicação serial RS232 , com
compressor interno de dados e com resolução entre 80x60 até 640x480.
• Chassis veícular com um motor para tração e outro para direção, com
tensão nominal até 6V e corrente nominal até 1 A.
• Microcontrolador com 2 UARTs e de programação em circuito (in-circuit).
• Display de LCD 16x2.
Módulo de comunicação por tecnologia GPRS.
• Massa máxima do veículo: 1,5 kg
63
6.2- Software de interface com a câmera
Para entender melhor o protocolo de comunicação da câmera foi
necessário implementar um software no compilador C++ Builder 6 que envia e
recebe dados através da porta serial como é mostrado na figura 36.
Este compilador é mundialmente conhecido e é uma poderosa
ferramenta de desenvolvimento. Optou-se também por usá-lo, uma vez que o
aluno responsável pelo trabalho familiariza-se mais com este software.
Contudo, qualquer outro compilador será capaz de realizar as funções que aqui
estão descritas.
O código fonte completo do programa está disponível no anexo B.
Figura 36- Interface do software gerado em linguagem C++
64
Como mostra a interface do software, foram implementados
comandos para cada botão e, também, criou-se uma janela ao lado (ScrollBox)
que permite a visualização dos comandos recebidos pela porta serial do
computador (depuração do programa). Com isso é possível acompanhar passo
a passo o processo de conexão, captura e transferência da imagem para o
dispositivo externo a câmera.
Para conectar-se à câmera e capturar um quadro de imagem
utilizando o programa gerado segue-se os seguintes passos:
1. Definir porta (no caso deste computador é a porta 4) e clicar em Open;
2. Botão SYNC- envia comando de sincronia para a câmera. Esperar ACK;
3. Botão Baudrate- Set Baudrate de 115200bps;
4. Botão Init – resolução de 80x60;
5. Botão Size – define o tamanho de cada pacote.
6. Snapshot – armazena uma imagem no buffer da câmera;
7. Get Picture- recebe a imagem;
8. Draw Picture- exibe a imagem no programa.
6.3- Software de medição de atrasos
Sabe-se que a rede GPRS, como qualquer outra rede física, possui
atrasos na transmissão e recepção de dados. No caso da tecnologia GPPRS,
onde os pacotes são transmitidos por comutação, pretende-se medir o atraso
que este tipo de tecnologia pode acarretar no controle do robô.
Criou-se um programa para o envio de um dado ao robô e o
recebimento da sua resposta. O funcionamento do programa é bastante
simples. Primeiramente envia-se o dado, um timer inicia sua contagem em
milisegundos, quando recebido o dado do robô o timer para sua contagem e
registra o valor do atraso total em uma tabela. A figura 37 ilustra a interface
criada.
65
Figura 37- Programa de medição de atraso de dados na rede.
O diagrama de blocos da figura 38 ilustra o princípio de
funcionamento do programa criado:
Figura 38- Diagrama de blocos do programa de medição.
Observa-se que existe atraso tanto na transmissão do dado para o
robô, quanto na recepção deste dado pela programa do usuário. Contudo, o
66
intervalo medido equivale ao atraso de ida e volta do dado, uma vez que não é
possível afirmar que o atraso de transmissão é o mesmo atraso de recepção.
Com o uso deste programa foi possível obter dados sobre a
disponibilidade da rede e seus atrasos. Fez-se a média dos resultados obtidos
e seu desvio padrão.
6.4- Software de interface com o veículo
Foi desenvolvido na plataforma de desenvolvimento da Borland, C++
Builder, o programa que enviará os comandos de acionamento ao robô e
receberá as imagens da câmera. A comunicação será estabelecida diretamente
entre o computador e o robô através de uma conexão do tipo Soquete (Socket).
A figura 39 exibe uma impressão da tela da interface visual criada
para o controle do robô.
67
Figura 39- Interface de comando remoto do veículo
Destacado em vermelho e rotulado como SOCKET, pode ser visto o
ícone que representa um objeto disponível para uso neste compilador. Trata-se
de um objeto que cria uma conexão do tipo Socket para a aplicação e a define
como servidor. Como esta aplicação é do tipo servidor, não é necessário saber
o número IP de seu cliente, neste caso, o veículo a ser controlado. Na figura 30
têm-se as configurações do objeto ServerSocket através da janela Object
Inspector.
68
Figura 40- Propriedades do objeto ServerSocket.
A configuração vital para a conectividade do servidor com o veículo é
a porta, definida acima como sendo 1111. Com isso, na programação do
veículo será preciso informar ao modem GPRS o número IP do servidor e sua
respectiva porta, como será visto posteriormente.
Outro objeto utilizado no programa foi o Timer. O objeto Timer
destacado na figura 31 nada mais é que uma função que executa seu conteúdo
em intervalos de tempo programados. Neste trabalho, utilizou-se o Timer para
enviar comandos ao robô em intervalos de tempo programados. As
propriedades do Timer podem ser acessadas na janela Object Inspector na
figura abaixo.
Figura 41- Propriedades do Timer
69
É preciso dizer que foram usados outros objetos na interface
apresentada, tais como botões, rótulos (labels), barra de progresso e Imagem
(objeto Image) para a exibição das imagens vindas do robô. O código fonte
completo e comentado do Software encontra-se anexado neste trabalho.
6.5- Mapeamento e utilização dos sinais do carro
Para a realização do projeto, adquiriu-se um carro de controle remoto
usado, mas comumente encontrado no mercado. O receptor original do carro
obtido possui duas pontes H para o controle de sentido dos dois motores a
bordo. Com base no circuito pronto, procurou-se aproveita-lo no projeto para
amplificar a corrente de saída do microcontrolador e, assim, acionar os motores
do mesmo.
Contudo, o veículo não possuia manual do fabricante e os nomes
dos componentes é inacessível. Para o aproveitamento do circuito foi preciso
mapear os pontos de conexão dos transistores a fim de encontrar suas bases.
Uma idéia para encontrar os pontos de controle de cada ponte H foi testar
ponto a ponto através da medição de resistência no multímetro. Para ser mais
claro, o multímetro cria uma diferença de potencial em suas ponteiras a fim de
induzir uma corrente em um condutor e medir sua resistência elétrica. Quando
aplicado este potencial na base de um transistor, este passa a conduzir uma
pequena corrente de base e o motor do carro é acionado. A figura 42
exemplifica o procedimento.
70
Figura 42- Polarização de um transistor bipolar de junção (TBJ).
Fez-se o teste para todos os pontos (com o circuito energizado) e
foram encontrados 4 pontos responsáveis pelo controle dos dois motores do
veículo. A figura 43 ilustra os pontos encontrados.
Figura 43- Placa de circuito integrado com a ponte H e seus pontos de controle
Os pontos foram rotulados respectivamente de P1 (aciona o carro
para frente), P2 (aciona o movimento reverso), P3 (aciona a direção para a
direita) e P4 (aciona a direção para a esquerda). Faz o teste de acionamento
com duas pilhas, num total de 3V, e os transistores foram excitados a fim de
71
acionar os motores. Com isso, sabe-se que a porta do microcontrolador será
capaz de acionar os motores do veículo sem dificuldade.
6.6- Concepção do sistema Para a implementação de todo o sistema, primeiramente, foi necessário
criar um diagrama de blocos, dando funções para os dispositivos e seus meios
de comunicação dentro do hadrware do robô e este com o servidor. A figura 44
Ilustra o diagrama de blocos criado.
Figura 44- Diagrama de blocos do sistema.
Como mostrado no diagrama, um usuário atua na interface gráfica do
servidor criado e o servidor envia e recebe dados do robô. Estes dados podem
72
comandar o acionamento dos motores ou representar as imagens capturadas
da câmera.
O hardware do robô é composto de microcontrolador, display do tipo
LCD, driver de motor de corrente contínua, modem GPRS, câmera, dois
motores. O modem e a câmera possuem comunicação bidirecional com o
microcontrolador, enquanto os dispositivos de acionamento dos motores e o
display apenas recebem comandos do microcontrolador através de seus pinos
de saída.
Analisando-se o diagrama de blocos, sabe-se que o firmware do robô,
cujo microcontrolador é responsável pela execução, é a etapa mais elaborada
do sistema, pois o mesmo deve se comunicacar e administrar todos os
dispositivos do hardware.
Antes de escrever o código do programa, para o funcionamento do
veículo, foi necessário organizar o firmware em diversas etapas através da
representação em um fluxograma de blocos funcionais (figura 45).
73
Figura 45- Fluxograma do Firmware do Veículo.
Nota-se que, para simplificar o fluxograma, não foram consideradas
ações de escrita sobre o display de LCD , pois o mesmo será utilizado apenas
para a visualização das etapas e não irá influenciar nas tomadas de decisão do
programa.
74
Faz-se uma análise mais detalhada do primeiro bloco do fluxograma
(INÍCIO). Este bloco é responsável pela inicialização de todos os registradores
do microcontrolador, responsáveis por definir a velocidade que o núcleo e seus
periféricos irão operar, definir a função de cada porta (para acionamento dos
motores, display e dispositivos seriais) e configurar a velocidade de
comunicação das duas portas seriais utilizadas.
Após o bloco INÍCIO, tem-se a inicialização do display de LCD que será
útil para visualizar erros e resultados obtidos no programa. Configurado o
display de LCD, o passo seguinte e o mais importante, é a inicialização do
modem e o estabelecimento de uma conexão do tipo Socket com o servidor
criado.
Após a conexão estar estabelecida entre servidor e o veículo móvel,
o sistema espera um comando vindo do usuário, caso contrário não deve
realizar função alguma. No recebimento de comando, comparar se o valor
recebido é compreendido entre os valores 0x80 e 0x8A, representados na base
hexadecimal, e se a sentença for verdadeira, acionar o motor de tração e o
motor de direção de acordo com cada comando, ou no caso do comando 0x8A,
enviar um comando ACK (confirmação).
Um tratamento especial deve ser dado para o comando recebido
0x91, encarregado da sincronização com a câmera, obtenção de um quadro de
imagem e o envio do mesmo na forma de pacotes para o servidor que irá
remontar os dados para a exibição na interface do usuário.
6.7- Inicialização dos Registradores
Microcontroladores de núcleo ARM7 exigem a escolha da
velocidade de operação de seu processador e de seus periféricos de forma
separada. O PLL (Phase Locked Loop) é usado em conjunto com o cristal
ligado externamente. O PLL é composto por dois registradores M (multiplicador
do PLL) e P (divisor do PLL), com isso é possível configurar a velocidade de
75
operação do núcleo do microprocessador, que não deve exceder 60Mhz. O
divisor VPB é um complemento do sistema de clock e pode dividir o valor do
PLL por 1, 2 ou 4 para o funcionamento dos periféricos. No caso da placa
adquirida, o cristal utilizado é de 16Mhz.
A função void init_PLL_VPB(void) criada configura a frequência de
operação do núcleo do ARM e o sinal de clock aplicado aos periféricos, por
exemplo PWM, Timer, UART (serial) e etc. Para isso foram utilizados os
registradores PLLCFG, PLLCON, PLLFEED e VPBDIV (LPC2148, 2009).
Foi configurado o CCLK (Core Clock) como sendo 32Mhz (frequência de
operação do núcleo) e o PCLK (Peripheral Clock), frequência de operação dos
periféricos em 16Mhz.
void init_PLL_VPB(void)
{
PLLCFG=0x00000041; //frequencia de 32MHZ com um
//cristal de 16MHz OBS.: (M-1)
PLLCON=0x00000001; //Habilita o PLL
PLLFEED=0x000000AA; //Atualiza os registradores
PLLFEED=0x00000055;
while (!(PLLSTAT & 0x00000400)); //Testa o PLOCK
PLLCON=0x00000003; //conecta o PLL
PLLCON=0x00000003; //Conecta ao PLL
PLLFEED=0x000000AA; //Atualiza os registradores
PLLFEED=0x00000055;
VPBDIV=0x00000002; //VPB=2 PCLK de 16 MHz
}
6.7.1- Função de temporização O microcontrolador e seus periféricos trabalham em
frequências altas para alguns dispositivos, não dando tempo de resposta a
eles. O atraso (delay) foi amplamente utilizado entre funções e comandos para
76
dar tempo de resposta e, também, para acionar os motores do veículo por um
determinado tempo sem interferência de outras funções.
Foi criada uma função chamada Delay_1ms(unsigned int x) que executa
um atraso x na escala de milisegundos. Dá-se o uso do temporizador Timer1
que é uma interrupção, ou seja, durante o período de atraso o microcontrolador
não responde a outro processo. Os registradores utilizados foram T1PR,
T1MR0, T1IR, T1TC, T1TC, e T1TCR (LPC2148, 2009). O trecho seguinte
corresponde à função de atraso utilizada:
void Delay_1ms(unsigned int x) //16K/16M= 1ms
{
T1PR=0x00000064; //100
T1MR0=x*0x000000A0; //160
T1IR|=0x00000001; // Limpa o flag de interrupção do Timer
T1MCR=3; //Habilita o reset do contador do Timer
T1TC=0; //Zera o contador do Timer
T1TCR=1; //Habilita o Timer
while (!(T1IR&0x00000001)); //Executa o delay de X ms
}
6.7.2- Portas Seriais (UART0 e UART1)
O LPC2148 tem duas portas seriais (UART0, UART1), que podem ser
configuradas de modo semelhante. Inicialmente devem-se selecionar as
funções TxD0 e RxD0 nos pinos do microprocessador. Os registradores
PINSEL0 e PINSEL1 servem para selecionar uma das 4 possíveis funções de
cada pino do microcontrolador. A cada pino correspondem 2 bits dos
registradores PINSEL. Os sinais TXD0 e RXD0 são selecionados colocando o
valor 01 nos bits 1:0 e 3:2 do PINSEL0. Para evitar o efeito de alterar a
configuração de outros pinos, recomenda-se usar uma operação OU com o
valor anterior do PINSEL0.
77
void UART0_Init(void)
{
PINSEL0 |= 0x05; //Habilita os pinos RxD e TxD da UART0
U0FCR = 0x07; // Habilita e reseta os buffers de transmissão e recepção
U0LCR = 0x83; // UART 8N1
U0DLL = 0x68; // baud rate fixed to 9600 bps @ PCLK = 16 Mhz e VPB = 0x02
U0DLM = 0x00; // parte alta do baud rate
U0LCR = 0x03; // UART 8N1, desabilita divisor do baud rate }
O registrador U0FCR habilita os buffers de transmissão e recepção da
UART0 através dos bits 0, 1 e 2. U0LCR configura UART0 para transmitir e
receber 8 bits com mais 1 bit de parada (stop bit).
Os registradores U0DLL e U0DLM irão determinar o baudrate
(velocidade de dados+) da porta serial UART0 com o valor anteriormente
adotado para PCLK na configuração da velocidade de processamento do
núcleo. A relação entre os registradores é descrita na equação (1).
(1)
A configuração dos registradores da UART1, cujos pinos serão
ligados ao Tx e Rx do modem GPRS, foi dada da mesma maneira da UART0,
porém foi acrescentada uma linha que acionará em nível lógico 1 dois pinos
P0.10 e P0.11 do microcontrolador, responsáveis por ligar o modem e habilitar
sua porta serial através do pino DTR (Data Terminal Ready).
void UART1_Init(void)
{
PINSEL0 |= 0x50000; // Habilita o pino TxD1e RxD1 da UART1
U1FCR = 0x07; // Habilita e reseta os buffers de transmissão e recepção
U1LCR = 0x83; // UART 8N1,
U1DLL = 0x68; // baud rate fixado em 9600 bps @ PCLK = 16 Mhz e VPB = 0x02
78
U1DLM = 0x00; // parte alta do baud rate
U1LCR = 0x03; // UART 8N1, desabilita divisor do baud rate
IODIR0= 0X2000; // Pino 0.13 como entrada.
IOSET0= 0xC00; // POWER_CONTROL e DTR em nível lógico 1. }
6.8- Interface com o LCD
Para o correto funcionamento do display, foi simulado o programa do
seu controle através do software Proteus v7.6 SP4 (Versão de Demonstração),
como mostra a figura 46. Contudo, o microcontrolador utilizado para a
simulação foi o LPC2138, uma versão mais simplificada do LPC2148 (que vem
com recursos de USB 2.0).
Figura 46- Esquema do circuito do microcontrolador e o display.
Os displays de LCD de caracteres 16x2 possuem comandos
padronizados para sua configuração e escrita. Com isso, escreveu-se a
seguinte função de inicialização para cada vez que o microcontrolador for
inicializado.
79
void inicia_display()
{
for (i=0;i<3;i++) // envia o comando 3 vezes para garantir a inicialização.
{
IOSET1=0x2000000;
IOSET1=0x380000;
Delay_1ms(3);
IOCLR1=0x2000000; //pulso E (Enable).
IOCLR1=0x380000;
Delay_1ms(15); // espera o display processar o comando.
}
/*Ctrl do display */
IOSET1=0x2000000; //pulso E (Enable).
IOSET1=0xE0000;
Delay_1ms(3);
IOCLR1=0x2000000; //pulso E (Enable).
IOCLR1=0xE0000;
Delay_1ms(15);
/*Deslocamento DO CURSOR*/
IOSET1=0x2000000;
IOSET1=0x00006000;
Delay_1ms(3);
IOCLR1=0x2000000; //pulso E (Enable).
IOCLR1=0x00006000;
Delay_1ms(15);
/*Retorno do cursor*/
IOSET1=0x2000000; //pulso E (Enable).
IOSET1=0x20000;
Delay_1ms(3);
IOCLR1=0x2000000; //pulso E (Enable).
80
IOCLR1=0x20000;
Delay_1ms(15);
/*Limpar display*/
IOSET1=0x2000000; //pulso E (Enable).
IOSET1=0x10000;
Delay_1ms(3);
IOCLR1=0x2000000; //pulso E (Enable).
IOCLR1=0x10000;
Delay_1ms(15);
}
Após a inicialização do display, foi criada a função
posição_escrita() e também a função escreve_lcd(int caracter). A função
posição_escrita(int pos) é responsável por definir a posição inicial na qual o
caracter seguinte ou uma sequência de caracteres serão exibidos no display. A
chamada da função escreve_lcd(int caracter) exibe um caractere, de padrão
ASCII, no display. As funções de manipulação do display são mostradas
abaixo.
void posicao_escrita(int pos)
{
IOSET1=0x2000000; //pulso E (Enable).
IOSET1=0x00000000|pos<<16; // indica posição “pos”
Delay_1ms(3);
IOCLR1=0x2000000; //pulso E
IOCLR1= 0x00000000|pos<<16; // indica posição “pos”
Delay_1ms(15);
}
void escreve_lcd(int caracter)
{
IOSET1=0x2000000; //pulso E (Enable).
IOSET1=0x1000000|(caracter<<16); // escreve “caracter”
81
Delay_1ms(3);
IOCLR1=0x2000000; //pulso E (Enable).
IOCLR1=0x1000000|(caracter<<16); // escreve “caracter”
Delay_1ms(20);
}
6.9- Configurando uma conexão Socket entre cliente e servidor
O primeiro passo adotado para criar uma conexão entre o veículo e o
software desenvolvido em um computador local foi escolher uma operadora de
telefonia celular que oferecesse o serviço de Internet por GPRS. Após verificar
que a operadora de serviços da CLARO oferece acesso a este serviço, para
clientes do sistema pré-pago e a um custo bem reduzido, optou-se por usar
esta operadora.
No site da operadora adotada (http://www.claro.com.br) foram
encontradas algumas informações de configuração para acessar seus serviços
de acesso a rede:
Nome da conexão: Claro Dados GPRS
Número de discagem: *99***1#
Nome do Ponto de Acesso (APN – Access Point Name): claro.com.br
Usuário: claro
Senha: claro
Para iniciar uma conexão entre o modem GPRS e um serviço de
Internet, o modem necessita de algumas informações prévias agrupadas em
uma lista de parâmetros denominados Perfil de Conexão (Internet Connection
Setup Profile). Estas informações foram criadas através do comando AT^SICS
e agrupadas no Perfil 0. Os comandos usados para configurar a conexão foram
armazenados em um vetor do tipo char como descrito abaixo:
82
unsigned char comando1[6]={"AT\r\n"},
comando2[27]={"at^sics=0,conType,GPRS0\r\n"},
comando3[28]={"AT^SICS=0,\"inactTO\",\"20\"\r\n"},
comando4[26]={"AT^SICS=0,user,\"claro\"\r\n"},
comando5[28]={"AT^SICS=0,passwd,\"claro\"\r\n"},
comando6[32]={"AT^SICS=0,apn,\"claro.com.br\"\r\n"},
É preciso notar que para cada final de comando foram incluídos
caracteres especiais denominados Retorno de Carro (Carriage Return \r) e
Nova Linha (Line Feed \n). Após o firmware do modem identificar esses dois
caracteres de controle, é feita a execução do comando recebido do
microcontrolador.
A string comando1 inicia a comunicação com o modem GSM através
do comando “AT”, no qual irá retornar um comando de “OK” e assegurar a
conexão serial com o microcontrolador. O Comando2 configura a conexão de
rede no Perfil 0 como sendo do tipo GPRS. O comando 3 é optional e fecha a
conexão após 20 segundos sem atividade. Os comandos 4,5 e 6 configuram o
usuário, senha e APN específico de cada operadora de telefonia.
Após a configuração com sucesso do Perfil de conexão, é preciso
informar ao modem o endereço e o tipo de conexão que será estabelecida com
o servidor. Neste trabalho, foi estabelecido que a conexão será do tipo Soquete
(Socket), permitindo conexão entre cliente e servidor sem grandes dificuldades.
O comando AT^SISS define o tipo de conexão utilizado e armazena
esses dados em um perfil definido:
Unsigned char
comando7[28]={"at^siss=1,srvType,socket\r\n"},
83
comando8[21]={"at^siss=1,conId,0\r\n"},
comando9[56]={"at^siss=1,address,\"socktcp://201.52.80.172:1111\"\r\n"};
O comando7 configura no Perfil 1 uma conexão do tipo Soquete
(socket). O comando8 associa a conexão configurada no Perfil 0 (operadora
CLARO) para criar o serviço de Soquete. O comando9 especifica o endereço
IP no qual o veículo será conectado.
É preciso notar o uso da porta 1111 utilizada em conjunto com o
endereço IP do servidor. Esta porta foi adotada nas configurações iniciais do
servidor e no roteador local da LAN que ele se encontra e é necessária para
estabelecer a conexão cliente-servidor.
A partir deste ponto, o modem estará pronto para abrir a conexão
configurada. Para isto, é preciso dar o comando AT^SISO=1 para ordenar a
abertura do serviço de conexão configurada no Perfil 1:
Unsigned char comando10[13]={"AT^SISO=1\r\n"};
Depois de declarados os comandos no firmware, foi preciso criar
uma subrotina que enviasse esses comandos através da porta serial UART1,
na ordem do comando1 até o comando10. Esta subrotina foi chamada de
putchar() e envia um vetor de caracteres de um comando através da porta
serial:
static void putchar (unsigned char *c, unsigned int lenght)
{ int i;
for(i=0;i<lenght;i++) // envia todos os caracteres da string de comando
{
U1THR=c[i]; //envia um byte para o registrador da serial
while(!(U1LSR & 0x40)) ; //aguarda confirmação de envio
}
}
84
Com a função putchar() fica simples o envio de vetores de caracteres
para a porta serial. Com esta função foram enviados os comando de 1 a 10
para o modem em intervalos que variam de 150 ms até 5 segundos, de acordo
com o tempo de resposta do dispositivo, como é mostrado abaixo.
putchar(comando1,6);//envia o vetor comando1 de 6 caracteres
Delay_1ms(150); // espera 150 ms
while(flag_ok!=2); // espera receber comando OK
flag_ok=0; //zera flag OK
putchar(comando2,27); //envia o vetor comando1 de 6 caracteres
while(flag_ok!=2); // espera receber comando OK
flag_ok=0; //zera flag OK
Delay_1ms(500); // espera 500 ms
putchar(comando3,28); //envia o vetor comando2 de 28 caracteres
while(flag_ok!=2); // espera receber comando OK
flag_ok=0; //zera flag OK
Delay_1ms(500); // espera 500 ms
putchar(comando4,26); //envia o vetor comando4 de 26 caracteres
while(flag_ok!=2); // espera receber comando OK
flag_ok=0; //zera flag OK
Delay_1ms(500); // espera 500 ms
putchar(comando5,28); //envia o vetor comando5 de 28 caracteres
while(flag_ok!=2); // espera receber comando OK
flag_ok=0; //zera flag OK
Delay_1ms(500); // espera 500 ms
putchar(comando6,32); //envia o vetor comando6 de 32 caracteres
while(flag_ok!=2); // espera receber comando OK
flag_ok=0; //zera flag OK
85
Delay_1ms(500); // espera 500 ms
putchar(comando7,28); //envia o vetor comando7 de 28 caracteres
while(flag_ok!=2); // espera receber comando OK
flag_ok=0; //zera flag OK
Delay_1ms(500); // espera 500 ms
putchar(comando8,21); //envia o vetor comando8 de 21 caracteres
while(flag_ok!=2); // espera receber comando OK
flag_ok=0; //zera flag OK
Delay_1ms(150); // espera 150 ms
putchar(comando9,51); //envia o vetor comando9 de 51 caracteres
while(flag_ok!=2); // espera receber comando OK
flag_ok=0; //zera flag OK
Delay_1ms(500); // espera 500 ms
putchar(comando10,13); //envia o vetor comando10
while(flag_ok!=2); // espera receber comando OK
flag_ok=0; //zera flag OK
Delay_1ms(5000); // espera 5s
Adotados estes procedimentos e o servidor preparado para a
conexão, o veículo estará pronto para enviar e receber os dados provenientes
do usuário. Contudo, como o microcontrolador pode estar ocupado quando for
recebido algum dado ou comando, na urgência do tratamento destes dados, foi
preciso usar os recursos de interrupção do microcontrolador. Estes recursos
permitem a parada imediata de um processo para a execução de uma
subrotina de recepção dos dados provenientes do servidor.
86
6.9.1- Interrupção da Porta Serial (UART1)
Para o controle de comandos e dados entre o microcontrolador
LPC2148 e o modem MC55i da Siemens, foi preciso usar o recurso de
interrupção do microcontrolador. Com o uso da interrupção adotada inter (que
não retorna valor), para cada byte recebido no buffer da UART1, a função de
comunicação com o modem será chamada. Isto garante que nenhum dado seja
ignorado na recepção no caso do processamento estar voltado para outro
processo.
Para que a interrupção da UART1 funcione foram usados quatro
passos. Primeiramente declarou-se a rotina geradora da interrupção como uma
subrotina comum, armazenou-se o endereço da função que tratará a
interrupção no registrador de endereço VICVectAddr0, escolheu-se o canal
usado pela UART1 através do registrador VICVectCntl0 e, por último, habilitou-
se a execução da interrupção através do registrador U1IER:
void __irq inter(void); // declaração da função no cabeçalho do firmware
main()
{
VICVectAddr0= (unsigned) inter;
VICVectCntl0=0x27; //Canal 7 (UART1)
U1IER=0x01; // Habilita interrução de recepção
/*CORPO DO PROGRAMA PRINCIPAL....*/
}
Após a função principal Main() , foi escrita a função de interrupção inter
cujo código é apresentado abaixo:
void __irq inter(void)
{
unsigned char buf, comando1[16]={"AT^SISR=1,10\r\n"}; // requisita ler 10 bytes
87
buf=U1RBR; // armazena o byte recebido do modem
if(buf =='O')
{flag_ok=1;}
if(flag_ok==1 && buf =='K')
{flag_ok=2;} // recebeu OK? Se sim, flag_ok=2.
//------------------------------------- TRATA OUTRO CASO
if(flag_sisr == 6) // recebe o comando vindo do usuário (Servidor)
{
if(buf>=0x80)
{opt=buf;} // Comando do usuário
if(flag_ok==2) // Ok? Sem mais dados.
{
flag_ok=0; //zera flag Ok
flag_sisr=0; // zera flag de recepção
}
}
else
{
if(buf ==' '̂)
{flag_sisr=1;}
if(flag_sisr==1 && buf =='S')
{flag_sisr=2;}
if(flag_sisr==2 && buf =='I')
{flag_sisr=3;}
if(flag_sisr==3 && buf =='S')
{flag_sisr=4;}
if(flag_sisr==4 && buf =='R')
{flag_sisr=5;}
if(flag_sisr == 5)
88
{
Delay_1ms(1);
putchar(comando1,16); //Envia AT^SISR
flag_sisr=6;
}
}
U1FCR=0x07; // limpa buffers de transmissão e recepção
U1IER=0x01; //habilita interrupção
VICVectAddr= 0; //volta ao endereço inicial da função
}
A função acima, basicamente, é encarregada de armazenar o
byte recebido na UART1 em uma variável do tipo char e, após isto, verificar se
os bytes recebidos formam o datagrama “OK” ou “SISR”. A recepção do
comando “OK” significa que o modem executou com sucesso alguma ação
enviada e, com isto, a variável flag_ok deve ser igual a 2 (valor adotado).
Quando o datagrama “SISR” é recebido, algum dado foi recebido do Servidor.
Com isso, é enviada ao modem a requisição da leitura destes dados através do
comando “AT^SISR=1,10” (envia no máximo 10 bytes para o microcontrolador).
Após o envio da requisição “AT^SISR=1,10”, os bytes recebidos
serão comparados. Se o valor do byte for maior que 0x80 significa que é um
comando proveniente do Servidor e será armazenado na variável opt,
constantemente verificada para acionar as ações do robô na função Main().
6.10- Envio de dados do cliente para o servidor
Até o momento, viu-se o comando de recepção dos dados AT^SISR.
Após o microcontrolador sincronizar com a câmera C328 através da porta serial
UART0, obter um quadro de imagem e armazená-lo em sua memória
temporária, será preciso utilizar o comando AT^SISW para enviar esses dados
através do modem GSM. O trecho de código que envia o vetor imagem para o
servidor é mostrado abaixo:
89
Unsigned char comando11[15]={"AT^SISW=1,2\r\n"}, comando12[18]={"AT^SISW=1,1400\r\n"}, comando13[10]={"AT^SISW=1,"}, comando14[4]={"\r\n"}, putchar(comando11,15); // requisita o envio de dois bytes
Delay_1ms(100); // espera 100ms para enviar os bytes
send_byte(i2%0x100); // envia a parte baixa do tamanho do quadro
send_byte(i2/0x100); //envia a parte alta do tamanho do quadro
Delay_1ms(50); // espera 50 ms
putchar(comando12,18); //requisita enviar os primeiros 1400 bytes do quadro
Delay_1ms(100); // espera 100 ms
for(i=0;i<1400;i++) //envia 1400 bytes para o modem
{
send_byte(imagem[i]);
}
while(flag_ok!=2); // espera OK do modem
flag_ok=0;
Delay_1ms(200); // espera 200 ms
SUBT=i2-1400; //verifica quantos bytes faltam para enviar
// requisita o envio dos bytes restantes
putchar(comando13,10);
send_byte((SUBT/100)+0x30);
send_byte(((SUBT%100)/10)+0x30);
send_byte((SUBT%10)+0x30);
putchar(comando14,4);
Delay_1ms(50); // espera 50 ms
90
for(i=1400;i<i2;i++) //envia os bytes restantes
{
send_byte(imagem[i]);
}
}
O trecho do código mostrado basicamente requisita ao modem o envio
dos primeiros 2 bytes que informam o tamanho da imagem capturada. Logo
em seguida do envio do tamanho da imagem, é requisitado o envio dos
primeiros 1400 bytes da imagem e, após isto, o envio dos bytes restantes. Com
isto, o Servidor tem todos os dados necessários para reproduzir a imagem na
interface gráfica.
6.11- Sincronização com a câmera C328
A câmera serial utilizada faz comunicação com os pinos RXD0 e
TXD0 do microcontrolador. Contudo, os pinos do microcontrolador trabalham
na tensão nominal de 3.3V. A câmera comunica-se serialmente através de
níveis de tensão em torno de +15V e –15V (para aumentar o alcance de
transmissão), com isso, é incompatível com a tensão do microcontrolador.
Acrescentou-se ao sistema o circuito integrado MAX232, responsável por
diminuir a tensão para 5V que é um nível aceitável para o microcontrolador
LPC2148.
Feito a ligação elétrica entre a câmera e o microcontrolador, definiu-
se o tipo de imagem a ser trabalhada neste projeto, uma vez que são
fornecidas inúmeras opções de tamanhos e formatos de imagem. Adotou-se a
imagem que possuísse o menor tamanho possível, ou seja, o padrão de
compressão deverá ser JPEG e a resolução mínima para entender o ambiente
em que se encontra o veículo será 80x60.
91
Para sincronizar e configurar a câmera e receber as imagens no
formato correto sempre que solicitadas, criou-se algumas funções que
auxiliassem este processo. A primeira função chamada é a função sync(). A
função sync() é responsável por enviar comandos de sincronismo para a
câmera até que a mesma identifique a taxa de comunicação (baudrate) do
microcontrolador e esteja pronta para receber outros comandos. A função
sync() é descrita abaixo:
void send_sync() //Sincroniza ao enviar 0xAA, 0x0D,0x00,0x00,0x00,0x00
{
send_byte_UART0(0xAA);
send_byte_UART0(0x0D);
send_byte_UART0(0x00);
send_byte_UART0(0x00);
send_byte_UART0(0x00);
send_byte_UART0(0x00);
Delay_1ms(10);
}
Após o microcontrolador receber um comando de sincronismo, o
mesmo deve enviar um comando de reconhecimento (ACK) para a câmera:
void send_ack(unsigned char byte_ID,unsigned char byte_packID0,unsigned
char byte_packID1)
{
send_byte_UART0(0xAA);
send_byte_UART0(0x0E);
send_byte_UART0(byte_ID); // ID equivalente do comando confirmado
send_byte_UART0(0x00);
send_byte_UART0(byte_packID0); // usado na recepção de pacotes
send_byte_UART0(byte_packID1); //usado na recepção de pacotes
Delay_1ms(10);
}
92
Com a sincronia estabelecida entre ambos os dipositivos, o
comando seguinte (Initial) define os parâmetros da imagem que será
requisitada. O quarto byte deste comando especifica o formato da imagem
utilizada (JPEG) e o último, a resolução (80x60). O terceiro e o quinta byte não
irá importar para esta configuração.
void send_initial() //configura parametros 0xAA,0x01,0x00,0x07,0x01,0x03
{
send_byte_UART0(0xAA);
send_byte_UART0(0x01);
send_byte_UART0(0x00);
send_byte_UART0(0x07); // JPEG
send_byte_UART0(0x01); // resolucao de 80x60 (comprimido)
send_byte_UART0(0x03); // resolução 80x60 JPEG
Delay_1ms(10); /
}
Os bytes provenientes da imagem obtida serão transferidos em lotes
chamados pacotes. Estes pacotes possuem tamanhos definidos de acordo com
a função enviada previamente para a câmera. Escreveu-se a função
set_package_size() para limitar o pacote em no máximo 64 bytes.
void set_package_size() // tamanho pacote de dados
{
send_byte_UART0(0xAA);
send_byte_UART0(0x06);
send_byte_UART0(0x08);
send_byte_UART0(0x40); //64 bytes
send_byte_UART0(0x00);
send_byte_UART0(0x00);
Delay_1ms(20);
}
93
O comando send_getpicture() é o último comando da lista de
comandos da câmera para capturar uma imagem. Contudo, o quadro da
imagem permanecerá na memória da câmera até que uma sequência de
comandos ACK requisitem o envio da imagem por pacotes para o
microcontrolador.
void send_getpicture() // 0XAA04
{
send_byte_UART0(0xAA);
send_byte_UART0(0x04);
send_byte_UART0(0x05); // 80x60
send_byte_UART0(0x00);
send_byte_UART0(0x00);
send_byte_UART0(0x00);
Delay_1ms(10);
}
Com as funções de sincronismo e configuração da câmera prontos,
a sequência de chamadas foi seguida como descrito no trecho de código
abaixo:
If (CAM_CONECTADA==0)
{
while(ACK==0)
{send_sync();} // envia comando de sincronia até receber comando ACK
ACK=0;
send_ack(0x0D,0x00,0x00); // após recever ACK, envia um ACK
while(ACK==0)
{send_initial();} //configura formato da imagem e resolução
94
ACK=0;
Delay_1ms(50);
while(ACK==0)
{set_package_size();} // configura o tamanho do pacote
ACK=0;
Delay_1ms(50);
CAM_CONECTADA=1; // sincroniza a camera na primeira chamada apenas.
}
O trecho de código descrito acima certifica o envio do comando
SYNC (sincronismo de baudrate), Initial (Início) e Package_Size (tamanho de
pacote). Após a confirmação destes comandos, a câmera será capaz de aceitar
comandos relacionados com a captura e envio de imagens capturadas. Para
tanto, fez-se o uso da interrupção do controlador serial UART0 para o
tratamento dos dados recebidos da câmera.
6.11.1- Interrupção UART0
Para o controle de comandos e dados entre o microcontrolador
LPC2148 e a câmera C328 do fabricante COMedia, foi preciso usar o recurso
de interrupção do microcontrolador. Com o uso da interrupção adotada
inter_UART0 (que não retorna valor), para cada byte recebido no buffer da
UART0, a função de comunicação com a câmera será chamada. Isto garante
que nenhum dado seja ignorado na recepção no caso do processamento estar
voltado para outro processo.
void __irq inter_UART0(void) // interrupção que trata os dados da câmera.
{
if(rcb_image==1) // Se a flag rcb_image é 1, armazena a imagem.
95
{
pacote[iglobal]=U0RBR; //armazena bytes do quadro de imagem
if(iglobal==2) // Byte 2 contém o tamanho dos dados do
// pacote
{data_lenght=pacote[2];}
if(iglobal>=data_lenght+5) /* verifica se recebeu todos os
bytes do pacote*/
{
iglobal=0;
pacote_recebido=1;
contagem++;
}
else
{
iglobal++;
}
}
else
{
comando[iglobal]=U0RBR; // armazena byte vindo da câmera.
if(iglobal<5)
{iglobal++;}
else
{iglobal=0;}
if(iglobal==0)
{
if(comando[0]==0xAA && comando[1]==0x0E)
{ACK=1;}
if(comando[0]==0xAA && comando[1]==0x0A)
96
{
ACK=1;
image_size=comando[3]+comando[4]*0x100+comando[5]*0x10000;
n_pacotes=image_size/58; // n. de pacotes
if(image_size%58!=0)
{n_pacotes++;}
rcb_image=2;
iglobal=0;
}
if(comando[1]==0x0F) // Erro?
{escreve_lcd('N'); } // N no LCD
}
} // fim do else
U0FCR=0x07; // limpa buffers de transmissão e recepção
U0IER=0x01; // habilita interrupção
VICVectAddr= 0;
}
6.11.2- Captura de uma imagem da câmera
Com a rotina de recepção de interrupção dos dados da UART0 e a
câmera devidamente configurada, o último passo para obter um quadro de
imagem é descrito no trecho de código abaixo:
while(rcb_image!=2)
{
97
send_getpicture(); // requisita captura de imagem
Delay_1ms(10);
}
rcb_image=1;
while(contagem!=(n_pacotes))
{
send_ack(0x00,contagem,0x00); //para cada ACK enviado, recebe um pacote
while(pacote_recebido!=1); //espera receber o quadro
for(i=4;i<=(data_lenght+3);i++)
{
imagem[i2]=pacote[i]; // salva o pacote num vetor global
i2++;
}
pacote_recebido=0;
}
send_ack(0x00,0xF0,0xF0); // último ack , último pacote
Delay_1ms(100);
escreve_lcd_hex(data_lenght); // exibe o tamanho da imagem no lcd
escreve_lcd_hex(i2/0x100); // exibe a parte alta em hexacimal.
escreve_lcd_hex(i2%0x100); // exibe a parte baixe em hexadecimal.
O código de requisição e montagem dos pacotes descrito acima é
basicamente simples. Envia-se o comando send_getpicture() até ser recebido o
comando ACK da câmera e, com isso, sabe-se que o quadro da imagem está
disponível para a recepção. Os comandos ACKs subsequentes possuem a
identificação do pacote requisitado localizado no quarto byte do comando. Por
exemplo, se enviado um comando ACK 0xAA, 0x0E,0x00, 0x00 ,0x01, 0x00
significa que o primeiro pacote de dados será enviado ao microcontrolador.
98
6.12- Construção do veículo É preciso dizer que, antes da implementação do sistema eletrônico
no veículo, foi possível testar a comunicação entre todos os dispositivos:
câmera e modem com o microcontrolador e este sistema com o servidor. Após
todas as funções estarem operando satisfatoriamente, partiu-se para a fase de
fixação do sistema em um veículo de controle remoto facilmente encontrado no
mercado. Como discutido anteriormente, utilizou-se o circuito de acionamento
original do veículo a fim de testar o sistema embarcado desenvolvido.
O veículo utilizado como plataforma móvel possui as seguintes
características:
• Comprimento: 20 cm.
• Largura: 5,5 cm.
• Altura: 10 cm.
• Massa: aproximadamente 500g, sem baterias.
• Tipo de motores: motor com escovas, corrente contínua e 6V.
• Material: com excessão dos motores e dos eixos das rodas, todo o
veículo é composto de material plástico.
Procurou-se facilitar a implementação dos circuitos eletrônicos no
veículo através de suportes feitos a partir de placas de fenolite perfuradas
(figura 47), cortadas e furadas com o auxílio de uma serra elétrica e uma
furadeira elétrica.
Figura 47- placa de fenolite perfurada
101
Figura 50- Visão de topo do robô
As figuras 48 à 50 ilustram o resultado final do robô montado com
toda a eletrônica embarcada. É possível identificar todos os seus dispositivos,
com excessão das baterias, que estão localizadas em regiões não visíveis
desses ângulos. O veículo possue três baterias independentes para sua
alimentação: uma bateria de 4,5V e capacidade de 2500 mAh para alimentar os
motores, uma bateria de 4,8V de capacidade de 700mAh para alimentar o
microcontrolador+lcd+modem, e finalmente, uma bateria de 4,5V para
alimentar a câmera de forma independente.
102
Optou-se pelo uso de baterias independentes para a alimentação do
robô pela simples facilidade de uso das mesmas e espaço suficiente para
alocá-las sem problemas no veículo. Com isso, por exemplo, se os motores
drenam toda a energia das baterias de acionamento dos motores, as baterias
de acionamento da lógica do veículo estarão com capacidade para que fossem
continuados os testes do programa sem interromper o trabalho.
103
7- Resultados
Encontraram-se, inicialmente, alguns problemas para comunicar o
microcontrolador embarcado no veículo com a câmera e o modem GPRS.
Ambos os dispositivos paravam de responder repentinamente ou simplesmente
não funcionavam. Após alguns testes, descobriu-se que os intervalos de tempo
entre comandos eram muito curtos e não eram suficientes para os dispositivos
responderem à demanda de comandos do microcontrolador.
O documento do fabricante da câmera não informa o intervalo
mínimo entre comando necessário para garantir o funcionamento da mesma,
então se adotou, por segurança, intervalos entre comandos que variam de 10
ms até 50 ms para processos mais complexos.
Na comunicação com o modem, surgiu um grande desafio para
conecta-lo inicialmente à rede de telefonia e estabelecer uma conexão com o
servidor. O fabricante sugere um intervalo de no mínimo 100ms para taxas de
comunicação a partir de 9600 bps. Contudo, após inúmeras tentativas sem
sucesso, descobriu-se que alguns trechos do programa foram necessários 5
segundos para estabelecer uma conexão. Isto se deve ao atraso inerente do
serviço prestado no momento da conexão. Após a conexão estabelecida com
sucesso entre cliente e servidor, os atrasos utilizados entre os comandos foram
100 ms.
Após a superação dos problemas, o projeto apresentou os
seguintes resultados:
• Autonomia do veículo acima de 3 horas.
• Massa em torno de 1,2 Kg.
• Tempo de resposta de acionamento dos motores indefinido, uma vez
que depende da latência da rede. Contudo, o tempo médio de resposta
104
foi de aproximadamente 1648 ms, que depende das condições de
tráfego de dados na rede.
• Conexão estável. Raramente ocorreu perda de conexão entre cliente e
servidor.
• Taxa de recepção da imagem do veículo variável, porém, em boas
condições conseguiu-se receber uma imagem com um atraso de
aproximadamente 2s em relação ao momento da requisição.
• Alcance de conexão com ampla cobertura de sinal, mesmo com a
antena do veículo recolhida.
7.1- Medição da latência da rede
Através do programa de medição, anteriormente discutido, foi
possível obter os atrasos envolvidos na transmissão e recepção dos dados do
robô criado. O gráfico 01 mostra os resultados obtidos.
0
500
1000
1500
2000
2500
3000
0 30 60 90 120
150
180
210
240
270
300
330
360
390
420
450
Tempo (s)
Atr
aso
(ms)
Gráfico 1- Latência da rede x tempo.
A medição obtida possui 46 amostras em intervalos de 15 segundos
(total de 7,5 minutos). O gráfico 1 mostra que os comandos do usuários podem
ser reconhecidos pelo robô e recebidos pela interface em no mínimo 800 ms
até 2700 ms. O valor médio obtido foi 1649 ms e seu desvio padrão de 650 ms.
105
7.2 Taxa de transmissão O sistema desenvolvido possui limitações quanto à sua velocidade
de comunicação. Apesar do módulo GPRS poder comunicar-se em velocidades
de até 86 kbps, a média real que pode ser encontrada nas redes fica em torno
de 56 kbps. Porém, existe um fator limitante no projeto, que é a velocidade
serial adotada de 9600 bps entre os dispositivos do robô e que limita a
velocidade máxima de comunicação com o servidor.
A velocidade serial adotada se deve ao fato do uso inadequado do cristal
na placa SOM utilizada. O fabricante fornece a placa com um cristal de 16 Mhz,
valor incompatível com outras velocidades seriais, fornecendo erros
significativos de comunicação para outros valores. Contudo, com o uso de um
cristal adequado, pode-se configurar a comunicação dos dispositivos do robô
até 115200 bps.
106
8- Conclusão
De forma geral, foi possível familiarizar-se e desenvolver habilidades
nas áres de atuação: programação em plataforma Windows, programação de
sistemas embarcados, tecnologias de rede Ethernet e GPRS e, também,
acionamento de motores.
O projeto apresentou resultados satisfatórios, pois foi possível
implementar com sucesso todos os dispositivos essenciais para o
funcionamento de um veículo controlado, tais como câmera, microcontrolador,
modem e software de comunicação. O projeto também permitiu que todos os
dispositivos funcionassem sem conflitos, de acordo como desenvolvido
inicialmente pelo fluxograma.
O sistema desenvolvido possui ainda algumas deficiências
inerentes da tecnologia de comunicação adotada. Existe um atraso de
recepção dos comandos por parte do robô e, também, atraso no envio da
imagem. Este atraso é característica da conexão por comutação de pacotes,
porém pode ser minimizada com a contratação de uma qualidade de serviço
(QoS) melhor por parte do cliente com a operadora de telefonia.
Foi possível, com um investimento muito reduzido , criar um
sistema de controle remoto que possuísse ampla cobertura em território
brasileiro e que pode ser aplicável em diversas áreas, não ficando limitado à
aplicação neste projeto.
Esta aplicação é uma possibilidade em áreas rurais, longe de
qualquer cobertura de tecnologias mais recentes, como por exemplo a 3G. Por
possuir maior cobertura em território brasileiro, a tecnologia GPRS pode ser a
única alternativa para monitoração de estações isoladas e automação em
fazendas agropecuárias ou agrícolas.
107
9- Referências Bibliográficas
[1] Bianchini, D.; Meneses, M. B.; Marchi, V. L. Robô Móvel Controlado
Remotamente.Faculdade de Valinhos, 2007.
[2] Info Abril. PF apresenta robô antibomba para Copa. Disponível em:
<http://info.abril.com.br/noticias/ti/pf-apresenta-robo-antibomba-para-copa-
02082010-35.shl>. Acesso em 2011.
[3] Bueno, M. Compressão de Arquivos JPEG: Como funciona.
<http://www.cdt.com.br/index.php/artigos/odontologia/66-compressao-de-
arquivos-jpeg-como-funciona.html>. Acesso em 2011.
[4] Suporte Microsoft. Definição sete camadas do modelo OSI e explicação de funções. Disponível em:
<http://support.microsoft.com/kb/103884/pt-br>. Acesso em 2011. [5] Kioskea. O Protocolo TCP. Disponível em:
<http://pt.kioskea.net/contents/internet/tcp.php3>. Acesso em 2011.
[6] Clube do Hardware. Como o Protocolo TCP/IP Funciona- Parte 1.
Disponível em: <http://www.clubedohardware.com.br/artigos/1351>. Acesso em
2011.
[7] Usha Communications Technogy. General Packet Radio Service.
Disponível em: < http://www.mobilein.com/GPRS.pdf> . Acesso em 2011.
[8] ASCOM.Protocol Overhead in GPRS. Disponível em:
<http://www.ascom.fr/cn/protocol-overhead.pdf> .Acessado em 2011.
[9] ARVM. Transistores Bipolares. Disponível em: <
http://www.arvm.org/exames/trasistor.htm > .Acesso em 2011.
[10] Patsko, L. F. Tutorial – Montagem da Ponte H . Disponível em:
108
<http://www.maxwellbohr.com.br/downloads/robotica/mec1000_kdr5000/tuto
rial_eletronica_-_montagem_de_uma_ponte_h.pdf > .Acesso em 2011.
[11] ASCII Table and Description. Disponível em: <http://www.asciitable.com/> .
Acesso em 2011.
[12] Terroso, A. R. Controle de Display LCD. Disponível em:
<http://www.ee.pucrs.br/~terroso/html/lcd.html> Acesso em 2011.
[13] MARCHI, J. Navegacão de robôs móveis autônomos: Estudo e
implementacão de abordagens. Master’s thesis, UFSC - Universidade Federal
de Santa Catarina, 2001.
[14] Pieri, E, R. Curso de Robótica Móvel. Universidade Federal de Santa Catarina, 2002. [15] COMedia Ltda. Disponível em <http://www.comedia.com.hk/>.Acessado em dezembro de 2009. [16] EsysTech < http://www.esystech.com.br/produtos/eLPC/eLPC64.php>.Acesso em dezembro de 2009. [17] Fakir, F. Implementação de um Robô Autônomo Controlado por Sistema de Navegação Nebuloso. 2009. 141 f. Universidade Estadual Paulista – UNESP. [18] Serra, D. N. Sistema de Controle Veicular Através de Processamento de Imagem. 2010. 233 f. Universidade Estadual Paulista – UNESP. [19] Souza, D. R. Microcontroladores ARM7- Philips família LPC213x- O Poder
dos 32 Bits – Teoria e Prática.Ed.: Érica 1ª Edição 2006.
109
ANEXO A- Código fonte do Servidor
//---------------------------------------------------------------------------
#include <vcl.h>
#include <jpeg.hpp>
#include <stdio.h>
#pragma hdrstop
#include "Main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
TIPO_SERIAL TS ;
bool f_serial_opened = false ;
AnsiString ipServer,msg;
unsigned char buffer[3000]={0x00},buffer2[2000]={0x00};
int size=0,ibuf2=0,i2=0,cont=0,pacote=0;
byte comando[1]={0x09}, comando2[1]={0x89};
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void TForm1::DrawJPEG(TImage *pimage,unsigned char *buffer,unsigned long size)
{
/* Esta rotina exibe em canvas uma imagem no formato JPEG*/
TJPEGImage *jpg = new TJPEGImage();
TMemoryStream *ms = new TMemoryStream ;
ms->Clear() ;
ms->SetSize((int)size);
110
ms->WriteBuffer(buffer,size) ;
ms->Seek(soFromBeginning ,0);
try
{
/* jpg->LoadFromFile("image.jpg"); */
jpg->LoadFromStream(ms) ;
pimage->Canvas->StretchDraw(Rect(0,0,pimage->Width,pimage->Height),jpg);
}
catch(...)
{
ShowMessage("Unable to load JPEG image");
}
delete ms ;
delete jpg;
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Form1->server->Active=true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::EnviarClick(TObject *Sender) // Envia comando 0x91
{
byte comando2[1]={0x91};
if(Form1->server->Active==True)
{
CheckBox5->Checked=false;
Form1->server->Socket->Connections[0]->SendBuf(comando2,1);
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::serverAccept(TObject *Sender,
TCustomWinSocket *Socket)
{
111
Label2->Caption="Servidor Conectado";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OnClientRead(TObject *Sender,
TCustomWinSocket *Socket) // Recebe dados do cliente (Imagens)
{
unsigned char tamanho[2]={0x00};
int i=0;
pacote ++;
if(ibuf2==1)
{
// Recebe os dois primeiros bytes relacionados com o tamanho do pacote
i2=Form1->server->Socket->Connections[0]->ReceiveLength();
Form1->server->Socket->Connections[0]->ReceiveBuf(buffer2,i2);
for(i=0;i<i2;i++) // armazena o pacote em um vetor da imagem
{
buffer[cont]=buffer2[i];
cont++;
ProgressBar1->Position=cont;
}
}
if(ibuf2==0)
{
// recebe o tamanho total da imagem capturada e convertido para size.
Form1->server->Socket->Connections[0]->ReceiveBuf(tamanho,2);
size=tamanho[0]+tamanho[1]*0x100;
Label3->Caption=size;
ProgressBar1->Max=size;
ibuf2=1;
i2=0;
}
112
Label7->Caption=pacote;
Label8->Caption=cont;
if(cont>=size)
{
DrawJPEG(Image1,buffer,size) ; // exibe a imagem a partir do buffer completo
ibuf2=0;
cont=0;
pacote=0;
i2=0;
size=0;
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
// com o timer acionado, envia comando a cada intervalo de tempo
if( CheckBox5->Checked==true && Form1->server->Active==true )
{
Form1->server->Socket->Connections[0]->SendBuf(comando2,1);
Label1->Caption="SYNC enviado";
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
byte comando2[1]={0x84};
Form1->server->Socket->Connections[0]->SendBuf(comando2,1);
Form1->server->Socket->Connections[0]->SendText(" ");
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ClientConnect(TObject *Sender,
TCustomWinSocket *Socket)
{
Label2->Caption="Servidor e Cliente";
113
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ClientDisconnect(TObject *Sender,
TCustomWinSocket *Socket)
{
Label2->Caption="Cliente desconectado.";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button4Click(TObject *Sender)
{
comando2[0]=0x81;
Form1->server->Socket->Connections[0]->SendBuf(comando2,1);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button5Click(TObject *Sender)
{
comando2[0]=0x87;
Form1->server->Socket->Connections[0]->SendBuf(comando2,1);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button6Click(TObject *Sender)
{
comando2[0]=0x85;
Form1->server->Socket->Connections[0]->SendBuf(comando2,1);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button7Click(TObject *Sender)
{
comando2[0]=0x83;
Form1->server->Socket->Connections[0]->SendBuf(comando2,1);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button9Click(TObject *Sender)
114
{
comando2[0]=0x82;
//Form1->server->Socket->Connections[0]->SendBuf(comando2,1);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button10Click(TObject *Sender)
{
comando2[0]=0x88;
//Form1->server->Socket->Connections[0]->SendBuf(comando2,1);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button11Click(TObject *Sender)
{
comando2[0]=0x86;
//Form1->server->Socket->Connections[0]->SendBuf(comando2,1);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button8Click(TObject *Sender)
{
comando2[0]=0x80;
//Form1->server->Socket->Connections[0]->SendBuf(comando2,1);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
byte comando2[1]={0x8A};
Form1->server->Socket->Connections[0]->SendBuf(comando2,1);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button12Click(TObject *Sender)
{
byte comando2[1]={0x89};
Form1->server->Socket->Connections[0]->SendBuf(comando2,1);
}
116
ANEXO B- Firmware do Robô
#include <LPC214x.H>
void __irq inter(void);
void __irq inter_UART0(void);
int flag_ok=0,
iglobal=0,
flag_sisr=0,
j=0,
opt=0x69,
opt2=0x69,
img_ok=0,
SYNC=0,
image_size=0,
ACK=0,
ID=0,
data_lenght=0,
n_pacotes=0,
pacote_recebido=0,
contagem=0,
pixel=0,
rcb_image=0,
lcd_pos=0;
unsigned char pacote[100],imagem[10000], comando
[6],CAM_CONECTADA=0,MC_RESPONSE[16],buf=0;
// ------------------Rotina de atraso
void Delay_1ms(unsigned int x) //16K/16M= 1ms
{
T1PR=0x00000064; //100
T1MR0=x*0x000000A0; //160
T1IR|=0x00000001; // Limpa o flag de interrupção do Timer
T1MCR=3; //Habilita o reset do contador do Timer
117
T1TC=0; //Zera o contador do Timer
T1TCR=1; //Habilita o Timer
while (!(T1IR&0x00000001)); //Executa o delay de X ms
}
//-----------------------------------------------------
void inicia_display()
{
int i;
// Conf. Função 00111000b
for (i=0;i<3;i++)
{
IOSET1=0x2000000; //pulso E
IOSET1=0x380000;
Delay_1ms(5);
IOCLR1=0x2000000; //pulso E
IOCLR1=0x380000;
Delay_1ms(15);
}
//Ctrl do display 00001110b
IOSET1=0x2000000 ; //pulso E
IOSET1=0xE0000;
Delay_1ms(5);
IOCLR1=0x2000000; //pulso E
IOCLR1=0xE0000;
Delay_1ms(15);
//Deslocamento DO CURSOR 00000110b
IOSET1=0x2000000; ///pulso E
IOSET1=0x00006000;
Delay_1ms(5);
IOCLR1=0x2000000; //pulso E
IOCLR1=0x00006000;
Delay_1ms(15);
118
// retorno do cursor 10
IOSET1=0x2000000; //pulso E
IOSET1=0x20000;
Delay_1ms(5);
IOCLR1=0x2000000; //pulso E
IOCLR1=0x20000;
Delay_1ms(15);
//Limpar display 01h
IOSET1=0x2000000; //pulso E
IOSET1=0x10000;
Delay_1ms(5);
IOCLR1=0x2000000; //pulso E
IOCLR1=0x10000;
Delay_1ms(15);
}
void limpa_display()
{
//Limpar display 01h
IOSET1=0x2000000; ; //pulso E
IOSET1=0x10000;
Delay_1ms(5);
IOCLR1=0x2000000; //pulso E
IOCLR1=0x10000;
Delay_1ms(15);
}
void posicao_escrita(int pos)
{
//POSICAO DE ESCRITA DO VALOR ANGULO
IOSET1=0x2000000; //pulso E
IOSET1=0x00000000|pos<<16;
119
Delay_1ms(5);
IOCLR1=0x2000000; //pulso E
IOCLR1= 0x00000000|pos<<16;
Delay_1ms(15);
}
void escreve_lcd(int caracter)
{
IOSET1=0x2000000; //pulso E
IOSET1=0x1000000|(caracter<<16;
Delay_1ms(5);
IOCLR1=0x2000000; //pulso E
IOCLR1=0x1000000|(caracter<<16);
Delay_1ms(20);
}
void UART0_Init(void)
{
PINSEL0 |= 0x05; // Habilita os pinos RxD e TxD da UART0
U0FCR = 0x07; //Habilita e reseta os buffers de transmissão e recepção
U0LCR = 0x83; // UART 8N1, allow access to divider-latches
U0DLL = 0x68; // baud rate fixed to 9600 bps @ PCLK = 16 Mhz e VPB = 0x02
U0DLM = 0x00; // parte alta do baud rate
U0LCR = 0x03; // UART 8N1, desabilita divisor do baud rate
}
//-----------------------------------------------------------------
//envia 1 byte para o buffer
static void send_byte_UART0 (unsigned char c)
{
U0THR = c;
while(!(U0LSR & 0x40)) ; //#1000000
}
//------------------------------------------------------------------------
120
----
// ----------- Inicia PLL
void init_PLL_VPB(void)
{
PLL0CFG=0x00000041; //frequencia de 32MHZ com um cristal de 16MHz OBS.: (M-1)
PLL0CON=0x00000001; //Habilita o PLL
PLL0FEED=0x000000AA; //Atualiza os registradores
PLL0FEED=0x00000055;
while (!(PLL0STAT & 0x00000400)); //Testa o PLOCK
PLL0CON=0x00000003; //conecta o PLL
PLL0CON=0x00000003; //Conecta ao PLL
PLL0FEED=0x000000AA; //Atualiza os registradores
PLL0FEED=0x00000055;
VPBDIV=0x00000002; //VPB=2 PCLK de 16 MHz
}
//-------------------- Configura UART1
void UART1_Init(void)
{
/*
Pino 0.9 como RXD1 (Entrada)
Pino 0.8 como TXD1 (Saída)
Pino 0.12 como POWER_CONTROL (Saída)
Pino 0.10 como DTR (Saída)
Pino 0.13 como DCD (Entrada)
*/
PINSEL0 |= 0x50000; //Habilita o pino TxD1e RxD1
da UART1
U1FCR = 0x07; //(# 00000111b) Habilita e reseta os buffers de transmissão e recepção
U1LCR = 0x83; // UART 8N1, allow access to divider-latches
U1DLL = 0x68; // baud rate fixed to 9600 bps @ PCLK = 16 Mhz e VPB = 0x02
121
U1DLM = 0x00; // parte alta do baud rate
U1LCR = 0x03; // UART 8N1, desabilita divisor do baud rate
IODIR0 |= 0x1400; // Pino 0.13 como entrada.
IOSET0 |= 0x400; // DTR em nível lógico 1.
IOSET0 |= 0x1000;
Delay_1ms(50);
IOCLR0 |= 0x1000;
Delay_1ms(150);
IOSET0 |= 0x1000;
}
//-------------------------------------- Envia byte pela UART1
static void send_byte (unsigned char c) //envia 1 byte para o buffer
{
U1THR = c;
while(!(U1LSR & 0x40)) ; //#1000000
}
//----------------------------------------------------------------------
static void putchar (unsigned char *c, unsigned int lenght) //envia
1 byte para o buffer
{
int i;
for(i=0;i<lenght;i++)
{
U1THR=c[i];
while(!(U1LSR & 0x40)) ; //#1000000
}
}
//-------------------------------------------------------------------
122
void send_initial()
{
send_byte_UART0(0xAA);
send_byte_UART0(0x01);
send_byte_UART0(0x00);
send_byte_UART0(0x07); // JPEG
send_byte_UART0(0x01); // resolucao de 80x60 (nao comprimido)
send_byte_UART0(0x03); // resolução 60x80 JPEG
Delay_1ms(10);
}
//-----------------------------------------------------------------
void send_snapshot()
{
send_byte_UART0(0xAA);
send_byte_UART0(0x05);
send_byte_UART0(0x00); // comprimido
send_byte_UART0(0x00);
send_byte_UART0(0x00);
send_byte_UART0(0x00);
Delay_1ms(10);
}
//----------------------------------------------------------------
//-----------------------------------------------------------------
void set_package_size() // pacote de dados de 512 bytes
{
send_byte_UART0(0xAA);
send_byte_UART0(0x06);
send_byte_UART0(0x08);
send_byte_UART0(0x40); //64 bytes
send_byte_UART0(0x00);
send_byte_UART0(0x00);
Delay_1ms(20);
}
//----------------------------------------------------------------
void send_getpicture()
{
send_byte_UART0(0xAA);
123
send_byte_UART0(0x04);
send_byte_UART0(0x05); // preview
send_byte_UART0(0x00);
send_byte_UART0(0x00);
send_byte_UART0(0x00);
Delay_1ms(10);
}
//-----------------------------------------------------------------
void send_sync()
{
send_byte_UART0(0xAA);
send_byte_UART0(0x0D);
send_byte_UART0(0x00);
send_byte_UART0(0x00);
send_byte_UART0(0x00);
send_byte_UART0(0x00);
Delay_1ms(10);
}
//--------------------------------------------------------------------
void send_ack(unsigned char byte_ID,unsigned char byte_packID0,unsigned
char byte_packID1)
{
send_byte_UART0(0xAA);
send_byte_UART0(0x0E);
send_byte_UART0(byte_ID);
send_byte_UART0(0x00);
send_byte_UART0(byte_packID0);
send_byte_UART0(byte_packID1);
Delay_1ms(10);
}
//----------------------------------------------------------------------
//--------------------------------------------------------------------
void escreve_lcd_hex(unsigned char hex)
{
int dezena=0,unidade=0;
124
dezena= hex/0x10;
unidade= hex%0x10;
if(dezena>=0 && dezena<=9)
{escreve_lcd(0x30+dezena);}
else
{escreve_lcd(0x37+dezena);}
if(unidade>=0 && unidade<=9)
{escreve_lcd(0x30+unidade);}
else
{escreve_lcd(0x37+unidade);}
escreve_lcd(0x2E);
Delay_1ms(5);
}
// --------------------------------------------------------------------
int main (void)
{ int i=0,i2=0,SUBT=1500;
// pág. 229
unsigned char comando1[6]={"AT\r\n"},
comando2[27]={"at^sics=0,conType,GPRS0
\r\n"},
comando3[28]={"AT^SICS=0,\"inactTO\",\"20\"\r\n"},
comando4[26]=
{"AT^SICS=0,user,\"claro\"\r\n"},
comando5[28]=
{"AT^SICS=0,passwd,\"claro\"\r\n"},
comando6[32]=
{"AT^SICS=0,apn,\"claro.com.br\"\r\n"},
comando7[28]={"at^siss=1,srvType,socket\r\n"},
comando8[21]={"at^siss=1,conId,0\r\n"},
comando9[52]=
{"at^siss=1,address,\"socktcp://189.5.6.204:1111\"\r\n"}, // OBSERVAR IP DO SERVIDOR
comando10[13]={"AT^SISO=1\r\n"},
comando11[15]={"AT^SISW=1,2\r\n"},
125
comando12[18]={"AT^SISW=1,1400\r\n"},
comando13[10]={"AT^SISW=1,"},
comando14[4]={"\r\n"},
comando15[15]={"AT^SISW=1,2\r\n"};
// comando11[13]={"AT^SISC=1\r\n"};
init_PLL_VPB();
UART1_Init();
UART0_Init();
VICVectAddr0= (unsigned) inter;
VICVectAddr1= (unsigned) inter_UART0;
VICVectCntl0=0x27; //Canal 7 (UART1)
VICVectCntl1=0x26; //Canal 6 (UART0)
VICIntEnable=0xC0; //Habilita o canal 6 e 7;
U1IER=0x01; // Habilita interrução de recepção
U0IER=0x01; // Habilita interrução de recepção
PINSEL1=0x00000000;
PINSEL2=0x00000000;
IODIR1 =0xFFFFFFFF; //Todos os pinos como saída
IODIR0 =0xFFFFFCFF;
IOCLR0= 0xFFFFE8FF;
inicia_display();
posicao_escrita(0x80);
escreve_lcd('C');
escreve_lcd('o');
escreve_lcd('n');
escreve_lcd('e');
escreve_lcd('c');
escreve_lcd('t');
escreve_lcd('a');
escreve_lcd('n');
escreve_lcd('d');
126
escreve_lcd('o');
escreve_lcd(':');
posicao_escrita(0x8B);
escreve_lcd('1');
Delay_1ms(15000);
putchar(comando1,6);
Delay_1ms(150);
while(flag_ok!=2);
flag_ok=0;
posicao_escrita(0x8B);
escreve_lcd('2');
putchar(comando2,27);
while(flag_ok!=2);
flag_ok=0;
Delay_1ms(500);
posicao_escrita(0x8B);
escreve_lcd('3');
putchar(comando3,28);
while(flag_ok!=2);
flag_ok=0;
Delay_1ms(500);
posicao_escrita(0x8B);
escreve_lcd('4');
putchar(comando4,26);
while(flag_ok!=2);
flag_ok=0;
Delay_1ms(500);
posicao_escrita(0x8B);
127
escreve_lcd('5');
putchar(comando5,28);
while(flag_ok!=2);
flag_ok=0;
Delay_1ms(500);
posicao_escrita(0x8B);
escreve_lcd('6');
putchar(comando6,32);
while(flag_ok!=2);
flag_ok=0;
Delay_1ms(500);
posicao_escrita(0x8B);
escreve_lcd('7');
putchar(comando7,28);
while(flag_ok!=2);
flag_ok=0;
Delay_1ms(500);
posicao_escrita(0x8B);
escreve_lcd('8');
putchar(comando8,21);
while(flag_ok!=2);
flag_ok=0;
Delay_1ms(150);
posicao_escrita(0x8B);
escreve_lcd('9');
putchar(comando9,52);
while(flag_ok!=2);
128
flag_ok=0;
Delay_1ms(500);
posicao_escrita(0x8B);
escreve_lcd('1');
escreve_lcd('0');
putchar(comando10,13);
while(flag_ok!=2);
flag_ok=0;
Delay_1ms(5000);
posicao_escrita(0x8B);
escreve_lcd('1');
escreve_lcd('1');
limpa_display();
while(1)
{
if(opt==0x83) // ESQUERDA
{
IOCLR0=0x00000020; //direita
Delay_1ms(10);
IOSET0=0x00000080; //P0.7 esquerda
posicao_escrita(0x82);
escreve_lcd('1');
}
if(opt==0x86) // ESQUERDA + RE
{
IOCLR0=0x00000020; //direita
IOCLR0=0x00100000;//FRENTE
Delay_1ms(10);
IOSET0=0x00000080; //P0.7 esquerda
IOSET0=0x00040000; //P0.18 Re
posicao_escrita(0x82);
escreve_lcd('2');
}
129
if(opt==0x80) // ESQUERDA + FRENTE
{
IOCLR0=0x00000020; //direita
IOCLR0=0x00040000; //re
Delay_1ms(10);
IOSET0=0x00000080; //P0.7 esquerda
IOSET0=0x00100000; //P0.20 Frente
posicao_escrita(0x82);
escreve_lcd('3');
}
if(opt==0x85) // DIREITA
{
IOCLR0=0x00000080;//esquerda
Delay_1ms(10);
IOSET0=0x00000020; //P0.5 direita
posicao_escrita(0x82);
escreve_lcd('4');
}
if(opt==0x88) // DIREITA + RE
{
IOCLR0=0x00000080;//esquerda
IOCLR0=0x00100000; //FRENTE
Delay_1ms(10);
IOSET0=0x00000020; //P0.5 direita
IOSET0=0x00040000; //P0.18 Re
posicao_escrita(0x82);
escreve_lcd('5');
}
if(opt==0x82) // DIREITA + FRENTE
{
IOCLR0=0x00000080;//esquerda
IOCLR0=0x00040000; //re
Delay_1ms(10);
IOSET0=0x00000020; //P0.5 direita
IOSET0=0x00100000; //P0.20 Frente
posicao_escrita(0x82);
escreve_lcd('6');
130
}
if(opt==0x87) // RE
{
IOCLR0=0x00100000;//FRENTE
Delay_1ms(10);
IOSET0=0x00040000; //P0.18
Re
posicao_escrita(0x82);
escreve_lcd('7');
}
if(opt==0x81) // FRENTE
{
IOCLR0=0x00040000; //re
Delay_1ms(10);
IOSET0=0x00100000; //P0.20 Frente
posicao_escrita(0x82);
escreve_lcd('8');
}
if(opt==0x84) // PARAR
{
IOCLR0=0x00040000;
IOCLR0=0x00100000;
IOCLR0=0x00000080;
IOCLR0=0x00000020;
posicao_escrita(0x82);
escreve_lcd('A');
}
if(opt==0x8A)
{
putchar(comando15,15);
Delay_1ms(100);
send_byte(0xff);
send_byte(0xff);
Delay_1ms(50);
}
131
//------------------------------------------------------
if(opt==0x91) // Captura e Envia Frame
{
if(CAM_CONECTADA==0)
{
// Comunicação com a câmera
while(ACK==0)
{send_sync();}
ACK=0;
send_ack(0x0D,0x00,0x00);
escreve_lcd('2');
while(ACK==0)
{send_initial();}
ACK=0;
escreve_lcd('3');
Delay_1ms(50);
while(ACK==0)
{set_package_size();}
ACK=0;
escreve_lcd('4');
Delay_1ms(50);
CAM_CONECTADA=1; // sincroniza a camera na primeira chamada apenas.
}
rcb_image=0;
contagem=0;
n_pacotes=0;
pacote_recebido=0;
i2=0;
image_size=0;
132
while(rcb_image!=2)
{
send_getpicture();
Delay_1ms(1000);
}
rcb_image=1;
while(contagem!=(n_pacotes))
{
send_ack
(0x00,contagem,0x00);
while
(pacote_recebido!=1); //espera receber o quadro
for
(i=4;i<=(data_lenght+3);i++)
{
imagem[i2]=pacote[i];
i2++;
}
pacote_recebido=0;
}
send_ack
(0x00,0xF0,0xF0); // último ack
Delay_1ms(200);
escreve_lcd_hex(data_lenght);
escreve_lcd('O');
escreve_lcd('k');
escreve_lcd_hex(i2/0x100);
escreve_lcd_hex(i2%0x100);
//--------------------------------------------ENVIA QUADRO PARA O SERVIDOR
putchar(comando11,15);
133
Delay_1ms(100);
send_byte(i2%0x100);
send_byte(i2/0x100);
Delay_1ms(50);
putchar(comando12,18);
Delay_1ms(100);
for(i=0;i<1400;i++)
{
send_byte(imagem[i]);
}
while(flag_ok!=2);
flag_ok=0;
Delay_1ms(200);
SUBT=i2-1400;
putchar(comando13,10);
send_byte((SUBT/100)+0x30);
send_byte(((SUBT%100)/10)+0x30);
send_byte((SUBT%10)+0x30);
putchar(comando14,4);
Delay_1ms(100);
for(i=1400;i<i2;i++)
{
send_byte(imagem[i]);
}
}
//---------------------------- FIM DO ALGORITMO DA CÂMERA
opt=0x69;
posicao_escrita(0x80);
134
} // fim do while(1);
} // fim da funcao Main
//-----------------------------------------------------------
// ------------- Rotina da interrupção de recepção da UART1
void __irq inter(void)
{
unsigned char comando1[16]={"AT^SISR=1,20\r\n"};
buf=U1RBR;
if(buf =='O')
{
flag_ok=1;
}
if(flag_ok==1 && buf =='K')
{
flag_ok=2;
}
//-------------------------------------
if(flag_sisr == 6)
{
if(buf>=0x80)
{opt=buf;}
if(flag_ok==2)
{
flag_ok=0;
flag_sisr=0;
}
}
135
else
{
if(buf =='^')
{flag_sisr=1;}
if(flag_sisr==1 && buf =='S')
{flag_sisr=2;}
if(flag_sisr==2 && buf =='I')
{flag_sisr=3;}
if(flag_sisr==3 && buf =='S')
{flag_sisr=4;}
if(flag_sisr==4 && buf =='R')
{flag_sisr=5;}
if(flag_sisr == 5)
{
Delay_1ms(100);
putchar
(comando1,16);
flag_sisr=6;
}
}
//----------------------------------------------------
U1FCR=0x07; // limpa buffers de transmissão e recepção
U1IER=0x01;
VICVectAddr= 0;
}
// ------------- Rotina da interrupção de recepção da UART0
void __irq inter_UART0(void)
136
{
if(rcb_image==1)
{
pacote[iglobal]=U0RBR;
if(iglobal==2)
{data_lenght=pacote[2];}
if(iglobal>=data_lenght+5)
{
iglobal=0;
pacote_recebido=1;
contagem++;
}
else
{
iglobal++;
}
}
//----------------------------------------------
else
{
comando[iglobal]=U0RBR;
if(iglobal<5)
{iglobal++;}
else
{iglobal=0;}
if(iglobal==0)
{
if(comando[0]==0xAA && comando[1]==0x0E)
{ACK=1;}
if(comando[0]==0xAA && comando[1]==0x0A)
{
posicao_escrita(0x82);
137
escreve_lcd('D');
ACK=1;
escreve_lcd_hex(comando[5]);
escreve_lcd_hex(comando[4]);
escreve_lcd_hex(comando[3]);
image_size=comando[3]+comando[4]*0x100+comando[5]*0x10000;
n_pacotes=image_size/58;
if(image_size%58!=0)
{n_pacotes++;}
rcb_image=2;
posicao_escrita(0xC0);
escreve_lcd_hex(n_pacotes);
iglobal=0;
}
if(comando[1]==0x0F)
{escreve_lcd('N'); }
}
} // fim do else
U0FCR=0x07; // limpa buffers de transmissão e recepção
U0IER=0x01;
VICVectAddr= 0;
}
138
ANEXO C- Código fonte, computador e a câmera via RS232. //---------------------------------------------------------------------------
#include <vcl.h>
#include <jpeg.hpp>
#include <stdio.h>
#pragma hdrstop
#include "Main.h"
#include "serial.h"
#include "camera.h"
#include "debug.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
TIPO_SERIAL TS ;
bool f_serial_opened = false ;
void ReceiveFunction(BYTE c,WORD id) ;
void ErrorFunction(char *txt) ;
void RefreshDebug(void) ;
void ClearDebug(void) ;
void DrawBitmap(TCanvas *Canvas,unsigned char *buffer) ;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ButtonOpenClick(TObject *Sender)
{
if (!f_serial_opened)
{
TS.hwnd = Application->Handle ;
TS.com = StrToInt(ComPort->Text) ;
TS.RecebeByte = ReceiveFunction ;
139
TS.Error = ErrorFunction ;
TS.ByteEvento = '\n' ;
TS.BaudRate = CBR_115200 ;
TS.ID = 0 ;
if (IniciaSerial(&TS))
{
f_serial_opened = true ;
ButtonOpen->Caption = "Close" ;
ComPort->Enabled = false ;
Timer1->Enabled = true ;
}
}
else
{
TerminaSerial(&TS) ;
f_serial_opened = false ;
ComPort->Enabled = true ;
ButtonOpen->Caption = "Open" ;
Timer1->Enabled = false ;
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ButtonSyncClick(TObject *Sender)
{
int i ;
if (f_serial_opened)
{
for (i=0;i<60;i++)
{
if (cam_state != CAM_SYNC_RECEIVED)
{
camera_sync();
Sleep(10) ;
}
else
break ;
}
camera_sync();
}
140
}
//---------------------------------------------------------------------------
/****************************************
* *
****************************************/
void ReceiveFunction(BYTE c,WORD id)
{
camera_rx(c) ;
if (Form1->CheckBoxDebug->Checked)
{
debuglock() ;
debug(c,cam_state) ;
debugunlock() ;
}
}
/****************************************
* *
****************************************/
void ErrorFunction(char *txt)
{
Application->MessageBox(txt,"Error",MB_OK) ;
}
void __fastcall TForm1::ButtonInitClick(TObject *Sender)
{
unsigned char resolution ;
// Color, Preview Resolution, JPEG Resolution
//
// Picture Resolution :
// 0x01 -> 80x60 or 80x64 (compressed)
// 0x03 -> 160x120 or 160x128 (compressed)
// 0x05 -> 320x240
// 0x07 -> 640x480
//
// Color Type :
// 0x06 -> 16-bit Color
// 0x07 -> JPEG Color
//
141
cam_compressed = CheckBoxCompressed->Checked ? 1:0 ;
switch(RadioGroupResolution->ItemIndex)
{
case 0 : resolution = 0x01 ; break ;
case 1 : resolution = 0x03 ; break ;
case 2 : resolution = 0x05 ; break ;
case 3 : resolution = 0x07 ; break ;
default : resolution = 0x01 ; break ;
}
camera_init(
cam_compressed?0x07:0x06, // color type
resolution, // raw resolution
resolution // jpeg resolution
) ;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ButtonImageClick(TObject *Sender)
{
// Gets a Picture (from camera to host)
// Picture Type :
// 0x01 -> snapshot
// 0x02 -> preview picture
// 0x05 -> jpeg preview picture
//
camera_get_picture(
0x01 // Picture Type
) ;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ButtonSizeClick(TObject *Sender)
{
camera_package_size(512) ;
}
142
//---------------------------------------------------------------------------
void __fastcall TForm1::ButtonSnapshotClick(TObject *Sender)
{
// Image Capture
// (the camera keeps a single frame of still image after this command)
camera_snapshot(
cam_compressed?0x00:0x01, // 0x00=compressed, 0x01=uncompressed
0x0000 // skip counter (0x0000 is default)
) ;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ButtonResetClick(TObject *Sender)
{
camera_reset(0x00,1) ;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
debug_setup() ;
camera_setup() ;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ButtonRefreshClick(TObject *Sender)
{
unsigned long int size ;
unsigned char * buffer ;
camera_get_buffer(&buffer,&size) ;
switch(cam_compressed)
{
case 0 : // uncompressed image (raw image bitmap)
DrawBitmap(Image1,buffer,size) ;
break ;
143
case 1 : // compressed image (JPEG)
DrawJPEG(Image1,buffer,size) ;
break ;
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
StatusBar1->SimpleText = camera_state_string() ;
if (Form1->CheckBoxDebug->Checked)
{
debuglock() ;
RefreshDebug() ;
debugunlock() ;
}
Beep(440,10) ;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ButtonBaudClick(TObject *Sender)
{
camera_baudrate(CAM_BAUD_115200) ;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ButtonClearDebugClick(TObject *Sender)
{
ClearDebug() ;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
camera_terminate() ;
debug_terminate() ;
144
}
//---------------------------------------------------------------------------
void RefreshDebug(void)
{
unsigned long int i ;
unsigned int col = 0 ;
static unsigned long int last_idt ;
AnsiString str = "" ;
if (idt != last_idt)
last_idt = idt ;
else
return ;
for (i=0;i<idt;i++)
{
str += IntToHex(dt[i].c,2) + " ";
switch(dt[i].s)
{
case CAM_ACK_RECEIVED :
case CAM_NACK_RECEIVED :
case CAM_SYNC_RECEIVED :
case CAM_IMAGE_RECEIVED :
if ( (i>1) && (dt[i].s != dt[i-1].s) )
str += "\r" ;
break ;
case CAM_STATE_WAIT_DATA :
col++ ;
if (col == 64)
{
col = 0 ;
str += "\r" ;
}
break ;
}
}
Form1->Debug->Caption = str ;
}
//---------------------------------------------------------------------------
145
void ClearDebug(void)
{
debuglock() ;
idt = 0 ;
debugunlock() ;
}
void TForm1::DrawBitmap(TImage *pimage,unsigned char *buffer,unsigned long size)
{
Graphics::TBitmap *bmp = new Graphics::TBitmap() ;
unsigned int x,y ;
unsigned long int pos ;
unsigned short int color ;
unsigned unsigned short int *ptr ;
bmp->Width = cam_width ;
bmp->Height = cam_height ;
bmp->PixelFormat = pf16bit ;
for (y=0;y<bmp->Height;y++)
{
ptr = (unsigned short int *) (bmp->ScanLine[y]) ;
for (x=0;x<bmp->Width;x++)
{
pos = (x + y * bmp->Width)*2 ;
color = (buffer[pos]<<8) | buffer[pos+1] ;
ptr[x] = color ;
}
}
try
{
pimage->Canvas->StretchDraw(Rect(0,0,pimage->Width,pimage->Height),bmp);
}
catch(...)
{
ShowMessage("Unable to load raw image");
}
delete bmp ;
}
146
void TForm1::DrawJPEG(TImage *pimage,unsigned char *buffer,unsigned long size)
{
TJPEGImage *jpg = new TJPEGImage();
TMemoryStream *ms = new TMemoryStream ;
ms->Clear() ;
ms->SetSize((int)size);
ms->WriteBuffer(buffer,size) ;
ms->Seek(soFromBeginning ,0);
try
{
/* jpg->LoadFromFile("image.jpg"); */
jpg->LoadFromStream(ms) ;
pimage->Canvas->StretchDraw(Rect(0,0,pimage->Width,pimage->Height),jpg);
}
catch(...)
{
ShowMessage("Unable to load JPEG image");
}
delete ms ;
delete jpg;}