Universidade Federal do Rio de Janeiro Escola Politécnica Departamento de Eletrônica e de Computação Android Oscilloscope: Osciloscópio com Tecnologia Android Autor: _________________________________________________ Luiz Alberto Santos da Silva Orientador: _________________________________________________ Prof. Sergio Barbosa Villas-Boas, Ph. D. Examinador: _________________________________________________ Prof. Aloysio de Castro Pinto Pedroza, Dr. Examinador: _________________________________________________ Prof. Jorge Lopes de Souza Leão, Dr. DEL Janeiro de 2014 UNIVERSIDADE FEDERAL DO RIO DE JANEIRO Escola Politécnica – Departamento de Eletrônica e de Computação Centro de Tecnologia, bloco H, sala H-217, Cidade Universitária Rio de Janeiro – RJ CEP 21949-900 Este exemplar é de propriedade da Universidade Federal do Rio de Janeiro, que poderá incluí-lo em base de dados, armazenar em computador, microfilmar ou adotar qualquer forma de arquivamento. É permitida a menção, reprodução parcial ou integral e a transmissão entre bibliotecas deste trabalho, sem modificação de seu texto, em qualquer meio que esteja ou venha a ser fixado, para pesquisa acadêmica, comentários e citações, desde3 que sem finalidade comercial e que seja feita a referência bibliográfica completa. Os conceitos expressos neste trabalho são de responsabilidade do(s) autor(es) e do(s) orientador(es). ii iii AGRADECIMENTO Dedico este trabalho, primeiramente, a Deus, à minha família, ao meu Orientador Prof. Sergio Barbosa Villas-Boas e a todos que contribuíram de forma significativa à minha formação e estada nesta Universidade. Este projeto é uma pequena forma de retribuir o investimento e confiança em mim depositados. iv RESUMO O presente trabalho visa implementar um osciloscópio em um sistema operacional Android, que se comunique com um hardware utilizando a tecnologia Bluetooth. Dessa forma, será possível trazer um pouco do instrumento de bancada mais utilizado em laboratórios de eletrônica para diversos lugares, através de um dispositivo móvel. Palavras-Chave: osciloscópio, Android, Arduino, Bluetooth. v ABSTRACT The objective of this project is to implement an oscilloscope on Android operating system that communicates with a hardware using Bluetooth technology. That way, it’ll be possible bring a little more of that bench instrument, heavily used in electronic laboratories, to different places, through a mobile device. Key-words: oscilloscope, Android, Arduino, Bluetooth. vi SIGLAS SDK – Software Development Kit iOS – iPhone Operational System OS – Operational System IDE – Integrated Development Environment ADT – Android Development Tools A/D – Analógico / Digital ISR – Interrupt Service Routine UART - Universal asynchronous receiver/transmitter API – Application Programming Interface ADSC – A/D Start Conversion vii Sumário 1 Introdução 1.1 – Tema 1.2 – Delimitação 1.3 – Justificativa 1.4 – Objetivos 1.5 – Metodologia 1.6 – Descrição 1 1 1 1 2 2 2 2 Android 2.1 – Sistema Operacional Android 2.2 – Recursos do Android 2.3 – Versões do Android 2.4 – Ferramentas para Desenvolvimento 2.5 – Estrutura de um Aplicativo Android 2.5.1 – Estrutura do Projeto no IDE Eclipse 2.5.2 – Activities e Intents 2.5.2.1 – Activity 2.5.2.2 – Intent 2.6 – API Bluetooth para Android 2.6.1 – Tornando o dispositivo descobrível e procurando por outros dispositivos 2.6.2 – Comunicação Bluetooth 2.7 – API aChartEngine 1.0.0 4 4 4 5 5 6 6 7 8 12 14 3 Hardware 3.1 – Arduino 3.1.1 – Conversor A/D do Arduino 3.1.1.1 – Arquitetura 3.1.1.2 – Clock e Prescaler 3.1.2 – Software Arduino IDE 3.2 – Módulo Bluetooth 21 21 22 23 24 27 30 4 Android Oscilloscope 4.1 – Análise do Código para o Arduino 4.1.1 – Definições do Código para o Arduino 4.1.2 – Tecnologias Arduino e Módulo Bluetooth 4.2 – Análise do Aplicativo Android 4.2.1 – Activity Inicial 4.2.2 – Bluetooth Android 4.2.3 – Activity do Osciloscópio 4.2.3.1 – Processo de Exibição do Gráfico 4.2.3.2 – Cálculo de Vmáx, Vpp e Frequência 4.2.3.3 – Trigger do Osciloscópio 32 32 32 34 35 35 37 38 41 43 46 5 Conclusões Bibliografia 49 50 viii 16 17 18 Lista de Figuras Figura 2.1 – Exemplo AndroidManifest.xml Figura 2.2 – Exemplo Activity Figura 2.3 – Ciclo de Vida da Activity Figura 2.4 – Ciclo de Vida da Activity com Instances Figura 2.5 – Exemplo de Instances Figura 2.6 – Intent no AndroidManifest Figura 2.7 – Métodos para chamar outra Activity Figura 2.8 – Resultado da Activity Figura 2.9 – Armazenar valor para a próxima Activity Figura 2.10 – Exemplo de onActivityResult Figura 2.11 – Permissão Bluetooth no AndroidManifest Figura 2.12 – Verifica se Bluetooth está Ativo Figura 2.13 – Solicitar Ativação Bluetooth Figura 2.14 – Conexão com Dispositivo Bluetooth Figura 2.15 – Site da API AChartEngine Figura 3.1 – Site da Arduino Figura 3.2 – Diagrama de Blocos do Conversor A/D Figura 3.3 – Configuração padrão do Prescaler do Microcontrolador Figura 3.4 – Código Setup do Teste de Prescaler Figura 3.5 – Código Loop do Teste de Prescaler Figura 3.6 – Resultado com Prescaler igual a 64 Figura 3.7 – Resultado com Prescaler igual a 4 Figura 3.8 – Código Exemplo de Estrutura de Programa para Arduino Figura 3.9 – Módulo Bluetooth Figura 4.1 – Exemplo de Profundidade de Memória Figura 4.2 – Tela Inicial do Aplicativo Figura 4.3 – Tela About do Aplicativo Figura 4.4 – Solicitando Permissão para ativar Bluetooth Figura 4.5 – Menu do Aplicativo Figura 4.6 – DeviceListActivity Figura 4.7 – Conectando ao dispositivo Bluetooth Figura 4.8 – Exemplo 1 – Cálculo Vmax e Vpp Figura 4.9 – Exemplo 2 – Cálculo Vmax e Vpp Figura 4.10 – Exemplo – Cálculo de Frequência Figura 4.11 – Exemplo – Trigger do Osciloscópio Figura 4.12 – Exemplo dos Botões da Activity Principal ix 7 8 10 11 12 12 13 13 13 14 14 15 15 18 20 22 23 24 25 25 26 27 29 31 33 36 37 39 40 41 42 44 45 46 47 48 Capítulo 1 Introdução 1.1 – Tema O tema do trabalho consiste no estudo e implementação de um aplicativo com funções de um osciloscópio, armazenado em um dispositivo móvel com sistema operacional Android. Este dispositivo recebe o sinal amostrado por um Arduino, via comunicação Bluetooth. Desta forma, o dispositivo com Android vai possibilitar ao usuário a visualização do sinal na tela do mobile. 1.2 – Delimitação O desenvolvimento restringe-se ao ambiente Android, plataforma que, junto com o iOS (Apple), domina o mercado de smartphones. A escolha da plataforma se deve a facilidade para desenvolver no ambiente Android, podendo-se utilizar computadores com Windows, Mac OS ou Linux. Além de ser uma plataforma aberta, qualquer um pode baixar o código-fonte do Android e o Android SDK para desenvolvimento, sem custos. 1.3 – Justificativa A escolha da plataforma de desenvolvimento se justifica, conforme citado anteriormente, ao baixo custo de desenvolvimento e por possuir, atualmente, um grande número de consumidores. Quanto ao osciloscópio, este é um instrumento que nos permite observar e efetuar medidas de um sinal de tensão elétrica. A intenção do projeto, pelo fato de ser portátil, é alcançar outros usuários. 1 1.4 – Objetivos O objetivo geral é criar uma aplicação para Android que simule as funcionalidades de um osciloscópio real, logicamente com algumas limitações que o hardware impõe. O sinal a ser observado na tela do mobile é o sinal lido e amostrado pelo Arduino e transmitido via Bluetooth. O objetivo não é desenvolver um aplicativo que possua exatamente as mesmas especificações ou algo próximo de um osciloscópio real, pois para isso seria necessário o uso de um hardware mais específico e consequentemente mais custoso. 1.5 – Metodologia Este projeto foi desenvolvido, em sua maioria, utilizando linguagem de programação Java e uma biblioteca open source (achartengine) para construir os gráficos e exibi-los na tela. A IDE escolhida para o desenvolvimento do Software Android foi o Eclipse, também open source e possui compatibilidade com as ferramentas Android: componentes Android SDK e ADT Plugin para Eclipse. O computador utilizado foi um com sistema operacional Windows 7. Para o hardware, responsável por tratar o sinal e depois transmiti-lo para o dispositivo móvel, foram utilizados: um microcontrolador Arduino, modelo UNO R3, com um conversor A/D com entrada analógica de no máximo 5 Volts de tensão e capaz de amostrar sinais analógicos com resolução de 10 bits e um módulo de comunicação serial Bluetooth, modelo HC-05. No software para Arduino foi utilizada a linguagem de programação C e uma IDE disponibilizada pela própria fabricante do Arduino que nos permite desenvolver e fazer o upload do aplicativo para a memória do microcontrolador. 1.6 – Descrição No capítulo 2 falaremos sobre o Android: como está o cenário atual para os desenvolvedores e para os usuários, assim como sua arquitetura de sistema operacional, bibliotecas e recursos disponíveis e a estrutura de um aplicativo Android em linguagem 2 de programação Java. Esse capítulo foi reservado para explicitar o conhecimento teórico de programação Android absorvido na graduação que foi de grande valia para o desenvolvimento do projeto. O capítulo 3 abordará o hardware do projeto: características do Arduino e do módulo de comunicação Bluetooth. Os detalhes de implementação do projeto e a análise dos resultados serão apresentados no capítulo 4. Por fim, o capítulo 5 com as conclusões acerca do projeto: objetivos realizados e possíveis melhorias a serem feitas. 3 Capítulo 2 Android 2.1 – Sistema Operacional Android O Android é um sistema operacional para mobile que é baseado em uma versão modificada do Linux. Este foi adquirido, junto com a equipe de desenvolvimento, pela Google, como parte da estratégia para entrar no mercado de dispositivos móveis. Quando o iPhone foi lançado, muitos fabricantes tiveram que encontrar novas formas de revitalizar seus produtos. Para estes fabricantes de hardware, o Android foi visto como uma solução, eles continuam a fabricar seu hardware e usam o Android como o sistema operacional que o potencializa. Existir um sistema operacional para mobile, open source, como o Android, possibilita-os customizar o sistema para diferenciar seu produto. Para os desenvolvedores, a principal vantagem de programar para Android é que ele oferece uma abordagem única nas aplicações. Desenvolvedores precisam desenvolver somente para Android, e, com isso, suas aplicações devem ser capazes de rodar em diferentes dispositivos. 2.2 – Recursos do Android Um dos benefícios de desenvolver para o Android é o fato da plataforma ser open source. O sistema operacional é aberto e livre, permitindo que o desenvolvedor veja o código-fonte e veja como seus recursos são implementados. O desenvolvedor pode também contribuir reportando erros ou participando de grupos de discussão. Existem inúmeros aplicativos Android da Google e outros disponíveis na internet. Por ser um sistema livre, não existem hardwares ou softwares fixos, no entanto, existem recursos que o Android oferece: Suporta GSM/EDGE, CDMA, Bluetooth, Wi-Fi e 3G; Sensores de acelerômetro e proximidade, câmera e GPS; 4 Suporta telas multi-touch (capaz de reconhecer mais de dois pontos de contato com a tela); Suporta aplicações multitarefa; Inclui suporte a diversos formatos de mídia: H.264, H.263, MP4, MP3, JPEG, PNG, GIF; Usa SQLite para armazenagem de dados. 2.3 – Versões do Android Cada versão do Android é nomeada com o nome de um doce, e segue ordem alfabética: Android 1.6 (Donut); Android 2.0/2.1 (Eclair); Android 2.2 (Froyo); Android 2.3 (Gingerbread); Android 3.0/3.1/3.2 (Honeycomb); Android 4.0 (Ice Cream Sandwich); Android 4.1/4.2/4.3 (Jelly Bean). O aplicativo Android desenvolvido para este projeto pode ser executado em celulares com a versão 2.3 ou maior. 2.4 – Ferramentas para Desenvolvimento O ambiente de desenvolvimento mais recomendado para programar aplicativos Android é o Eclipse. É uma IDE que suporta diversas linguagens, incluindo Java, linguagem utilizada na maioria dos aplicativos Android. É uma IDE que segue o modelo de open souce no desenvolvimento de Software. A IDE escolhida para este projeto foi o Eclipse, por se tratar de um ambiente que possui maior compatibilidade com o Android. O Eclipse, juntamente com o plugin ADT, é o único oficialmente suportado e recomendado pela Google. O ADT (Android Development Tools) permite criar, executar e depurar aplicativos Android, e é possível também exportar o aplicativo para arquivo .apk para futura distribuição, no Android Market, por exemplo. Este plugin também inclui uma 5 interface gráfica de desenvolvimento (GUI), sendo possível arrastar e largar componentes em qualquer lugar da tela, sem uso de código para tal. Uma outra ferramenta é o Android Emulator, inclusa no Android SDK, que permite executar aplicativos Android em um ambiente simulado. Este emulador apresenta a tela de um mobile com Android. Antes de executar o aplicativo, é necessário criar um AVD (Android Virtual Device) que define as características do dispositivo, como o hardware, o tamanho da tela, armazenagem dos dados e outros. Para testar o aplicativo em diferentes dispositivos Android é preciso criar diferentes AVD’s, cada um emulando um dispositivo específico. O Android Emulator não se faz tão necessário se o desenvolvedor já possuir um dispositivo móvel. Neste projeto não foi preciso usar esta ferramenta, se fez uso de um dispositivo Android da fabricante Samsung. É possível encontrar um passo a passo de como instalar e configurar o ambiente no site: http://developer.Android.com. 2.5 – Estrutura de um Aplicativo Android O próximo passo é entender como é a estrutura de um aplicativo Android: estrutura do projeto no IDE Eclipse, o arquivo AndroidManifest.xml, Activities e Intents, componentes de uma tela Android, trabalhar com orientação da tela. 2.5.1 – Estrutura do Projeto no IDE Eclipse São várias as pastas e arquivos que compõe um projeto Android no Eclipse, seguem as principais pastas abaixo: src – a pasta que contém todos os arquivos-fonte .java do projeto; gen – o arquivo R.java fica localizado nesta pasta. Um arquivo gerado pelo compilador que referencia todos os recursos do projeto. Este arquivo não deve ser alterado pelo desenvolvedor; Android 2.3.3 – contém o arquivo android.jar, possui todas as classes necessárias para uma aplicação Android; assets – contém arquivos HTML, arquivos texto, banco de dados, etc; bin – onde fica armazenado o arquivo .apk gerado; res – possui algumas subpastas como: layout, menus e values; 6 AndroidManifest.xml – o arquivo manifest da aplicação, discutido mais a frente. O arquivo AndroidManifest.xml contém informações sobre a aplicação: Figura 2.1 – Exemplo AndroidManifest.xml. Fonte: Oscilloscope Android. Define o nome do pacote da aplicação; Define permissões de uso como, por exemplo, a do Bluetooth; Na aba application alguns atributos definem o nome da aplicação, string app_name, e a figura do ícone da aplicação e, dentro, as declarações das activity’s; A aba action dentro de intent-filter indica a activity ChartDemo como a principal da aplicação. A aba category define que esta mesma activity é a que será executada quando o usuário clicar no ícone da aplicação; Mais abaixo o atributo android:minSdkVersion da aba uses-sdk especifica a menor versão do sistema operacional, na qual a aplicação funcionará. 2.5.2 – Activities e Intents Uma activity é uma janela que contém a interface com o usuário da aplicação. É um componente que possui vários estágios dentro de uma aplicação, conhecido como o ciclo de vida da activity. Conhecer este ciclo é importantíssimo para ter certeza que a aplicação funciona corretamente. 7 Outro componente abstrato importante em um aplicativo Android é o intent. É basicamente o que une diferentes activities de diferentes aplicações, podendo ser usada para “chamar” aplicações nativas do Android como o navegador, telefone, mapas, email, e outras. 2.5.2.1 – Activity Para criar uma Activity basta criar uma classe Java que estende uma classe base Activity. Figura 2.2 – Exemplo Activity. Fonte: Oscilloscope Android. Todos esses métodos podem ser sobrescritos, já que com o extends pode-se estender as funcionalidades da classe Activity e herdar todos os métodos. O método super inicializa a classe pai antes de inicializar a classe herdeira. A Activity é definida de acordo com o arquivo XML que fica no diretório res/layout do projeto. O método setContentView vai indicar o XML específico da activity. Toda activity do projeto deve ser declarada no AndroidManifest.xml. A classe base segue uma série de eventos que definem o ciclo de vida de uma Activity. Os eventos são: 8 onCreate() – evento chamado quando a Activity é criada pela primeira vez. Sempre seguido de onStart(); onStart() – evento chamado quando ela se torna visível para o usuário. Seguido por onResume() se a activity estiver entrando em primeiro plano ou por onStop() se estiver saindo do primeiro plano; onResume() – chamado quando a Activity começa a interagir com usuário. Sempre seguido por um onPause(); onPause() – acontece quando a activity atual é pausada e a anterior começa a interagir com o usuário. Seguido por onResume(), se a activity estiver voltando para o primeiro plano ou onStop(), se estiver ficando invisível para o usuário; onStop() – quando a activity não é mais visível para o usuário. Seguido por onRestart(), se a activity estiver voltando a interagir com o usuário ou onDestroy(), se estiver sendo encerrada; onDestroy() – chamada antes da activity ser destruída pelo sistema (manualmente ou para o sistema conservar memória). Pode acontecer se a activity está sendo finalizada pela (chamada do método finish()) ou porque o sistema está tentando liberar recursos; onRestart() – chamada quando a activity for parada e depois reiniciada. Sempre seguida do onStart(). O ciclo de vida inteiro de uma activity acontece entre o onCreate() e o onDestroy(). No onCreate() são feitas todas as configurações globais, como criar as views, instanciar objetos que serão usados na aplicação e chamar o método setContentView(), por exemplo, e no onDestroy() são liberados os recursos utilizados. O ciclo de vida visível acontece entre o onStart() e o onStop(). Neste intervalo, o usuário pode ver a activity, mesmo que esta esteja em segundo plano e não esteja interagindo com o usuário. O ciclo de vida em primeiro plano acontece entre o onResume() e o onPause(). Entre estes dois métodos, a activity está em primeiro plano e interagindo com o usuário. No onResume() podemos iniciar qualquer serviço ou código que precisa ser executado enquanto a activity está em primeiro plano. Enquanto no onPause() podemos parar os serviços ou códigos que não precisam ser executados quando a activity está em segundo plano. 9 Segue abaixo um esquemático do ciclo de vida da Activity: Figura 2.3 – Ciclo de Vida da Activity. Fonte: http://developer.Android.com/reference/Android/app/Activity.html. Outros dois métodos importantes dentro do ciclo de vida de uma activity são: onSaveInstanceState() e o onRestoreInstanceState(). Quando uma activity é pausada ou parada, o objeto da classe Activity se mantém na memória, isto é, o estado atual do objeto permanece intacto. Todas as alterações que o usuário faz são salvas e quando a activity retorna para o primeiro plano, essas mudanças permanecem. Mas quando o 10 sistema destrói e o usuário inicia a activity novamente, o objeto é recriado. Para preservar o estado da activity pode-se sobrescrever o método onSaveInstanceState(). O sistema passa para esse método um Bundle (contém pares de nomes e valores), onde podemos guardar as informações. Assim, quando o sistema destrói e recria a activity, este Bundle é passado o onCreate() e o onRestoreInstanceState(). Figura 2.4 – Ciclo de Vida da Activity com Instances. Fonte: http://developer.Android.com/reference/Android/app/Activity.html. Este dois métodos são muito úteis quando uma mudança no dispositivo ocorre durante a execução do aplicativo, por exemplo, na orientação do mobile. Quando acontece, a activity é destruída e criada novamente. Pode-se tratar esta mudança de orientação usando esses dois métodos, pois, antes de a activity ser destruída, o onSaveInstanceState() é chamado e, quando for reconstruída, o onRestoreInstanceState() é chamado. Abaixo temos um exemplo, onde as variáveis x e i foram salvas para, posteriormente, serem recuperadas. 11 Figura 2.5 – Exemplo de Instances. Fonte: Oscilloscope Android. Também podemos adicionar uma tag, para cada activity, no AndroidManifest.xml e definir uma orientação fixa (screenOrientation) ou avisar ao Android para não chamar o onCreate() a cada mudança de orientação (configChanges). 2.5.2.2 – Intent Quando a aplicação tem mais de uma activity, inevitavelmente será necessário navegar de uma para outra. No Android, essa navegação entre activities é conhecida como intent. Como visto anteriormente, toda nova activity do projeto deve possuir um arquivo xml para definir o layout e uma classe que herda de Activity. No AndroidManifest.xml deve-se declarar a nova activity também e, nesse arquivo, pode-se inserir a tag intent-filter para definir o nome e a categoria do intent filter. Outras activities que quiserem chamar esta nova devem fazê-lo pelo nome do intent filter. Figura 2.6 – Intent no AndroidManifest. Fonte: Oscilloscope Android. Utiliza-se o método startActivity() para iniciar outra activity, criando uma instância da classe Intent e passando para o construtor dessa classe o nome do intent 12 filter. Desta forma, a activity pode ser chamada por qualquer outra aplicação do dispositivo móvel. Mas se a activity a ser invocada é da mesma aplicação, o método startActivity() pode ser usado da segunda maneira abaixo. Figura 2.7 – Métodos para chamar outra Activity. Fonte: Oscilloscope Android. O método startActivity() invoca uma outra activity mas não possibilita o retorno de informação para a activity atual. Para isso, pode-se utilizar o método startActivityForResult(). Além de passar um objeto da classe Intent, é necessário passar um inteiro porque quando uma activity retorna um valor precisamos de uma forma de identificar qual foi a activity. Figura 2.8 – Resultado da Activity. Fonte: Oscilloscope Android. Na activity chamada, para retornar um valor, pode-se usar o método setData() ou putExtra() da classe Intent. Neste segundo, passamos o par de atributos nome e valor, conforme visto na figura abaixo. Figura 2.9 – Armazenar valor para a próxima Activity. Fonte: Oscilloscope Android. Além destes métodos, podemos criar um objeto da classe Bundle e utilizar o método putExtras(). Para recuperar os dados na activity original, utilizamos o método onActivityResult(). Este método recebe dois inteiros e um objeto da classe Intent. O 13 requestCode é o código original fornecido para o método startActivityForResult(), para identificar de qual activity veio o resultado. O resultCode é o código enviado pela activity chamada no método setResult(). O objeto da classe Intent é o que fornecerá os dados enviados pela activity chamada. Com o método, da classe Intent, getStringExtra() podemos recuperar os dados enviados pela activity chamada. Figura 2.10 – Exemplo de onActivityResult. Fonte: Oscilloscope Android. 2.6 – API Bluetooth para Android Utilizando a API do Bluetooth, pode-se procurar por e conectar-se a outros dispositivos Bluetooth. Iniciando o link de comunicação, usando os Sockets Bluetooth, é possível transmitir e receber dados entre dispositivos. O dispositivo Bluetooth local é controlado através da classe BluetoothAdapter, que representa o dispositivo Android em que a aplicação está executando. Para acessar o adaptador Bluetooth padrão pode-se utilizar o método getDefaultAdapter(). Antes de iniciar a busca por dispositivos Bluetooth, deve-se incluir as permissões do Bluetooth no AndroidManifest.xml. Para modificar as propriedades do dispositivo local, a permissão de BLUETOOTH_ADMIN deve ser concedida. Abaixo temos um exemplo das linhas a serem adicionadas no arquivo AndroidManifest.xml. Figura 2.11 – Permissão Bluetooth no AndroidManifest. Fonte: Oscilloscope Android. 14 O adaptador Bluetooth oferece métodos para leitura e configuração das propriedades do hardware Bluetooth. Esse adaptador pode ler ou configurar se estiver habilitado. Caso não esteja, o método getDefaultAdapter() retorna null. Este teste é feito no onCreate() da activity principal do projeto, conforme código abaixo. Figura 2.12 – Verifica se Bluetooth está Ativo. Fonte: Oscilloscope Android. Para conservar a vida da bateria, a maioria dos usuários mantém o Bluetooth desabilitado até eles planejarem utilizá-lo. Para habilitar o adaptador Bluetooth, pode-se usar a constante BluetoothAdapter.ACTION_REQUEST_ENABLE com o método startActivityForResult(). Aparecerá uma tela pedindo que o usuário habilite o Bluetooth. Código utilizado para tal pode ser visto abaixo: Figura 2.13 – Solicitar Ativação Bluetooth. Fonte: Oscilloscope Android. Com a permissão do BLUETOOTH_ADMIN inclusa no manifest é possível habilitar e desabilitar o Bluetooth do dispositivo usando os métodos enable e disable. Segue abaixo uma descrição das classes dessa API utilizadas para configurar o Bluetooth, procurar por dispositivos, conectar-se aos dispositivos pareados e transferir dados entre os dispositivos. BluetoothAdapter: representa o adaptador Bluetooth. Com essa classe, é possível procurar por outros dispositivos e se conectar a eles; BluetoothDevice: representa o outro dispositivo Bluetooth. Pode-se solicitar ao dispositivo remoto uma conexão ou informações do dispositivo; BluetoothSocket: representa a interface para um soquete Bluetooth; 15 BluetoothServerSocket: representa um servidor aberto para atender requisições de outros dispositivos. Funciona com um host. 2.6.1 – Tornando o dispositivo descobrível e procurando por outros dispositivos Para o dispositivo remoto encontrar o dispositivo local (Adaptador Bluetooth) é necessário que este esteja configurado como descobrível. Existe uma maneira de saber se o dispositivo local está descobrível ou não através do método getScanMode da classe BluetoothAdapter. Esse método retorna uma das seguintes constantes: SCAN_MODE_CONNECTABLE_DISCOVERABLE – significa que o adaptador local Bluetooth pode ser descoberto por qualquer outro dispositivo; SCAN_MODE_CONNECTABLE – significa que este não está descobrível para novos dispositivos remotos, ou seja, só pode conectar-se a dispositivos que já o descobriram anteriormente; SCAN_MODE_NONE – nenhum dispositivo remoto pode encontrar o adaptador Bluetooth local. Por questões de privacidade, esta ação fica, por padrão, desabilitada. É possível ligá-la através de uma permissão explícita do usuário, iniciando uma nova Activity usando ACTION_REQUEST_DISCOVERABLE. Também por padrão, o dispositivo local fica descobrível por dois minutos, porém é possível alterar a duração adicionando EXTRA_DISCOVERABLE_DURATION na execução do Intent. Para saber se o usuário permitiu ou não que o dispositivo fique apto a ser descoberto por outros dispositivos Bluetooth pode-se sobrescrever o onActivityResult() e verificar o parâmetro resultCode. Caso ele seja positivo, indica o tempo, em segundos, que o adaptador Bluetooth local ficará numa situação possível de ser descoberto. Caso seja negativo, indica que o usuário rejeitou o pedido. Alguns métodos úteis da classe BluetoothAdapter para encontrar outros dispositivos seguem abaixo: isDiscovering() – retorna um boolean que indica se o dispositivo está ou não fazendo uma busca por outros dispositivos remotos; 16 startDiscovery() – inicia uma busca por dispositivos que se encontram dentro do alcance do adaptador Bluetooth local; cancelDiscovery() – cancela a procura por outros dispositivo. 2.6.2 – Comunicação Bluetooth As API’s do Bluetooth para Android se baseiam no protocolo de comunicação RFCOMM, que são um mecanismo para abrir soquetes de comunicação entre dois dispositivos Bluetooth pareados. Antes que a aplicação possa estabelecer a comunicação entre os dispositivos, estes devem estar pareados, ou seja, ligados. Se o usuário tentar se conectar antes de parear, os dispositivos vão primeiro parear para em seguida se conectarem. Para estabelecer uma comunicação Bluetooth RFCOMM bidirecional podemos usar as classes: BluetoothServerSocket e BluetoothSocket. A primeira designa um dispositivo que age como um servidor, que atende e pode aceitar pedidos de conexão. Já a segunda, funciona como um cliente. Uma vez que estabelecemos uma conexão entre os dispositivos, os Bluetooth Sockets são usados para transferir dados. Um Bluetooth Server Socket é usado para esperar e atender pedidos de conexão de outros dispositivos Bluetooth. Para dois dispositivos Bluetooth se conectarem, um deles deve agir como servidor e o outro como cliente. Depois de conectados, a comunicação entre os dois é tratada por um Bluetooth Socket. O método listenUsingRfcommWithServiceRecord é usado para deixar o dispositivo “esperando” por pedidos de conexão. Os parâmetros são o nome que identifica o servidor e um identificador universalmente único (UUID). Para que o cliente possa se conectar ele deverá “saber” esse UUID. O método retorna um objeto BluetoothServerSocket. Quando o método accept() é chamado, o Server Socket irá bloquear até que um cliente tente se conectar com o UUID definido pelo servidor. Se a tentativa de conexão for realizada com um dispositivo remoto não pareado, aparecerá uma tela com um pedido de pareamento. Se a conexão for concluída com sucesso, o método accept() retornará um BluetoothSocket e este pode ser usado para transferência de dados entre os dispositivos. Abaixo segue código utilizado no projeto: 17 Figura 2.14 – Conexão com Dispositivo Bluetooth. Fonte: Oscilloscope Android. Depois de conectados, teremos um Bluetooth Socket para o dispositivo cliente e o servidor. Esse conceito de cliente e servidor só serve para exemplificar como funciona a comunicação entre os dispositivos até a conexão ser estabelecida. A partir deste momento não existe distinção entre os dispositivos, pode-se enviar e receber dados através do Bluetooth Socket. A transferência de dados entre os dispositivos é tratado pelas classe Java OutputStream e InputStream, que pode-se obter do Bluetooth Socket através dos métodos getOutputStream e getInputStream. 2.7 – API aChartEngine 1.0.0 Esta é uma API Android open source utilizada para criação de gráficos. São diversos tipos de gráficos disponíveis e muitas funcionalidades. Pode ser baixada no Google Code através do link: https://code.google.com/p/achartengine/. Pode ser baixada também no site dos desenvolvedores www.achartengine.org. Alguns dos recursos incluem: Classe Pan – permite que o usuário “arraste” o gráfico e possibilita uma visão maior deste. Também possui uma classe panListener própria; 18 Classe Zoom – obviamente, permite que o usuário efetue um zoom no gráfico. Também é possível criar um zoomListener para tratar um evento de zoom; Os gráficos são criados como uma view; Suporta vários tipos de gráficos; Suporta mais de uma série de dados em um mesmo gráfico. Para o projeto, foi utilizado o gráfico de linha com algumas modificações no renderizador (classe XYSeriesRenderer), que dizem respeito a parte estética do gráfico. A XYSeries é a classe que armazena os valores dos pontos do gráfico. É possível também remover um dado ponto e obter o valor máximo e o mínimo com seus métodos. A classe XYSeriesRenderer trata da estética da curva, no caso do gráfico de linha, como o estilo dos pontos do gráfico e a largura da linha. A XYMultipleSeriesRenderer é similar a classe anterior mas possui mais ferramentas e maiores possibilidades de alterar a estética do gráfico. Com esta última é possível alterar a cor da curva e do fundo, alterar a escala dos eixos, habilitar ou desabilitar o zoom e o “arrastar” do gráfico (pan), colocar rótulo para cada curva do gráfico, etc. É uma API de fácil utilização. O site dos desenvolvedores disponibiliza diversos exemplos para download, para auxiliar na compreensão e implementação de suas funcionalidades. Também estão disponíveis todos os javadocs. 19 Figura 2.15 – Site da API AChartEngine. Fonte: http://www.achartengine.org/. 20 Capítulo 3 Hardware 3.1 – Arduino É uma plataforma eletrônica open source, com um microcontrolador, que possui um ambiente de desenvolvimento específico para programar os componentes que o fazem parte. Ela pode ser comprada já pré-programada ou, por ser open source, pode ser construída pelo próprio usuário, ou seja, eles podem adaptá-la as suas necessidades e depois atualizar e distribuir suas próprias versões. Os esquemas, as características de cada versão, os datasheets dos seus componentes, além dos arquivos EAGLE para a montagem da própria placa podem ser encontrados no site do Arduino: www.arduino.cc. O software pode ser programado utilizando as linguagens C ou C++. No site do Arduino estão disponíveis para download a IDE, que permite o desenvolvimento e o carregamento do Software para o microcontrolador, e diversos exemplos para auxiliar todos os tipos de usuário do Arduino, que vão desde aqueles que levam como um passatempo até aqueles que possuem certa especialização em eletrônica. 21 Figura 3.1 – Site da Arduino. Fonte: http://arduino.cc/. No projeto do osciloscópio foi utilizada a versão Arduino Uno R3, por se tratar de uma versão que possui os componentes necessários e por ser menos custosa. Nesse tópico iremos tratar da arquitetura deste Arduino, evidenciando o conversor A/D, como funciona a programação utilizando a IDE e o código do projeto. 3.1.1 – Conversor A/D do Arduino O Arduino Uno R3 é baseado em um microcontrolador (ATmega238) que possui alguns componentes necessários para que este dispositivo possa se comunicar com o computador. Seguem abaixo algumas características dessa versão: Tensão de entrada: 7-12V; 14 pinos de entrada e saída digitais (6 saídas PWM – 8 bits); 6 entradas analógicas; 32 kbytes de memória Flash; Clock de 16 MHz; Suporta comunicação TWI; Conversor A/D de 10 bits de resolução. 22 Destes, o mais relevante para ser citado é o conversor A/D (ou ADC), pois foi trabalhado muito em cima dele, neste projeto. 3.1.1.1 – Arquitetura O ADC é usado para converter um sinal analógico (varia continuamente) em valores digitais. O valor analógico representa alguma medida real, neste caso uma medida de tensão elétrica. Como já é conhecido, os valores digitais não são contínuos, eles são amostrados um certo número de vezes a cada período de tempo. O conversor A/D do Arduino realiza a conversão através do método de aproximações sucessivas. Abaixo temos um diagrama simples que ilustra o ADC. Figura 3.2 – Diagrama de Blocos do Conversor A/D. Fonte: Modelo do datasheets do microcontrolador - http://www.atmel.com/Images/doc8161.pdf. O ADC possui oito entradas analógicas e que são controladas pelo multiplexador, isto é, a operação de conversão é realizada para uma entrada de cada vez. Após a conversão valor digital é armazenado em dois registradores (ADCH e ADCL), já que o ATmega328 é um microcontrolador de 8 bits e o conversor A/D possui 10 bits de resolução. A tensão de entrada (Vin), do sinal analógico, deve estar entre 0 volts e a tensão de referência do ADC (Vref). Normalmente, o Vref é igual a tensão de alimentação do Arduino. O valor convertido é o inteiro mais próximo do resultado da operação: Vin 10 2 1 . Vref 23 Existem dois modos de operação do conversor: conversão simples e o modo livre. No modo de conversão simples é necessário iniciar cada conversão, isto é, quando uma conversão é finalizada, os resultados são guardados nos registradores ADCH e ADCL. Nenhuma outra conversão é iniciada. Só será possível iniciar uma outra conversão quando o bit ADSC for para 1. Para indicar um evento de término de conversão, pode ser utilizada uma rotina de interrupção (ISR). No modo livre, a primeira conversão é iniciada e as outras subseqüentes são iniciadas automaticamente. Só será necessário indicar qual canal será convertido, através do registrador ADMUX. 3.1.1.2 – Clock e Prescaler O ADC deve ter um clock recomendado entre 50 kHz e 200 kHz, quando desejamos uma resolução de 10 bits. Isso nos leva a crer que existe um prescaler (divisor) para configurar o mesmo, já que o clock do microcontrolador é de 16 MHz. Para configurar o divisor, devemos trabalhar com os bits ADPS (2..0). Esses bits estão armazenados no registrador ADCSRA e podem ser atribuídos os valores 2, 4, 8, 16, 32, 64 e 128. Esse registrador é configurado por padrão no arquivo wiring.c da biblioteca do Arduino. Figura 3.3 – Configuração padrão do Prescaler do Microcontrolador. Fonte: código de API disponibilizada pelo fabricante Portanto, o clock do conversor A/D pode ser: 16 MHz / 2 = 8 MHz 24 16 MHz / 4 = 4 MHz 16 MHz / 8 = 2 MHz 16 MHz / 16 = 1 MHz 16 MHz / 32 = 500 kHz 16 MHz / 64 = 250 kHz 16 MHz / 128 = 125 kHz Para calcular ou chegar próximo de um valor para o tempo de amostragem, devemos levar em consideração quantos clock’s do ADC são necessários para uma conversão. De acordo com o datasheets do microcontrolador, na primeira conversão são necessários 25 clock’s de ADC e nas subseqüentes somente 13 clock’s. Logo, se configurarmos o prescaler para 64, teremos por volta de 19.230 amostras por segundo. Utilizando o código abaixo, somos capazes de medir o tempo de amostragem para cada conversão. Neste código, que será explicado mais a frente, configuramos o prescaler para 64. Mais abaixo, foram feitas cem medidas e, a cada conversão, tomamos o tempo antes e depois. O resultado está ilustrado na figura abaixo. Figura 3.4 – Código Setup do Teste de Prescaler. Fonte: Oscilloscope Android Figura 3.5 – Código Loop do Teste de Prescaler. Fonte: Oscilloscope Android 25 Pelo resultado abaixo, podemos calcular uma freqüência de amostragem de 16,667 kHz, ou seja, temos 16.667 amostras por segundo com o prescaler de 64, valor próximo do calculado anteriormente. Figura 3.6 – Resultado com Prescaler igual a 64. Fonte: Oscilloscope Android Por experiência neste projeto, pudemos comprovar que, conforme diminuímos o prescaler (tornando o ADC mais rápido), os valores de freqüência de amostragem medidos e calculados foram se afastando cada vez mais. Quando o divisor de freqüência foi configurado para 4, tivemos o resultado abaixo. Com um tempo de amostragem médio de 10 us. Essa é a configuração inicial utilizada no projeto, pois neste foram utilizados três tipos de prescaler, dependendo de qual escala de tempo o usuário escolher para fazer a análise do sinal. 26 Figura 3.7 – Resultado com Prescaler igual a 4. Fonte: Oscilloscope Android No datasheets do microocontrolador consta que quanto maior o clock do conversor A/D, menos se pode garantir uma resolução de 10 bits. Por facilitar a comunicação do Arduino com o dispositivo Android e baseado nesta recomendação a resolução utilizada para o conversor, no projeto do osciloscópio, foi de 8 bits. 3.1.2 – Software Arduino IDE Depois de entender como funciona, em parte, o hardware do Arduino, se faz necessário implementar esse entendimento via software. Através do código em C ou C++ podemos fazer todo o tratamento dos dados convertidos pelo ADC e transmiti-los via Bluetooth para o dispositivo Android. Neste tópico iremos abordar a estrutura de um programa para o microcontrolador do Arduino. Antes de adentrarmos a estrutura de um programa do Arduino, precisamos nos atentar a configuração do ambiente, para nos prevenir de futuros contratempos na etapa de programação e carregamento do software para o microcontrolador. 27 A plataforma (IDE) de desenvolvimento do software para o microcontrolador Arduino recomendada é a disponibilizada pela própria faricante: Arduino IDE. Apesar de possuir poucas funcionalidades, ela se mostra uma IDE simples e de fácil utilização. Para inicialmente instalar o ambiente de desenvolvimento devemos seguir alguns passos de configuração da plataforma, são eles: A própria instalação da IDE (executável no endereço www.arduino.cc/en/Main/Software); Necessário também instalar os drivers referentes à versão do hardware (placa) utilizada; Já na própria IDE, identificar e configurar a porta serial onde a placa está conectada. Essas etapas de configuração são simples e podem ser encontradas no manual disponibilizado pelo fabricante. Após conclusão, podemos nos dirigir diretamente ao código em si. Como já dito anteriormente, podemos programar o software do Arduino utilizando as linguagens de programação C e C++. A placa utilizada neste projeto (Arduino Uno R3) nos permite programar com as duas linguagens. Já que o código do projeto não possui uma complexidade alta, a ponto de fazermos uso de orientação a objetos, foi escolhido como linguagem padrão o C. A figura abaixo ilustra a interface gráfica da IDE e como é a estrutura de um programa do Arduino. 28 Figura 3.8 – Código Exemplo de Estrutura de Programa para Arduino. Fonte: Oscilloscope Android Existem dois blocos principais no programa, o setup e o loop. O setup é o bloco que é executado somente uma vez e no início da execução. Na maior parte dos códigos e exemplos presentes no IDE, no setup se coloca todas as configurações iniciais do programa. No exemplo acima, foi inicializada e configurada a velocidade da comunicação serial. Já no bloco de loop, o usuário aplica a parte do software que precisa ser executada continuamente. Obviamente, como indica o próprio nome, o loop é executado seguidamente até cessa a alimentação do hardware. Neste bloco, normalmente é onde fica a parte principal do código, seria como o main da programação voltada para 29 computadores. No exemplo acima, é feita uma conversão analógico-digital do pino A0, através da função analogRead(). Logo após é calculado o valor da tensão, a partir do valor digital medido, e depois este é transmitido pela porta serial. O Arduino possui uma biblioteca própria com diversas funções, abaixo seguem as mais conhecidas: pinMode() – configurar um pino específico da placa. Como entrada (INPUT) ou saída (OUTPUT) no caso de pinos digitais, por exemplo; digitalWrite() – com esta função é possível ligar ou desligar um pino digital, estado alto (HIGH) ou estado baixo (LOW). O pino deve ser previamente configurado como saída; digitalRead() – retorna o estado de um pino digital de entrada; analogReference() – atribui o valor da tensão de referência de uma entrada analógica. O padrão é 5 volts; analogRead() – retorna o valor digital convertido de um dado pino analógico; tone() – gera uma função quadrada de freqüência e duração desejadas. Foi utilizada para efeito de testes; micros() – retorna o tempo, em microssegundos, que decorreu desde que o programa iniciou a execução. Ainda existe a biblioteca de comunicação serial, muito utilizada nesse projeto. Essa API possui diversas funções, entre elas as de iniciar ou finalizar uma comunicação e de enviar e receber dados pelas vias TX e RX. 3.2 – Módulo Bluetooth O dispositivo usado no projeto para fazer a comunicação Bluetooth dos dados convertidos no Arduino para o dispositivo Android foi o modelo HC-05. Este é um módulo Bluetooth padrão no mercado, ou seja, é pouco custoso e é muito utilizado em aplicações simples. Para o propósito do projeto do osciloscópio Android, este dispositivo possui as características necessárias e se adéqua bem ao placa do Arduino. Este módulo quatro pinos: dois de alimentação e dois de transmissão e recepção dos dados. O VCC e GND foram ligados diretamente nos pinos de 5 volts e de comum 30 do Arduino e os pinos que possibilitam a comunicação foram ligados nos pinos da porta serial do Arduino. Segue abaixo uma imagem do dispositivo: Figura 3.9 – Módulo Bluetooth. Fonte:Imagem retirada do datasheets do módulo - http://www.exp-tech.de/service/datasheet/HCSerial-Bluetooth-Products.pdf 31 Capítulo 4 Android Oscilloscope 4.1 – Análise do Código para o Arduino Depois de entender como funciona a programação no Arduino, foi feita uma análise do que era preciso ser feito no software do projeto e foram definidos a estrutura e os requisitos para o programa no Arduino. Neste tópico serão abordadas as principais definições no software do Arduino, as tecnologias utilizadas e a comunicação serial via Bluetooth. 4.1.1 – Definições do Código para o Arduino A quantidade de informação enviada pelo Arduino para o Android é uma das definições mais importante do sistema, pois esta afeta diversos aspectos importantes neste projeto. Em um osciloscópio, dentre várias outras características, devemos nos atentar a uma em especial: taxa de atualização de tela ou também conhecida como “tempo morto”. Este é o tempo necessário para que o osciloscópio possa converter, disparar, processar os dados e então exibi-los na tela. Quanto maior essa taxa de atualização, maior a probabilidade de capturar um evento não freqüente. Neste projeto, a taxa de atualização ficou consideravelmente alta, mesmo o hardware utilizado não sendo de alta performance. Obviamente, nada comparado aos osciloscópios padrões de bancada disponíveis no mercado. Estes podem alcançar taxas de atualização da ordem de femtossegundos. Para a quantidade de informação enviada (quantidade de amostras) ficou definido o envio de 500 amostras com valores convertidos pelo ADC para o dispositivo Android. Parece uma quantidade exagerada de amostras, mas foi o necessário para varrer o gráfico em uma tela inteira do programa Android e garantir que teremos amostras suficientes sem que prejudique o sistema de trigger do Osciloscópio. Isto é, 32 devemos ter uma quantidade de amostras que permita ao software do Android, após identificar o ponto de início do gráfico (trigger point), preencher a tela inteira. A essa quantidade de amostras capturadas pelo osciloscópio é dado o nome de profundidade de memória, que seria igual à taxa de amostragem multiplicado pela configuração do tempo por divisão (escala no tempo) multiplicado ainda pela quantidade de divisões. No exemplo abaixo do aplicativo Oscilloscope, podemos ver que temos cinco divisões no tempo e que a escala no tempo é de 1,0 milissegundos por divisão. Sabendo que a taxa de amostragem para esta situação é de 100 kHz, podemos chegar à conclusão que a profundidade de memória mínima é de 500 pontos (amostras). Figura 4.1 – Exemplo de Profundidade de Memória. Fonte: Oscilloscope Android 33 No programa do Arduino foi necessária a criação de um vetor de bytes, esse array recebe como primeiro valor um byte de start (valor digital 254), logo após quinhentas amostras e depois um byte de stop, identificando assim quando se inicia e termina o array de dados. Outro ponto a ser destacado é a velocidade de conversão (clock do ADC) já discutida anteriormente nesse texto. O programa do Arduino possibilita ao programa do Android a escolha entre três taxas de amostragem diferentes, ou seja, dependendo da mensagem enviada pelo Android solicitando novos dados, eles podem ser convertidos com velocidades distintas. O prescaler pode ser igual a 4, 8 ou 16. Essas opções de taxa de amostragem seriam um início de melhoria do aplicativo Android para que este possa ter uma ou mais taxas de amostragem configuráveis. Essa possibilidade será discutida mais adiante. Conforme dito anteriormente, o conversor A/D do Arduino Uno R3 possui uma resolução de 10 bits, porém essa configuração é não é editável. Em uma versão mais recente desse microcontrolador foi adicionada esta funcionalidade em que o usuário pode, através de uma função da API do Arduino, informar qual a resolução. É a versão do Arduino Due. Essa placa possui um ADC de até 12 bits, porém o usuário, via software, pode, por exemplo, configurar para 8 bits e assim os 12 bits previamente convertido são mapeados para formarem um byte. Caso o usuário coloque 16 bits, por exemplo, os outros 4 bits que complementar os 12 bits convertidos são preenchidos com zero. No projeto, para realizar esse mapeamento manualmente foi construída uma função para transformar os valores de 0 a 1023 em valores de 0 a 253 (254 e 255 foram reservados para start e stop byte). As funções utilizadas para a porta serial do Arduino (UART ou USART) também devem ser ressaltadas. A porta foi configurada para transmitir 9600 bits por segundo e as funções de read – recebe a mensagem enviada pelo Android – e write – envia a mensagem/dados para o dispositivo móvel. 4.1.2 – Tecnologias Arduino e Módulo Bluetooth A tecnologia utilizada tanto para o Arduino (Arduino Uno R3) como para o módulo Bluetooth foram inteiramente suficientes para o bom funcionamento do osciloscópio. Apesar de sempre existirem versões e produtos no mercado que 34 possibilitam uma maior performance, conforme dito anteriormente no caso do Arduino Due, o hardware deste projeto, incluindo o celular Android, foi o adequado e suportou bem a todos os testes realizados. Em nenhum momento houve falhas neste hardware. Uma versão futura do projeto poderia incluir comunicação com mais de um dispositivo, ou seja, seria necessário um hardware com mais portas seriais. A conclusão óbvia que podemos tirar é que um hardware que possui melhor performance ou mais recursos, isto é, maior velocidade e precisão na conversão analógico-digital, mais portas seriais, maior velocidade de processamento, teria facilitado e permitido mais funcionalidades para o projeto. 4.2 – Análise do Aplicativo Android Neste tópico será feita a análise do programa Oscilloscope desenvolvido na plataforma Android. Os aspectos do código que serão abordados: as activities do software e todos os componentes pertencentes a elas (time e voltage scales, trigger, cálculo das propriedades do sinal e o gráfico do sinal), dando ênfase à tela onde o osciloscópio é executado, e a comunicação Bluetooth. 4.2.1 – Activity Inicial Logo quando o aplicativo é executado o usuário se depara com a activity inicial (figura abaixo), esta é uma tela que possui dois botões, onde cada um deles direciona para uma activity diferente. 35 Figura 4.2 – Tela Inicial do Aplicativo. Fonte: Oscilloscope Android Foi utilizada uma técnica para inserir os botões, através de imagens. Um onClickListener no próprio LinearLayout, isto é, um layout foi criado, mas, ao invés de adicionar componentes a ele, este foi utilizado como um botão. Assim, caso o usuário clique na região de uma das figuras, este será direcionado para a tela de “About”, com as informações do projeto, ou para a tela do osciloscópio, onde poderá “inicializar” a aplicação propriamente dita. Segue abaixo uma figura da tela “About” do aplicativo, esta activity possui alguns textViews com as informações básicas do projeto. 36 Figura 4.3 – Tela About do Aplicativo. Fonte: Oscilloscope Android 4.2.2 – Bluetooth Android Um dos exemplos disponíveis para os desenvolvedores em plataforma Android é o Bluetooth Chat, este que é um aplicativo que permite conversa (chat) entre dois dispositivos Android onde as mensagens são enviadas e recebidas pelo Bluetooth. Este aplicativo serviu como base na elaboração da comunicação Bluetooth do aplicativo Oscilloscope Android. A classe BluetoothChatService foi inteiramente aproveitada para o projeto. É a classe que possui os métodos para tratar a conexão Bluetooth, como iniciar e finalizar a comunicação, mudanças do estado da conexão. O construtor dessa classe recebe como parâmetro um Handler, para quando, por exemplo, houver perda de conexão o método sendMessage é acionado e o usuário recebe um Toast com a informação. 37 4.2.3 – Activity do Osciloscópio A tela principal do aplicativo, onde o propósito do projeto se encontra, é a OscilloscopeActivity. Nela existem diversos componentes e funcionalidades que serão explicitados adiante. O primeiro ponto que precisa ser destacado na análise dessa tela é a funcionalidade de WakeLock. É dada a esta activity a permissão para alterar o gerenciamento de energia do celular Android, por isso, enquanto o usuário estiver nesta tela, o sistema não poderá entrar em modo de espera (apagar a tela). Essa funcionalidade se faz possível utilizando a classe PowerManager.WakeLock e de fato facilita a medição do sinal exibido no osciloscópio. Como já é conhecido, o aplicativo só funciona quando o Bluetooth do celular estiver ativo, por isso a primeira verificação que esta activity faz ao ser iniciada é para saber se o dispositivo Android está com o recurso do Bluetooth habilitado. Caso não esteja, uma activity central será inicializada solicitando a ativação do Bluetooth. Essa solicitação é automática e nativa de dispositivos Android, sempre que o software requisitar pelo adaptador Bluetooth e este não estiver habilitado. Caso o usuário clique em “Não”, a aplicação será encerrada. 38 Figura 4.4 – Solicitando Permissão para ativar Bluetooth. Fonte: Oscilloscope Android Depois de permitir a ativação do Bluetooth, o usuário precisa conectar o celular ao módulo Bluetooth e iniciar o processo de aquisição de dados. Para isto, é necessário clicar no botão “menu” do celular Android (imagem abaixo) e então “Conect a Device”. A aplicação vai exibir a DeviceListActivity que permite fazer um escâner por dispositivos Bluetooth disponíveis e selecionar a qual irá conectar-se. O módulo Bluetooth está representado como “linvor” na figura abaixo. 39 Figura 4.5 – Menu do Aplicativo. Fonte: Oscilloscope Android 40 Figura 4.6 – DeviceListActivity. Fonte: Oscilloscope Android Após conectar-se a um dispositivo, o usuário deve clicar no “menu” novamente e iniciar o processo de conversão e exibição do sinal medido clicando em “Start”. 4.2.3.1 – Processo de Exibição do Gráfico Após entender o comportamento do aplicativo quanto à ativação do Bluetooth e o gerenciamento de energia, podemos seguir com a análise do processo de aquisição, tratamento e exibição do gráfico. No capítulo anterior foi definido que o período em que o osciloscópio faz a conversão, tratamento e processamento dos dados, antes de exibi-los na tela, se chama “tempo morto”. Nesta aplicação, este período começa quando o usuário clicar no botão “Start”. 41 O fluxo dos dados começa quando o botão “Start” é acionado, neste momento o celular envia para o módulo Bluetooth uma requisição de dados, esta mensagem é interpretada pelo microcontrolador e inicia-se processo de tratamento dos dados convertidos, conforme explicitado anteriormente. Para fazer o controle de transmissão e recepção dos dados, na aplicação Android, foi utilizado um método da classe Handler chamado handleMessage. Logo, quando uma mensagem contendo os dados do sinal analógico convertido chega ao celular, este método de controle é acionado. Este método recebe como parâmetro um objeto da classe Message. São quatro tipos de mensagem: DEVICE_NAME – quando ocorre esta mensagem, o usuário recebe um Toast indicando que a conexão foi realizada com sucesso e exibe na tela o nome do dispositivo ao qual se conectou; Figura 4.7 – Conectando ao dispositivo Bluetooth. Fonte: Oscilloscope Android 42 STATE_CHANGE – essa mensagem traz como argumento um dos quatro possíveis estados do dispositivo Bluetooth: CONECTED, CONECTING, LISTEN e NONE; WRITE – quando uma mensagem foi enviada. Esse é o momento de reiniciar as variáveis de controle do código; READ – este é acionado quando uma mensagem foi recebida. Neste bloco do programa é feito o tratamento dos dados em sua forma “pura”, isto é, uma mensagem com vários bytes é recebida e se faz necessário dividir em blocos de um byte e identificar o início da cadeia de dados (start byte) e o término (stop byte). Somente após a chegada do stop byte é que o programa chama a rotina para desenhar o gráfico. Dentro da rotina de desenhar o gráfico (plotData) são chamadas outras três rotinas que serão tratadas mais adiante: Trigger do osciloscópio e o cálculo de algumas propriedades do sinal. A rotina de desenhar o gráfico simplesmente exibe todos os dados, começando pelo valor definido pelo Trigger, para preencher a tela inteira da View que ilustra a curva. Após carregar todos os dados no objeto da classe XYSeries (achartengine), existe uma linha do código para atualizar a tela, utilizando o método repaint. 4.2.3.2 – Cálculo de Vmáx, Vpp e Frequência Essa rotina de cálculo é acionada dentro da rotina responsável por desenhar o gráfico. As informações de tensão máxima, valor pico-a-pico e de freqüência são atualizados a com base na mesma taxa de atualização da tela, isto é, a cada novo array de dados, essas informações são recalculadas. Os cálculos de Vmáx e Vpp são feitos utilizando os métodos da API achartengine: getMaxY e getMinY, métodos da classe XYSeries. Abaixo podemos ver um exemplo de uma onda quadrada gerada por um timer 555, alimentado com 5 volts. 43 Figura 4.8 – Exemplo 1 – Cálculo Vmax e Vpp. Fonte: Oscilloscope Android No exemplo acima, podemos conferir que o Vmax e o Vpp estão de acordo com o esperado, sabendo que o Timer 555 em sua configuração astável possui tensão máxima na saída igual a tensão de alimentação. Na figura abaixo temos um outro exemplo com uma onda triangular: 44 Figura 4.9 – Exemplo 2 – Cálculo Vmax e Vpp. Fonte: Oscilloscope Android Para o cálculo da freqüência, a fórmula utilizada já é conhecida. A freqüência de uma onda periódica é igual ao inverso da duração de um período dessa curva. Portanto, tendo como valor inicial o ponto de Trigger, o vetor de dados foi “varrido” até achar o próximo ponto com o mesmo valor inicial “subindo”, ou seja, o valor encontrado precisa ter um valor anterior menor do que o próprio para identificar que a onda neste instante está com derivada positiva. Segue exemplo abaixo de uma onda triangular com freqüência de aproximadamente 500 Hz. 45 Figura 4.10 – Exemplo – Cálculo de Frequência. Fonte: Oscilloscope Android 4.2.3.3 – Trigger do Osciloscópio O sistema de funcionamento do Trigger de um osciloscópio foi de essencial entendimento para dar prosseguimento no projeto. A importância desta funcionalidade é máxima por diversos aspectos, podemos destacar o principal. O sistema de Trigger permite que o usuário do osciloscópio possa ver uma onda periódica como se ela estivesse “parada” na tela, possibilitando as medições e o entendimento de como uma dada tensão varia no tempo. Esse processo é essencial no momento de desenhar o gráfico, pois, antes de fazêlo, é necessário identificar o ponto de Trigger no vetor de dados recebido. É importante ressaltar que não basta identificar somente o valor, é necessário identificar também se este está em uma região de derivada positiva ou negativa. 46 Neste projeto, foi tomado como padrão a região do Trigger onde a derivada é positiva e o valor inicial é calculado e é igual à média do valor máximo com o valor mínimo do vetor de dados. Esse valor inicial só é alterado quando o usuário alterar o nível de Trigger. Para identificar se o Trigger está ativo e com bom funcionamento é necessário verificar, em várias atualizações de tela, se a onda periódica está “fixa”, mas para ilustrar seguem abaixo algumas imagens do osciloscópio, onde o valor do ponto de Trigger foi alterado pelo usuário. Figura 4.11 – Exemplo – Trigger do Osciloscópio. Fonte: Oscilloscope Android 4.2.3.4 – Botões da Activity do Osciloscópio Além da view que compõe o gráfico, existem quatro componentes na OscilloscopeActivity: os dois seekBar para alterar as escalas de tempo e tensão, os dois botões para alterar o valor do Trigger e outros dois botões para alterar a posição curva no eixo das ordenadas. Tanto o Trigger Level como o Position são botões simples que alteram os valores discretamente. As barras para mudança de escala possuem cinco posições cada. Para a escala de tensão os valores por divisão são: 0,1 V, 0.2 V, 0.5V, 1,0 V e 2,0 V. 47 Para a escala de tempo os valores definidos por divisão são: 0,1 ms, 0,2 ms, 0,5 ms, 1.0 ms e 2.0 ms. Seguem abaixo alguns exemplos de alteração das escalas: Figura 4.12 – Exemplo dos Botões da Activity Principal. Fonte: Oscilloscope Android 48 Capítulo 5 Conclusões Esse projeto teve início durante o período letivo em que cursava a disciplina de Software para Smartphone. O trabalho evoluiu de apenas um simulador no trabalho final da disciplina eletiva a um aplicativo que realmente pode ser utilizado para análises de sinais de tensão. Obviamente, este trabalho ainda não tem a pretensão de substituir um osciloscópio de bancada, que vem sendo utilizado há muitos anos em diversos laboratórios de várias universidades e escolas, mas pode entregar ao usuário (leigo em eletrônica ou não) um Software para dispositivo móvel que possibilita análise de sinais de tensão em qualquer lugar. Houveram dificuldades por se tratar de um projeto que lida com dois blocos separados de hardware e software, foi necessário um ajuste (sincronismo) entre as duas camadas. Outra dificuldade seria em relação aos testes, foram necessárias diversas visitas ao laboratório para fazer uso do gerador de funções e do osciloscópio de bancada (questões de comparação). Entre outras, todas foram superadas. Realmente o trabalho atingiu os objetivos traçados na proposta inicial, porém existem muitas possibilidades e melhorias para este. Seguem abaixo alguns possíveis trabalhos futuros: Voltage Level Shifting – é uma técnica para ajustar de tensão de um circuito. O conversor A/D utilizado nesse permite apenas entradas de 0 a 5 volts e maioria dos conversores no mercado funcionam da mesma forma, porém é possível ajustar o nível de tensão na entrada do conversor para que o usuário possa medir, por exemplo, um sinal de -10 a 10 volts, este sinal ser tratado pelo circuito de voltage level shifting e entrar no conversor como um sinal de 0a 5 volts; Osciloscópio com mais de um canal – esse segundo canal poderia ser implementado de diversas formas, talvez a mais correta seja a utilização de um Arduino com mais de uma porta serial. Dessa forma, o hardware poderia enviar dois sinais em paralelo. 49 Bibliografia [1] AGILENT TECHNOLOGIES., Arquiteturas de memória de osciloscópio – Por que toda memória de aquisição não é criada igualmente. 2012 [2] DON WILCHER. Learn Electronics with Arduino. 2010. [3] _________ Datasheets ATmega 328. 2009. [4] RETO MEIER. Profissional Android 4 application development, 2012. [5] http://www.exp-tech.de/service/datasheet/HC-Serial-Bluetooth-Products.pdf [6] http://developer.Android.com/reference/Android/app/Activity.html [7] http://www.achartengine.org/ [8] http://arduino.cc/ [9] http://www.atmel.com/Images/doc8161.pdf 50