quarta-feira, 28 de novembro de 2012

Criando Bibliotecas no Arduino



Este documento explica como criar bibliotecas para o Arduino. Começaremos com um programa exemplo de Código Morse, explicando como converter suas funcionalidades em uma biblioteca. Isto permite que outras pessoas possam facilmente utilizar seu código receber atualizações, conforme você melhorar a biblioteca.

Começamos com este Sketch (programa) que lida com Código Morse:
int pin = 13;

void setup()
{
  pinMode(pin, OUTPUT);
}

void loop()
{
  dot(); dot(); dot();
  dash(); dash(); dash();
  dot(); dot(); dot();
  delay(3000);
}

void dot()
{
  digitalWrite(pin, HIGH);
  delay(250);
  digitalWrite(pin, LOW);
  delay(250);
}

void dash()
{
  digitalWrite(pin, HIGH);
  delay(1000);
  digitalWrite(pin, LOW);
  delay(250);
}
Se você executar o sketch acima, ele piscará o código S.O.S. na porta 13.
Este sketch possui partes diferentes que serão implementadas na nossa biblioteca. Primeiro, é claro, temos as funções dot() and dash() que executam a funcionalidade de piscar. Segundo, temos a variável ledPin que é utilizada pelas funções para determinar qual porta utilizar. Finalmente, temos a chamada da função pinMode() que inicia a porta como saída.

Vamos começar a transformar esse sketch em uma biblioteca!

Você precisa de pelo menos dois arquivos para criar uma biblioteca: um arquivo de cabeçalho (header file), com a extensão .h, e o arquivo de código-fonte (source file), com a extensão .cpp. O arquivo de cabeçalho possui as definições da biblioteca: basicamente uma listagem de tudo que a biblioteca possui; enquanto o arquivo de código-fonte, é o código real, que executa as funções. Vamos chamar nossa biblioteca de "Morse", então nosso arquivo de cabeçalho será Morse.h. Vamos ver o que vai dentro dele. Pode parecer um pouco estranho a primeira vista, mas fará mais sentido quando você vir o código-fonte, que acompanha este arquivo.

O truque desse arquivo de cabeçalho é criar em uma linha para cada função da biblioteca, contida em uma classe, acompanhada das variáveis que você utilizará:
class Morse
{
  public:
    Morse(int pin);
    void dot();
    void dash();
  private:
    int _pin;
};
Uma classe é simplesmente uma coleção de funções e variáveis que estão organizadas em um pacote. Estas funções e variáveis, podem ser public (públicas), significando que podem ser acessadas pelos programadores que a implementarão, ou private (privada), significando que elas só podem ser utilizadas internamente na classe em si. Cada classe tem uma função especial conhecida por constructor (construtor), que é utilizada para criar uma instância da classe, em tempo de execução. O construtor possui o mesmo nome da classe, e sem tipo de retorno.

Você precisa de algumas outras coisas no seu arquivo de cabeçalho. Uma delas é uma declaração #include que lhe dá acesso aos tipos e constantes da linguagem do Arduino (isto é automaticamente feito quando você cria um sketch, mas não em uma biblioteca, devendo ser adicionado manualmente).
#include "Arduino.h"
Finalmente, é comum empacotar o arquivo de cabeçalho, em uma construção de declarações, com a seguir:
#ifndef Morse_h
#define Morse_h

// the #include statment and code go here...

#endif
Basicamente, isto previne que alguém acidentalmente adicione mais de uma vez o cabeçalho da sua biblioteca.
Para encerrar, normalmente colocamos um comentário no início do arquivo, com o nome da biblioteca, uma breve descrição, nome do autor, data e termos de uso.
Vamos dar uma olhada no arquivo de cabeçalho completo:
/*
  Morse.h - Library for flashing Morse code.
  Created by David A. Mellis, November 2, 2007.
  Released into the public domain.
*/

#ifndef Morse_h
#define Morse_h

#include "Arduino.h"

class Morse
{
  public:
    Morse(int pin);
    void dot();
    void dash();
  private:
    int _pin;
};

#endif
Agora veremos as várias partes do arquivo de código-fonte, Morse.cpp.
Primeiro vem umas declarações #include. Elas trazem o código necessário para as funções básicas do Arduino, e as definições implementadas no seu arquivo de cabeçalho:
#include "Arduino.h"
#include "Morse.h"
Então vem o construtor. Novamente, ele é iniciado cada vez que alguém cria uma instância da sua classe. Neste caso, o usuário especifica qual porta ele deseja utilizar. Configuramos então a porta como saída, gravando o parâmetro em uma variável privada, utilizada posteriormente em outras funções:
Morse::Morse(int pin)
{
  pinMode(pin, OUTPUT);
  _pin = pin;
}
Este código possui algumas coisas estranhas nele. Primeiro é o Morse:: antes do nome da função. Ele mostra que a função é parte da classe Morse  Você verá isto novamente na criação das outras funções da classe também. A segunda coisa é o underline (traço-baixo) no nome da nossa variável privada, _pin  Esta variável pode ter qualquer nome que você desejar, desde que coincida com a definição no arquivo de cabeçalho. Adicionar um underline no começo do nome é uma convenção para clarificar a ideia de que a variável é privada e também distinguir do nome de argumento da função.
Em seguida, temos o código realmente originado do sketch que estamos transformando em biblioteca. Não mudou, muito, exceto pelo Morse:: na frente dos nomes das funções, e _pin ao invés de pin:
void Morse::dot()
{
  digitalWrite(_pin, HIGH);
  delay(250);
  digitalWrite(_pin, LOW);
  delay(250); 
}

void Morse::dash()
{
  digitalWrite(_pin, HIGH);
  delay(1000);
  digitalWrite(_pin, LOW);
  delay(250);
}
Finalmente, é comum incluir o comentário no início, como fizemos no arquivo do cabeçalho. Vamos ver como ficou o código-fonte completo:
/*
  Morse.cpp - Library for flashing Morse code.
  Created by David A. Mellis, November 2, 2007.
  Released into the public domain.
*/


#include "Arduino.h"
#include "Morse.h"

Morse::Morse(int pin)
{
  pinMode(pin, OUTPUT);
  _pin = pin;
}

void Morse::dot()
{
  digitalWrite(_pin, HIGH);
  delay(250);
  digitalWrite(_pin, LOW);
  delay(250); 
}

void Morse::dash()
{
  digitalWrite(_pin, HIGH);
  delay(1000);
  digitalWrite(_pin, LOW);
  delay(250);
}
E isto é tudo que você precisa (existem algumas coisas adicionais interessantes, mas falaremos disso a seguir). Vamos ver como utilizar nossa biblioteca.
Primeiro, crie um diretório chamado Morse dentro do sub-diretório libraries do seu sketchbook (lugar padrão onde salva os sketches que você cria). Copie ou mova os arquivos Morse.h e Morse.cpp para esse diretório. Agora inicie o programa do Arduino (IDE). Se você abrir o menu Sketch > Import Library, verá que a biblioteca Morse está lá. A biblioteca será compilada com os sketches que a utilizarem.
Vamos ver como vai ficar nosso sketch SOS agora, usando a biblioteca:
#include

Morse morse(13);

void setup()
{
}

void loop()
{
  morse.dot(); morse.dot(); morse.dot();
  morse.dash(); morse.dash(); morse.dash();
  morse.dot(); morse.dot(); morse.dot();
  delay(3000);
}
Existem algumas diferenças entre a versão original e este novo sketch (além do código que foi movido para dentro da biblioteca).
Primeiro, adicionamos uma declaração #include, no início do sketch. Isto faz a biblioteca Morse se tornar disponível durante o código. Isso significa que ao encontrar essa linha o compilador vai linkar o código da biblioteca e publicar na placa. Ou seja, caso não vá utilizar mais a biblioteca, lembre-se de retirar essa linha para o seu sketch gerar um arquivo final menor.
Segundo, declaramos uma instância da classe Morse, chamada morse :
Morse morse(13);
Quando esta linha é executada (o que acontece até mesmo antes da função setup()), o construtor da classe Morse será chamado, passando o argumento da porta (no nosso caso, 13).
Finalmente, para chamar as funções dot() e dash(), você precisa utilizar um prefixo morse. - o nome da instância (objeto) que queremos utilizar. Podemos ter várias instâncias da classe Morse, cada qual configurando uma porta diferente, independentemente umas das outras com suas próprias variáveis privadas. Fazemos isso alterando o parâmetro inicial que será passado, conforme exemplo:
Morse morse(13);
Morse morse2(12);
então dentro da chamada na função morse2.dot()_pin seria 12.
Se você testou o novo sketch, provavelmente notou que alguns termos de nossa biblioteca não ficaram ressaltados pelo esquema de cores do Arduino. Infelizmente o programa do Arduino não pode reconhecer automaticamente o que você define dentro da biblioteca (embora essa seria uma funcionalidade interessante para as próximas versões), então você precisa dar uma mãozinha, criando um arquivo chamado keywords.txt dentro do diretório Morse. Deve se parecer com este:
Morse   KEYWORD1
dash    KEYWORD2
dot     KEYWORD2
Cada linha tem o nome da palavra-chave, seguida por uma tabulação (não espaços), seguidos pelo tipo da palavra. As classes devem ser do tipo KEYWORD1, e coloridas de laranja; funções devem ser do tipo KEYWORD2, e serão marrons. Você deve reiniciar o ambiente do Arduino para que as modificações sejam aplicadas.

Seria bacana enviar um exemplo do uso da biblioteca junto com o pacote. Para fazer isso crie um diretório examples dentro do diretório Morse  Então copie ou mova o diretório contendo o sketch do SOS  que criamos, acima. Se você reiniciar o Arduino mais uma vez, a última, prometo - você verá sua Library-Morse dentro do menu File > Sketchbook > Examples.

Adicionalmente você pode adicionar comentários no seu código de exemplo para ensinar as pessoas como utilizar sua biblioteca.
Se você quiser o código completo da biblioteca (com exemplos de palavras-chave), você pode baixar aqui: Morse.zip.

Fonte: http://arduino.cc/en/Hacking/LibraryTutorial

5 comentários:

  1. Renato,
    Parabéns por seu curso.
    Tem me ajudado muito.
    Obrigado

    ResponderExcluir
  2. Ola. Como faço para salvar o arquivo do sketch como .h ou .cpp?! Obrigado

    ResponderExcluir
    Respostas
    1. Olá GustavoSuim,
      Eu utilizo o programa Notepad++ (http://notepad-plus-plus.org/download/v6.3.3.html). É gratuito e com ele é possível criar os arquivos e salvar com as extensões .h e .cpp, além de outras mais.
      Na hora de salvar, basta você ir na opção "Tipo" e escolher C++ source files. Depois disso, quando for dar um nome ao seu arquivo digite .h ou .cpp no final do nome que o arquivo será salvo com estas extensões.
      Este programa é como o bloco de notas, porém feito especialmente para se criar arquivos de programação e afins.

      Excluir
  3. cara esse post me foi muito util, parabens!

    ResponderExcluir