UNIVERSIDADE FEDERAL DE GOIÁS ESCOLA DAS ENGENHARIAS MECÂNICA ELÉTRICA E DE COMPUTAÇÃO Marcelo Pereira Barros Murillo de Lima Inomata MÓDULO DE COMUNICAÇÃO BLUETOOTH UTILIZANDO O MICROCONTROLADOR 8051 PARA MANIPULAR UM GUINCHO Goiânia 2013 Marcelo Pereira Barros Murillo de Lima Inomata MÓDULO DE COMUNICAÇÃO BLUETOOTH UTILIZANDO O MICROCONTROLADOR 8051 PARA MANIPULAR UM GUINCHO Trabalho de Conclusão de Curso apresentado à Coordenadoria do Curso de Engenharia de Computação da Universidade Federal de Goiás para a obtenção do título de Engenheiro de Computação. Orientador: Prof. Dr. José Wilson Lima Nerys Goiânia 2013 Marcelo Pereira Barros Murillo de Lima Inomata MÓDULO DE COMUNICAÇÃO BLUETOOTH UTILIZANDO O MICROCONTROLADOR 8051 PARA MANIPULAR UM GUINCHO Trabalho de Conclusão de Curso apresentado à Coordenadoria do Curso de Engenharia de Computação da Universidade Federal de Goiás para a obtenção do título de Engenheiro de Computação. Aprovado em __/__/____ BANCA EXAMINADORA Prof. Dr. José Wilson Lima Nerys Prof. Dr. Marcelo Stehling de Castro Ms. Gustavo Souto de Sá e Souza 1 RESUMO O presente trabalho visa desenvolver um manipulador robótico de baixo custo, fazendo uso do microcontrolador 8051 que é o núcleo de toda a família MSC51. O sistema baseado em microcontrolador deverá receber sinais de um dispositivo móvel através do protocolo de comunicação Bluetooth, e realizar os movimentos solicitados pelo usuário que está controlando o guindaste. A interface deverá ser simples e intuitiva, e os sensores de posição deverão ter um controle rígido de posição. Palavras-chaves: Microcontrolador, guindaste, 8051, Bluetooth, braço mecânico, dispositivos móveis, motores de passo. 2 ABSTRACT This work aims to develop a low-cost robotic manipulator, using the 8051 microcontroller which is the core of the whole family MSC-51. The microcontroller based system will receive signals from a mobile device via Bluetooth communication protocol, and perform the movements required by the user who is controlling the crane. The interface should be simple and intuitive, and the position sensors should have tight control of the crane position. Keywords: Microcontroller, crane, 8051, Bluetooth, mechanical arm, mobile devices, stepper motors. 3 AGRADECIMENTOS Agradeço, acima de tudo, a Deus, que me deu a vida e a força. Aos meus filhos, por serem minha inspiração, e a minha esposa, por todo apoio. Mas em especial agradeço aos meus pais, por tudo, e dedico a eles essa conquista. Marcelo Pereira Barros Agradeço primeiramente a Deus que sempre me deu forças para alcançar vitórias, a minha família pelo apoio e aos meus companheiros de curso que me motivaram Agradeço a todos os professores e servidores da UFG pela paciência e competência no exercício de suas atividades. Murillo de Lima Inomata "É preciso que o discípulo da sabedoria tenha o coração grande e corajoso. O fardo é pesado e a viagem longa." Confúncio "O grau mais elevado da sabedoria humana é saber adaptar o seu caráter às circunstâncias e ficar interiormente calmo apesar das tempestades exteriores." Daniel Defoe SUMÁRIO 1 RESUMO .............................................................................................................. 4 2 ABSTRACT........................................................................................................... 5 3 AGRADECIMENTOS ............................................................................................ 6 4 Índice de Figuras ................................................................................................ 12 5 Índice de Tabelas ............................................................................................... 14 6 Símbolos e Siglas ............................................................................................... 15 7 CAPÍTULO 1 - INTRODUÇÃO............................................................................ 16 8 7.1 Descrição da Parte Física do Guincho ......................................................... 17 7.2 Fluxo de Desenvolvimento do Projeto .......................................................... 19 Capítulo 2 - Microcontroladores .......................................................................... 20 8.1 9 Aplicações de Microcontroladores ............................................................... 21 CAPÍTULO 3 – A FAMÍLIA MCS-51 ................................................................... 22 9.1 Introdução Histórica ..................................................................................... 22 9.2 Por que usar o 8051 ..................................................................................... 22 9.3 Principais Características Comuns da família 8051 ..................................... 23 9.4 Arquitetura Interna 8051............................................................................... 24 9.5 Configuração e descrição dos pinos do 8051 .............................................. 25 9.6 ORGANIZAÇÃO DA MEMÓRIA ................................................................... 28 9.6.1 Memória RAM Interna ............................................................................ 28 9.6.2 Memória RAM Externa .......................................................................... 29 9.7 REGISTRADORES DE FUNÇÕES ESPECIAIS .......................................... 29 9.8 CONJUNTO DE INSTRUÇÕES ................................................................... 31 10 CAPÍTULO 3 – BLUETOOTH .......................................................................... 32 10.1 11 Processo de estabelecimento de conexões .............................................. 34 DISPOSITIVOS UTILIZADOS ......................................................................... 36 11.1 AT89C52 ................................................................................................... 36 11.1.1 11.2 Memória de Dados ............................................................................. 37 MOTOR DE PASSO ................................................................................. 39 11.2.1 Definição ............................................................................................ 39 11.2.2 Parâmetros dos motores de passo: .................................................... 40 11.2.3 Ponte H .............................................................................................. 41 11.3 Módulo Bluetooth RS232 TTL ................................................................... 43 11.4 Conversor A/D (ADC0804)........................................................................ 44 11.4.1 Características: .................................................................................. 45 11.4.2 Funcionamento: .................................................................................. 46 11.4.3 Converter a entrada analógica e ler a saída do ADC0804. ................ 47 11.5 ULN2803 ................................................................................................... 48 11.6 Potenciômetro ........................................................................................... 49 11.7 L298N ....................................................................................................... 50 12 FERRAMENTAS E DISPOSITIVOS UTILIZADOS .......................................... 53 12.1 Proteus...................................................................................................... 53 12.2 PEQui........................................................................................................ 54 12.2.1 Funcionamento: .................................................................................. 54 12.3 ChipMax2 .................................................................................................. 55 12.4 MaxLoader ................................................................................................ 56 12.5 Eclipse e Android SDK .............................................................................. 57 13 RESULTADOS OBTIDOS ............................................................................... 58 13.1 Esquemático do circuito eletrônico ........................................................... 58 13.2 Placa de Circuito Impresso ....................................................................... 60 13.3 Processo de confecção da placa .............................................................. 61 13.4 Comunicação com os Dispositivos Bluetooth ........................................... 64 14 CONCLUSÃO E TRABALHOS FUTUROS...................................................... 67 15 BIBLIOGRAFIA................................................................................................ 69 16 APÊNDICE A – CÓDIGO EM ASSEMBLY DO PROGRAMA DO MICROCONTROLADOR........................................................................................... 74 17 APÊNDICE B – CÓDIGO EM JAVA DO PROGRAMA ANDROID/BLUETOOTH 79 4 Índice de Figuras Figura 1 - Etapas de funcionamento do projeto......................................................... 16 Figura 2 - Descrição e funcionamento do guincho .................................................... 18 Figura 3 - Conexão das engrenagens do guincho..................................................... 18 Figura 4 - Fluxo de desenvolvimento do projeto........................................................ 19 Figura 5 - Arquitetura típica de um microcontrolador ................................................ 20 Figura 6 - Características Especiais da Família MCS-51 .......................................... 24 Figura 7 - Arquitetura Interna do 8051 ...................................................................... 25 Figura 8 - Pinagem do 8051 ...................................................................................... 26 Figura 9 - Memória RAM do 8051. ............................................................................ 29 Figura 10 - Duas piconets formando uma scatternet, com um dispositivo escravo em comum. ..................................................................................................................... 33 Figura 11 - Conjunto de estados dos dispositivos Bluetooth. .................................... 35 Figura 12 - Mapa dos SRF e seus valores de Reset ................................................. 38 Figura 13 - Ponte H chaveada................................................................................... 42 Figura 14 - ponte H automatizada. ............................................................................ 42 Figura 15 - Pinos usados do módulo Bluetooth. ........................................................ 44 Figura 16 - Cálculo de resolução do ADC. ................................................................ 45 Figura 17 - Interface do ADC 0804 com o 8051. ....................................................... 47 Figura 18 - CI ULN2803. ........................................................................................... 48 Figura 19 - Partes de um potenciômetro linear. ........................................................ 49 Figura 20 - Relação entre giro do cursor e as resistências. ...................................... 50 Figura 21 - Pinagem do L298N. ................................................................................ 51 Figura 22 - Ligação do L298N com motor de passo bipolar. ..................................... 52 Figura 23 - Ambientes ISIS (esquerda) e ARES (direita). ......................................... 54 Figura 24 - Ambiente do PEQui................................................................................. 55 Figura 25 - Dispositivo de gravação de chips ChipMax2. .......................................... 56 Figura 26 - Ambiente do MaxLoader. ........................................................................ 56 Figura 27 - Esquemático básico do guincho.............................................................. 58 Figura 28 - PCI do 8052. ........................................................................................... 62 Figura 29 - PCI da ponte H com L298N. ................................................................... 63 Figura 30 - PCI de ativação do eletroímã. ................................................................. 63 Figura 31 - Circuito eletrônico completo. ................................................................... 63 Figura 32 - Interface do dispositivo Bluetooth. .......................................................... 64 Figura 33 - Controle dos motores. ............................................................................. 65 Figura 34 - Tela de Configuração .............................................................................. 66 5 Índice de Tabelas Tabela 1 - Principais modelos da família MCS-51 com especificação de ROM, RAM e T/C. ........................................................................................................................ 22 Tabela 2 - Descrição e funcionamento da pinagem do 8051 .................................... 26 Tabela 3 - Função básica dos SFRs. ........................................................................ 30 Tabela 4 - Classificação dos dispositivos Bluetooth. ................................................. 34 Tabela 5 - Descrição da Pinagem do ADC0804 ........................................................ 45 6 Símbolos e Siglas ADT: Android Development Tools AFH: Adaptive Frequency Hopping API: Application Programming Interface CISC: Complex Instruction Set Computer CLP: Controlador lógico programável CMOS: Complementary metal-oxide-semiconductor CPU: Central Processing Unit DC: Direct Current EPROM: Erasable Programmable Read-Only Memory FCE: Força contra-eletromotriz GFSK: Gaussian Frequency-Shift Keying IDE: Integrated development environment ISM: Industrial, Scientific and Medicine LED: Light-emitting diode PAN: Personal Area Networks PC: Personal Computer PCI: Placa de Circuito Impresso PHP: Hypertext Preprocessor RAM: Random Access Memory ROM: Read Only Memory SDK: Software Development Kit SIG: Special Interest Group SWT: Standard Widget Toolkit TTL: Transistor–Transistor Logic USB: Universal Serial Bus ULA: Unidade lógica e aritmética 7 CAPÍTULO 1 - INTRODUÇÃO Os microcontroladores estão presentes no cotidiano da população, conquistando cada vez mais espaço em diversas aplicações e ganhando cada vez mais espaço no mercado. Nos sistemas eletrônicos, eles são responsáveis pela diminuição das dimensões dos equipamentos, gerenciam e controlam as tarefas internas, facilitam a manutenção, tornam alguns sistemas mais baratos e robustos, além de otimizar e automatizar tarefas, facilitando a vida moderna. Em questão de investimentos o microcontrolador fornece um excelente custobenefício, sendo um componente versátil que se adéqua a vários tipos de aplicações diferentes, geralmente voltados para propósitos específicos. Por possuir a maioria dos componentes necessários para o desenvolvimento de um sistema em um único chip, torna muito mais viável sua utilização em vários projetos, deixando o sistema mais simples, barato e reduzido. Cada vez mais os sistemas microcontrolados ganham mais destaque e importância, sendo de suma importância em sistemas de automação e controle. Neste contexto, propomos o desenvolvimento de um sistema microcontrolado que manipule e controle um guincho. Este sistema microcontrolado deverá implementar um sistema de comunicação móvel baseado na tecnologia Bluetooth, para que dispositivos móveis que possuam comunicação Bluetooth, enviem sinais de controle para o sistema microcontrolado com o intuito de manipular um guincho. A figura 1 resume as etapas de funcionamento do nosso projeto. Figura 1 - Etapas de funcionamento do projeto. 16 Como podemos observar o projeto é composto pelas seguintes etapas: 1. Um dispositivo que possua capacidade de comunicação wireless utilizando o protocolo Bluetooth, envia o sinal de controle para o módulo transceptor Bluetooth. 2. O módulo Bluetooth envia os sinais recebidos do dispositivo móvel para o microcontrolador AT89C52. 3. O microcontrolador recebe o sinal do módulo Bluetooth e envia o sinal para o L298N que irá movimentar o motor que passo para realizar os movimentos do guincho. O motor de passo está acoplado ao guincho por engrenagens poderá movimentar o guincho na direção horizontal (horário e anti-horário) e vertical (para cima e para baixo). O microcontrolador poderá também ligar o eletroímã se for solicitado. 4. Os movimentos do braço do guincho irão mover o cursor do potenciômetro, variando a resistência entre suas extremidades e a derivação central. 5. O ADC0804 vai converter os dados de analógico para digital, devido a variação da resistência dos potenciômetros (sensores). 6. O sinal convertido para digital será enviado pelo módulo transceptor Bluetooth para o dispositivo móvel, informando os movimentos e a posição atual do braço do guincho. 7.1 Descrição da Parte Física do Guincho O guincho utilizado no nosso projeto consiste em um braço mecânico que realiza movimentos horizontais e verticais. Tal braço possui seu eixo central fixo, um motor de passo que controla o movimento horizontal e outro motor de passo responsável pelo controle vertical. Foi adicionado um fim de curso no eixo vertical para controlar a altura máxima do guincho. Na extremidade do guincho está presente um eletroímã que quando energizado passa a produzir os mesmos efeitos magnéticos de um ímã, com pólo norte e sul definidos, podendo então atrair materiais ferromagnéticos. 17 Foram instalados dois potenciômetros lineares, sendo um para cada motor de passo unipolar utilizado, com o intuito de controlar fielmente seus movimentos. O microcontrolador da família MCS-51 utilizado, irá receber sinais de controle através de um dispositivo móvel e irá movimentar o potenciômetro, que está acoplado ao motor de passo através de engrenagens. A figura 2 descreve os componentes e o funcionamento do guincho, e a figura 3 mostra a conexão das engrenagens do guincho. Figura 2 - Descrição e funcionamento do guincho Figura 3 - Conexão das engrenagens do guincho 18 7.2 Fluxo de Desenvolvimento do Projeto Após um estudo sobre a viabilidade do projeto, elaboramos um fluxo de desenvolvimento a ser seguido, onde cada etapa posterior é dependende das anteriores. Figura 4 - Fluxo de desenvolvimento do projeto 19 8 Capítulo 2 - Microcontroladores Um microcontrolador corresponde a um sistema computacional completo alocado em um chip. Possui como componentes principais a Unidade Cental de Processamento (CPU – Central Processor Unit), memória de dados (memória RAM) e de programa (ROM/PROM/EPROM), linhas de entrada e saída. É composto também por outros periféricos, que podem ou não ser utilizados dependendo da aplicação, tais como, módulos de temporização, conversores A/D e D/A, osciladores, codificadores, portas serial e paralela, modulação de largura de pulso, entre outros. A Figura 5 representa a arquitetura típica de um microcontrolador, em que todos os componentes estão alocados em um único chip. Figura 5 - Arquitetura típica de um microcontrolador 20 8.1 Aplicações de Microcontroladores É bastante vasta a aplicação dos microcontroladores no mundo atualmente, ele está presente nos mais diversos dispositivos eletro-eletrônicos. Na indústria está presente em CLPs, equipamentos de medição, controle de processos, esteira de chão de fábrica. Nos automóveis estão presentes nos alarmes contra roubo, GPS, computadores de bordo, injeção eletrônica, etc. Nas residências, estão presentes nos fornos microondas, nas máquinas de lavar, portão eletrônico, porta retrato digital, brinquedos, eletrônicos, etc. No cotidiano está presente em elevadores, alarmes de incêndio, caixas eletrônicos, leitores de código de barras, chaveiro localizador, celulares, sensores, câmeras de segurança, etc. 21 9 CAPÍTULO 3 – A FAMÍLIA MCS-51 9.1 Introdução Histórica A família MSC-51 teve sua origem a partir da MCS-48 (lançada pela INTEL em 1976), que foi a primeira família de controladores lançada pela INTEL. Por não ser tão limitada quanto seu antecessor e nem tão cara como é a MCS-96, é praticamente a família de controladores mais usada e popular atualmente. Atualmente diversos fabricantes produzem o 8051, tais como AMD, Atmel, Dallas, OKI, Matra, Philips, Siemens, entre outros. Tem como membro original o microcontrolador 8051, que também é o núcleo para toda a MCS-51. Seus principais modelos são: Tabela 1 - Principais modelos da família MCS-51 com especificação de ROM, RAM e T/C. Modelo ROM RAM Temporizadores/ Contadores 8031 sem ROM (ROMLESS) 128 bytes de RAM 2 T/C 8051 com 4KB de ROM 128 bytes de RAM 2 T/C 8751 com 4KB de EPROM 128 bytes de RAM 2 T/C 8032 sem ROM (ROMLESS) 256 bytes de RAM 3 T/C 8052 com 8KB de ROM 256 bytes de RAM 3 T/C 8752 com 8KB de EPROM 256 bytes de RAM 3 T/C 9.2 Por que usar o 8051 Optamos pelo uso do 8051 devido às seguintes vantagens: Por ser um microcontrolador de baixo custo e de alto nível de integração, podendo assim montar um sistema completo funcional fazendo uso de poucos componentes. 22 É o microcontrolador mais popular atualmente, oferecendo um amplo suporte e de fácil aquisição. Oferece um amplo conjunto de instruções por ser um microcontrolador CISC (Computador com um Conjunto Complexo de Instruções), sendo muito utilizado em inúmeras aplicações desde um simples programa que faz piscar um LED, até programas mais complexos, como um controlador robótico manipulado via Bluetooth. Bastante usado no meio acadêmico, pois proporciona economia real em termos de custo de ferramentas, treinamento além de possuir softwares livres que compilam e simulam o funcionamento do circuito. É rápido e eficaz, pois a sua arquitetura se correlaciona de perto com o sistemas de controle, e menos bytes precisam ser buscados e menos jumps condicionais são processados, por suas instruções serem especializadas. Possui aperfeiçoamentos constantes, como aumento da velocidade e melhorias na manufatura, sendo produzido por diversos fabricantes, e possui centenas de variedades, que são compatíveis por possuírem o mesmo núcleo de arquitetura. 9.3 Principais Características Comuns da família 8051 CPU de 8 bits 128 bytes de RAM interna 4 portas bidirecionais de I/O de 8 bits cada (P0, P1, P2 E P3), com bits individualmente endereçáveis. Memória de dados externa e memória de programa externa com capacidade de até 64KB cada. 23 Frequência de clock de 1 até 12MHz. 2 temporizadores /contadores de 16 bits 1 canal de comunicação serial 5 fontes de interrupção, com dois níveis de prioridade selecionáveis por software. Das 5 fontes de interrupção, duas são timers, duas externas e mais o canal de comunicação serial. Oscilador de clock interno Arquitetura CISC, que permite executar operações aritméticas e lógicas mais complexas. Os diversos fabricantes do 8051, adicionam algumas características especiais, além das características comuns à todos modelos do 8051, de acordo com a aplicação e o mercado que se destinam. As características especiais da família 8051 que podem ser adicionadas estão especificadas na figura 6. Figura 6 - Características Especiais da Família MCS-51 9.4 Arquitetura Interna 8051 O microcontrolador da família MCS-51 possui todos os componentes relevantes para se obter um sistema em um único chip, como podemos observar 24 pela figura 7. A CPU de 8 bits controla as memórias, as portas bidirecionais, a parta serial, os contadores/temporizadores, interrupções e barramentos. O oscilador é responsável por gerar o clock que define a frequencia de funcionamento do microcontrolador, já o controle de interrupção auxilia a CPU quando for gerada uma interrupção externa, ou do canal serial, ou dos contadores/temporizadores. Figura 7 - Arquitetura Interna do 8051 9.5 Configuração e descrição dos pinos do 8051 A figura 8 demonstra a localização dos pinos do microcontrolador baseado na família MCS-51, ela relaciona o nome do pino com a sua real localização nos pinos do 8051. Já a tabela 2, descreve o funcionamento dos pinos típicos de qualquer chip baseado no 8051. 25 Figura 8 - Pinagem do 8051 Tabela 2 - Descrição e funcionamento da pinagem do 8051 Nome do Pino Numeração Descrição / Funcionamento Porta P0 (P0.0 a P0.7) 39 a 32 A porta P0 corresponde a uma porta bidirecional de entrada e saída de 8 bits de dreno aberto. Se escrever o nível lógico 1 nas em qualquer pino da porta P0, eles flutuam, podendo assim esses estados serem usados como entradas de alta impedância. Fornece multiplexada a parte menos significativa do barramento de endereço (A0 a A7) e do barramento de dados (D0 a D7) durante o acesso a uma memória de programa ou de dados externa. Portanto se estiver sendo usada como um barramento de endereços, a porta P0 não poderá ser usada como uma porta bidirecional de entrada e saída. Porta P1 (P1.0 a P1.7) 1a8 A porta P1 corresponde a uma porta bidirecional de 8 bits para entra e saída co pull-ups internos. O resistor de pull-up fornece uma corrente de entrada em nível baixo se aplicar um nível lógico zero. Se colocarmos a porta P1 para funcionar como entrada, os seus pinos são externamente elevados para o nível lógico zero, que acaba fornecendo corrente devido aos pull-upss internos dos pinos. Porta P2 (P2.0 a P2.7) 21 a 28 A porta P2 corresponde a uma porta bidirecional de 8 bits para entra e saída co pull-ups internos. Pode ser usada como saída ou como parte mais significativa do endereço que é necessário quando se deseja acessar a memória externa. Recebe o byte mais significativo do endereço durante a verificação da ROM e da EPROM e durante a programação da EPROM. 26 Porta P3 (P3.0 a P3.7) 10 a 17 A porta P3 também pode ser usada como uma porta bidirecional de entrada e saída de 8 bits. Porém, se o Latch da porta P3 estiver em nível lógico um, a sua saída será controlada pelo sinal de Função de Saída Alternativa. Assim a pinagem da porta P3 passa a ter as seguintes funções especiais: P3.0: Entrada Serial P3.1: Saída Serial P3.2: Interrupção 0 P3.3: Interrupção 1 P3.4: Contador 0 P3.5: Contador 1 P3.6: Sinal de Escrita P3.7: Sinal de Leitura Fonte de alimentação Vcc 40 Entrada do positivo da fonte de alimentação Terra - Vss 20 Entrada do Terra (GND) Reset 9 Pino de entrada do Reset do circuito. Enquanto o oscilador interno estiver sendo executado, se mantivermos o nível lógico um no pino de reset por 2 ciclos de máquina, ele inicializa alguns registradores internos com os valores predefinidos de fábrica, resetando o dispositivo. Adress Latch Enable 30 Responsável por controlar a demultiplexação de dados ou endereço da Porta P0. Indica a um dispositivo externo quando ele deve capturar o sinal de endereço e os dados que devem ser multiplexados no tempo. Pode ser utilizado para fins de clock ou de temporizador externo. Program Store Enable 29 Sinal de leitura para a memória de programa externa. XTAL1 e XTAL2 18 e 19. Conexão do cristal para funcionamento do oscilador de clock interno. External Access Enable 31 Se ligado ao terra, habilita a busca na memória de programa externa (0000h a FFFFh). Se estiver no nível lógico alto, executa apenas os primeiros 4K na memória ROM interna. 27 9.6 ORGANIZAÇÃO DA MEMÓRIA O 8051 não segue a arquitetura de Von Newmann em que a memória de dados e de programa podem ser armazenadas no mesmo espaço de memória, ele adota o modelo de arquitetura de Harward podendo assim ter dados e programas alocados em memórias distintas. As memórias de dados e de programa, que são denominadas memórias externas, podem conter até 64KB cada. A utilização ou não dos 4KB da ROM interna do microcontrolador vai ser definida pelo nivel lógico do pino EA (External Access Enable). Se EA=0, então os 64KB de memória serão a de programa externa. Se EA=1, então teremos 4KB de ROM interna mais 64KB de memória de programa externa. Para acessar a memória de programa externa, são emitidos endereços de 16 bits (0h – Fh), sacrificando então as porta P0 e P2 quando se deseja fazer uso da memória de programa externa. 9.6.1 Memória RAM Interna O 8051 fornece uma memória de dados interna com um mínimo de 128 bytes, com isso para muitas aplicações que não necessitam de grande quantidade de memória, não há a necessidade de fazer uso da RAM externa. De acordo com a figura 8, a memória interna é dividida em três blocos fisicamente distintos, sendo dois deles blocos de RAM de 128 bytes cada, mapeados nos endereços 00H-7FH e 80H-FFH, também tem os registradores de funções especiais, que estão endereçados na faixa de 80H-FFH. O modo de endereçamento acessa de maneira distinta o bloco superior e o de registradores de funções especiais, que possuem o mesmo endereço. 28 Figura 9 - Memória RAM do 8051. 9.6.2 Memória RAM Externa Conforme explicado anteriormente, a memória de dados externa pode ocupar até 64KB. Porém, como a faixa de endereço da memória de programa e da memória de dados interna, que corresponde de 00h – FFh, é a mesma, há conflitos no endereçamento. Tal conflito pode ser resolvido de duas maneiras. Um corresponde a ativação ou não do sinal PSEN (Program Store Enable), responsável pela leitura na memória de programa. O hardware utiliza esse sinal para habilitar o banco de memória correspondente. A outra forma corresponde à utilização das instruções MOV e MOVX, sendo que a MOV é utilizada para acessar a memória de interna, e a MOVX para acessas a memória externa. 9.7 REGISTRADORES DE FUNÇÕES ESPECIAIS Os Registros de Função Especial (SFRs - Special Function Registers) são de suma importância no do controle do 8051. Os registradores podem ser endereçados 29 a byte através do endereço correspondente (exemplo: MOV P0, #2FH), ou através do nome (exemplo: MOV DPL, DPH). Está descrito na tabela 3, os registradores especiais com seu endereço na RAM ao lado, e a descrição de sua função básica. Tabela 3 - Função básica dos SFRs. Registrador de Função Especial Função básica P0 (80H), P1 (90H), P2 Corresponde aos endereços na RAM que contém os (A0H) e P3 (B0) dados das 4 portas de I/O do micro, caso as mesmas sejam utilizadas com essa finalidade. Ao realizar uma escrita em um desses registros, o conteúdo presente na saída do pino será automaticamente alterado. Ao realizar uma leitura dos mesmos, coloca o estado atual do pino em um desses registradores. SP (81H) É o apontador de pilha (Stack Pointer), que aponta para o topo da pilha, ou seja, indica o último endereço que foi armazenado na pilha. DPL (82H) e DPH (83H) Em conjunto formam o DPTR, endereçamento indireto de 16 bits. utilizado para PCON (87H) O registro PCON (Power Control) permite controlar o consumo de energia do microcontrolador com segurança. TCON (88H) e TMOD (89H) Registros responsáveis pelo Controle e de Modo de Operação dos Temporizadores/Contadores, permitindo a programação dos mesmos. TL0 (8AH), TH0 (8CH), São os registros que contem os valores a serem contados TL1 (8BH) e TH1 (8DH) dos Temporizadores/Contadores (T0 e T1). SCON (98H) e SBUF (99H) SCON permite trabalhar com a porta de comunicação serial e o SBUF armazena os dados recebidos e escreve os dados transmitidos. IE (A8H) e IP (B8H) Registro para programação (habilitação/desabilitação, prioridade etc.) das interrupções. PSW (D0H) O PSW (Program Status Word - palavra de status do programa) é responsável pelo registro dos Flags do 8051, indica as operações que ocorreram na ALU e o banco de registradores que foi acessado por último. ACC (E0H) É o acumulador. É acessível como posição de memória. B ( F0H) Registro auxiliar B. É acessível como posição de memória. 30 9.8 CONJUNTO DE INSTRUÇÕES A família MCS-51 apresenta um total de 111 instruções, sendo elas aritméticas, lógicas, booleanas, transferência de dados e de desvios. As instruções são otimizadas para melhorar o desempenho das aplicações de 8 bits. Abaixo estão relacionados exemplos de instruções e o seu tipo correspondente. MOV A, 20h; move para o acumulador o dado presente no endereço 20h - Instrução de transferência de dados. INC 23h; incrementa o conteúdo da memória RAM de endereço 23h Instrução Aritmética. ORL P1, A; seta os pinos de P1 segundo os valores dos bits do acumulador - Instrução Lógica. JB P3.4, T0_ON; testa se a entrada do temporizador 0 está setado Instrução booleana. SJMP 00h; desvia para a próxima instrução (offset = 0) - Instrução de desvio. 31 10 CAPÍTULO 3 – BLUETOOTH Bluetooth é um padrão global para a comunicação sem fio de curto alcance, automático e de baixo consumo de energia. Para isso ela usa ondas de rádio freqüência, para substituir todo o cabeamento necessário para trocar dados entre dispositivos eletrônicos. Dentre suas principais vantagens citamos: elevados níveis de segurança, baixo custo efetivo, baixo consumo de energia ao manter a potência de transmissão em níveis bem baixos, comunicação simples e eficiente, além de fornecer serviços síncronos (como voz sobre ip), e assíncronos (como transferências de arquivos). A história do Bluetooth começa em 1994, quando a Ericsson estudava a viabilidade de transmitir dados entre celulares usando rádio frequencia no lugar nos cabos convencionais, resultando no MCLink que é um sistema de rádio de curto alcance. Após o lançamento a Intel, IBM, Toshiba e Nokia se uniram a Ericsson e criaram o consórcio Bluetooth SIG (Special Interest Group). Com empresas das mais diversas tecnologias pertencentes ao consórcio SIG, tornou-se possível a interoperabilidade da tecnologia nos mais diversos tipos de aparelhos eletrônicos. O SIG é uma organização privada sem fins lucrativos, e é responsável por proteger os direitos da marca Bluetooth, publicar especificações, administrar a qualificação do programa e difundir o uso da tecnologia de comunicação sem fio. O Bluetooth opera na faixa ISM (Industrial, Scientific, Medical), que opera à freqüência de 2,45 GHz, ela está livremente disponível e não é licenciada na maioria dos países, a sua faixa de operação varia de 2,4 GHz a 2,5 GHz. Por operar em uma banda que não é licenciada, ocorrem interferências com outros aparelhos operantes na mesma faixa, por isso se utiliza a técnica de saltos adaptativos em frequência (Adaptive frequency hopping – AFH) com o intuito de diminuir tal interferência. 32 O AFH detecta os outros dispositivos no espectro e evita as frequência que eles estão utilizando, para isso ele divide a faixa em 79 canais e muda de canal regularmente podendo mudar até 1600 vezes por segundo. Com isso qualquer interferência que ocorrer dura em fração de segundo. Os sistemas Bluetooth podem, através dessas faixas de alcance, formar pequenas redes privadas conhecidas como PANS (Personal Area Networks – Redes de Área Pessoal) ou piconets. Uma piconet é uma rede formada por até oito dispositivos, assim cada aparelho dotado da tecnologia Bluetooth pode comunicar com até outros 7 aparelhos da mesma piconet. A piconet é formada automaticamente à medida que os aparelhos saem e entram na cobertura da piconet. O dispositivo Bluetooth que iniciar a conexão assume o papel de master (mestre), enquanto que os demais dispositivos se tornam slave (escravos), com isso em cada piconet deve haver um master e no máximo sete slaves. Um dispositivo pode fazer parte de mais de uma piconet ao mesmo tempo, como por exemplo na figura 10, o mesmo dispositivo é escravo na piconet A (slave A3) e na piconet B(slaveB3). Desta forma ocorre a formação de uma scatternet, onde uma piconet se comunica com outra dentro de um limite de alcance. Figura 10 - Duas piconets formando uma scatternet, com um dispositivo escravo em comum. 33 O raio de operação da piconet vai depender dos dispositivos que estão sendo utilizados. Tais dispositivos são classificados em três categorias, de acordo com a tabela 4. Tabela 4 - Classificação dos dispositivos Bluetooth. Classe Alcance Potência Classe 1 Longo alcance (100 m) Entre 1 mW e 100 mW Classe 2 Curto alcance (10 m) Entre 0,25 mW e 2,5 mW Classe 3 Curtíssimo (1 m) Até 1 mW 10.1 Processo de estabelecimento de conexões Assim que um dispositivo Bluetooth detectar outro, este assume o papel de master e passa a gerenciar a conexão sobre o outro dispositivo que assume o papel de slave. O master pode realizar a conexão de duas maneiras: 1. Comando Inquiry - é utilizado quando não é conhecido o número de identificação ou endereço dos slaves. Permite que descubra quais os dispositivos que estão ao alcance do master. 2. Comando Page - é utilizado assim que o endereço do slave for obtido e tem a função de completar o estabelecimento da conexão. Quando for estabelecida a conexão os dispositivos Bluetooth trocam pacotes entre si para sincronizar seus relógios, definir a identificação de cada dispositivo e controlar a troca de mensagens. Depois de estabelecida a conexão o dispositivo pode assumir os seguintes estados: Estado de Espera: Quando o dispositivo está ligado mas ainda não se conectou a uma piconet. Estado de Solicitação: Quando um dispositivo envia requisições para encontrar outros que estejam ao seu alcance e que ele pode se conectar. Estado de Página: Estado onde há um envio de mensagens para encontrar outros dispositivos que possam entrar ao alcance na sua piconet, e apenas dispositivos mestres podem ficar neste estado de página. 34 Estado Conectado: Assim que for estabelecida a conexão, e um dos dispositivos assumir o papel de mestre e o outro de escravo. Estado de Transmissão: Estado em ocorre a transmissão de dados de um dispositivo a outro. Depois da transmissão, retorna-se ao estado conectado. Estado de Escuta: Quando o escravo fica inativo por uma quantidade definida de slots. Estado bloqueado: Semelhante ao estado de escuta, porém não ocorre transferência de dados. Estado estacionado: Um dispositivo entra nesse estado quando perde o seu endereço atual na piconet. A figura 11 mostra o conjunto de estados que um dispositivo Bluetooth pode encontrar, assim que for estabelecida a conexão. Figura 11 - Conjunto de estados dos dispositivos Bluetooth. 35 11 DISPOSITIVOS UTILIZADOS 11.1 AT89C52 O AT89C52 é um microcontrolador baseado no 8051, que possui uma CPU de 8 bits de alta performance baseado na tecnologia CMOS, possui baixo consumo de energia, e 8 KB de EPROM. O dispositivo é produzido usando a tecnologia de memória não-volátil de alta densidade, e é compatível com os padrões de pinagem e conjunto de instruções do 80C51 e 80C52. O Flash on-chip permite a memória de programa ser reprogramada no sistema, ou por um programador convencional de memória não-volátil. Através da combinação de uma CPU de 8 bits versátil com flash em um chip monolítico, o AT89C52 é um poderoso microcomputador que fornece uma solução altamente flexível e de baixo custo para a maioria das aplicações de controle embarcados. O AT89C52 foi projetado com lógica estática para operar com freqüências próximas de zero, e possui dois modos de economia de energia selecionáveis por software. O modo de espera interrompe a CPU enquanto permite que a RAM, temporizadores/contadores, a porta serial, e o sistema de interrupção permaneçam funcionando. O modo de desligamento salva o conteúdo da RAM, mas congela o oscilador, desabilitando todas as outras funções do chip, até o próximo sinal de reset do hardware. Características: • Compatível com produtos de MCS-51 • 8KB de memória Flash reprogramável • Operação inteiramente de estática: 0 hertz a 24 megahertz • Fechamento em três níveis da memória do programa • RAM interno de 8 bits de 256 x 36 • 32 linhas programáveis de entrada/saída • Três temporizadores/contadores de 16 bits • Oito fontes da interrupção • Canal de comunicação serial programável • Baixo consumo de potência no estado de espera e modo de desligamento 11.1.1 Memória de Dados O AT89C52 implementa 256 bytes de RAM on-chip. Os 128 bytes superiores ocupam um espaço de endereçamento paralelo ao dos registradores de função especiais (Special Function Registers). Isso significa que os 128 bytes superiores possuem o mesmo endereço que os Registradores de Funções Especiais, mas estão fisicamente seprados no espaço de memória. Quando uma instrução acessa um endereço de memória interno abaixo do endereço 7FH, o modo de endereçamento usado na instrução especifica se a CPU deve acessar os 128 bytes superiores da memória RAM ou o espaço de endereçamento dos registradores de função especiais. Por exemplo a instrução seguinte que usa o modo de endereçamento direto no endereço 0A0H (correspondente a P2) MOV 0A0H, #data Instruções que usam o modo de endereçamento indireto acessam os 128 bytes superior da RAM. Por exemplo a instrução abaixo que usa endereçamento indireto, onde R0 contem 0A0H, que acessa os dados do endereço 0A0H em vez de P2 cujo endereço também é 0A0H. MOV @R0, #data 37 Podemos observar que as operações de pilha são exemplos de endereçamento indireto, então os 128 bytes de dados da RAM estão disponíveis como espaço de pilha. A figura 12 representa o mapa dos Registradores de Função Especiais e os valores de Reset do AT89C52. Figura 12 - Mapa dos SRF e seus valores de Reset 38 11.2 MOTOR DE PASSO 11.2.1 Definição Os Motores de Passo são dispositivos eletro-mecânicos síncronos, que possuem a função de converter pulsos digital de algum sinal (geralmente sinais elétricos) em movimentos mecânicos rotativos bem preciso, gerando variações angulares discretas. Os motores de passo podem ser aplicados em sistemas de malha aberta, ou seja, sem qualquer controle de realimentação, e possuem três tipos básicos: de relutância variável, ímã permanente e híbridos. Relutância Variável Consiste de um rotor de ferro, com múltiplos dentes e um estator com uma quantidade especifica de enrolamentos. Se energizarmos os enrolamentos do estator com corrente DC os pólos ficam magnetizados. A rotação ocorre quando os dentes do estator são atraídos para os pólos do estator energizado, para que o sistema tenha o circuito com menor relutância. Ímã Permanente Possuem baixo custo e baixa resolução e baixo torque. O rotor é construído com ímãs permanentes e não possui dentes. Os pólos magnetizados do rotor provêm uma maior intensidade de fluxo magnético exibindo então uma melhor característica de torque. Híbrido Mais caro do que os demais, porém possui melhor desempenho com respeito à resolução de passo, torque e velocidade. O rotor é multi-dentado e contem um ímã permanente ao redor do seu eixo. Para aplicações que exigem um controle bem rígido e um ajuste fino de posicionamento, em máquinas de pequena e média dimensão, os motores de passo híbrido são os mais utilizados devido à sua ótima relação custo/benefício. O motor de passo diferencia da maioria dos motores elétricos devido a sua capacidade de controlar movimentos de forma bem precisa, sendo amplamente usados em impressoras, robôs e na automação industrial. 39 A precisão de movimento aliado ao seu torque, a capacidade de atingir uma boa velocidade, a boa resposta a aceleração e desaceleração, e por seguir uma lógica digital, fez do motor de passo o mais viável para o nosso projeto de controle do guincho. Os motores de passo possuem como componentes o rotor e o estator. O rotor é o conjunto eixo-imã que rodam solidariamente na parte móvel do motor, e o estator correspondem a trave fica onde são enroladas as bobinas. Se aplicarmos uma seqüência definida de pulsos elétricos nos terminais do motor, o rotor de um motor de passo é rotacionado em incrementos angulares específicos, denominados “passos”. Abaixo especificamos os principais parâmetros dos motores de passo e com o que estão relacionados. 11.2.2 Parâmetros dos motores de passo: Rotação do motor: diretamente relacionado com os impulsos elétricos recebidos. Direção: relacionado com a seqüência que pulsos elétricos são aplicados. Invertendo a seqüência dos pulsos, muda-se a direção de rotação do motor. Velocidade: relacionado com a freqüência de pulsos recebidos. Quanto menor o intervalo entre os pulsos maior a velocidade, e vice-versa. O intervalo não deve ser inferior a 10ms entre cada passo, pois geralmente o motor perderá o torque e em vez de rodar, irá vibrar. Ângulo rotacionado: relacionado com o número de pulsos aplicados. O motor de passo utilizado é o 23LM-C004, que corresponde a um motor de passo unipolar, com tensão de 6V/fase, corrente de 1,2A/fase e deslocamento angular de 1,8graus/fase. Por ser unipolar é caracterizado por ter 2 enrolamentos por fase sendo que a corrente atravessa em um sentido em cada enrolamento, e possui uma derivação central (center-tape) em cada uma das bobinas. 40 Essa derivação central é usada para alimentar o motor, e o motor de passo basicamente é controlado aterrando seus enrolamentos. O aterramento é feito por um circuito controlador e um driver, para que conforme acionado possa produzir uma rotação contínua em alguma direção. O circuito de controle pode inverter o sentido rotação do motor (horário/anti-horário) e até mesmo variar a sua velocidade. Para que o motor de passo funcione corretamente, a alimentação deve ser de forma seqüencial (energizando as bobinas em uma ordem específica) e repetida (para que execute o movimento contínuo, definido pelo número de passos). 11.2.3 Ponte H Os motores de passo podem ter seu sentido de rotação invertido, apenas mudando o sentido dos pulsos elétricos aplicados no mesmo, ou seja se invertermos o sentido da corrente elétrica que atravessa as bobinas do motor. Poderíamos então inverter a polaridade dos terminais elétricos de um circuito, que conseqüentemente inverteria o sentido da corrente. Para inverter a polaridade elétrica poderíamos usar chaves, no qual se estiverem devidamente usadas para este propósito controlariam facilmente o sentido do motor. Porém como a maioria dos motores de passo são usados em processos automatizados, o uso de chaves torna-se inadequado, para resolver este problema podemos inserir transistores no circuito para poder controlar a corrente elétrica sem o uso de partes móveis. A Ponte H é um circuito transistorizado que visa controlar esse sentido de corrente, permitindo que um determinado motor rode tanto no sentido horário quanto no anti-horário, e o seu nome "ponte H" é devido ao formato do circuito quando montado. Para construir um circuito Ponte H chaveado, basta ligar conforme a figura 13, na qual um par de chaves são acionadas de forma alternada (S1 e S4 ou S2 e S3) para inverter o sentido da corrente. De acordo com a figura 13, se as chaves S1 e S4 estiverem fechadas e as chaves S2 e S3 abertas, uma tensão positiva será aplicada no motor, já se as chaves S1 e S4 estiverem fechadas e S2 e S3 estiverem abertas, uma "tensão negativa" será aplicada ao motor, invertendo o sentido da corrente. Nesta 41 configuração, as chaves S1 e S2 nunca poderão ser fechadas ao mesmo tempo, pois isso ocasionaria um curto-circuito da fonte de tensão, de forma análoga as chaves S3 e S4 não podem ser fechadas ao mesmo tempo. Figura 13 - Ponte H chaveada Para construir uma ponte H automatizada podemos utilizar qualquer dispositivo que simule uma chave, como transistores, relés ou mosfets. No nosso projeto usamos transistores que quando estiverem no corte funcionam como uma chave fechada, e quando estiverem saturados funcionam como uma chave aberta. A presença de diodos entre os transistores serve de proteção devido à FCE (força contra eletromotriz) que é gerada pelo motor durante a partida e durante as paradas, e serve também para controlar a circulação da corrente como no caso do motor deixar de funcionar, fazendo com que a corrente volte para a fonte de alimentação. Capacitores podem ser adicionados para minimizar picos de tensão nas bobinas do motor, evitando faiscamento nas escovas. Além disso, serve também para filtrar ruídos de alta-freqüência e minimizar interferências em equipamentos de RF. Figura 14 - ponte H automatizada. 42 11.3 Módulo Bluetooth RS232 TTL É um módulo transceptor criado para permitir a comunicação sem-fio entre dispositivos utilizando o protocolo Bluetooth. É interessante para a comunicação de um dispositivo como um guincho e outros dispositivos móveis para mandar mensagens de controle, pois ele permite que o dispositivo de destino envie e receba dados TTL (Lógica Transistor-Transistor) usando o protocolo Bluetooth sem a necessidade de cabos seriais. Características: Fácil de usar e completamente encapsulado. Chipset da CSR (empresa pioneira em projetos que usam Bluetooth). Bluetooth de classe 2 (possui um alcance de até 10 metros e um consumo de potência entre 0,25 mW e 2,5 mW) . Modulação: GFSK (Gaussian Frequency Shift Keying), que é a técnica de modulação mais usados nos sistemas Bluetooth, pois fornecem uma melhor eficiência espectral. Opções de Segurança: Autenticação e encriptação Baud Rate definido pelo usuário: 1200, 2400, 4800, 9600, 19200, 38400, 57600, and 115200. Tensão: de 3,6 até 6V. No nosso projeto é necessário usar apenas 4 pinos do módulo Bluetooth, que são: Vcc, Terra(GND), Tx (transferência de informação) e Rx (recebimento de informação), conforme a figura 15. 43 Figura 15 - Pinos usados do módulo Bluetooth. 11.4 Conversor A/D (ADC0804) Um conversor analógico-digital é um dispositivo eletrônico capaz de converter grandezas analógicas em digital (zeros e uns). O conversor ADC0804 usado em nosso projeto, é um circuito integrado produzido pela National Semicondutor que é um dos maiores fabricantes de semicondutores, circuitos integrados, processadores embutidos e softwares e ferramentas de apoio, sediada na Califórnia – EUA. O ADC0804 converte amostras analógicas (de 0 a 5 Voltz), em um valor binário de 8 bits, baseado em CMOS, converte os valores por aproximação, baseado em uma escada diferencial potenciométrica. Não é necessário nenhum interfaceamento lógico, pois o conversor é visto como endereço de memória ou portas de entrada/saída pelo microprocessador. Entradas analógicas diferenciais de tensão permitem o aumento da rejeição de modo comum e compensando o valor zero analógico da tensão de entrada. Em compensação a tensão de referência pode ser ajustada para permitir a codificação de qualquer tensão analógica para a sua respectiva resolução de 8 bits. A sua saída poderá assumir valores entre 0 a 255 decimal (ou de 00000000 até 11111111 binário), sendo equivalente a 5V podendo ser convertidos em valores 44 múltiplos de 1*0,0195V=19,5mV até 255*0,0195V= 4,99V, conforme o esquema da figura abaixo. Figura 16 - Cálculo de resolução do ADC. 11.4.1 Características: Interface fácil e simples com todos os microprocessadores, ou opera no modo "stand alone". Interface lógica não requerida e tempo de acesso de 135 ns. Entradas de tensão analógica diferencial Funciona com 2.5V (tensão de referência), com máximo de 6,5V Corrente de alimentação de 1,3mA (típica), 2,5mA (máxima) Gerador de clock interno (on chip) Chip moldado com 20 pinos Nenhum ajuste zero. Fornece de 0 até 5V a partir de uma única alimentação de 5V. Características da Pinagem do ADC0804: Tabela 5 - Descrição da Pinagem do ADC0804 Pinos VIN(+) e VIN(-) DB0 a DB7 Função/Descrição Entradas analógicas diferenciais Saídas digitais 45 /CS (entrada) Seleção do Chip quando em nível "0" /RD (entrada) Habilita leitura disponibilizando os dados na saída quando em nível "0" /WR (entrada) Comanda início de conversão quando em nível "0" CLOCK IN (entrada) /INTR (saída) Terminal de malha RC Sinal indicando fim de conversão quando comutado para nível "0" AGND Terra analógico DGND Terra digital VREF/2 Tensão de referência no valor da metade de V+, para correção de fundo de escala CLOCK R (entrada) V+ ou VREF Segundo terminal para geração de clock interno Tensão de alimentação 11.4.2 Funcionamento: O conversor possui 2 entradas analógicas diferencias VIN(+) e VIN(-), fora do modo livre uma ligação do pino 3 (/WR) com o pino 5 (/INTR) providencia um sinal de início de conversão. Uma tensão de referência VRE/2 de precisão pode corrigir um erro no fundo de escala do conversor. O seu terminal /CS é capaz de habilitar o dispositivo em um endereçamento de I/O para dispositivos externos pela CPU. O pino /RD habilita diretamente a saída colocando os dados no barramento do sistema. O sinal de clock é gerado internamente bastando apenas a colocação de um resistor e um capacitor externo, sua freqüência será determinado pela fórmula abaixo. Onde: R é o valor da resistência, C é o valor da capacitância. Observação: O valor do resistor recomendado pelo fabricante é de 10K. 46 11.4.3 Converter a entrada analógica e ler a saída do ADC0804. 1. Faça CS = 0 e envie um pulso de alta para baixa o pino WR para iniciar a conversão. 2. Continue monitorando o pino INTR. INTR será 1 se a conversão estiver concluída, e será 0 se a conversão ainda não estiver terminada. 3. Se a conversão não está terminada (INTR = 0), aguarde até que esteja terminado. 4. Se a conversão for concluída (INTR = 1), vá para o passo seguinte. 5. Fazer CS = 0 e enviar um pulso de alta para baixa para o pino RD para ler os dados a partir do ADC (trazer os dados convertidos para os pinos de saída). Figura 17 - Interface do ADC 0804 com o 8051. A figura 17 acima mostra o esquema usado para fazer o interfaceamento ADC0804 com o 8051. Basicamente o circuito converte uma entrada analógica de tensão (Vin) em dados digitais e exibe este resultado sobre os 8 LEDs que estão ligados na porta P0 do microcontrolador. 47 Se a tensão de entrada Vin for 5V, todos os LEDs acenderão representando 255 em binário que equivale a 11111111, e a cada queda de tensão de 19,5mV (referente ao cálculo da resolução) fará com que os LEDs representem uma unidade a menos referente ao valor máximo de 255 em decimal. Neste esquema a porta P1 do microcontrolador está funcionando como entrada e a porta P0 está funcionando como saída. E os sinais de controle INTR, WR, RD e CS, estão respectivamente conectados aos pinos P3.4 a P3.7 do microcontrolador. O resistor R9 e o capacitor C1 estão associados com o circuito de relógio interno do ADC, os resistores R1 a R8 são limitadores de corrente, já o resistor R10 forma um divisor de tensão, que é aplicado aos pinos de entrada analógica do ADC. 11.5 ULN2803 O CI ULN2803 tem 8 entradas que podem controlar até 8 saídas. Um CI ULN2803 pode controlar até 2 motores de passo simultaneamente. Figura 18 - CI ULN2803. Como podemos observar na figura 18, o CI ULN2803 contêm 8 transistores com emissores comum e diodos de supressão integral para cargas indutivas. Cada transistor comporta uma corrente de carga de pico de 500mA contínuo, e pode 48 suportar pelo menos 50V no estado desligado. As saídas podem ser configuradas em paralelo para suportarem uma corrente maior. Possui um resistor de entrada 2.7kW para 5V TTL e CMOS. Apresentam um pino de saída oposto ao de entrada para simplificar o layout da placa. 11.6 Potenciômetro Potenciômetros são dispositivos elétricos formados por resistores variáveis com uma derivação central, sendo que a resistência entre os terminais extremos (valor nominal) é fixa, como por exemplo, 10KΩ (usado em nosso projeto). Já a resistência entre a derivação central e um dos terminais extremos vai ser definido pelo posicionamento do cursor, podendo ser ajustada de um valor muito baixo de resistência (aproximadamente 0Ω) até o seu valor nominal. A figura 19 mostra as principais partes de um potenciômetro linear. Figura 19 - Partes de um potenciômetro linear. 49 Os potenciômetros mecânicos possuem internamente uma pista de material resistivo (carbono, cromo, níquel, etc) por onde desliza o cursor, se a resistência entre a derivação central e uma das extremidades variar linearmente com relação ao movimento do cursor, o potenciômetro é dito linear. A figura 20 mostra a relação entra as resistências dos terminais (A e C) e o cursor (B), com o deslocamento do cursor (giro). Figura 20 - Relação entre giro do cursor e as resistências. 11.7 L298N O Circuito Integrado L298N é um circuito integrado monolítico, constituído de dupla Ponte-H e projetado para aceitar níveis lógicos TTL padrão e unidade de cargas indutivas tais como relés, solenóides, DC e motores de passo. Internamente, o L298N consiste de quatro amplificadores de potência independentes, com entradas digitais de 5V, sendo que estes amplificadores de conduzir motores DC, ou motores de passo unipolar e bipolar. Os quatro amplificadores de são freqüentemente usados em pares, formando uma ponte H para alternar a polaridade com o intuito de controlar a direção de um motor DC. 50 Características: Driver de ponte dupla Corrente de saída: 2A Voltagem de saída: 46V N º de pinos: 15 N º de saídas: 4 Faixa de Tensão: 4.5V – 7V Temperatura de Operação: -25 ° C a 130 ° C Corrente máxima: 4A Tensão máxima: 50V A pinagem do L298N do modelo Multiwatt15 utilizado neste projeto está descrita na figura 21. Figura 21 - Pinagem do L298N. Os pinos 1 e 15 são usados como sensor de corrente (current sensor). Eles podem ser ligados diretamente ao terra do circuito, porém é aconselhável conectá-lo 51 a um resistor de baixo valor (até 0,5Ω) para não influenciar na corrente de saída, e para que possa ser medido a tensão em cima do mesmo e calcular a corrente que está sendo fornecida. Os pinos ENA, ENB, e IN1-IN4 possuem o padrão de 5V lógica TTL para fazer a conexão com a maioria dos microcontroladores de maneira simples e fácil. O pino Supply voltage corresponde a tensão de alimentação para os motores de passo, enquanto que o pino Logical Supply Voltage corresponde a tensão do circuito de controle +5V do 8051. O pino 8, GND é ligado diretamente ao terra. Entre as tensões de alimentação e o terra são inseridos capacitores de desacoplamento. Os pinos Enable A e Enable B, podem ser colocados em nível alto diretamente conectados ao Vs, ou podem ser usados por pinos de controle provenientes do 8051. A figura 22 mostra o esquema de ligação do L298N com um motor de passo bipolar. Figura 22 - Ligação do L298N com motor de passo bipolar. 52 12 FERRAMENTAS E DISPOSITIVOS UTILIZADOS 12.1 Proteus Proteus é um software de projeto e simulação de circuitos eletrônicos, desenvolvido pela empresa inglesa Labcenter Electronics, é muito útil para estudantes e profissionais que desejam desenvolver projetos com aplicações analógicas e digitais. O software possui dois ambientes (ISIS e ARES) para criar esquemáticos e realizar simulações, e para posteriormente criar layout de placas de circuito impresso se necessário. Possui um entorno gráfico no qual podem inserir os símbolos representativos dos componentes do circuito que desejamos projetar, podendo verificar a viabilidade das conexões, e simular o funcionamento do circuito para evitar danos aos componentes. Durante a simulação podemos incluir instrumentos de medição e gráficos que demonstrem os sinais obtidos durante a simulação do circuito. Ele pode simular circuitos com os microcontroladores mais populares e usados atualmente, como 8051, PIC, ATMEL-AVR, Motorola, entre outros. No ambiente ISIS podemos criar esquemas elétricos utilizando microcontrolador e componentes necessários para nosso projeto. Assim que for criado o esquema podemos programar o microcontrolador e fazer simulações e testes que verificam a viabilidade do projeto. No ambiente ARES, podemos transformar o esquemático do circuito eletrônico em um layout para a confecção de placas de circuito impresso. No ARES, podemos definir as trilhas para uma correta comunicação entre os componentes, evitar cruzamento e proximidade das trilhas, prevenindo interferências eletromagnéticas e possível mal funcionamento do circuito. A figura 23 mostra os ambientes ISIS (esquerda) e ARES (direita). 53 Figura 23 - Ambientes ISIS (esquerda) e ARES (direita). 12.2 PEQui O simulador PEQui é um software gratuito desenvolvido na Escola das Engenharias Elétrica Mecânica e de Computação, da Universidade Federal de Goiás, que auxilia estudantes e desenvolvedores que desejam projetar circuitos com o microcontrolador 8051. No ambiente do PEQui podemos digitar, compilar e simular o programa escrito em Assembly a ser carregado no microcontrolador 8051. O PEQui é capaz de simular as todas as funcionalidades do microcontrolador 8051, como comunicação serial, fontes de interrupção, contadores/temporizadores, etc. Também é capaz de transmitir os arquivos “hex” para o microcontrolador através da porta serial do computador. 12.2.1 Funcionamento: O programa digitado é gravado automaticamente com a extensão ".asm”. A compilação do programa gera um arquivo com extensão “.hex” e outro com extensão ".lst". O programa “.lst” fornece a listagem do programa em assembly e o código hexadecimal equivalente, além de possíveis mensagens de erro. O kit didático é acompanhado de um programa que é usado para transferir o arquivo ".hex" para o kit. O programa transferido inicia automaticamente sua execução. 54 Figura 24 - Ambiente do PEQui. O simulador permite visualizar os conteúdo dos principais registradores do 8051, além de poder depurar o programa passo a passo (por instrução), verificando alterações na memória RAM, do conteúdo das portas de 8 bits e dos registradores. 12.3 ChipMax2 ChipMax2 é um dispositivo programador universal de baixo custo e alto desempenho que utiliza a interface PC USB 2.0. Pode programar uma memória flash de 64Mb em 42 segundos. Suporta mais de 13.000 dispositivos programáveis de baixa tensão, oferece uma interface amigável e várias facilidades para programação de chips. Suporta EPROM e microcontroladores, identifica se o chip foi corretamente inserido antes de programar assim como pinos mal conectados. 55 Figura 25 - Dispositivo de gravação de chips ChipMax2. 12.4 MaxLoader O maxloader é uma ferramenta da EETools. Apresenta uma interface simples como podemos verificar na figura 26, que permite ler, apagar, verificar e programar memórias e microcontroladores. Possui um catálogo variado de microcontroladores, e trabalha com o dispositivo de gravação ChipMax2. Figura 26 - Ambiente do MaxLoader. 56 12.5 Eclipse e Android SDK O Eclipse é uma IDE (integrated development environment) desenvolvida em JAVA, usada para facilitar o desenvolvimento de aplicações em várias linguagens de programação, entre elas o JAVA, C++, PHP, entre outras. Formada por um consórcio da IBM, é a IDE líder de mercado, e segue o modelo open source de desenvolvimento de software. Suas principais características são: Utiliza o SWT (The Standard Widget Toolkit) como biblioteca gráfica, que usa componentes nativos do sistema operacional. Isso permite criar aplicações gráficas multiplataforma sem sacrificar a compatibilidade. Orientação ao desenvolvimento baseado em plugins, que possuem inúmeras funcionalidades diferentes, como: suporte a servidores de aplicação, visualizadores de banco de dados, geradores de diagramas UML, etc. Portátil, ou seja, as aplicações desenvolvidas são compatíveis com vários ambientes. Permite a refatoração do código, permitindo melhorar o design sem alterar a funcionalidade. Juntamente com o Eclipse, foi preciso baixar e instalar o SDK (kit de desenvolvimento de software) do Android. Depois de instalar o Android SDK, através do Android SDK Manager, baixamos a API 2.3.3 para Android, escolhida como versão mínima requerida para o aplicativo. Após isso baixamos e instalamos o plugin de desenvolvimento Andoid para o Eclipse, o Android Development Tools (ADT). O ADT possibilita criar mais rapidamente novos projetos Android, construir uma interface do aplicativo, depurar o aplicativo e exportar pacotes para distribuição. 57 13 RESULTADOS OBTIDOS 13.1 Esquemático do circuito eletrônico A figura 27 mostra o esquemático que foi projetado e simulado no Proteus. Figura 27 - Esquemático básico do guincho. 58 Após montar e simular o esquemático do projeto, com o programa em assembly do Apêndice A, notou-se seu correto funcionamento, e esse circuito serviu de base para a confecção da placa de circuito impresso. Para facilitar a confecção do circuito impresso e para adaptá-lo melhor à nossa necessidade, alteramos as seguintes características do circuito: Os conversores analógico digitais (ADC0804) foram conectados nas portas P1 e P2, e o driver L298N foi conectado na porta P0 do microcontrolador. O eletroímã foi conectado no pino T0 do microcontrolador. Não foram necessárias as resistências dos pinos de sensor de corrente do L298N. Visto que o mesmo fornece na porta uma tensão de 6V e a resistência interna do motor de passos é de 6Ω, ele fornece a corrente de aproximadamente 1A para o motor se desconsiderarmos a queda de tensão dentro L298N. Nos resultados práticos, considerando a queda de tensão do L298N, a corrente que entra no motor girou em torno de 750mA. As entradas do L298N foram conectadas na porta P0 do microcontrolador, e suas saídas ligadas às fases de cada motor. Visto que cada motor de passo possui 4 fases, foi necessário o uso de quatro pinos do microcontrolador por cada motor. Os pinos sensA e sensB (sensor de corrente) do L298N foram ligados à porta GND do mesmo (aterrados). O Vs é ligado à tensão de controle do micro e o Vss na tensão de alimentação do motor de passo. Os conversores analógico-digital de 8 bits (ADC0804), foram conectados na porta P1 e P2 do microcontrolador, sendo que o bit menos significativo do conversor foi ligado na .0 e o mais significativo na .7. Os pinos VIN(+) e VIN(-) que correspondem às entradas analógicas diferenciais são conectados ao terminal de derivação central do potenciômetro e no GND, respectivamente. Os pinos de escrita (WR) e leitura (RD) do conversor foram ligados aos pinos de 16 e 17 do microcontrolador. Os pinos CLK IN e CLK R são conectados ao gerador de clock do 59 micro e separados por um resistor e um capacitor em série para geração do clock interno. O pino Rx e o Tx do módulo Bluetooth são conectados respectivamente nos pinos TxD(11) e RxD(10) do microcontrolador. A tensão de operação do módulo é ligado à tensão de controle do microcontrolador, que corresponde a 5V. Já o eletroímã foi ligado no pino T0 do microcontrolador. Com o programa em assembly, usamos o software PEQui para emular e depurar todo o funcionamento do micro, verificando alteração dos registradores e envio de sinais. Para gravar o programa no chip usamos o software MaxLoader e o dispositivo ChipMax2, que são compatíveis com os mais diversos fabricantes do 8051, inclusive o AT89C51 usado no projeto. Convertemos o esquemático do ambiente ISIS, para o ambiente ARES do Proteus, fizemos as modificações necessárias como trilhas cruzadas e correção das mesmas, e otimizamos o espaço entre os componentes para deixar o circuito mais simples e funcional. 13.2 Placa de Circuito Impresso A Placa de Circuito Impresso é composta por camadas de materiais plásticos e fibrosos, que contem finas películas de alguma substância metálica como cobre níquel ou ouro. Essas películas serão responsáveis pela formação das trilhas nas placas, onde irá fluir a corrente elétrica pelos componentes do circuito. O desenho da placa foi feito depois de inúmeras simulações no ambiente do PROTEUS e vários testes físicos, verificando a viabilidade do projeto. A construção das placas veio tornar mais simples, eficaz e menos suscetível a erros os testes físicos do sistema, pois foi reduzido drasticamente o número de fios e conexões defeituosas. 60 Para o desenho da placa, visamos otimizar o espaço dos componentes na placa, evitando trilhas abertas e cruzamentos, e também possíveis interferências eletromagnéticas que poderiam ser causadas pelas proximidades das trilhas. Deixamos também pinos para entrada de corrente e comunicação com outras placas. 13.3 Processo de confecção da placa 1. Depois de gerado o layout da placa no ambiente ARES do PROTEUS, imprimimos em uma impressora a laser de boa qualidade, usando papel fotográfico. 2. Lixamos a superfície da placa de circuito com uma esponja de aço para tirar possíveis resíduos e a parte oxidada. Depois de lixada, limpamos com álcool para retirar a gordura da placa. 3. Fixamos o layout da placa com uma fita isolante e deixamos o papel bem firme e esticado para evitar defeitos no desenho do circuito. 4. Passamos um ferro já quente na região do desenho para transferi-lo para a placa. 5. Deixamos a placa esfriar e retiramos o papel da placa. 6. Corroemos a placa de cobre usando percloreto de ferro, deixando de molho em uma vasilha plástica. Depois de corroído lavamos a placa em água corrente, e limpamos com tiner para tirar a tinta de cima das trilhas. 7. Fizemos os furos nas ilhas da placa para fixação dos componentes do circuito. Soldamos os componentes na placa com cuidado para evitar curto circuito e falhas nas trilhas. As placas individuais podem ser vistas nas figuras 28, 29 e 30. Já a figura 31 mostra o circuito eletrônico completo necessário para o funcionando do projeto. 61 Figura 28 - PCI do 8052. 62 Figura 29 - PCI da ponte H com L298N. Figura 30 - PCI de ativação do eletroímã. Figura 31 - Circuito eletrônico completo. 63 13.4 Comunicação com os Dispositivos Bluetooth Todo o programa para a comunicação com o Bluetooth foi feito na linguagem de programação JAVA, e utilizando a SDK Android. O código do programa em JAVA da comunicação Bluetooth, está no Apêndice B. Foi desenvolvido primeiramente a interface gráfica que buscou ser simples e intuitiva, depois foi desenvolvido a interface para a comunicação com o módulo Bluetooth. Depois foi desenvolvida toda a estrutura lógica do sistema, que buscava adequar ao correto funcionamento de todos os dispositivos usados no projeto, e suas respectivas limitações. Com a conclusão do programa e em posse de um celular Android com capacidade de comunicação Bluetooth, foi selecionado o módulo Bluetooth para realizar a conexão. Após conectado, é mostrado uma interface simples e intuitiva, de modo que o usuário possa operá-la sem grandes problemas. A figura 32 mostra a interface do programa através da tela do celular. Figura 32 - Interface do dispositivo Bluetooth. 64 Figura 33 - Controle dos motores. Foi criada uma tela de configurações (figura 34), para possibilitar ao usuário mudar, em tempo de execução, os valores de algumas constantes do sistema. Através desta tela é possível limitar o curso do guincho e definir a precisão de parada. A definição de um valor limitador para o guincho não é só uma comodidade, como também um fator de segurança, podendo evitar acidentes e danos nos sensores. Através das relações de engrenagens, e usando os limitadores de curso, foi possível realizar a aferição dos sensores, para que indique uma posição aproximada, traduzida em Graus, e mostrada em tempo real na tela do celular. 65 O funcionamento do programa está descrito abaixo: - A barra de posição atual do motor pode ser vista como a porção de giro do cursor do potenciômetro. - A barra de posição desejada do motor é onde o usuário irá controlar o movimento do motor, fazendo com que a barra de posição atual se locomova até a posição desejada. - A interface contém botões para ligar e desligar os motores, o ímã, e também para conectar e desconectar os dispositivos Bluetooth. Figura 34 - Tela de Configuração 66 14 CONCLUSÃO E TRABALHOS FUTUROS O desenvolvimento deste projeto mostrou ser um grande desafio. E o principal motivo foi a integração entre as várias áreas de conhecimento aplicadas durante seu desenvolvimento. Durante seu processo foi necessário estudo de Mecânica, Microcontroladores, Eletrônica e Linguagens de programação. Em cada uma dessas áreas tivemos que realizar inúmeras pesquisas e aprofundar no conhecimento. O processo de adequação da estrutura física para instalação de sensores e adaptação dos motores foi bastante dispendioso. Vimos como pode ser difícil criar um projeto baseando-se em algo já construído, em que não foi projetado para essas mudanças. A instalação dos sensores demandou diversas horas na confecção de engrenagens com apertos precisos, que coubessem em espaços curtos e que não foram criados para esse propósito. Além das engrenagens diversos ajustes tiveram que ser feitos na estrutura física, tendo em vista o desgaste sofrido com o tempo, de forma que o funcionamento não deixasse a desejar. O projeto eletrônico também foi de grande valor. O contato próximo com as diversas ferramentas como conversores analógico-digital e transistores foram fundamentais para agregar conhecimento. Nesse estudo temos que ressaltar a importância de leitura minuciosa da documentação do fabricante, que detalha o funcionamento de cada componente. Ainda sim, vimos que essa documentação vez ou outra pode se apresentar confusa ou incompleta, onde se mostra importante a troca de experiência e a orientação. No trabalho pudemos concretizar, na prática, uma grande parte do conhecimento aprendido nos diversos anos desta graduação. A confecção de circuitos se mostrou um exemplo de algo que, apesar de aprendido em sua teoria, mostra diversos desafios que só aparecem com a prática, e que agregam bastante conhecimento. Considerando o desafio com extensa área de conhecimento, o problema foi enfrentado por partes. Essa abordagem foi fundamental para conseguir o resultado, 67 resolvendo problemas menores e juntando os resultados. Durante o trabalho, cada um dos componentes foi estudado e conhecido a fundo seu funcionamento, e, só então, iniciado o próximo, seguindo o nosso fluxo de desenvolvimento. O componente de software também foi desenvolvido seguindo esta proposta, onde foi desenvolvido sua interface gráfica, sua interface para comunicação Bluetooth e, por fim, a lógica do programa. Durante o desenvolvimento do projeto vimos também como os erros de projeto podem atingir o andamento dos trabalhos. Com o projeto já na fase final experimentamos um erro de cálculo em duas engrenagens no sistema, ao qual, apesar de funcionarem, não estavam adequadas aos requisitos do projeto. Essas modificações tiveram custo ao projeto e também serviram de aprendizado, onde remodelamos a forma de trabalho para que não ocorresse novamente. Por fim, o trabalho gera grandes expectativas para o futuro, tendo em vista apresentar uma tecnologia que, apesar de não ser muito nova, ainda mostra um enorme potencial para o mercado. Os dispositivos Bluetooth, considerando a integração com dispositivos móveis, são uma tendência de mercado para os novos dispositivos, e ainda não possuem um concorrente com abrangência comparável. Isso significa que aplicações escritas para estes dispositivos podem atingir a um número muito grande de usuários, com a provável tendência de que este quadro não se altere nos próximos anos. Assim, esta integração de componentes eletrônicos com dispositivos móveis se mostra uma grande área de pesquisa, contendo inúmeros exemplos em que podem ser trabalhados. Desde o conforto, como na automação residencial, quanto na medicina, com sensores de saúde, até a área de segurança, as aplicações são diversas e demanda uma mão de obra bem específica do Engenheiro de Computação. 68 15 BIBLIOGRAFIA [1] STALLINGS, W. Arquitetura e Organização de Computadores, Edição 5. Editora Pearson Addison Wesley. 2005. [2] TAUB, H.; Circuitos Digitais e Microprocessadores. São Paulo: Mc- Graw Hill, 1984. [3] SILVA JÚNIOR , Vidal Pereira da . Microcontrolador 8051. São Paulo:Ática, 2. ed, 1999; [4] NICOLOSI, D.E.C. Microcontrolador 8051 Detalhado. 2a. edição. São Paulo: Editora Érica, 2000. [5] Microcontrolador. Disponível em: <http://pt.wikipedia.org/wiki/Microcontrolador> Acessado em 11 nov. 2012. [6] Denardin, G.W. Apostila de microcontroladores. Disponível em: <http://pessoal.utfpr.edu.br/gustavo/apostila_micro.pdf> Acessado em 11 nov. 2012. [7] Lima, J.W. Notas das aulas de microcontroladores e microprocessadores. Disponível em: <http://www.eeec.ufg.br/~jwilson/aulasmicro/ > Acessado em 11 nov. 2012. [8] Brain, M. Como funcionam os microcontroladores. Disponível em: <http://eletronicos.hsw.uol.com.br/microcontroladores.htm> Acessado em 17 nov. 2012. [9] Zelenovsky, R. Mendonça, A. Arquitetura de Microcontroladores Modernos. Disponível em: <http://www.mzeditora.com.br/artigos/mic_modernos.htm> Acessado em 17 nov. 2012. 69 [10] Jucá, S. A apostila PIC e Periféricos. Disponível em: <http://mecatronicananet.blogspot.com.br/2011/11/apostila-pic-e-perifericosatualizada.html> Acessado em 08 dez. 2012. [11] Antônio, M. Apostila de:programação de microcontroladores usando linguagem C. Disponível em: <http://www.pictronics.com.br/downloads/apostilas/Apostila-PicC.pdf> Acessado em 08 dez. 2012. [12] Ruiz, W. Microcontroladores–Família MCS-51 Conceitos, Aplicações e Projetos. Disponível em: <http://aragao.spo.ifsp.edu.br/files/apostilas/microcontroladores.pdf> Acessado em 08 dez. 2012. [13] Intel 8051. Disponível em: <http://pt.wikipedia.org/wiki/Intel_8051> Acessado em 09 dez. 2012. [15] Neto, H.G. MICROCONTROLADORES MCS51. Disponível em: <http://pessoal.utfpr.edu.br/hvieir/download/mcs51_1.pdf> Acessado em 09 dez. 2012. [16] Aplicações de Microprocessadores II. Disponível em: <http://iris.sel.eesc.sc.usp.br/sel337> Acessado em 09 dez. 2012. [17] Aplicação de Microprocessadores I. Disponível em: <http://iris.sel.eesc.usp.br/sel433/Aula8-i4.pdf> Acessado em 09 dez. 2012. [18] Interfaciing ADC to 8051. Disponível em: <http://www.circuitstoday.com/interfacing-ADC-to-8051> Acessado em 13 jan. 2013. [19] Tateoki, G.T. Disponpivel em: <http://www.getulio.eng.br/meusalunos/sad/ADC0804.pdf> Acessado em 13 jan. 2013. 70 [20] How to Interface Bluetooth with 8051. Disponível em: <http://www.pantechsolutions.net/accessory-boards/Bluetooth-interfacing-with-8051> Acessado em 27 jan. 2013. [21] Brites, F.G. Santos, V.P. Disponível em: <http://www.telecom.uff.br/pet/petws/downloads/tutoriais/stepmotor/stepmotor2k8111 9.pdf> Acessado em 02 fev. 2013. [22] Controle de motor de passo através da porta paralela. Disponível em: <http://www.rogercom.com/pparalela/IntroMotorPasso.htm> Acessado em 03 fev. 2013. [23] O que são e como funcionam os potenciômetros digitais. Braga, N.C.Disponível em: <http://www.sabereletronica.com.br/secoes/leitura/115> Acessado em 03 fev. 2013. [24] Moraes, M. L298N Ponte H Dupla. Disponível em: <http://arduinobymyself.blogspot.com.br/2013/02/l298n-ponte-h-dupla-breakoutboard.html> Acessado em 10 fev. 2013. [25] L298 Dual H-Bridge Motor Driver. Disponível em: <http://billwaa.wordpress.com/2012/06/06/arduino-l298-dual-h-bridge-motor-driver/> Acessado em 10 fev. 2013. [26]Patsko, L.F. Tutorial de Montagem da Ponte H. Disponível em: <http://www.maxwellbohr.com.br/downloads/robotica/mec1000_kdr5000/tutorial_eletr onica_-_montagem_de_uma_ponte_h.pdf> Acessado em 10 fev. 2013. [27] L298 Dataseet. Disponível em: <http://www.sparkfun.com/datasheets/Robotics/L298_H_Bridge.pdf> Acessado em 10 fev. 2013. 71 [28] Motores de passo (passo a passo). Disponível em: <http://www.roboticasimples.com/artigos.php?acao=14> Acessado em 10 fev. 2013. [29] Moraes,M. Ponte H - Controle de Motores DC. Disponível em: <http://arduinobymyself.blogspot.com.br/2012/08/ponte-h-controle-de-motoresdc.html >Acessado em 10 fev. 2013. [30] Manual em português do Proteus. Disponível em: <http://mecatronicadegaragem.blogspot.com.br/2011/02/manual-em-portugues-doproteus-que.html> Acessado em 24 jan. 2013. [31] Bluetooth - Camada Física e Camada de Acesso ao Meio. Disponível em: <http://www.gta.ufrj.br/grad/09_1/Bluetooth/index.html> Acessado em 24 fev. 2013. [32] Layton, J. Franklin, C. Como funciona o Bluetooth. Disponível em: <http://informatica.hsw.uol.com.br/Bluetooth.htm> Acessado em 24 fev. 2013. [33] Alecrim, E. Tecnologia Bluetooth. Disponível em: <http://www.infowester.com/Bluetooth.php> Acessado em 24 fev. 2013. [34] Kobayashi, C. Y. A Tecnologia Bluetooth e aplicações. Disponível em: <http://grenoble.ime.usp.br/movel/monografia_Bluetooth.pdf> Acessado em 24 fev. 2013. [35] Cavalheiro, L. Como fazer sua PCI (Placa de Circuito Impresso). Disponível em: <http://lucascavalheiro.wordpress.com/2008/10/22/como-fazer-pci/> Acessado em 26 fev. 2013. [36] Braga, N. Como funcionam potenciômetros e trimpots. Disponível em: <http://www.newtoncbraga.com.br/index.php/como-funciona/3379-art472.html> Acessado em 26 fev. 2013. 72 [37] Loflin, L. Connecting the Arduino to a L298N H-Bridge. Disponível em: <http://www.bristolwatch.com/L298N/L298N_arduino.htm> Acessado em 27 fev. 2013. 73 16 APÊNDICE A – CÓDIGO EM ASSEMBLY DO PROGRAMA DO MICROCONTROLADOR $mod51 IMA equ T0; MOTOR1 equ R1; MOTOR2 equ R2; MOTOR1_LIGADO equ 00h; MOTOR1_SENTIDO equ 01h; MOTOR2_LIGADO equ 02h; MOTOR2_SENTIDO equ 03h; IMA_LIGADO equ 04h; RESULTADO_ENTRADA equ 20h; RESULTADO_SAIDA equ R0; MOTOR equ P0; GIROMINIMO equ R3; INTS1 equ P3.2; INTS2 equ P3.3; ADC_VAL1 equ R4; ADC_VAL2 equ R5; ADC_SENSOR1 equ P1; ADC_SENSOR2 equ P2; org 00h; ajmp INICIALIZAR; org 23h; ajmp SERIAL; org 40h; INICIALIZAR: 74 mov SP, #2Fh; mov RESULTADO_ENTRADA, #0h; mov RESULTADO_SAIDA, #0h; mov MOTOR1, #0CCh; mov MOTOR2, #0CCh; mov GIROMINIMO, #0Fh; mov IE, #10010000b; mov SCON, #01010000b; mov PCON, #00000000b; mov TMOD, #00100000b; mov TH1, #0FDh; setb TR1; INICIO: acall APRESENTAR_RESULTADO; acall AGUARDAR_TEMPO; PROXIMO1: jnb MOTOR1_LIGADO, PROXIMO2; jnb MOTOR1_SENTIDO, INVERSO1; mov A, MOTOR1; rr A; mov MOTOR1, A; ajmp PROXIMO2; INVERSO1: mov A, MOTOR1; rl A; mov MOTOR1, A; PROXIMO2: jnb MOTOR2_LIGADO, PROXIMO3; jnb MOTOR2_SENTIDO, INVERSO2; mov A, MOTOR2; rr A; mov MOTOR2, A; ajmp PROXIMO3; 75 INVERSO2: mov A, MOTOR2; rl A; mov MOTOR2, A; PROXIMO3: jnb IMA_LIGADO, IMA_DESLIGADO; setb IMA; ajmp FIM; IMA_DESLIGADO: clr IMA; FIM: djnz GIROMINIMO, INICIO; inc GIROMINIMO; ajmp FIM; APRESENTAR_RESULTADO: mov A, MOTOR1; clr C; rrc A; clr C; rrc A; clr C; rrc A; clr C; rrc A; mov RESULTADO_SAIDA, A; mov A, MOTOR2; clr C; rlc A; clr C; rlc A; clr C; rlc A; clr C; rlc A; 76 add A, RESULTADO_SAIDA; mov RESULTADO_SAIDA, A; mov MOTOR, A; ret; AGUARDAR_TEMPO: push B; mov B,#0FAh; Tempo2: push B; mov B,#0FFh; Tempo1: djnz B,Tempo1; pop B; djnz B,Tempo2; pop B; ret; SERIAL: mov GIROMINIMO, #0Fh; mov RESULTADO_ENTRADA, SBUF; clr RI; acall ADC_Converter; mov SBUF, ADC_VAL1; jnb TI, $; clr TI; mov SBUF, ADC_VAL2; jnb TI, $; clr TI; reti; ADC_Converter: clr wr 77 nop setb wr jb INTS1,$ jb INTS2,$ clr rd mov ADC_VAL1,ADC_SENSOR1 mov ADC_VAL2,ADC_SENSOR2 setb rd ret; end; 78 17 APÊNDICE B – CÓDIGO EM JAVA DO PROGRAMA ANDROID/BLUETOOTH package ufg.eeec.guincho; import java.io.IOException; import ufg.eeec.guincho.BluetoothConnection.Motor; import import import import import import import import import import import import import import import import import import import import import import android.app.Activity; android.app.Notification; android.app.PendingIntent; android.app.Service; android.content.BroadcastReceiver; android.content.Context; android.content.Intent; android.content.IntentFilter; android.content.SharedPreferences; android.os.AsyncTask; android.os.Bundle; android.os.IBinder; android.preference.PreferenceManager; android.view.Menu; android.view.MenuItem; android.view.View; android.widget.Button; android.widget.ProgressBar; android.widget.SeekBar; android.widget.TextView; android.widget.ToggleButton; android.widget.SeekBar.OnSeekBarChangeListener; public class Principal extends Activity { private private private private private private private private private private private private private private ToggleButton cmdLigaDeslMot1; ToggleButton cmdLigaDeslMot2; ToggleButton cmdLigaDeslIma; ProgressBar pbPosMot1; ProgressBar pbPosMot2; SeekBar sbPosDesMot1; SeekBar sbPosDesMot2; TextView txtPosDesMot1; TextView txtPosDesMot2; TextView txtPosMot1; TextView txtPosMot2; Button cmdBluetooth; Button cmdConnect; Button cmdDisconnect; private private private private private private private private static static static static static static static static final final final final final final final final int int int int int int int int numEngrenagemSup1 numEngrenagemSup2 numEngrenagemSup3 numEngrenagemSup4 numEngrenagemInf1 numEngrenagemInf2 numEngrenagemInf3 numEngrenagemInf4 = = = = = = = = 90; 12; 42; 12; 40; 12; 36; 17; 79 private static final int numVoltasSensor = 10; private static final int anguloMaxMotor1 = (int) (360 numVoltasSensor / ((((float) numEngrenagemInf1) / numEngrenagemInf2) (((float) numEngrenagemInf3) / numEngrenagemInf4))); private static final int anguloMaxMotor2 = (int) (360 numVoltasSensor / ((((float) numEngrenagemSup1) / numEngrenagemSup2) (((float) numEngrenagemSup3) / numEngrenagemSup4))); private static final int margemSeguranca = 1; private static final int margemSegurancaMotor1 (margemSeguranca * ((float) anguloMaxMotor1) / numVoltasSensor); private static final int margemSegurancaMotor2 (margemSeguranca * ((float) anguloMaxMotor2) / numVoltasSensor); * * * * = (int) = (int) @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.guincho); if (context == null) context = getApplicationContext(); // Registra um BroadcastReciever para receber solicitacoes das threads. RegistrarReciever(); System.out.println(margemSegurancaMotor1); System.out.println(margemSegurancaMotor2); // Mantem uma referencia aos controles cmdLigaDeslMot1 = (ToggleButton) findViewById(R.id.cmdLigaDeslMot1); cmdLigaDeslMot2 = (ToggleButton) findViewById(R.id.cmdLigaDeslMot2); cmdLigaDeslIma = (ToggleButton) findViewById(R.id.cmdLigaDeslIma); pbPosMot1 = (ProgressBar) findViewById(R.id.pbPosMot1); pbPosMot2 = (ProgressBar) findViewById(R.id.pbPosMot2); sbPosDesMot1 = (SeekBar) findViewById(R.id.sbPosDesMot1); sbPosDesMot2 = (SeekBar) findViewById(R.id.sbPosDesMot2); txtPosDesMot1 = (TextView) findViewById(R.id.txtPosDesMot1); txtPosDesMot2 = (TextView) findViewById(R.id.txtPosDesMot2); txtPosMot1 = (TextView) findViewById(R.id.txtPosMot1); txtPosMot2 = (TextView) findViewById(R.id.txtPosMot2); cmdBluetooth = (Button) findViewById(R.id.cmdBluetooth); cmdConnect = (Button) findViewById(R.id.cmdConnect); cmdDisconnect = (Button) findViewById(R.id.cmdDisconnect); //Chama os valores padrao nas preferencias, caso o usuario nao as tenha modificado. PreferenceManager.setDefaultValues(this, R.xml.preferences, false); CarregarValoresPreferencias(); // CRIA OS EVENTOS PARA OS BOTOES cmdBluetooth.setOnClickListener(new Button.OnClickListener() { @Override public void onClick(View v) { 80 SelecionarDispositivoBluetooth(); } }); cmdConnect.setOnClickListener(new Button.OnClickListener() { @Override public void onClick(View v) { Conectar(); } }); cmdDisconnect.setOnClickListener(new Button.OnClickListener() { @Override public void onClick(View v) { Desconectar(); } }); sbPosDesMot1.setOnSeekBarChangeListener(new onSeekBarChange(txtPosDesMot1, onSeekBarChange.Motor1)); sbPosDesMot2.setOnSeekBarChangeListener(new onSeekBarChange(txtPosDesMot2, onSeekBarChange.Motor2)); } /** * Cria o menu de opcoes. */ @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menuprincipal, menu); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.dispositivoBT: SelecionarDispositivoBluetooth(); break; case R.id.configuracoes: Configuracoes(); break; case R.id.sair: if (PodeSair()) { finish(); System.exit(0); } break; default: break; } return super.onOptionsItemSelected(item); } /** * Recebe respostas das atividades iniciadas, como solicitacao de procura de dispositivos Bluetooth * e abrir tela de propriedades. */ 81 @Override protected void onActivityResult(int requestCode, Intent data) { // Recebe resposta as solicitacoes switch (requestCode) { int resultCode, // Recebe o dispositivo Bluetooth escolhido na atividade case ProcuraDispositivo: if (resultCode == RESULT_OK) dispositivoBluetooth = new DispositivoBluetooth(data.getStringExtra(BluetoothActivity.name), data.getStringExtra(BluetoothActivity.address)); break; case AbrePreferencias: CarregarValoresPreferencias(); break; } super.onActivityResult(requestCode, resultCode, data); } @Override protected void onResume() { AtualizarInterface(); super.onResume(); } @Override protected void onDestroy() { unregisterReceiver(broadcastReceiver); super.onDestroy(); } /** Nome para salvar estado persistente da variavel "strEstado" **/ private static final String strEstado = "estado"; /** Nome para salvar estado persistente da variavel "strNomeDispositivoBluetooth" **/ private static final String strNomeDispositivoBluetooth = "nome"; /** Nome para salvar estado persistente da variavel "strEnderecoDispositivoBluetooth" **/ private static final String strEnderecoDispositivoBluetooth = "endereco"; /** * Permite ao aplicativo manter seu estado apos a tela ser redesenhada, * seja na rotacao da tela, ou se o aplicativo for fechado pelo sistema. * */ @Override protected void onSaveInstanceState(Bundle outState) { outState.putInt(strEstado, estado); if (dispositivoBluetooth != null) { outState.putString(strNomeDispositivoBluetooth, DispositivoBluetooth.getNome()); outState.putString(strEnderecoDispositivoBluetooth, DispositivoBluetooth.getEndereco()); } super.onSaveInstanceState(outState); 82 } /** * Permite ao aplicativo manter seu estado apos a tela ser redesenhada, * seja na rotacao da tela, ou se o aplicativo for fechado pelo sistema. */ @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { String nome = savedInstanceState.getString(strNomeDispositivoBluetooth); String endereco = savedInstanceState.getString(strEnderecoDispositivoBluetooth); if (nome != null && endereco != null) dispositivoBluetooth = new endereco); DispositivoBluetooth(nome, estado = savedInstanceState.getInt(strEstado); super.onRestoreInstanceState(savedInstanceState); } /** * Nao permite o usuario fechar o aplicativo sem estar no estado desconectado. */ @Override public void onBackPressed() { if (PodeSair()) { super.onBackPressed(); System.exit(0); } } /** * Apresenta na tela os valores dos angulos dos motores, conforme modificado nas barras de progresso. */ private class onSeekBarChange implements OnSeekBarChangeListener { private TextView textView; private boolean Motor; public static final boolean Motor1 = false, Motor2 = true; public onSeekBarChange(TextView textView, boolean Motor) { this.textView = textView; this.Motor = Motor; } @Override public void onStopTrackingTouch(SeekBar seekBar) {} @Override public void onStartTrackingTouch(SeekBar seekBar) {} @Override public void onProgressChanged(SeekBar seekBar, int progress, 83 boolean fromUser) { if (fromUser) { if (Motor == Motor1) textView.setText(progress ValoresPreferencias.limiteInferiorMotor1 + "º"); else if (Motor == Motor2) textView.setText(progress ValoresPreferencias.limiteInferiorMotor2 + "º"); } } } + + private static final int ProcuraDispositivo = 1; private static final int AbrePreferencias = 2; /** Permite ao usuario selecionar um dispositivo Bluetooth. **/ private void SelecionarDispositivoBluetooth() { // Inicializa uma atividade para escolher um dispositivo Bluetooth if (estado == estadoDesconectado) startActivityForResult(new Intent(Principal.this, BluetoothActivity.class), ProcuraDispositivo); } /** Abre a tela de configuracoes. **/ private void Configuracoes() { if (estado == estadoDesconectado) startActivityForResult(new Preferencias.class), AbrePreferencias); Intent(Principal.this, } /** * Carrega da memoria persistente os valores salvos das configuracoes. */ private void CarregarValoresPreferencias() { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); ValoresPreferencias.limiteInferiorMotor1 = Integer.parseInt(sharedPreferences.getString(getString(R.string.limite_infe rior_motor1), getString(R.string.limite_inferior_motor1_defaultValue))); ValoresPreferencias.limiteSuperiorMotor1 = Integer.parseInt(sharedPreferences.getString(getString(R.string.limite_supe rior_motor1), getString(R.string.limite_superior_motor1_defaultValue))); ValoresPreferencias.limiteInferiorMotor2 = Integer.parseInt(sharedPreferences.getString(getString(R.string.limite_infe rior_motor2), getString(R.string.limite_inferior_motor2_defaultValue))); ValoresPreferencias.limiteSuperiorMotor2 = Integer.parseInt(sharedPreferences.getString(getString(R.string.limite_supe rior_motor2), getString(R.string.limite_superior_motor2_defaultValue))); ValoresPreferencias.precisao = Integer.parseInt(sharedPreferences.getString(getString(R.string.precisao_ke y), getString(R.string.precisao_defaultValue))); if (ValoresPreferencias.limiteInferiorMotor1 ValoresPreferencias.limiteSuperiorMotor1 ValoresPreferencias.limiteInferiorMotor1 < margemSegurancaMotor1 ValoresPreferencias.limiteSuperiorMotor1 > anguloMaxMotor1 margemSegurancaMotor1 ) { ValoresPreferencias.limiteInferiorMotor1 >= || || = 84 Integer.parseInt(getString(R.string.limite_inferior_motor1_defaultValue)); ValoresPreferencias.limiteSuperiorMotor1 = Integer.parseInt(getString(R.string.limite_superior_motor1_defaultValue)); String[] mensagens = {"Limites do Motor inferior maior que superior", "Redefinindo valores padrao."}; Mensagens.Notificacao(context, mensagens); } 1", "Valor if (ValoresPreferencias.limiteInferiorMotor2 >= ValoresPreferencias.limiteSuperiorMotor2 || ValoresPreferencias.limiteInferiorMotor2 < margemSegurancaMotor2 || ValoresPreferencias.limiteSuperiorMotor2 > anguloMaxMotor2 margemSegurancaMotor2) { ValoresPreferencias.limiteInferiorMotor2 = Integer.parseInt(getString(R.string.limite_inferior_motor2_defaultValue)); ValoresPreferencias.limiteSuperiorMotor2 = Integer.parseInt(getString(R.string.limite_superior_motor2_defaultValue)); String[] mensagens = {"Limites do Motor inferior maior que superior", "Redefinindo valores padrao."}; Mensagens.Notificacao(context, mensagens); } 2", "Valor sbPosDesMot1.setMax(ValoresPreferencias.limiteSuperiorMotor1 ValoresPreferencias.limiteInferiorMotor1); sbPosDesMot2.setMax(ValoresPreferencias.limiteSuperiorMotor2 ValoresPreferencias.limiteInferiorMotor2); - pbPosMot1.setMax(anguloMaxMotor1); pbPosMot2.setMax(anguloMaxMotor2); sbPosDesMot1.setProgress(sbPosDesMot1.getMax() / 2); sbPosDesMot2.setProgress(sbPosDesMot2.getMax() / 2); } /** * Registra um {@link BroadcastReceiver} para receber comandos das threads. */ private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(bcAtualizarInterface)) { AtualizarInterface(); } else if (intent.getAction().equals(bcIniciarServico)) { Intent intentBluetoothService = new Intent(BluetoothService.ConexaoBluetoothGuincho); intentBluetoothService.setClass(Principal.this, BluetoothService.class); Principal.this.startService(intentBluetoothService); } else if (intent.getAction().equals(bcPararServico)) { Intent intentBluetoothService = new Intent(BluetoothService.ConexaoBluetoothGuincho); intentBluetoothService.setClass(Principal.this, BluetoothService.class); Principal.this.stopService(intentBluetoothService); } else if 85 (intent.getAction().equals(bcAtualizaValoresMotor)) { AtualizaValoresMotor(); } else if (intent.getAction().equals(bcAtualizaSensor1)) { int valor = intent.getIntExtra(bcAtualizaSensor1, 1); System.out.println("Valor 1: " + valor); if (valor != -1) { valor = (int) (valor * anguloMaxMotor1) / 255)); pbPosMot1.setProgress(valor); txtPosMot1.setText(valor + "º"); } (((float) } else if (intent.getAction().equals(bcAtualizaSensor2)) { int valor = intent.getIntExtra(bcAtualizaSensor2, 1); System.out.println("Valor 2: " + valor); if (valor != -1) { valor = (int) (valor * anguloMaxMotor2) / 255)); pbPosMot2.setProgress(valor); txtPosMot2.setText(valor + "º"); } (((float) } } }; /** * Registra um filtro para um {@link BroadcastReceiver}, para filtrar as solicitacoes desejadas. */ private void RegistrarReciever() { IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(bcAtualizarInterface); intentFilter.addAction(bcIniciarServico); intentFilter.addAction(bcPararServico); intentFilter.addAction(bcAtualizaValoresMotor); intentFilter.addAction(bcAtualizaSensor1); intentFilter.addAction(bcAtualizaSensor2); registerReceiver(broadcastReceiver, intentFilter); } private static Context context; private static final String bcAtualizarInterface "ufg.eeec.principal.AtualizarInterface"; private static final String bcIniciarServico "ufg.eeec.principal.IniciarServico"; private static final String bcPararServico "ufg.eeec.principal.PararServico"; private static final String bcAtualizaValoresMotor "ufg.eeec.principal.AtualizaValoresMotor"; private static final String bcAtualizaSensor1 = = = = = 86 "ufg.eeec.principal.AtualizaSensor1"; private static final "ufg.eeec.principal.AtualizaSensor2"; String bcAtualizaSensor2 = /** Solicita uma conexao Bluetooth com o dispositivo selecionado. **/ private static void Conectar() { if (estado == estadoDesconectado && dispositivoBluetooth != null) { estado = estadoConectando; context.sendBroadcast(new Intent(bcAtualizarInterface)); // CONECTA A INTERFACE BLUETOOTH (new TarefaConectar()).execute((Void) null); } } /** Expressa o desejo do usuario em desconectar a conexao Bluetooth. **/ private static void Desconectar() { if (estado == estadoConectado) { estado = estadoDesconectando; context.sendBroadcast(new Intent(bcAtualizarInterface)); SolicitarDesconexao(); } } /** * Verifica se o aplicativo esta em condicoes de ser fechado, ou seja, se as conexoes foram fechadas. **/ private static boolean PodeSair() { // Verifica se foi desconectado if (estado == estadoDesconectado) { return true; } else { String[] mensagens = {"Dispositivo conectado.", "Por favor, desconecte antes de sair."}; Mensagens.Notificacao(context, mensagens); return false; } } /** Cria os estados do ambiente grafico. **/ private static final int estadoConectado = 0, estadoDesconectado = 1, estadoConectando = 2, estadoDesconectando = 3; private static int estado = estadoDesconectado; /** Objeto que armazena os dados de um dispositivo Bluetooth **/ private static class DispositivoBluetooth { private static String nome; private static String endereco; public DispositivoBluetooth(String nome, String endereco) { DispositivoBluetooth.nome = nome; DispositivoBluetooth.endereco = endereco; } public static String getNome() { 87 return nome; } public static String getEndereco() { return endereco; } } /** Armazena um {@link DispositivoBluetooth} com o dispositivo selecionado. **/ private static DispositivoBluetooth dispositivoBluetooth; /** Armazena uma solicitacao de desconexao. **/ private static boolean solicitadoDesconexao = false; /** Registrar que foi solicitado uma desconexao. **/ private synchronized static void SolicitarDesconexao() { solicitadoDesconexao = true; } /** Registrar que a solicitacao de desconexao foi atendida. **/ private synchronized static void SolicitacaoAtendida() { solicitadoDesconexao = false; } /** Retorna um valor represenando se existe uma solicitacao desconexao. **/ private synchronized static boolean SolicitadoDesconexao() { return solicitadoDesconexao; } de /** * Tarefa executada em segundo plano, responsavel por inicar a comunicacao Bluetooth atraves * da classe {@link BluetoothConnection}. */ private static class TarefaConectar extends AsyncTask<Void, Void, Boolean> { @Override protected void onPostExecute(Boolean resultado) { if (resultado.booleanValue()) { estado = estadoConectado; context.sendBroadcast(new Intent(bcIniciarServico)); (new TarefaComunicar()).execute((Void) null); } else { String[] mensagens {BluetoothConnection.getMensagemErro()}; Mensagens.Notificacao(context, mensagens); estado = estadoDesconectado; } = context.sendBroadcast(new Intent(bcAtualizarInterface)); super.onPostExecute(resultado); } @Override protected Boolean doInBackground(Void... params) { return 88 Boolean.valueOf(BluetoothConnection.Conectar(DispositivoBluetooth.getEndere co())); } } /** * Tarefa executada em segundo plano, responsavel por realizar as chamadas as funcoes * de comunicacao Bluetooth definidas em {@link BluetoothConnection} seguindo o protocolo pre-especificado. */ private static class TarefaComunicar extends AsyncTask<Void, Integer, Boolean> { private static final int ValoresMotor = 0, Sensor1 = 1, Sensor2 = 2; /** * Executada assim que a tarefa e concluida. * Executa os procedimentos de desconexao e reestabelecimento das condicoes iniciais. */ @Override protected void onPostExecute(Boolean resultado) { BluetoothConnection.Desconectar(); SolicitacaoAtendida(); estado = estadoDesconectado; context.sendBroadcast(new Intent(bcPararServico)); context.sendBroadcast(new Intent(bcAtualizarInterface)); super.onPostExecute(resultado); } /** * Executada para publicar os eventos da tarefa na interface grafica do aplicativo. */ @Override protected void onProgressUpdate(Integer... values) { Intent intent; switch (values[0].intValue()) { case ValoresMotor: context.sendBroadcast(new Intent(bcAtualizaValoresMotor)); break; case Sensor1: intent = new Intent(bcAtualizaSensor1); intent.putExtra(bcAtualizaSensor1, values[1]); context.sendBroadcast(intent); break; case Sensor2: intent = new Intent(bcAtualizaSensor2); intent.putExtra(bcAtualizaSensor2, values[1]); context.sendBroadcast(intent); break; } 89 super.onProgressUpdate(values); } /** * Tread responsavel por executar a tarefa. Define o protocolo a nivel de Software * a ser utilizado na comunicacao. */ @Override protected Boolean doInBackground(Void... params) { try { while (!SolicitadoDesconexao()) { publishProgress(ValoresMotor); BluetoothConnection.Escrever(PegaValoresMotor()); publishProgress(Sensor1, BluetoothConnection.Ler()); publishProgress(Sensor2, BluetoothConnection.Ler()); } return Boolean.TRUE; } catch (IOException e) { return Boolean.FALSE; } } } /** * * Define o servico que mantem ativa a conexao Bluetooth * para o caso da interface grafica ser encerrada, nao permitindo * que o sistema mate a aplicacao. * */ public static class BluetoothService extends Service { public static final int id = 5114463; public static final String ConexaoBluetoothGuincho "ufg.eeec.guincho.bluetooth"; = @Override public void onDestroy() { stopForeground(true); super.onDestroy(); } @Override public void onCreate() { super.onCreate(); Notification notification= Notification(R.drawable.ic_launcher, getText(R.string.conexao_inicializada), System.currentTimeMillis()); new Intent intents = new Intent(this, Principal.class); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intents, 0); 90 notification.setLatestEventInfo(this, getText(R.string.conexao_inicializada), getText(R.string.dispositivo_bluetooth_conectado), contentIntent); startForeground(id, notification); } @Override public int onStartCommand(Intent intent, int flags, int startId) { return START_NOT_STICKY; } @Override public IBinder onBind(Intent intent) { return null; } }; /** * Faz as alteracoes visuais nos controles, habilitando desabilitando, * de acordo com a condicao do aplicativo: conectado desconectado. */ private void AtualizarInterface() { String[] mensagens; ou ou cmdLigaDeslMot1.setEnabled(estado == estadoConectado); cmdLigaDeslMot2.setEnabled(estado == estadoConectado); cmdLigaDeslIma.setEnabled(estado == estadoConectado); cmdBluetooth.setEnabled(estado == estadoDesconectado); cmdConnect.setEnabled(dispositivoBluetooth != null && estado == estadoDesconectado); cmdDisconnect.setEnabled(estado == estadoConectado); if (dispositivoBluetooth != null) { mensagens = new String[3]; if (estado == estadoConectado) { mensagens[0] = "Conectado:"; } else if (estado == estadoConectando) { mensagens[0] = "Conectando:"; } else if (estado == estadoDesconectando) { mensagens[0] = "Desconectando:"; } else if (estado == estadoDesconectado) { mensagens[0] = "Selecionado:"; } mensagens[1] = DispositivoBluetooth.getNome(); mensagens[2] = " (" + DispositivoBluetooth.getEndereco() + ")"; } else { mensagens = new String[1]; mensagens[0] = getString(R.string.SemDispositivo); } Mensagens.Notificacao(getApplicationContext(), mensagens); } 91 /** * Busca as informacoes nos controles visuais, como botoes ou barras de progresso, * e armazena estas informacoes em objetos {@link Motor}. */ private synchronized void AtualizaValoresMotor() { if (BluetoothConnection.Motor1 != null) { BluetoothConnection.Motor1.setLigado(cmdLigaDeslMot1.isChecked() Math.abs(sbPosDesMot1.getProgress() ValoresPreferencias.limiteInferiorMotor1 pbPosMot1.getProgress()) ValoresPreferencias.precisao); BluetoothConnection.Motor1.setHorario(sbPosDesMot1.getProgress() ValoresPreferencias.limiteInferiorMotor1 > pbPosMot1.getProgress()); } && + > + if (BluetoothConnection.Motor2 != null) { BluetoothConnection.Motor2.setLigado(cmdLigaDeslMot2.isChecked() Math.abs(sbPosDesMot2.getProgress() ValoresPreferencias.limiteInferiorMotor2 pbPosMot2.getProgress()) ValoresPreferencias.precisao); BluetoothConnection.Motor2.setHorario(sbPosDesMot2.getProgress() ValoresPreferencias.limiteInferiorMotor2 > pbPosMot2.getProgress()); } && + > + BluetoothConnection.Ima = cmdLigaDeslIma.isChecked(); } /** * Pega os valores dos objetos {@link Motor} e serializa em um numero inteiro de 0 a 255. * O numero e formado somando-se os valores conforme abaixo: * <br> * <br> Motor1 Ligado = 1 * <br> Motor1 Sentido = 2 * <br> Motor2 Ligado = 4 * <br> Motor2 Sentido = 8 * <br> Ima Ligado = 16 * * @return Um inteiro de 0 a 255. */ private synchronized static int PegaValoresMotor() { int retorno = 0; if (BluetoothConnection.Motor1.isLigado()) retorno += if (BluetoothConnection.Motor1.isHorario()) retorno += if (BluetoothConnection.Motor2.isLigado()) retorno += if (BluetoothConnection.Motor2.isHorario()) retorno += if (BluetoothConnection.Ima) retorno += 0x01; 0x02; 0x04; 0x08; 0x10; return retorno; } 92 /** * Armazena os valores das ultimas preferencias salvas. */ private static class ValoresPreferencias { private static int limiteInferiorMotor1; private static int limiteSuperiorMotor1; private static int limiteInferiorMotor2; private static int limiteSuperiorMotor2; private static int precisao; } } package ufg.eeec.guincho; import import import import java.io.IOException; java.io.InputStream; java.io.OutputStream; java.util.UUID; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; /** * Cria todas as condicoes para comunicacao Bluetooth. * */ public class BluetoothConnection { /** * * Define os parametros da conexao Bluetooth * * */ private static String mensagemErro; private static BluetoothSocket bluetoothSocket; private static OutputStream outputStream; private static InputStream inputStream; public static Motor Motor1, Motor2; public static boolean Ima; public static boolean Conectar(String enderecoDispositivo) { BluetoothAdapter bluetoothAdapter BluetoothAdapter.getDefaultAdapter(); if (bluetoothAdapter != null) { BluetoothDevice bluetoothDevice bluetoothAdapter.getRemoteDevice(enderecoDispositivo); = = try { mensagemErro = "Erro ao criar conexao com dispositivo"; bluetoothSocket = bluetoothDevice.createRfcommSocketToServiceRecord(UUID.fromString("00001101 -0000-1000-8000-00805F9B34FB")); 93 mensagemErro = "Erro ao conectar ao dispositivo"; bluetoothSocket.connect(); mensagemErro = "Erro ao solicitar Canal de Saida"; outputStream = bluetoothSocket.getOutputStream(); mensagemErro = "Erro ao solicitar Canal de Entrada"; inputStream = bluetoothSocket.getInputStream(); Motor1 = new Motor(); Motor2 = new Motor(); return true; } catch (IOException e) { Desconectar(); return false; } } else { mensagemErro = "Nao foi encontrado adaptador Bluetooth."; return false; } } public static boolean Desconectar() { try { if (outputStream != null) outputStream.close(); } catch (IOException e) {} try { if (inputStream != null) inputStream.close(); } catch (IOException e) {} try { if (bluetoothSocket != null) bluetoothSocket.close(); } catch (IOException e) {} outputStream = null; inputStream = null; bluetoothSocket = null; Motor1 = null; Motor2 = null; Ima = false; return true; } public static int Ler() throws IOException { int valor = inputStream.read(); System.out.println("In: " + valor); return valor; } public static void Escrever(int valor) throws IOException { outputStream.write(valor); System.out.println("Out: " + valor); 94 } public static String getMensagemErro() { return mensagemErro; } /** * * Define os valores ativados para os Motores e para o Ima * */ public static class Motor { private boolean ligado = false; private boolean horario = true; public synchronized boolean isLigado() { return ligado; } public synchronized void setLigado(boolean ligado) { this.ligado = ligado; } public synchronized boolean isHorario() { return horario; } public synchronized void setHorario(boolean horario) { this.horario = horario; } } } package ufg.eeec.guincho; import import import import import java.util.ArrayList; java.util.HashMap; java.util.Iterator; java.util.Map; java.util.Set; import import import import import import import import import import import import import import import import import android.app.Activity; android.app.AlertDialog; android.app.Dialog; android.bluetooth.BluetoothAdapter; android.bluetooth.BluetoothDevice; android.content.BroadcastReceiver; android.content.Context; android.content.DialogInterface; android.content.Intent; android.content.IntentFilter; android.os.Bundle; android.provider.Settings; android.view.View; android.widget.AdapterView; android.widget.Button; android.widget.ListView; android.widget.SimpleAdapter; 95 public class BluetoothActivity extends Activity { private BluetoothAdapter bluetooth; @Override protected void onDestroy() { try { unregisterReceiver(broadcastReceiver); } catch (Exception e) {} super.onDestroy(); } private int DialogTitle, DialogText; private String DialogTitleString; private DialogInterface.OnClickListener DialogOkAction; private DialogInterface.OnClickListener DialogCancelAction; final private int DialogOk = 0, DialogOkCancel = 1, DialogWishConnect = 2; final private int turnOnBluetooth = 100; final private int showBluetoothConfig = 200; @Override protected Dialog onCreateDialog(int id) { switch (id) { case DialogOk: return AlertDialog.Builder(BluetoothActivity.this) .setTitle(DialogTitle) .setPositiveButton(android.R.string.ok, DialogOkAction) .setMessage(DialogText) .create(); case DialogOkCancel: return AlertDialog.Builder(BluetoothActivity.this) .setTitle(DialogTitle) .setPositiveButton(android.R.string.ok, DialogOkAction) .setNegativeButton(android.R.string.cancel, DialogCancelAction) .setMessage(DialogText) .create(); case DialogWishConnect: return AlertDialog.Builder(BluetoothActivity.this) .setTitle(DialogTitleString) .setPositiveButton(android.R.string.ok, DialogOkAction) .setNegativeButton(android.R.string.cancel, DialogCancelAction) .setMessage(DialogText) .create(); default: return null; } } @Override protected Intent data) { void onActivityResult(int requestCode, int new new new resultCode, 96 switch (requestCode) { case turnOnBluetooth: if (resultCode == RESULT_CANCELED) TurnOnBluetooth(); break; case showBluetoothConfig: LoadBTTypes(); break; } super.onActivityResult(requestCode, resultCode, data); } private final BroadcastReceiver() { BroadcastReceiver broadcastReceiver = @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().compareTo(BluetoothAdapter.ACTION_STATE_CHANGED) { if (intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1) BluetoothAdapter.STATE_OFF) TurnOnBluetooth(); else (intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1) BluetoothAdapter.STATE_ON) LoadBTTypes(); } } }; new == 0) == if == private void TurnOnBluetooth() { if (!bluetooth.isEnabled()) { DialogTitle = R.string.BluetoothOffTitle; DialogText = R.string.BluetoothOffText; DialogOkAction = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE), turnOnBluetooth); } }; DialogCancelAction = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (!bluetooth.isEnabled()) BluetoothActivity.this.finish(); } }; showDialog(DialogOkCancel); } else LoadBTTypes(); } 97 public static final String name = "Name", address = "Address"; private void LoadBTTypes() { final ListView findViewById(R.id.lstBTTypes); lstBTTypes = (ListView) String[] from = {name, address}; int[] to = {android.R.id.text1, android.R.id.text2}; Set<BluetoothDevice> devices = bluetooth.getBondedDevices(); if (devices != null) lstBTTypes.setAdapter(new SimpleAdapter(this, DevicesToNameAddress(devices), android.R.layout.simple_list_item_2, from, to)); } private ArrayList<Map<String, DevicesToNameAddress(Set<BluetoothDevice> devices) { ArrayList<Map<String, String>> nameAddress ArrayList<Map<String,String>>(); String>> = new Iterator<BluetoothDevice> iterator = devices.iterator(); while (iterator.hasNext()) nameAddress.add(DeviceToMap(iterator.next())); return nameAddress; } private Map<String, String> DeviceToMap(BluetoothDevice device) { Map<String, String> map = new HashMap<String, String>(); map.put(name, device.getName()); map.put(address, device.getAddress()); return map; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.bluetooth); bluetooth = BluetoothAdapter.getDefaultAdapter(); if (bluetooth != null) { registerReceiver(broadcastReceiver, IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED)); TurnOnBluetooth(); new ((Button) findViewById(R.id.btnBTConfig)).setOnClickListener(new Button.OnClickListener() { @Override public void onClick(View v) { startActivityForResult(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS), showBluetoothConfig); } }); 98 final ListView findViewById(R.id.lstBTTypes); lstBTTypes = (ListView) lstBTTypes.setOnItemClickListener(new ListView.OnItemClickListener() { @Override public void arg1, int item, long arg3) { final lstBTTypes.getItemAtPosition(item); onItemClick(AdapterView<?> Map<?, ?> map = arg0, View (Map<?, ?>) DialogTitleString = ((String) map.get(name)) + "\n(" + ((String) map.get(address)) + ")"; DialogText = R.string.WishConnect; DialogOkAction = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Intent data = new Intent(); data.putExtra(name, (String) map.get(name)); data.putExtra(address, (String) map.get(address)); BluetoothActivity.this.setResult(BluetoothActivity.RESULT_OK, data); BluetoothActivity.this.finish(); } }; DialogCancelAction DialogInterface.OnClickListener() { @Override public void = new onClick(DialogInterface dialog, int which) {} }; showDialog(DialogWishConnect); } }); } else { DialogTitle = R.string.BluetoothAdapterNotFoundTitle; DialogText = R.string.BluetoothAdapterNotFoundText; DialogOkAction = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { BluetoothActivity.this.finish(); } }; showDialog(DialogOk); } } } 99 package ufg.eeec.guincho; import android.os.Bundle; import android.preference.PreferenceActivity; public class Preferencias extends PreferenceActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences); setResult(BluetoothActivity.RESULT_OK); } } package ufg.eeec.guincho; import import import import import import android.annotation.SuppressLint; android.content.Context; android.view.Gravity; android.widget.LinearLayout; android.widget.TextView; android.widget.Toast; public class Mensagens { @SuppressLint("ShowToast") public static void Notificacao(Context context, String[] mensagens) { if (mensagens != null) { if (mensagens.length > 0) { Toast toast = Toast.makeText(context, mensagens[0], Toast.LENGTH_SHORT); LinearLayout linearLayout = (LinearLayout) toast.getView(); for (int i = 1; i < mensagens.length; i++) { TextView textView = (TextView) Toast.makeText(context, mensagens[i], Toast.LENGTH_SHORT).getView().findViewById(android.R.id.message); ((LinearLayout) textView.getParent()).removeView(textView); linearLayout.addView(textView); } linearLayout.setGravity(Gravity.CENTER_HORIZONTAL); toast.show(); } } } } 100