0% acharam este documento útil (0 voto)
12 visualizações

Criando Libs Arduino

Direitos autorais
© © All Rights Reserved
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
12 visualizações

Criando Libs Arduino

Direitos autorais
© © All Rights Reserved
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
Você está na página 1/ 11

Biblioteca Arduino: aprenda como criar

a sua – Parte 1

Você que já é fã de Arduino e já desenvolveu vários projetos principalmente usando


módulos ou sensores como MPU6050, DHT11, BPM180 e etc, deve ter notado aquelas
linhas no topo do código que dizem #include <MPU6050.h> ou #include <DHT.h>.
Esses arquivos são chamados de bibliotecas e neste post iremos mostrar o que são as
bibliotecas, para que servem, porque são usadas e como desenvolver sua própria
biblioteca Arduino.

Como exemplo para este tutorial, iremos desenvolver uma biblioteca para utilização do
driver de motor NodeMCU

O que é e para que serve uma biblioteca Arduino


Uma biblioteca nada mais é do que um conjunto de instruções desenvolvidas para
executar tarefas específicas relacionadas a um determinado dispositivo. Por exemplo,
pensando em um acelerômetro MPU6050 e sua biblioteca MPU6050.h. Essa biblioteca
tem funções desenvolvidas especificamente para executar tarefas como, configurar o
acelerômetro, ler dados de aceleração, giroscópio, temperatura e etc.

A utilização de uma biblioteca facilita o desenvolvimento, tornando o código mais


simples e organizado. Por exemplo, a biblioteca do MPU6050 tem mais ou menos 4000
linhas de código (sem contar outras bibliotecas utilizadas dentro dela). É obrigatório o
uso dessa biblioteca? Não. Mas então teríamos que escrever, se não as 4000 linhas de
código, várias linhas para utilizar o MPU6050 em todo seu potencial.
Bibliotecas podem ser desenvolvidas por qualquer pessoa. Podemos ver muitas
bibliotecas da Adafruit e Sparkfun, dentre as outras milhares espalhadas pelo GitHub.
Podemos encontrar bibliotecas ótimas, ruins e até mesmo algumas que não funcionam.
Uma dica interessante ao avaliar uma biblioteca é olhar o número de estrelas e issues no
GitHub e ver também se ela está disponível oficialmente na IDE Arduino.

E foram as bibliotecas que ajudaram a tornar o Arduino tão popular, onde crianças e
adultos não precisam ser engenheiros ou desenvolvedores de software, para criarem
seus projetos e colocarem sua criatividade em prática. O próprio “jeitão” de escrever
código para Arduino segue o princípio da facilidade. Por exemplo a função
digitalWrite(pino, valor). Com apenas essa função ligamos ou desligamos um pino do
Arduino. Mas veja como ela é por dentro e o que teríamos que escrever caso não
usássemos as bibliotecas Arduino:

1
2
3 void
{
digitalWrite(uint8_t pin, uint8_t val)
4 uint8_t timer = digitalPinToTimer(pin);
5 uint8_t bit = digitalPinToBitMask(pin);
6 uint8_t port = digitalPinToPort(pin);
7 volatile uint8_t *out;
8
if (port == NOT_A_PIN) return;
9
10 // If the pin that support PWM output, we need to turn it off
11 // before doing a digital write.
12 if (timer != NOT_ON_TIMER) turnOffPWM(timer);
13
14 out = portOutputRegister(port);
15
16 uint8_t oldSREG = SREG;
cli();
17
18 if (val == LOW) {
19 *out &= ~bit;
20 } else {
21 *out |= bit;
}
22
23 SREG = oldSREG;
24}
25
26

Explore o seguinte link e descubra a origem das várias outras funções que facilitam o
desenvolvimento com Arduino como setup(), loop(), Serial.begin(), Serial.available(),
Serial.println(), digitalRead(), delay(), etc.

https://github.com/arduino/Arduino/tree/master/hardware/arduino/avr/cores/arduino

Componentes de uma biblioteca Arduino


Uma biblioteca Arduino consiste basicamente de 3 componentes/arquivos. São eles:
 Arquivo header(cabeçalho) com extensão “.h” que contém uma listagem
(declaração) de todas as funções e variáveis da nossa biblioteca.
 Arquivo source(fonte) com extensão “.cpp” que contém o corpo e
funcionamento/lógica (definição) das funções.
 Arquivo keywords.txt que é específico da IDE Arduino e usado para dar
coloração as funções da biblioteca enquanto se escreve um código.

Mais a frente no tutorial iremos mostrar como construir cada um desses arquivos já com
foco no driver de motor para NodeMCU.

Driver de motor para NodeMCU


Antes de começarmos a desenvolver uma biblioteca, precisamos de uma razão para tal e
entender o funcionamento do dispositivo para qual escreveremos a biblioteca.

Para este tutorial escolhemos o driver de motor para NodeMCU. Esse driver é baseado
no CI L293D, controla até dois motores além de expor vários pinos do NodeMCU como
pinos digitais, UART e SPI. Podemos também utilizar uma fonte separada para os
motores. Veja na figura abaixo as indicações de cada parte do driver:

Note que temos as saídas para motor A-, A+, B-, B+. As saídas A- e B- são utilizadas
para configurar a força com que os motores irão girar. Para isso utilizaremos PWM. Já
as saídas A+ e B+, configuram o sentido de rotação dos motores.
Quando o NodeMCU é encaixado no driver os pinos ficam conectados da seguinte
maneira:

Lembre-se desses pinos pois serão utilizados no desenvolvimento da nossa biblioteca.

O funcionamento do driver é bem simples. Para controlar um motor basta conectar seus
terminais nos pinos A- e A+. No pino A- utilizamos PWM para configurar a força do
motor e no pino A+ o sentido. Então se utilizarmos 10% de força no pino A- e
utilizarmos nível 1 na saída A+, o motor gira para um lado com força de 10%. Se
utilizarmos força de 100% no pino A- e utilizarmos nível 1 na saída A+, o pino gira
com força total para um lado. Se utilizarmos nível 0 na saída A+, o motor gira para o
lado contrário.

Colocando a ideia acima em forma de programação Arduino, teríamos algo parecido


com o seguinte, fazendo o driver ir para frente por 2 segundos e depois para trás por 2
segundos:

1
2
void setup() {
3 pinMode(5, OUTPUT); // saída A-
4 pinMode(0, OUTPUT); // saída A+
5 pinMode(4, OUTPUT); // saída B-
6 pinMode(2, OUTPUT); // saída B+
}
7
8 void loop() {
9 analogWrite(5, 1024); // PWM no pino A-
10 digitalWrite(0, HIGH); // sentido no pino A+
11 analogWrite(4, 1024); // PWM no pino B-
12 digitalWrite(2, HIGH); // sentido no pino B+
delay(2000);
13
14 analogWrite(5, 1024); // PWM no pino A-
15 digitalWrite(0, LOW); // sentido no pino A+
16 analogWrite(4, 1024); // PWM no pino A-
17 digitalWrite(2, LOW); // sentido no pino B+
delay(2000);
18}
19
20
Agora que sabemos o funcionamento do nosso dispositivo (driver motor NodeMCU), já
podemos seguir com o desenvolvimento da biblioteca.

Pensando nas funcionalidades da nossa biblioteca


arduino
Vamos pensar que nossa biblioteca irá precisar atender 5 tarefas/comandos do driver de
motor, considerando que temos 2 motores conectados.

1. ir para frente
2. ir para trás
3. virar a esquerda
4. virar a direita
5. parar

Cada uma dessas tarefas será uma função da nossa biblioteca.

Também daremos ao usuário da nossa biblioteca a opção de realizar os comandos acima


com uma determinada força(PWM). Isso será nosso parâmetro de função.

Assim teremos 4 funções que levam parâmetro mais a função de parada.

goForward(uint16_t pwm)
goBackward(uint16_t pwm)
turnRight(uint16_t pwm)
turnLeft(uint16_t pwm)
stop()

Construindo nossa biblioteca arduino


Arquivo header

Nossa biblioteca terá o nome de NodeMotorDriver, portanto nosso arquivo header terá
nome NodeMotorDriver.h

Dentro desse arquivo teremos uma classe com nome de nossa biblioteca. Dentro da
classe teremos nossas funções e variáveis que serão utilizadas.

1 class NodeMotorDriver
2 {
public:
3 NodeMotorDriver(uint8_t pinMotorA1, uint8_t pinMotorA2,
4 uint8_t pinMotorB1, uint8_t pinMotorB2);
5 void goForward(uint16_t pwm);
6 void goBackward(uint16_t pwm);
7 void turnRight(uint16_t pwm);
void turnLeft(uint16_t pwm);
8 void stop();
9
10 private:
11 uint8_t m_pinA1;
12 uint8_t m_pinA2;
13 uint8_t m_pinB1;
uint8_t m_pinB2;
14};
15
16

Veja que temos uma função ali que não estava em nosso planos:

NodeMotorDriver(uint8_t pinMotorA1, uint8_t pinMotorA2, uint8_t


1pinMotorB1, uint8_t pinMotorB2);

Essa função chama-se construtor(constructor) e será executada sempre quando criamos


um novo objeto da classe NodeMotorDriver. É útil para configuração de valores iniciais
para variáveis membros da classe. Geralmente irá conter código que iria na função
setup() do Arduino. Mais a frente mostraremos a definição dessa função construtora.

Note também que temos as palavras public e private. Public significa que as funções e
variáveis estarão acessíveis para o usuário da biblioteca. Private restringe o uso de
funções e bibliotecas para apenas aquela classe em específico. Dependendo do tipo de
variável não há necessidade do usuário escrever um valor diferente naquela variável,
então utilizamos como private. Já as funções e variáveis públicas estarão disponíveis
para o usuário chamá-las ao decorrer do programa.

Ainda no arquivo header precisamos incluir outra biblioteca que é a Arduino.h. Incluir
essa biblioteca nos possibilita utilizar funções como pinMode(), digitalWrite(), etc. que
são funções do Arduino.

1#include <Arduino.h>

E finalmente envolvemos o header em uma guarda de inclusão, que evita problemas de


compilação caso o usuário inclua nossa biblioteca duas vezes.

1#ifndef NodeMotorDriver_h
2#define NodeMotorDriver_h
3
4// código da classe aqui
5
6#endif

Veja abaixo o código completo do header:

/*
1
NodeMotorDriver.h - Library for use with NodeMCU L293D driver
2 board
3 MIT License
4 */
5
6 // guarda de inclusão
#ifndef NodeMotorDriver_h
7 #define NodeMotorDriver_h
8
9 #include <Arduino.h>
10
11class NodeMotorDriver
12{
public:
13 NodeMotorDriver(uint8_t pinMotorA1, uint8_t pinMotorA2,
14uint8_t pinMotorB1, uint8_t pinMotorB2);
15 void goForward(uint16_t pwm);
16 void goBackward(uint16_t pwm);
void turnRight(uint16_t pwm);
17 void turnLeft(uint16_t pwm);
18 void stop();
19
20 private:
21 uint8_t m_pinA1;
22 uint8_t m_pinA2;
uint8_t m_pinB1;
23 uint8_t m_pinB2;
24};
25
26#endif
27
28
29

Arquivo source

No arquivo source é onde definimos a lógica de nossas funções e utilizamos as variáveis


declaradas no arquivo header. Terá o mesmo nome da biblioteca com terminação .cpp.

Começando pela função construtora podemos ver a configuração do modo dos pinos
como OUTPUT e atribuição das variáveis membro da classe.

1 NodeMotorDriver::NodeMotorDriver(uint8_t pinMotorA1, uint8_t


2 pinMotorA2, uint8_t pinMotorB1, uint8_t pinMotorB2)
3 {
4 pinMode(pinMotorA1, OUTPUT);
5 pinMode(pinMotorA2, OUTPUT);
pinMode(pinMotorB1, OUTPUT);
6 pinMode(pinMotorB2, OUTPUT);
7 m_pinA1 = pinMotorA1; // speed
8 m_pinA2 = pinMotorA2; // direction
9 m_pinB1 = pinMotorB1; // speed
m_pinB2 = pinMotorB2; // direction
10}
11

Então definimos as funções de movimento.

1
void NodeMotorDriver::goForward(uint16_t pwm)
2{
3 analogWrite(m_pinA1, pwm);
4 digitalWrite(m_pinA2, HIGH);
5 analogWrite(m_pinB1, pwm);
digitalWrite(m_pinB2, HIGH);
6}
7
Note que o valor de PWM será passado pelo usuário como um parâmetro na chamada
de função e os valores das variáveis membro já foram atribuídos pela função
construtora. As outras funções de movimento seguem a mesma lógica apenas alternando
entre HIGH e LOW.

Por último temos a função stop que desliga todos os motores.

1
void NodeMotorDriver::stop()
2{
3 analogWrite(m_pinA1, 0);
4 digitalWrite(m_pinA2, 0);
5 analogWrite(m_pinB1, 0);
digitalWrite(m_pinB2, 0);
6}
7

Não podemos esquecer também de incluir nosso arquivo header onde fizemos as
declarações de função.

#include "NodeMotorDriver.h"

O arquivo source completo pode ser visto abaixo:

/*
1 NodeMotorDriver.cpp - Library for use with NodeMCU L293D driver
2 board
3 MIT License
4 */
5
6 #include "NodeMotorDriver.h"
7 NodeMotorDriver::NodeMotorDriver(uint8_t pinMotorA1, uint8_t
8 pinMotorA2, uint8_t pinMotorB1, uint8_t pinMotorB2)
9 {
10 pinMode(pinMotorA1, OUTPUT);
11 pinMode(pinMotorA2, OUTPUT);
pinMode(pinMotorB1, OUTPUT);
12 pinMode(pinMotorB2, OUTPUT);
13 m_pinA1 = pinMotorA1; // speed
14 m_pinA2 = pinMotorA2; // direction
15 m_pinB1 = pinMotorB1; // speed
16 m_pinB2 = pinMotorB2; // direction
}
17
18void NodeMotorDriver::goForward(uint16_t pwm)
19{
20 analogWrite(m_pinA1, pwm);
21 digitalWrite(m_pinA2, HIGH);
analogWrite(m_pinB1, pwm);
22 digitalWrite(m_pinB2, HIGH);
23}
24
25void NodeMotorDriver::goBackward(uint16_t pwm)
26{
27 analogWrite(m_pinA1, pwm);
digitalWrite(m_pinA2, LOW);
28 analogWrite(m_pinB1, pwm);
29 digitalWrite(m_pinB2, LOW);
30}
31
void NodeMotorDriver::turnRight(uint16_t pwm)
32{
33 analogWrite(m_pinA1, pwm);
34 digitalWrite(m_pinA2, HIGH);
35 analogWrite(m_pinB1, pwm);
digitalWrite(m_pinB2, LOW);
36}
37
38void NodeMotorDriver::turnLeft(uint16_t pwm)
39{
40 analogWrite(m_pinA1, pwm);
41 digitalWrite(m_pinA2, LOW);
analogWrite(m_pinB1, pwm);
42 digitalWrite(m_pinB2, HIGH);
43}
44
45void NodeMotorDriver::stop()
46{
analogWrite(m_pinA1, 0);
47 digitalWrite(m_pinA2, 0);
48 analogWrite(m_pinB1, 0);
49 digitalWrite(m_pinB2, 0);
50}
51
52
53
54
55
56
57
58

Arquivo keywords.txt

Esse arquivo não é obrigatório mas é interessante para a experiência do usuário que irá
utilizar nossa biblioteca. Com ele podemos definir quais funções terão uma coloração
diferente quando se escreve código.

1
2 # Arduino IDE Keywords for Syntax Coloring
3
# Keyword for class NodeMotorDriver
4 NodeMotorDriver KEYWORD1
5
6 # Keyword for class functions
7 goForward KEYWORD2
8 goBackward KEYWORD2
turnRight KEYWORD2
9 turnLeft KEYWORD2
10stop KEYWORD2
11
Nome de classe deve utilizar KEYWORD1 e terá coloração laranja negrito. Nome de
função deve utilizar KEYWORD2 e terá coloração laranja.

Utilização da biblioteca
Pronto agora temos toda a biblioteca construída. Para utilizá-la devemos colocar os 3
arquivos dentro de uma pasta com o nome da biblioteca NodeMotorDriver, e copiar
para a pasta libraries da IDE Arduino.

Então basta incluir a biblioteca no código e utilizar as funções. Veja abaixo um pequeno
exemplo de código utilizando nossa biblioteca.

1
2 #include <NodeMotorDriver.h>
3
4 NodeMotorDriver nodeMotorDriver(5, 0, 4, 2);
5
6 void setup() {
7
8 }
9
void loop() {
10 nodeMotorDriver.goForward(1024);
11 delay(1000);
12 nodeMotorDriver.goBackward(500);
13 delay(1000);
14 nodeMotorDriver.turnRight(1024);
delay(1000);
15 nodeMotorDriver.turnLeft(500);
16 delay(1000);
17 nodeMotorDriver.stop();
18 delay(1000);
19}
20

Primeiro utilizamos nossa função construtora definindo um nome de objeto da classe e


os pinos de saída dos motores. Na função loop apenas chamamos as funções de
movimento passando a força do movimento(PWM) como parâmetro de função.

No próximo post iremos mostrar como utilizar essa biblioteca arduino em um projeto
real de robô com NodeMCU e driver de motor controlado pelo celular. Fique ligado!

Veja também uma explicação em vídeo sobre criação de biblioteca Arduino no canal
WRKits:

Referências
https://www.arduino.cc/en/Hacking/LibraryTutorial
https://www.arduino.cc/en/Reference/APIStyleGuide
https://playground.arduino.cc/Code/Library
https://github.com/kecsot/Arduino-Motor-H-Bridge-L293d/tree/master/Motor
https://github.com/kecsot/Arduino-Motor-H-Bridge-
L293d/blob/master/Motor/Motor.cpp
https://github.com/kecsot/Arduino-Motor-H-Bridge-L293d/blob/master/Motor/Motor.h

Você também pode gostar