Apostila Arduino
Apostila Arduino
S ENSORES E ATUADORES
APOIO:
S ÃO C ARLOS , 2021
Sumário
1 Arduino 7
1.1 Definição . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2 Criação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.3 Arduino UNO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.4 Arduino só é utilizado por iniciantes? . . . . . . . . . . . . . . . . . . . 9
1.5 Quando NÃO usar o Arduino? . . . . . . . . . . . . . . . . . . . . . . . 10
2 IDE 11
2.1 Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.2 Função void setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.3 Função void loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.4 ATMEGA 328p . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3 VARIÁVEIS 15
3.1 Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.2 Tipos de Variáveis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.3 Variáveis Globais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.4 Variáveis Locais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.5 diretiva static . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.6 diretiva define . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4 Escrita Digital 18
4.1 Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
4.2 comando pinMode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
4.3 comando digitalWrite . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
4.4 comando delay . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
4.5 exemplo 1 - semáforo . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
5 Leitura Digital 22
5.1 Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
5.2 comando digitalRead . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
5.3 exemplo 2 - leitura de botões . . . . . . . . . . . . . . . . . . . . . . . . 23
5.4 pull up interno . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
6 Leitura Analógica 27
6.1 Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
6.2 comando analogRead . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
6.3 Prática 3 - lendo potenciômetro . . . . . . . . . . . . . . . . . . . . . . 28
7 Escrita Analógica 31
1
7.1 Sinais e formas de onda . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
7.2 Valor RMS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
7.3 PWM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
7.4 comando analogWrite . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
7.5 prática 4 - variando luminosidade do LED . . . . . . . . . . . . . . . . 34
8 Monitor Serial 37
8.1 Monitor Serial do Arduino . . . . . . . . . . . . . . . . . . . . . . . . . 37
8.2 Vendo dados no monitor serial . . . . . . . . . . . . . . . . . . . . . . 37
8.3 Código do Monitor Serial . . . . . . . . . . . . . . . . . . . . . . . . . . 37
8.4 prática 4 com monitor serial . . . . . . . . . . . . . . . . . . . . . . . . 38
8.5 Usando Monitor serial como prompt de comando na IDE . . . . . . 41
8.6 Variável do tipo string . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
8.7 Prática 5 - Controlando Arduino pelo monitor serial . . . . . . . . . . 42
9 Bibliotecas 44
9.1 O que são bibliotecas? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
9.2 Como importar bibliotecas . . . . . . . . . . . . . . . . . . . . . . . . . 45
9.2.1 Pasta Separada . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
9.2.2 arquivo .ZIP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
9.2.3 Importando dentro da IDE . . . . . . . . . . . . . . . . . . . . 49
9.3 Limpando EEPROM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
9.4 Outras informações . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
2
10.5.2 MISO - Master In, Slave Out . . . . . . . . . . . . . . . . . . . . 59
10.5.3 SCLK - Serial clock . . . . . . . . . . . . . . . . . . . . . . . . . 60
10.5.4 SSx - Slave Select . . . . . . . . . . . . . . . . . . . . . . . . . . 60
10.5.5 Prática 7 - exemplo de comunicação SPI entre 2 Arduinos . . 63
10.6 Prática 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
10.7 Prática 9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
11 Interrupções 67
11.1 O que são interrupções . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
11.2 Interrupção Externa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
11.3 Prática 10 - interrupção externa . . . . . . . . . . . . . . . . . . . . . . 68
11.4 Interrupção Interna ou por timer . . . . . . . . . . . . . . . . . . . . . 70
11.5 Prática 11 - Interrupção Interna . . . . . . . . . . . . . . . . . . . . . . 71
13 Matrizes 90
13.1 Matriz de LED . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
13.2 Prática 14.1 - Acionando matriz de leds 8x8 com multiplex . . . . . . 92
13.3 Matriz de botões . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
13.4 Prática 15 - Lendo teclado matricial . . . . . . . . . . . . . . . . . . . . 95
14 Sensores de Temperatura 98
14.1 Termistores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
14.1.1 NTC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
14.1.2 Método do fator β . . . . . . . . . . . . . . . . . . . . . . . . . 100
14.1.3 Método de Steinhart-Hart . . . . . . . . . . . . . . . . . . . . . 100
14.2 Prática 16.1 - NTC pelo método β . . . . . . . . . . . . . . . . . . . . . 100
14.3 Prática 16.2 - NTC pelo método de Steinhart Hart . . . . . . . . . . . 101
14.4 Termopar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
14.5 Prática 17 - Termopar tipo K com MAX6675 . . . . . . . . . . . . . . . 105
14.6 LM35 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
14.7 Prática 18 - LM35 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
14.8 DHT11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
3
14.9 PRÁTICA 19 - DHT11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
14.10MLX90614 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
14.11Prática 20 - MLX90614 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
14.12DS18B20 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
14.13Prática 21 - DS18B20 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
16 Extensômetros 136
16.1 Extensômetros, Strain Gauges e Células de Carga . . . . . . . . . . . . 136
16.2 Ponte de Wheatstone . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
16.3 Deformação do Strain Gauge . . . . . . . . . . . . . . . . . . . . . . . . 137
16.4 HX711 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
16.5 Célula de carga de 50kg da Sparkfun . . . . . . . . . . . . . . . . . . . 138
16.5.1 1 módulo de célula de carga, contendo 2 strain gauges . . . . 139
16.5.2 2 módulos de célula de carga, contendo 4 strain gauges . . . 141
16.5.3 4 módulos de célula de carga, contendo 8 strain gauges . . . 142
16.6 Prática 25 - lendo dados da célula de carga . . . . . . . . . . . . . . . 143
17 Motores 144
17.1 Motor DC universal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
17.2 Motor de passo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
17.3 Prática 26 - acionando motor de passo . . . . . . . . . . . . . . . . . . 152
4
17.4 Servo Motor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
17.5 Prática 27 - acionando servo motor SG90 . . . . . . . . . . . . . . . . 153
5
Sobre esta apostila
Esta apostila foi criada para fins educacionais sendo PROIBIDA sua comercialização com
fins lucrativos. Cópias e distribuições gratuitas são autorizadas, dadas as devidas referên-
cias bibliográficas aos autores e colaboradores.
6
1 Arduino
SECTION
Este capítulo apresenta uma breve introdução ao Arduino, mais especificamente o Arduino UNO,
sua história, características e aplicações típicas.
1.1 Definição
O Arduino é um conjunto constituido de uma placa eletrônica composta de um controlador AT-
MEL AVR 8 bits, junto a um circuito de hardware de livre acesso, que varia para cada modelo
de Arduino, mas é composto basicamente de uma fonte de alimentação regulada, uma comu-
nicação USB e pinos de entrada e saída. Junto a placa eletrônica (Fig. 1), usa-se sua IDE que
permite a programação em C++ (com algumas adaptações para o usuário). Perceba então, que o
Arduino, não é somente o microcontrolador, é todo o conjunto de hardware junto a IDE ao qual
ele é programado. [4]
1.2 Criação
O Arduino foi desenvolvido 2005, em Ivrea na Itália. Seu objetivo era a criação de um micro-
controlador de baixo custo e fácil acesso, para que jovens pudessem aprender lógica de progra-
mação e eletrônica básica, sem necessitar de conhecimentos avançados de microcontroladores,
memórias, arquitetura de computadores e outros.[4]
7
Figura 1: Arduino UNO - Fonte: [Link]
8
Figura 3: ATMEGA 328 pinagem - Fonte: [Link]
Como pode ser visto, a placa do Arduino já organiza os pinos de acordo com suas funções e
registradores e os autonomeia. Se você já trabalhou com algum outro microcontrolador, sabe
que devemos olhar pino a pino, ver qual registrador ele faz parte, verificar no datasheet qual as
funções daquele registrador e pino, quais outros registradores internos fazem parte, etc.
No caso do Arduino, o usuário não precisa fazer isso, já que a placa eletrônica já possui as liga-
ções feitas e agrupa os pinos por registradores e a IDE do programa, já pré configura os regis-
tradores e pinos, e os reconhece por meio de nomes simples que iremos abordar no próximo
capítulo. Caso você queira ajustar algum registrador interno, basta adicionar uma biblioteca ao
programa, que este registrador será reconhecido e pré configurado.
9
projeto, e caso o produto final apresente erros, é praticamente certeza que o erro está na lógica
de programação do novo controlador.
Assim, o Arduino se tornou uma ferramente muito versátil nos dias atuais, servindo para acelerar
o processo de criação e validação de produtos em empresas, criar protótipos em curto prazo,
treinar e capacitar novos trabalhadores em um curto período e de forma mais simplificada, etc...
10
2 SECTION
IDE
Este capítulo apresenta o Ambiente de Desenvolvimento Integrado (IDE na sigla em inglês para
Integrated Development Environment) do Arduino, incluindo uma descrição básica e estrutura
de código.
2.1 Introdução
Visite o site [Link] e baixe o IDE do programa na aba downloads. Execute como
administrador e siga os passos de instalação. No final abra a IDE do programa. A Figura 4 mostra
o ambiente de programação, compilação e gravação do seu código no Arduino [4].
Para conectar o Arduino ao computador, primeiro você deve ir na aba "ferramentas"e depois na
opção "placa"(vide Fig. 5). Em seguida escolha a opção correspondente ao seu Arduino, que
neste caso deve ser o Arduino UNO.
Em seguida, conecte a sua placa ao computador por meio do cabo USB. Tome cuidado com a
superfície onde você coloca seu Arduino. Umidade e pedaços metálicos podem curto-circuitar
as ligações e soldas elétricas na parte inferior da placa, podendo ocasionar até a queima da porta
USB do seu computador!.
11
Figura 4: - Fonte: Autor
pode ser apagada e deve ser mantida na posição inicial em que surge, antes da função void loop.
Quando o comando estiver pronto e for carregado no controlador, ele executa inicialmente as
ações descritas na void setup e então parte para void loop que é repetida indefinidamente. Sendo
assim, você pode executar comandos dentro da função void setup, mas saiba que eles serão exe-
cutados uma única vez.
12
Figura 5: IDE Arduino - Fonte: Autor
dia).
A seguir temos a pinagem completa do Arduino UNO com todas as funções de cada pino (Fig.
6). Vale ressaltar que as configurações mudam de modelo para modelo, então sempre confira o
datasheet do seu Arduino, caso não seja o UNO (que é o utilizado neste resumo) [10].
13
Figura 6: IDE Arduino - Fonte: [Link]
14
3.1 Introdução
3VARIÁVEIS
SECTION
Este resumo pressupõe que você tenha alguma noção de linguagem C ou C++, pois todos os co-
mandos empregados no Arduino são baseados e adaptados dessas linguagens.
A própria ideia de variável também. Existem variáveis locais, globais e fixas, além de outros re-
cursos que nos auxiliam a armazenar dados na memória.
A variável será um espaço reservado na memória do microcontrolador, no qual você guarda uma
informação, podendo ser um número inteiro, com casa decimal, um caractere ou conjunto de-
les, um valor binário (booleano), etc...
Porém, tome cuidado, pois a memória de um microcontrolador é pequena e devemos aproveitar
sabiamente seu espaço de armazenamento a fim de não faltar ou comprometer a otimização do
código.
15
• char: um caractere
Sempre declaramos primeiro o tipo de variável (se ela é inteira, ponto flutuante, caractere...)
e depois a nomeamos. Caso queira, você pode já armazenar um valor usando o símbolo de
atribuição ’=’.
Cuidado ao nomear a variavel, pois só é permitido um total de 31 caracteres na palavra que
a nomeia, sendo válido somente letras e números após o primeiro caractere. É vedado o uso
de acentos e caracteres especiais exceto o underline. As variáveis também são ’Case sensitive’,
então letras maiúsculas e minusculas também alteram o nome dela.
Veja os exemplos ERRADOS:
• char palavrão[];
• float núMEros ;
• int [Link];
• char palavrao[];
• float nuMEros ;
• int numeros_inteiros;
16
3.5 diretiva static
Esta diretiva acompanha um tipo de variável (ex: static int ’variavel’;).
Ela faz com que o valor contido na variável durante sua criação seja fixo, ou seja, estático. Desta
forma, mesmo que você tente associar outro valor aquela variável, ele não será alterado. É mais
comumente usado em variáveis globais para não ter que ficar reinicializando o valor da variável
via código, dentre outras aplicações.
17
4
Escrita Digital
SECTION
Neste capítulo iremos entender como é feita a escrita digital no arduino, os comandos a serem
utilizados e faremos um exercício de treino.
4.1 Introdução
As portas são os nossos pinos que possuem registradores. Estes pinos com registradores podem
ser do tipo digital, ou seja, aceitam apenas valores binários ’1’ ou ’0’; Analógico, ou seja, aferem
valores analógicos e digitalizam para o microcontrolador; podem ser de comunicação, dentre os
quais temos a comunicação SERIAL (USART), I2C, SPI, USB, 1 Wire, etc...; e podemos ter o pino
sem registrador no qual serve para alguma parte do funcionamento do microcontrolador como
alimentação e pino de reset.
Vale ressaltar que alguns registradores operam com pinos individuais, enquanto que outros ne-
cessitam de vários pinos. Neste capítulo vamos entender como usar os pinos digitais do Arduino
UNO, tanto para escrita como leitura de dados, sem envolver protocolo de comunicação, o qual
será visto mais adiante [4].
18
• pinMode(’valor’ , ’tipo’);
• digitalWrite(’valor’ , ’estado’);
Sendo ’valor’ um número inteiro positivo (0,1,2,3,...), referente ao pino digital do Arduino;
Sendo ’estado’ o nível lógico do pino, no qual você substitui por ’HIGH’ ou ’LOW’.
• delay(’tempo’);
Sendo ’tempo’ um valor inteiro positivo que será entendido pelo microcontrolador como o tempo
de pausa do programa em milissegundos.
19
Figura 7: diagrama elétrico prática 1 - Fonte: autor
Veja que este circuito é composto de três leds, representando as cores de um semáforo. O led
verde fica aceso por 3 segundos, o amarelo depois acende por 1 segundo e o vermelho acende
por último durante 2 segundos, então a sequência se reinicia. Quando um led está aceso os
outros estão apagados, assim como no funcionamento do semáforo normal. Os pinos 13,12,11
estão conectados aos Leds verde, amarelo e vermelho respectivamente, na configuração catodo
comum, ou seja, acendem com nivel lógico alto. Os resistores de 270R servem para limitar a cor-
rente em cada led. No código a seguir, teremos a diretiva ’define’ para nomear os pinos usados e
assim facilitar nossa leitura e atribuições no código. Usamos o comando ’pinMode’ para definir
os três pinos como saída de dados e o comando ’digitalWrite’ para escolher qual pino vai a nivel
lógico alto ou baixo.
20
Figura 8: código prática 1 - Fonte: autor
21
5
Leitura Digital
SECTION
Neste capítulo iremos entender como é feita a leitura digital no arduino, os comandos envolvi-
dos e faremos um exercício de fixação.
5.1 Introdução
Assim como é feita a escrita de dados digitais (binários) podemos fazer o mesmo com a leitura.
Neste caso iremos identificar apenas dois estados, ’1’ ou ’0’, ligado ou desligado, com energia ou
sem energia, etc...
Você também pode definir o tipo de lógica de acionamento, direta ou indireta, mas para o nosso
caso, vamos trabalhar só com lógica direta.
Para evitar problemas de ruído, devemos utilizar o sistema pull up ou pull down, assim asse-
gurando sempre o nível lógico. No momento, iremos efetuar isso fisicamente, ou seja, teremos
resistores no circuito para fazer essa configuração. Depois veremos uma forma de utilizar os
próprios registradores internos do Arduino para fazer isso. Veja a figura:
22
Figura 9: Ligação pull up e pull down - Fonte: [Link]
• digitalRead(’pino’);
23
Figura 10: pratica 2 - esquema de ligação - fonte: autor
Nesta prática há três botões conectados nos pinos 5,6 e 7 digitais. No pino 13 há um led co-
nectado para ser aceso. Para armazenar os valores lidos dos botões, temos que criar variáveis,
e neste caso, podem ser do tipo booleana, já que o microcontrolador irá guardar apenas dois
estados (1 - pressionado) ou (0 - despressionado). Quando os três botões são acionados, o led é
aceso.
24
Figura 11: pratica 2 - programação - Fonte: autor
• pinMode(’pino’, INPUT_PULLUP);
25
Figura 12: pratica 2 - circuito com pull up interno - Fonte: autor
No circuito da figura 12, não é necessário os resistores de pull down do exercício anterior, já que
nosso microcontrolador assume sempre nivel alto. Logo, os botões enviam nivel baixo ao serem
pressionados. Então, se seguirmos o algorítmo do programa anterior, em que o led só acendia
quando todos os botões fossem pressionados, enviando nivel alto, então para este código, te-
remos que o led sempre fica aceso, pois por padrão o pull up interno está ativado, e os leds só
apagam quando um botão é aceso. Veja as alterações necessárias no código da figura 13:
26
6
Leitura Analógica
SECTION
Neste capítulo iremos entender o que é a leitura analógica, os comandos envolvidos e faremos
um exercício de fixação.
6.1 Introdução
Apesar do nosso microcontrolador operar com lógica binária, ele é capaz de ler valores analógi-
cos. Porém é necessário digitalizar esses valores por meio de um conversor A/D. Alguns pinos do
microcontrolador são capazes de realizar essa conversão, mas são os pinos analógicos, variando
do A0 ao A5 (no Arduino UNO). A partir da faixa de tensão que o microcontrolador afere (0V a
5V para Arduino uno), e a resolução máxima (10 bits = 1024 divisões), podemos obter a mínima
resolução do microcontrolar [1]:
5−0
Resol ução = = 0, 004882813V /d i v ≈ 0, 005V /d i v (1)
1024
Podemos perceber então que a cada 0,005V de aumento de tensão, o microcontrolador irá adi-
cionar 1 a sua contagem do conversor A/D, sendo que:
27
Tensão [V] Valor binário
0,000 0000000000
0,005 0000000001
0,010 0000000010
0,015 0000000011
* *
* *
* *
5,000 11111111111
• analogRead(’pino’);
no qual ’pino’ é o pino ao qual faz a conversão A/D, sendo possível do A0 ao A5 no Arduino UNO.
Perceba que no microcontrolador o valor aferido vai de 0 a 1023 (pois temos 1024 divisões), neste
caso, devemos guardar o valor aferido numa variavel INTEIRA e fazer os ajustes para a conversão
física da grandeza aferida.
Depois para achar o valor do ângulo, se 180º = 5V, então por regra de três:
t ensão ∗ 180
âng ul o = (3)
5
Veja como isso é implementado no código e faça o experimento no software ou em bancada:
28
Figura 14: pratica 3 - circuito elétrico - Fonte: autor
29
Uma coisa muito importante a salientar é que as conversões requerem números com ponto
flutuante (float), então para não haver perda de dados, devemos realizar o ’cast’, quando mis-
turamos int com float. Dependendo do cast realizado, você pode consumir mais memória e
aumentar a precisão dos seus dados (float), ou pode diminuir a memória consumida mas per-
der um pouco a precisão dos dados (int), então tome cuidado para não estourar a memória do
microcontrolador, nem perder precisão nos cálculos. Este algorítmo não está otimizado, tente
melhorá-lo como forma de treino e memorização dos comandos.
30
7
Escrita Analógica
SECTION
Neste capítulo iremos entender o que é escrita anlógica, os comandos necessários no arduino e
faremos um exercício de fixação.
31
Figura 16: alguns tipos de forma de onda - Fonte: wikipedia
32
Como exemplo clássico, temos a tensão da nossa tomada. Quando falamos que uma tomada
é 127V, na verdade ela náo é 127V, mas sim seu valor RMS. Os 127V seriam caso eu trocasse
a corrente alteranda sinusoidal da tomada, por uma corrente contínua constante de 127V. Na
realidade temos uma onda sinusoidal de amplitude máxima de 180V, como mostrado na figura.
Perceba então que o valor RMS é como se fosse uma média, no nosso caso de análise, uma tensão
média. Porém o RMS é uma forma de comparar, pois na realidade temos a tensão sinusoidal da
tomada. Caso você aplique um filtro e eletrônica correspondente, pode tornar a forma de onda
do sinal muito próxima a do RMS. É a partir desta observação que vamos conseguir trabalhar
com a saída analógica do Arduino [22].
7.3 PWM
O PWM é conhecido também como onda quadrada, isto porque é um sinal com forma de onda
no qual não temos variação no tempo, mas apenas dois valores bem definidos, baseados em
lógica digital. Então hora o sinal é ligado, hora desligado. Se eu considerar a tensão do Arduino
UNO, então sua saída PWM, hora envia 5V (ligado), hora envia 0V (desligado). Veja a figura 18:
O PWM é criado a partir de dois parâmetros, o duty cicle e a frequência. A frequência é a quan-
tidade de vezes que o sinal se repetiu numa faixa de tempo. O duty cicle indica (em porcenta-
gem) quanto tempo o nivel lógico alto ficou ativo. A partir dessa combinação, podemos gerar
diferentes sinais PWM com diferentes valores RMS, só que no caso do PWM, o seu valor RMS é
diretamente proporcional ao duty cicle. Isto implica dizer que quanto mais tempo o pwm fica
em nível lógico alto (com tensão), maior é a média de tensão que ele gera, e quanto maior a
frequência, mais rápido essa onda se repete e mais próximo de um sinal médio emulado fica [1].
Veja a figura 19:
33
Figura 19: PWM com ajuste de duty cicle - Fonte: /[Link]
• analogWrite(’pino’,’duty cicle’);
34
Veja que no código, temos uma variável ao qual chamei de ’i’. Além de efetuar a contagem no
laço for, podemos usar ela para indicar qual o duty cicle no PWM.
No próximo capítulo vamos entender como usar o monitor serial do Arduino e o ploter; Desta
forma poderemos aferir os dados em tempo real e conferir se nosso algorítmo está operando cor-
retamente, se sensores e atuadores estão respondendo e até poderemos comunicar diretamente
do computador para o Arduino, enviando comandos em tempo real.
35
Figura 20: circuito prática 4 - Fonte: autor
36
8
Monitor Serial
SECTION
Neste capítulo iremos entender o que é o monitor serial do arduino, como ele pode nos aju-
dar a "enxergar"o comportamento do nosso código e realizar uma comunicação simples com o
computador. Também faremos exercícios de fixação.
37
Figura 22: monitor serial e ploter - Fonte: autor
• [Link](9600);
OBS: o 9600 é a taxa de transmissão de bits por segundo. Este é um valor padrão, porém pode
ser modificado de acordo com a necessidade do projeto.
este código deve ser inserido dentro da função void setup para habilitar o monitor serial e os
pinos digitais 0 e 1 do seu Arduino devem estar livres para evitar problemas de conflito interno.
O comando anterior vai permitir que você ative a janela de monitor e ploter mas não vai mostrar
os dados, pois vc precisa indicar a variável a qual você deseja aferir e mostrar os valores, logo use
o comando:
• [Link](’variavel’);
No qual ’variável’ é o nome da variável que você quer monitorar. Coloque este código toda vez
que você quiser aferir o valor ou atualizálo. Faça o código como a seguir, para o exemplo 4:
38
Figura 23: pratica 4 - monitor serial e ploter - Fonte: autor
Você perceberá no código que existe uma função um pouco diferente da print, e isso eu vou
explicar na próxima secção.
39
Figura 24: prática 4 - código com monitor Serial - Fonte: autor
40
8.5 Usando Monitor serial como prompt de comando na IDE
Para enviar comandos do monitor serial para o Arduino, temos que conhecer alguns comandos
possíveis, neste caso, vou pedir para você acessar o link [Link]
pt/language/functions/communication/serial/ e ler todos os comandos. Porém vou ex-
plicar de forma mais sucinta os mais usados [2]:
• [Link]();
escreve dados porém já convertendo para código ASCII, que no computador é lido como um
valor hexadecimal a partir da tabela ASCII, mas para o nosso monitor já é interpretado como
um caractere alfanumérico. Necessita aplicar para o texto lido e não pula linha automático,
sendo necessário o comando
n para pular linha.
• [Link]();
• [Link]();
Retorna o valor lido pelo monitor serial, caractere a caractere já convertido para código ASCII.
Quando o comando [Link] é acionado e não digitamos nada, o serial monitor lê ’0’. Pode-
mos usar esse fato para controlar quando queremos que nosso monitor serial leia e grave numa
variável o valor, mas se atente que o valor passado é inteiro mas corresponde ao código ASCII
em DECIMAL. Então por exemplo, se você digitar ’0’ e mandar mostrar na tela, vai aparecer ’48’,
pois equivale ao número 0 na tabela ASCII.
• [Link]();
Igual a função anterior, mas neste caso já lê uma string completa e pode ser manipulada direta-
mente sem estar no formato ASCII.
• [Link]();
Este comando retorna quantos bytes estão sendo usados na leitura do monitor serial. O máximo
de bytes que podemos escrever e ler é 64 (não é um editor de texto, mas da pra escrever muita
coisa, ja que cada caractere alfanumérico ocupa 1 byte). Quando nada é lido no monitor serial,
esta função retorna 0. Use uma estrutura condicional no programa ex: ([Link] > 0), para
que você possa identificar quando nada é escrito no monitor serial por exemplo.
• [Link]();
Se você digitar números e enviar para o monitor serial, ele vai "zoar"tudo, pois como eu disse
anteriormente, o monitor converte para decimal, caractere a caractere. Então no lugar de Se-
[Link], você usa essa função para ler inteiros. Faça um teste e coloque diferentes inteiros,
positivos e negativos, letras e float. Veja o que acontece.
• [Link]();
Mesma função do [Link], só que para floats. Lembrando que no Arduino, a cada deci-
mal é separa por ’.’ e não por ’,’.
41
8.6 Variável do tipo string
O Arduino possui uma facilidade imensa para ler strings. Enquanto que num microcontorlador
normal você deve criar um vetor do tipo char para armazenar caractere a caractere e caso queira
mostrar a palavra escrita, você deve ler o vetor com laço for, no Arduino, basta você declarar a
variável como do tipo string.
Você pode fazer no método ’old school’ e criar um vetor char, mas na maioria dos casos não é
preciso.
42
Figura 26: prática 5 - código - Fonte: autor
Nessa prática, escreva ’ON’ no monitor serial e depois clique em ’enviar’, o LED irá acender em
seguida. Faça o mesmo para a palavra ’OFF’, o LED irá apagar. Você pode capturar dados na
forma de string com o comando [Link](), desta forma algumas lógicas de automação
e monitoramento pelo Arduino podem ser executadas, faça algo para você brincar e se acostu-
mar a essa funcionalidade do Arduino.
Se você quiser entender outras funções adicionais e comandos mais avançados, basta acessar
o link: [Link]
43
9Bibliotecas
SECTION
Neste capítulo iremos entender o que são bibliotecas, sua importância para o arduino e como
utilizá-las.
44
9.2 Como importar bibliotecas
Importar uma biblioteca é você trazer ela para o seu programa, deixando-a disponível na IDE do
Arduino e podendo defini-lá no cabeçalho do programa. Existem 3 formas:
Nessa forma, você deverá abrir o diretório do Arduino no seu computador e achar a pasta ’li-
braries’. Dentro desse diretório você coloca a pasta contendo a biblioteca que você baixou na
internet. Fontes confiáveis são do fabricante do equipamento, GitHub ou da página oficial do
Arduino. Fontes confiáveis, além de não trazerem virus para o seu computador, são asseguradas
que irão funcionar e estão otimizadas, muitas vezes possuindo várias versões, mas em todo caso
seu antivirus deve dar conta.
Para achar a pasta ’libraries’ com facilidade siga os passos dentro da sua IDE:
Copie o link e vá no seu explorador de arquivos para encontrar a pasta raíz do Arduíno. Dentro
dela haverá a pasta ’libraries’, basta colar a pasta da biblioteca dentro:
45
Para verificar se deu certo e acessar a biblioteca na IDE, basta seguir a imagem:
46
Depois de selecionar a biblioteca, ela será importada para o seu programa e no cabeçalho vai
aparecer a escrita padrão em C++ para inserção de biblioteca (#include <biblioteca.h>). Você
também pode ver exemplos de como usar a biblioteca:
47
Se você tiver preguiça de ler ou não entender algo, pode caçar na internet como usa determinada
biblioteca. Lembre-se sempre de incluir a biblioteca no cabeçalho do programa para poder usá-
la, mas somenete depois de adicioná-la a IDE, como mostramos. Agora os outros métodos de
fazer isso.
As vezes a biblioteca bem compactada num arquivo .ZIP, então basta adicionar. Neste caso,
acesse a IDE como mostrado e selecione o arquivo .ZIP da biblioteca. Este método automatica-
mente inclui uma cópia na pasta ’libraries’ e já deixa disponível a biblioteca na IDE:
48
9.2.3 Importando dentro da IDE
Este é o método mais confiável, pois busca diretamente do banco de dados online da página
oficial do Arduino. Basta acessar como na figura e procurar pelo nome da biblioteca ou compo-
nente desejado:
49
Arduino e suas funções e não a programação em si. Neste caso não irei explicar como criar bibli-
otecas, mas sugiro que tenha uma boa noção de C e C++ e POO, caso queira criar sua biblioteca.
Esse conteúdo você acha facilmente na internet. A partir de agora iremos fazer uso constante
de bibliotecas, lógico que tudo será detalhado, mas elas irão facilitar nosso entendimento sobre
outros conteúdos.
50
10
Protocolos de Comunicação
Neste tipo de comunicação, os dados (bits) são transmitidos sequencialmente por um mesmo
caminho (fio condutor, por exemplo), sendo necessário um tempo entre o envio do sinal pelo
emissor, até o recebimento e confirmação do receptor. Apesar desse protocolo ser mais lento,
pois são necessários vários envios até que toda informação seja transmitida, ele é mais seguro
e permite implementação de métodos mais eficazes contra ruídos e perda de informação, além
de ser mais barato e mais simples de utilizar pelo usuário final. Um exemplo de comunicação
serial é o cabo USB do seu computador, porém existem variações desse tipo que serão mostradas
adiante [30].
51
10.1.2 Comunicação PARALELA
Neste tipo de comunicação, os dados são transmitidos todos juntos em diferentes caminhos (vá-
rios fios condutores, por exemplo), desta forma uma mensagem maior ou até completa, pode
ser transmitida diretamente do emissor para o receptor em um tempo muito reduzido. Todavia,
esse método é mais suscetível a falhas por ruído e perda de informações, além de ser mais com-
plexo para o usuário final. Um exemplo, são os antigos cabos de impressora que utilizavam o
protocolo IEEE 448 (acho que hoje em dia isso virou lenda), no qual cada pino tinha uma função
de transmitir um sinal diferente. Para que fique mais claro, um pino servia para enviar um dado
de posição inicial da tinta de impressão, outro autorizava a impressão, outro pino indicava o
nível de tinta, outro autorizava a impressora a ligar, etc...
Se isso fosse feito em comunicação serial (o que foi feito com o protocolo RS232 depois), mesmo
tendo um conector parecido e cheio de pinos (por razões de adaptação dos conectores), nem
todos os pinos eram usados e ele já possuia os pinos de comunicação serial RX e TX (como
veremos), porém ainda possuia alguns pinos auxiliares mas não vinculados diretamente a co-
municação. Posteriormente se tornou um protocolo "100%"serial, quando foi substituido pelo
USB [30].
É a velocidade com a qual podemos transmitir a informação. Se o seu sistema for síncrono
(depende de clock) ela é dada em bits por segundo (bps). Se a comunicação for assíncrona,
ela é dada em Baud Rate (Bd), muitas vezes confundido ou nomeado como (bps). Todavia, a
informação assíncrona acaba sendo mais rápida que a síncrona, logo não podemos considerar
1bps sendo igual para ambos os sistemas [30].
A transmissão síncrona não é exclusiva de sistemas seriais, porém como a comunicação para-
lela foi quase totalmente abandonada para protocolos de comunicação comerciais, os exemplos
dados são em 99% dos casos, com protocolo serial. No caso da transmissão síncrona, tanto o re-
ceptor como o emissor operam com um mesmo sinal mestre de sincronia chamado CLOCK. É
o clock que gerencia o tempo que cada componente tem para enviar e receber o sinal e man-
ter a coerência entre sinal lido e enviado, uma vez que na comunicação serial é necessário um
parâmetro para distinguir um sinal de outro. Na comunicação paralela, era usado apenas para
sincronizar o tempo de envio do de recebimento, não tendo a necessidade de separar os sinais,
já que eles eram enviados todos juntos por caminhos distintos (não no mesmo barramento) [30].
A transmissão assíncrona não depende de um CLOCK que comanda tanto o emissor como re-
ceptor, tendo cada um o seu próprio clock. Todavia, é necessário que o Baud Rate de ambos os
sistemas seja igual para não haver erro de comunicação [30].
52
10.1.6 Simplex
Neste caso, o dispositivo de comunicação só pode ou enviar ou receber o sinal, sendo impossível
que o receptor envie informação e o emissor receba informação [30].
10.1.7 Half-Duplex
Agora tanto o emissor como receptor podem inverter seus papéis, enviando e recebendo infor-
mações, porém um de cada vez. Enquanto um envia o sinal, o outro só pode receber [30].
10.1.8 Full-Duplex
Agora ambos, emissor e receptor podem inverter os papéis e podem enviar e receber informa-
ções ao mesmo tempo, sem ocorrer conflito [30].
• tensão de operação: 0V a 5V
Este protocolo é utilizado no Arduino UNO para fazer a comunicação entre o microcontrola-
dor e o computador, permitindo que possamos usar o monitor SERIAL e o ploter, como mos-
trado em capítulos anteriores. Também podemos usar para comunicação entre sensores que
usam esse protocolo e entre Arduinos. No Arduino UNO, os pinos digitais 0 e 1 estão vincu-
lados a este protocolo e não devem ser usados quando o mesmo estiver ligado ao computador,
pois podem causar problemas. Acesse [Link]
functions/communication/serial/ para entender mais sobre as funções desse protocolo na
placa, porém o método de inicialização dele já foi apresentado em capítulos anteriores, quando
aprendemos a manipular o monitor serial do Arduino na IDE e como ler strings e outras coisas
[30].
Esse protocolo possui 2 pinos de comunicação, o RX e o TX. PRESTE ATENÇÃO, o RX do emissor
vai ligado ao TX do receptor e o TX do emissor vai ligado ao RX do receptor, ou seja, faça a ligação
53
cruzada. Nunca esqueça de ligar os fios de GND entre os componentes. No Arduino UNO (a não
ser que você projete uma placa) não tem como mecher nisso, já que só tem 1 porta serial UART.
Porém outros tipos podem ter várias portas, por isso a explicação. Veja a figura 33:
Não confunda, todos os protocolos apresentados aqui serão serial, porém a UART especifica-
mente, todo mundo chama de serial não sei o porquê. Mas quando você ver serial, procure
perceber se estão se referindo a qualquer protocolo ou especificamente a UART.
54
10.4 I2C
• Tipo de Transmissão: Síncrono
• tensão de operação: 0V a 5V
Vamos explicar alguns aspectos desse protocolo para depois mostrar como utilizá-lo.
Em relação ao HARDWARE, este protocolo possui 1 MESTRE e os demais dispositivos são ES-
CRAVOS. O mestre envia o sinal de clock lido por todos, a partir do barramento SCL. entre todos
os componentes esse barramento é interligado, ou seja, você conecta o SCL de um no outro.
Para a comunicação, se usa o pino SDA, também compartilhado entre todos os componentes.
Apesar de ter 1 mestre por vez, você pode alterar entre qual dispositivo será o mestre, se este
permitir. Ambos os barramentos SCL e SDA necessitam que hajam resistores de pull up, no va-
lor próximo de 4.7K e os pinos de GND de todos os dispositivos devem estar conectados [30]. A
figura 34 mostra um esquema de ligação típico para I2C:
55
Figura 34: Esquema ligação protocolo I2C - Fonte: Autor
Uma vez que a comunicação ocorre, o mestre envia o sinal para todos os dispositivos simul-
taneamente, porém cada escravo só irá realmente receber a mensagem se seu endereço estiver
relacionado. O endereço é literalmente um endereço de memória fixo, no qual o hardware indica
um valor binário de 7 bits e que convertendo para hexadecimal, vão de 0x00 até 0x127, ou seja,
podemos comunicar 128 dispositivos distintos ao mestre, tudo no mesmo barramento. Alguns
hardwares possuem 8 bits, sendo o oitavo bit referente a leitura ou escrita fixos (0 para escrita,
1 para leitura). Caso seja de 7 bits, então o dispositivo pode ser usado tanto para leitura como
escrita OU possui uma função fixa que é definida via software. A maioria dos dispositivos é de
7 bits, gerando o endereço hexadecimal descrito anteriormente. É de suma importância que
os endereços não conflitem entre dispositivos, pois senão ocorrerá erro na comunicação, então
assegure que cada dispositivo está com o hardware configurado para um endereço único a ele
naquele barramento. Em próximos capítulos estudaremos componentes que usam I2C e desta
forma vou detalhar como selecionar o endereço no hardware. Não é obrigatório o uso sequen-
56
cial de endereços entre componentes (1,2,3.... pode ser 1,22,48,127, por exemplo) [30].
Agora falando sobre o software, a biblioteca para uso do protocolo I2C já vem previamente ins-
talada na sua IDE do Arduino, chamada de ’Wire’. Faça um #include <Wire.h> para importar a
biblioteca do protocolo I2C [5]. A seguir, eu listo alguns comandos úteis para usar a biblioteca:
• [Link]()
inicializa o protocolo I2C no Arduino
• [Link](’endereço’)
inicia a comunicação entre o Arduino e o periférico desejado. no lugar de ’endereço’, você
coloca o endereço real do componente em hexadecimal.
• [Link](’dado’)
Escreve (envia) um dado para o barramento. só será lido pelo escravo, caso seu endereço
tenha sido referenciado já com a função ’begintransmission’. No lugar de ’dado’ insira o
dado a ser enviado.
• [Link]()
esta função retorna um valor inteiro baseado em quantos bits estão sendo enviados no
barramento. Se for ’0’, então o barramento está livre e pronto para receber comunicação.
• [Link](’slave’,’bits’)
comando para requisitar informação do escravo. no lugar de ’slave’ coloque o valor do
endereço em hexadecimal do componente e no lugar de ’bits’ coloque quantos bits de
dados deseja receber.
• [Link]()
após o comanod anterior, pode-se usar este para salvar em alguma variável os valores
recebidos. faça uma atribuição de uma variável a este comando.
• [Link]()
finaliza a comunicação I2C entre o mestre e o escravo no endereço selecionado.
Vamos dar um exemplo de código comunicando dois Arduinos via I2C. O objetivo é que um Ar-
duino dê o comando para o outro acender um LED. Note que no Arduino UNO, os pinos SDA e
SCL são respectivamente os pinos ’A4’ e ’A5’. A seguir temos o esquema de ligação entre Ardui-
nos (com o barramento I2C) e o código de exemplo nas figuras 35, 36 e 37:
57
Figura 35: Esquemático entre Arduinos UNO para I2C - Fonte: Autor
Veja que no esquemático, os pinos SDA estão ligados entre si, bem como os SCL, ambos inter-
conectados a resistores de pull up de 4,7k. A alimentação de 5V fornece o nivel lógico alto para
o resistores e todos os negativos (GND) estão conectados entre si.
Na parte da programação se atente ao comando [Link](), pois seu parâmetro de en-
trada é uma função que executa uma rotina para o recebimento do sinal. sugiro estudar melhor
essa função para que você possa absorve-la, tudo disponível na página oficial do Arduino.
58
Figura 37: Programa I2C no Arduino ESCRAVO - Fonte: Autor
10.5 SPI
• Tipo de Transmissão: Síncrono
• tensão de operação: 0V a 5V
Este barramento é responsável pelo envio dos dados do mestre para o escravo. Todos os pinos
MOSI devem se interligar [30].
Este barramento é responsável pelo envio de dados do escravo para o mestre. Todos os pinos
MISO devem se interligar [30].
59
10.5.3 SCLK - Serial clock
Este barramento é responsável por enviar o sinal de clock síncrono do mestre para todos os
escravos. Todos os pinos SCLK devem estar interligados entre si [30].
Estes pinos são responsáveis pela seleção do escravo que vai comunicar com o mestre. Quando
o pino está em nível alto, o escravo IGNORA o mestre. quando o pino está em nível baixo, o
escravo COMUNICA com o mestre. Para cada escravo, devemos ter um barramento SSx sendo
ligado ao mestre, então para cada novo escravo, é adicionado um barramento [30]. Veja a figura
38:
60
Para o Arduino, a figura 39 mostra a pinagem para comunicação SPI:
Lembre-se de sempre conectar os GNDs de todos os componentes no circuito. Outra coisa im-
portante a salientar é que, como temos apenas 1 pino SSx, se precisarmos controlar mais de 1
dispositivo conectado ao barramento, devemos usar um multiplexador no pino do SSx e alguns
pinos digitais (depende do tamanho do multiplex) para selecionar qual componente escravo
será comunicado. Iremos fazer isso em práticas futuras quando precisarmos de mais de um
componente SPI.
Na parte da programação, devemos fazer a declaração da biblioteca SPI.h (#include <SPI.h>), já
padrão da sua IDE. Uma coisa importante a considerar é o modo de operação do barramento
SPI. Antes de explicar, vamos inserir um pouco de vocabulário necessário:
61
• CPHA - Fase do clock
indica em qual borda os dados devem ser inseridos ou desativos no barramento, ou seja,
qual borda irá separar as informações seriais recebidas [13].
A figura 40 ilustra os 4 modos de operação que podem ser obtidos ajustando o CPOL e o CPHA:
Esses modos de operação são necessários para comunicar corretamente o escravo ao mestre e
são parâmetros da biblioteca a serem definidos.
A seguir eu listo algumas funções úteis que serão usadas, mas todos os comandos da biblioteca
você pode acessar em [Link]
• [Link]()
Inicializa o protocolo SPI
• [Link](’parâmetro’)
define se a leitura da mensagem partirá do bit mais signficativo ou do menos significativo.
Em ’parâmetros’ use ’LSBFIRST’ ou ’MSBFIRST’, para definir a leitura do menos significa-
tivo ou mais significativo, respectivamente.
62
• [Link](’parâmetro’)
Indica por quanto o clock do Arduino será dividido para ser usado na comunicação (clock
do barramento SCLK). Por padrão o Arduino usa um cristal de 16MHz e o mínimo é um
clock de 4MHz. Não use um clock maior do que o dispositivo a ser comunicado. Em ’pa-
râmetro’ use os comandos: ’SPI_CLOCK_DIV2’,’SPI_CLOCK_DIV4’, ’SPI_CLOCK_DIV8’,
’SPI_CLOCK_DIV16’ ... ’SPI_CLOCK_DIV128’.
• [Link](’parâmetro’)
Define o modo de operação da comunicação SPI. Em lugar de ’parâmetro’, use: ’SPI_MODE0’
ou ’SPI_MODE1’ ou ’SPI_MODE2’ ou ’SPI_MODE3’.
• [Link](’parametro’)
função para envio e recebimento de dados. Em ’parâmetros’ indica o dado a ser enviado.
esta função sempre recebe um retorno resultado da operação de envio.
• [Link](’bits’,’modo’)
indica em ’bits’ quantos bits de dados serão transferidos e em ’modo’ o modo de operação.
• [Link](’frequencia’)
indica a frequencia do SCLK (clock). O valor padrão é 1MHz.
• [Link](’dados’)
a mesma coisa da função transfer, pois envia o dado e retorna o valor lido, lembrando que
a comunicação é full duplex, por isso.
Nesta prática faremos algo análogo a prática 6, tendo um Arduino mestre, um escravo e envi-
ando o sinal do mestre para o escravo e assim acionando um led na saída. A seguir temos o
esquemático de ligação e os códigos de exemplo do mestre e do escravo:
63
Figura 41: prática 7 - comunicação SPI entre arduinos (hardware) - Fonte: adaptação do
autor
Para cada código na figura 42, grave em um arduino diferente e efetue a ligação elétrica como
mostrado na figura 41. Ligue os arduinos a duas entradas USB distintas do seu computador, não
esqueça de alterar a porta USB correta na IDE para alterar entre o mestre e o escravo. Após com-
pilar e gravar em cada arduino, seu respectivo código, você deve abrir o monitor serial do mestre
e digitar alguma coisa e enviar. Esse dado será lido pelo escravo e armazenado. O código da
figura 42 não realiza nenhuma outra ação além de receber dados pelo escravo, logo, você pode
criar alguma condição para verificar a transmissão de dados ou analisar pelo osciloscópio.
Infelizmente, a biblioteca SPI do arduino é muito mais desenvolvida para código de mestre já
que, normalmente, o arduino atua como o mestre, lendo os dados dos periféricos que são escra-
vos, desta forma, o código do escravo é um pouco mais "feio".
64
Figura 42: prática 7 - comunicação SPI entre arduinos(software) - Fonte: adaptação do
autor
65
10.6 Prática 8
Pesquise sobre outros protocolos de comunicação para arduino ou que possam ser adaptados
como CAN, Ethernet, 1 wire ...
10.7 Prática 9
Pesquise shields e periféricos utilizados no arduino com os protocolos estudados nesse capítulo.
66
11.1 O que são interrupções
11 Interrupções
S ECTION
Interrupções são paradas programadas no programa para realização de uma ação. As condições
de parada podem ser externas (sinal) ou internas (flag ou lógica). Uma interrupção não trava o
código em uma determinada linha (como o comando delay() ), mas sim o redireciona para uma
outra função ou trecho de código. Devido a isso, o microcontrolador não para sua execução e
não ocorrem conflitos de sincronização entre informações recebidas ou enviadas. Claro que o
microcontrolador executa uma tarefa de cada vez, mas as interrupções permitem que diversas
partes (tanto hardware como software) sejam monitoradas e analisadas sem perda na coerência
do processamento.O Arduino uno possui dois pinos de interrupção externa(int0 e int 1, respec-
tivamente pinos D2 e D3) e uma rotina para interrupção interna, vamos estuda-los com calma
[32].
67
ção. A função deve ser do tipo void e não pode ter parâmetros de entrada;
No lugar de ’modo’, indique LOW (aciona quando pino em nivel baixo), CHANGE (aciona
quando houver uma transição de borda do sinal), RISING (aciona na borda de subida),
FALLING (aciona na borda de descida) [32].
• noInterrupts();
Função para desabilitar todas as interrupções.
• interrupts();
Função para habilitar todas as interrupções desabilitadas pelo noInterrupts.
Perceba que a rotina de interrupção já trata o botão quando ocorre uma borda de descida, uma
vez que ele está ligado em pull down. Quando isso acontece, implica que o usuário pressionou
68
Figura 44: código prática 10 - Fonte: autor
e soltou o dedo do botão e por isso o led (neste caso escolhi o vermelho) deve inverter seu es-
tado. Logo a função, ao qual o código é desviado, para ser executada precisa tratar apenas do led.
essa função que dei o nome de ’rotina_interrupção’ possui um laço ’for’ inicial, para gastar um
pouco de tempo, isso porquê para botões, podem acontecer o efeito ’bouncing’ e o pino digital
interpretar vários pulsos. Para corrigir isso, você pode implementar um sistema antibouncing
(com seus conhecimentos de eletrônica digital) ou fazer o tratamento via software (igual o que
eu fiz). Neste caso, voce retem o software naquele ponto de execução até o transitório passar,
desta forma, como em 16MHz o tempo de operação do Arduino é de 250nS, um laço de 10000
repetições obrigaria o programa a realizar essa operação por 25mS, que normalmente é sufici-
ente para corrigir o efeito de bouncing, qualquer coisa pode-se aumentar o tamanho do laço.
Em seguida, eu fiz o comando para alterar o estado do led.
Perceba que, mesmo no laço loop havendo pooling para o led verde, como a interrupção tem
prioridade na execução, e não trava o código, isso não interfere na dinâmica do laço ao mesmo
tempo que o pooling não afeta a interrupção, logo se torna possível a execução do programa
como descrito.
69
11.4 Interrupção Interna ou por timer
Esse tipo de interrupção possui um contador interno que, quando atinge um valor pré definido
da contagem, desvia para uma função a parte do código princial que é uma função de interrup-
ção. Quando o contador atinge o valor pré definido, dizemos que ocorreu o ’estouro do timer’ e
normalmente usamos uma flag (sinal indicativo) de que isso aconteceu. Devemos sempre lem-
brar de reinicializar o contador e sempre limpar a flag, voltando para o estado original [3].
Para usar a interrupção interna, devemos baixar e incluir a biblioteca ’TimerOne’.Em seguida,
devemos utilizar os comandos listados a seguir [31]:
• [Link](’time’)
essa função inicializa a interrupção por tempo e no lugar de ’time’ voce indica o tempo
em microssegundos.
• [Link](’função’,’time’)
esse comando indica qual função será chamada quando o estouro do timer1 for realizado.
No lugar de ’função’ coloque o nome da função auxiliar que você criou para executar a ro-
tina de interrupção. O parâmetro ’time’ pode ser substituido pelo tempo que você deseja
que essa função seja executada. Vamos supor que sua função auxiliar seja executada em
1 segundo, mas pode acontecer alguma coisa que a faça demorar ou ocasione erro. Neste
caso você pode indicar esse tempo ’time’ para obrigar a sair da sua função auxiliar e re-
tornar ao programa original. Tome muito cuidado pois isso normalmente causa erros de
memória, não sendo muito aconselhado. Se nada for digitado em ’time’ o programa só
retorna ao laço loop, quando a função auxiliar terminar de ser executada.
• [Link]()
disabilita a interrupção do timer1.
• [Link]()
para o contador interno do timer1;
• [Link]()
se pausado o contador, este comando retoma a contagem de onde parou;
• [Link]()
recomeça a contagem
• [Link](’time’)
no lugar de ’time’ insira o tempo do contador em microssegundos. este comando sobres-
creve o valor inicial definido para o timer
70
11.5 Prática 11 - Interrupção Interna
Nesta prática vamos fazer um pisca pisca com led, mas usando o timer. Veja as figuras 45 e 46:
71
Uma coisa muito importante e que confundo é: A INTERRUPÇÃO INTERNA NÃO PODE SER
INSERIDA DENTRO DA FUNÇÃO LOOP!!! Isso porque a função loop ira repetir os comandos
dentro dela. A interrupção por sua vez deve trabalhar a parte, sendo independente e não sendo
declarada todas as vezes. Desta forma, a função setup se torna a única opção. Caso necessite de
alguma lógica diferente, utilize variáveis de controle para armazenar os valores de contagem e
realizar ações, baseado no estouro de timer. Outra informação importante é que o timer1 pos-
sui 16 bits, enquanto os outros dois timers (0 e 2) do Arduino uno possuem 8 bits. Todavia esses
timers estão reservados a funções ou bibliotecas internas/ específicas e não serão abordados.
Lembrando que, estamos trabalhando com o Arduino uno, por isso essa parte se torna mais li-
mitada. Caso operassemos com o proprio atmega 328p, sofreríamos muito na programação que
seria em C e em outra IDE, mas daria para extrair mais do hardware, todavia, não é necessário
para as nossas aplicações nesta apostila e na grande maioria dos casos.
72
12
Displays e dispositivos
S ECTION
visuais
Chamamos de displays os dispositivos que transformam os sinais elétricos para sinais visuais
que possam ser lidos ou interpretados. Displays são compostos de vários elementos lumino-
sos que nos permitem enxergar a informação enviada. Um simples led, apesar de comunicar
uma informação visual, será somente um display de leds quando tivermos vários deles a ponto
de conseguirmos manipular a informação visual, criando códigos e padrões mais complexos.
Desta forma, existem diversos tipos de displays e nesse capítulo iremos estudar os mais comuns
usados no Arduino uno e sua programação [33].
Como o display é composto de leds, devemos nos preocupar com a configuração, se é catodo
comum (todos os leds estão ligados em comum pelo catodo, então nivel alto aciona cada led) ou
73
Figura 47: Display de 7 segmentos - fonte: ’diversas lojas de eletrônicos online’
são anodo comum (todos os leds estão ligados em comum pelo anodo, então nivel baixo aciona
cada led). Também não podemos esquecer dos resistores limitadores de corrente. Para 5V, use
por padrão 220Ω a 470Ω em c ad a l ed .
74
Podemos ligar diretamente 7 pinos digitais do Arduino aos 7 pinos do display (não esqueça dos
resistores), porém isso não é prático, pois usamos muitos pinos. Porém, podemos usar um de-
codificador para reduzir a apenas 4 pinos necessários ao funcionamento do display.
Nessa etapa eu preciso que você tenha conhecimento sobre codificadores e decodificadores,
pois para podermos usar o display de 7 segmentos necessitados de um decodificador de código
binário para display de 7 segmentos. Uma vez que o Arduino envia os sinais em binário a partir
dos seus pinos digitais, podemos com 4 bits representar os 10 algarismos no display. No total,
temos 16 possibilidades, porém como só precisamos de 10, ourtas 6 ficam livres para represen-
tar qualquer outra coisa. A maioria dos decodificadores de binário para display de 7 segmentos
assumem a respectiva tabela a seguir: No datasheet de cada decodificador você precisa iden-
tificar se ele serve para display de anodo comum ou catodo comum e também encontrará em
qual pino deve ligar os pinos do Arduino de envio de sinal e em quais pinos serão ligados aos do
display. Normalmente a sequência binária segue a decimal baseado no código BCD8421, mas
sempre é importante conferir no manual do fabricante essas informações [25].
75
12.2 Pratica 12.1 - acionando 1 display de 7 segmentos com decodifi-
cador CD4511
A seguir temos um esquemático com a montagem do Arduino para acionamento de um display
de 7 segmentos junto ao decodificador e a programação. Como a programação é mais complexa,
dividimos por bloco explicativo:
No hardware, lembre-se de ligar os GNDs de todos os componentes entre si. Nesta montagem o
decodificador CD4511 é compatível com display catodo comum.
76
Figura 52: Código prática 12.1 (2ª parte) - fonte: autor
Vamos entender esse projeto: Na parte do HARDWARE, basta voce ligar dos pinos 8 a 11 digitais
nos pinos D,C,B,A que são respectivamente do MSB ao LSB. Depois basta ligar no display as saí-
das do decodificador: a,b,c,d,e,f,g. A figura 46 mostra qual pino é qual do display para ser ligado
ao decodificador. Use os resistores de 220R e uma tensão de 5V para alimentar o conjunto, pode
usar a mesma do Arduino.
Sobre o SOFTWARE, vamos entender o código, que por uma questão de tamanho e didática di-
vidi em 2 partes, mas que são sequencia direta uma da outra.
Na PARTE 1, começo definindo os pinos do Arduino e o nome bit1,..,bit4 como alusão a posição
MSB ou LSB. No void SETUP, defino todos como saídas e começam em nível baixo (display apa-
gado), e inicializo a serial pois iremos ver o monitor dela.
Na PARTE 2, antes da função LOOP, temos uma função auxiliar declarada que tem como parâ-
metro de entrada uma variável que servirá para contagem (0 a 9). Existem várias formas de você
indicar qual número será mostrado, mas eu preferi a mais simples (e menos otimizada), que é
criar uma matriz de 10 posições (linhas), contendo 4 bits (colunas). Veja que em cada linha es-
77
tão definidos (em binário) dos números 0 a 9. Quando dermos a posição da linha, estaremos nos
referindo ao número a ser acionado e quando selecionamos a coluna estamos escolhendo o bit
a ser mostrado (bit4 ao bit 1).
Tome cuidado pois na nossa nomenclatura, o bit4 é o MSB, mas para acessar a matriz nesse
ponto, você precisa da posição ’0’ na coluna e para o bit1 LSB, você precisa da posição ’3’.
Depois de declarado essa matriz, veja que na escrita digital em seguida, eu referencio qual pino
será acionado e qual será a sua coluna respectiva, sendo a variável ’cont’ o parâmetro de entrada
na linha para indicar qual número será mostrado no momento. Faço a mesma coisa para o mo-
nitor serial, porém mostrando qual número está sendo vinculado no momento, você pode ver
isso no seu monitor.
Dentro da função LOOP, a variável ’i’ irá de 0 a 9 e será o parâmetro de entrada da função ’con-
versao’, ou seja, ’i’ será ’cont’ dentro da função. Desta forma, um ’if’ é usado para garantir que
sempre que ’i’ for passar de 9 ele retorne a 0.
Existem várias formas de mostrar dados no display e essa é uma das mais comuns, embora não
muito otimizada. Na próxima prática, veremos como acionar mais de um display ao mesmo
tempo.
78
Figura 53: tabela de acionamento do display de 7 segmentos -
fonte:[Link]
79
Figura 54: esquemático prática 12.2 - fonte: autor
80
Figura 55: código prática 12.2 (1ª parte) - fonte: autor
81
Figura 56: código prática 12.2 (2ª parte) - fonte: autor
82
Figura 57: código prática 12.2 (3ª parte) - fonte: autor
83
12.4 Display LCD
O display LCD, apesar de utilizar outra tecnologia, sua forma de operação é similar ao display
de 7 segmentos. A diferença agora é que ao invés de controlar apenas 7 elementos luminosos,
nos displays nós temos uma matriz deles. Vamos trabalhar com o display 16x2 (16 linhas por 2
colunas), no qual iremos repassar informações para ele, porém a lógica é a mesma para outros
tipos, sendo necessário implementar apenas a biblioteca respectiva ao seu display. Se você for
trabalhar com microcontroladores mais avançados que não possuem biblioteca, neste caso terá
de programar manualmente as configurações iniciais a serem enviadas ao display (ele possui
um microcontrolador interno que se comunica com o seu) e os dados. No Arduino, temos a bi-
blioteca ’LiquidCrystal.h’, ela já é padrão do Arduino, mas você pode baixar versões modificadas
para displays diferentes do LCD. A seguir temos a pinagem do nosso display [14]:
84
Usando a nossa biblioteca ’LiquidCrystal.h’devemos, baseado em suas funções de inicialização,
definir o hardware a ser usado compatível com a programação [6]. A seguir eu vou listar as prin-
cipais funções usadas para você entender:
• LiquidCrystal lcd(rs, rw, enable, d0, d1, d2, d3, d4, d5, d6, d7)
os nomes dos parâmetros da função, são relacionados aos pinos do display que serão
controlados. Você então deve substituir pelo pino do Arduino que irá enviar o sinal para
o respectivo pino do LCD. Se o seu pino ’rs’ for controlado pelo pino D13 do Arduino,
por exemplo, você substitui por ’rs’ por ’13’ no código e assim por diante. Uma coisa
importante são os modos de operação do LCD. Ele envia 1 byte (8 bits) por vez, de forma
paralela, ou seja, dos pinos d0 a d7. Se usarmos os 8 pinos, estaremos na configuração de
8 bits e a sintaxe da função é a descrita neste parágrafo.
• [Link](’colunas’, ’linhas’)
inicializa o display e no lugar de ’linhas’ você substitui o número de linhas do seu display
e no lugar de ’colunas’ você põe o número de colunas.
• [Link]()
limpa o display
• [Link]()
volta o cursor do display para a posição inicial
• [Link](data)
no lugar de ’data’, coloque a informação a ser mostrada no display. Lembre-se o número
de colunas expressa quantos caracteres você pode escrever por linha.
• [Link]("palavra")
essa função mostra palavras (strings) diretamente no display. Substitua ’palavra’ pela
frase que você quer.
85
• [Link](’coluna’, ’linha’)
indica em qual posição o cursor irá começar
86
Figura 60: Prática 13.1 - código - fonte: autor
87
12.6 Prática 13.2 - Display LCD configuração 4 bits
Como estamos usando menos pinos agora, usamos a configuração da biblioteca para 4 bits. Os
pinos do display não usados devemos aterrar. O resto da programação não se altera
Para outros tipos de display lcd, basta alterar as configurações de linha e coluna. Outros tipos de
dispositivos visuais seguem os mesmos principios dos dispositivos vistos neste capítulo, basta
utilizar a biblioteca correta.
88
Figura 62: Prática 13.2 - código - fonte: autor
89
13 Matrizes
S ECTION
Matrizes são arrays bidimensionais, mas neste caso estamos nos referindo ao software. Em todo
caso a definição também vale para o hardware e componentes que atuam com coordenadas
para linhas e colunas. Iremos entender como enviar dados para uma matriz de LED e sua lógica,
ao mesmo tempo que iremos entender como ler dados de uma matriz de botões e sua lógica.
A grande vantagem de trabalhar com matrizes é que podemos lidar com um número grande de
elementos e combinações sem necessitar de muitas entradas do microcontrolador, todavia, o
processamento de hardware torna-se mais pesado e uma boa otimização economiza espaço.
Para os exemplos desta seção, eu utilizei a matriz de led 1088AS, porém você precisa verificar o
modelo que tem com você. A figura a seguir mostra a disposição dos leds na matriz baseado na
linha e coluna, porém os pinos não estão na mesma sequência então, assim como no lcd, você
precisa definir cada pino no Arduino/hardware de controle e ligar corretamente na matriz.
90
Figura 63: Matriz de LED 1088AS - fonte: [Link]
A grande questão é, não podemos usar 16 pinos para acionar uma matriz 8x8, na verdade, no
Arduino uno nem temos essa quantidade de pinos digitais disponíveis. Cabe a nós então usar-
mos nossas mentes e pensarmos num hardware capaz de resolver nosso problema. Uma forma
simples de resolver isso é usando 2 demultiplexadores de 8 bits. Desta forma, usaremos 3 pinos
do Arduino para ligar ao demultiplexador que controla as linhas e 3 pinos para controlar o de-
multiplexador que controla as colunas, totalizando 6 pinos digitais usados.
Tendo os demultiplexadores, podemos fazer uma combinação BCD de 000b até 111b (b = biná-
rio), tendo 8 combinações e podendo selecionar individualmente uma das 8 linhas e 8 colunas.
Neste modelo de matriz, as COLUNAS são ANODO (ativa em 5V) e as LINHAS são CATODO
(ativa em 0V). Desta forma, o demultiplex das colunas precisar estar com o barramento de dado
ligado ao 5V e o demultiplex das linhas precisa estar ligado ao 0V. Por sua vez o Arduino comanda
o barramento de controle (combinações) para acionar os leds [24].
91
13.2 Prática 14.1 - Acionando matriz de leds 8x8 com multiplex
Para esta prática você pode usar o demultiplexador que desejar, porém eu utilizei o modelo
74HC238, por questão de comodidade. Ele possui os pinos ABC (A = MSB e C = LSB) de con-
trole da demultiplexação. Como o demultiplex da coluna precisa enviar positivo e o da linha
enviar sinal negativo a matriz, esse CI possui as entradas de sinal E1, E2! e E3! (vide datasheet).
Sendo assim, como a linha recebe negativo, basta aterrar todos os pinos de sinal e para a coluna,
aterrar E2! e E3!, sendo E1 responsável por receber um sinal do Arduino e assim ligar a matriz.
Conforme o Arduino faz a seleção de ABC para linha e coluna, os leds vão sendo acessos. OBS:
os pinos da matriz não são sequenciais! vide datasheet para fazer a ligação correta entre matriz
e demultiplex.
No código não temos muitas novidades. Defini cada pino do Arduino ligado ao respectivo pino
do demultiplex. Das variáveis, uma iria controlar o número da linha e o outro o número da co-
luna, lembrando que os pinos D2 a D4 controlam as colunas e os pinos D5 a D7 controlam as
linhas, pois estao ligados ao demultiplex. A função ’controle_matriz’ é uma rotina que analisa
um parâmetro de entrada (que pode ser a linha ou a coluna) e vai atribuindo valores de 0 a 7,
incrementando de 1 em 1, ou seja, aciono, por exemplo, a linha 1, depois a 2, depois a 3 ... até a
7. o mesmo é feito para as colunas. O pulo do gato nessa função está na recursividade.
Quando fazemos a recursividade da função, chamamos a rotina dela, para ser executada no-
92
vamente antes de terminar a rotina anterior. Desta forma, olhando a função LOOP, quando eu
chamo a rotina da função ’controle_matriz’ e dou parâmetro de entrada a ’linha’, eu irei acionar
linha a linha, porém como eu faço recursividade chamando o parâmetro ’coluna’, esta será efe-
tuada primeiro. Sendo assim, quando minha variável linha recebe 0, ela ativa o case 0 que ativa
a primeira linha da matriz. Só que antes de terminar essa rotina e ir para coluna = 1, eu ativo
novamente a função só que usando a coluna. Neste caso a variável coluna irá de 0 a 7, ligando
as colunas 1 a 8 da matriz.
Resumindo, neste caso eu estou acionando uma linha e depois cada coluna em sequencia, aci-
onando outra linha e depois cada coluna em sequencia novamente. Na matriz, você verá led
a led acionando da esquerda para a direita, de cima para baixo. Apesar de um pouco confuso
inicialmente, a recursividade nos auxilia muito a varrer matrizes desse tipo.
93
link: [Link] para que você possa estudar uma das biblio-
tecas existentes para essa funcionalidade chamada ’LedControl’. Porém, caso você não tenha o
módulo pronto e apenas a matriz, já sabe como realizar a lógica para controlar o sistema.
Figura 67: Teclado Matricial 4x4 para Arduino - fonte: não identificado
Veja que este teclado que estamos usando é do tipo 4x4, mas a lógica sempre será a mesma para
qualquer tipo. Veja nas linhas verdes que são os conectores do display, que elas estão ligadas as
linhas da matriz. Por sua vez, as linhas amarelas estão ligadas as colunas da matriz. Seguindo a
nomenclatura, caso você envie um sinal HIGH para ’L1’, os botões ’1’,’2’,’3’ e ’A’ podem ser pres-
sionados e caso isso ocorra, o caminho será fechado e o sinal irá passar para a coluna do botão
que for pressionado. Se, por exemplo, pressionarmos o botão ’A’, o pino ’C4’ receberá o sinal
vindo da linha ’L1’. Você pode efetuar a mesma lógica enviando sinal na coluna e recebendo na
linha, o importante é que algumas portas do seu Arduino serão de saída, já que vão enviar sinal
para a matriz e outras portas serão de entrada, pois recebem os sinais vindos da matriz. Fazendo
esse cruzamento de informação sobre quem envia e quem recebe, conseguimos identificar qual
94
botão foi pressionado.
95
Figura 69: Prática 15 - código - fonte: autor
96
Neste código, primeiro inicializei uma matriz 4x4 contendo, na sua respectiva posição, os ca-
racteres das teclas do teclado. Em seguida, criar uma função auxiliar que iria fazer a leitura das
teclas e mostrar no monitor serial. Nesta etapa preste atenção ao hardware! O Arduino nomeia
os pinos digitais de 1 a 13, desta forma, para poupar escrita, podemos fazer uma lógica para vin-
cular esses números aos das variáveis de controle que vão varrer a linha e a coluna da matriz.
A variável ’linha’ e ’coluna’ respectivamente vão ler as linhas e colunas da matriz do programa
(do índice 0 ao 3). Olhando o esquemático, vemos que os pinos 8,7,6,5 são os responsáveis por
enviar o sinal, logo controlam as colunas. Quando eu faço a lógica ’8-coluna’ dentro da função
digitalWrite, eu nada mais estou fazendo do que referenciando diretamente o pino do Arduino
com a coluna a ser acionada. Se na matriz o índice da coluna for ’0’, eu terei ’8-0 = 8’, logo digi-
talWrite no pino 8, que no hardware está ligado a primeira coluna da matriz! O mesmo vale para
os demais pinos. A mesma lógica é aplicada quando utilizo ’12-linha’, mas nesse caso eu leio a
linha que recebe sinal, pois os pinos responsáveis são 12,11,10 e 9.
O programa então executa 2 laços ’for’, um para controlar a linha e outro para controlar a coluna
da matriz, sendo que na coluna eu envio sinal pelo Arduino e na linha eu tenho que ler. Caso
alguma tecla seja pressionada, isso é mostrado no monitor serial. Toda vez que uma nova varre-
dura inicia, todos os pinos de envio de sinal, voltam ao nível lógico original para evitar que haja
cruzamento de informações de uma tecla anteriormente acionada e uma nova tecla.
Dentro de pinMode, o parâmetro INPUT_PULLUP aciona o pull up interno do Arduino e não ne-
cessita de resistor externo ao circuito. Na função LOOP é executado a rotina de leitura de botão e
um delay de 250ms é aplicado depois para reter o dado na tela e evitar bouncing. Você pode usar
interrupções internas caso queira prioridade na leitura do teclado e um sistema antibouncing
por código ou hardware.
97
14
Sensores de Temperatura
S ECTION
14.1 Termistores
Os termistores são resistores que variam significativamente sua resistência elétrica com a varia-
ção da temperatura sem serem danificados (na faixa de valores a que foram projetados). Existem
os sensores NTC (que diminui a resistência com o aumento da temperatura) e o PTC (que au-
menta a resistência com o aumento da temperatura). O mais comum e mais econômico de ser
encontrado é o NTC, porém a lógica é similar para ambos. Por ser um resistor, podemos utilizar
um divisor de tensão para efetuar a lógica de aferição de tensão, já que a resistência varia com a
temperatura, logo a tensão irá variar com a resistência [18].
98
14.1.1 NTC
Por ser o tipo mais comum e econômico, iremos utilizar este termistor como exemplo. A figura
a seguir mostra o diagrama elétrico para um NTC de 10kΩ
Figura 70: Ligando NTC ao Arduino com divisor de tensão - fonte: autor
No divisor de tensão estaremos aferindo a tensão sobre o resistor auxiliar e não sobre o NTC.
Este esquema de ligação será o mesmo para as duas práticas adiante. Lembre-se de que vamos
usar agora os pinos analógicos do Arduino para leitura de dados.
Antes de prosseguirmos, devemos entender como será feita a conversão de temperatura para
tensão e definir alguns parâmetros iniciais de projeto. Os NTCs para módulo de Arduino, nor-
malmente são de 10k, a partir disso escolhemos o valor do resistor auxiliar que para facilitar
nossos cálculos é do mesmo valor do NTC. A tensão de operação também afeta, logo vamos
operar com 5V. Nunca esqueça de interligar todos os GNDs dos circuitos.
Quando aferimos a tensão do divisor, podemos encontrar a resistência de cada elemento. Como
a resistência do resistor auxiliar é fixa em 10k, devemos usar a equação do divisor de tensão para
encontrar a resistência do NTC [18]. A seguir eu deixo a equação pronta para você:
V f ont e × R f i xo
R nt c = − R f i xo (4)
Va f er i d o
No qual nosso resitor fixo é o que tem sua tensão aferida. A tensão da fonte é a da alimentação.
Achado o valor de resistência do termistor, por se tratar de um equipamento não linear, deve-
mos encontar uma equação que relacione a temperatura com a resistência. Para isso, podemos
optar por dois métodos, que são descritos nos próximo tópicos.
99
14.1.2 Método do fator β
1 1 1 R nt c
= +( × l n( )) (5)
T a f er i d a Tr e f er ênci a β R r e f er ênci a
Veja que os valores de referência foram especificados anteriormente e a resistência do NTC nós
vimos no tópico anterior como calcular. Ao final encontraremos a temperatura aferida real.
Alguns fabricantes sugerem outro método, que conterá 3 constantes fixas, A,B e C. Neste caso,
basta calcularmos a resistência do NTC e com a equação de Steinhart-Hart e os coeficientes in-
dicados, calcular a temperatura aferida:
1
= A + B × l n(R nt c ) +C × (l n(R nt c ))3 (6)
T a f er i d a
100
Figura 71: Prática 16.1 - código - fonte: autor
No código se atente as diretivas define que serão usadas para substituir valores de constantes.
Para facilitar a diferenciação do que é constante e o que é variável a ser manipulada, deixei todas
as constantes com um underline ’_’ no nome. Em C e C++ caso você opere duas variáveis de tipos
distintos, o compilador terá preferência por um tipo, mas só efetuará o ’cast’ no final quando
for salvar na variável de destino. No nosso código, todas as constantes aparecem com ponto
decimal para indicar que são float. Caso não tivesse isso, seriam tratadas como inteiros e nas
operações, apesar das variáveis serem double (float com o dobro do tamanho), os calculos entre
’float’ e ’int’ teriam resultado com truncamento das casas decimais, e no final seria convertido
p um float, porém é o resultado errado. Se atente a isso pois, são fontes de erro. Para efetuar
operações além das convencionais (+,-,*,%), devemos usar a biblioteca ’math.h’ e os parâmetros
são variáveis ’double’.
Neste código cada etapa é mostrada. A primeira etapa é pegar o valor em bits da conversão A/D e
passar para nossa tensão real (vide capítulo 7). Em seguida, usamos a equação do tópico anterior
para calcular o valor de resistência do termistor e por último aplicamos esses parâmetros na
equação desse tópico para calcular a temperatura ambiente. Lembre-se que todos os calculos
de temperatura devem estar em kelvin e depois passados para ºC.
101
a maioria dos NTC (já que as constantes são muito proximas da maioria dos modelos). Caso
você tenha de alterar os valores das constantes, você precisa entrar no código fonte do arquivo
original (que está na pasta da biblioteca num arquivo em formato C ou C++) e alterar os valores
das constantes no código, depois salvar. No nosso caso só será preciso usar a biblioteca. A seguir
temos um exemplo, com o mesmo hardware de antes, usando a biblioteca para ler thermistores:
102
14.4 Termopar
Termopares são sensores de temperatura por contato, que internamente possuem um bimetá-
lico, no qual ao serem aquecidos geram um diferença de potencial em seus terminais. Existem
diferentes tipos (tipo K,J,N...) no qual essas letras indicam a composição da liga metálica no qual
é feito.
Esse sensor possui uma boa faixa de operação, podendo operar em temperaturas negativas e po-
sitivas elevadas. Todavia, sua utilização é um pouco mais trabalhosa pois seus sinais de tensão
gerados, com a variação da temperatura, são da ordem milivolts (mV) ou microvolts (uV). Logo,
uma aferição direta se torna impossível, sendo necessário o uso de amplificadores de sinal para,
no nosso caso, termos uma variação de 0V a 5V para ser lida no Arduino.
O termopar, ao contrário do NTC, possui uma característica linear de operação, sendo assim,
muitos fabricantes não fornecem o equacionamento para se obter a relação tensão/tempera-
tura, mas sim uma tabela com diversas medições. Desta forma é muito mais comum utilizar
matrizes com valores fixos e para cada valor de tensão lido relacionar a um valor de temperatura
da tabela. Isso se torna ainda mais vantajoso por ser uma curva de tenmperatura/tensão, muito
linear, então para o sinal amplificado, basta relacionar a constante de ganho [12].
Por exemplo: Se para 1mV, você tem um aumento de 1ºC, então se você tiver um ganho no seu
amplificador de 100, o seu Arduino irá ler 100mV para cada 1ºC.
Perceba algo muito importante. Quanto menor a relação tensão/temperatura, mais preciso é o
termopar, porém mais dificil de aferir o sinal, precisando de valores de amplificação maiores.
Porém, quanto mais amplificado, menor a faixa que pode ser aferida para o Arduino, que opera
de 0V a 5V. Logo, este sensor também é muitas vezes utilizado em tensões maiores de aferição
como 0V a 24V, o que aumenta a resolução, sendo muito usado em CLPs na indústria.
A seguir eu dou um código exemplo (figura 75), fictício, de um termopar. Os valores da tabela
são inventados, mas servem de exemplo para a situação real. O circuito amplificador (figura 74)
é real e pode ser adaptado para o seu projeto:
103
Figura 74: Circuito buffer para sinal de termopar genérico
Neste circuito, temos o ’TERMOPAR’ (que é o componente mesmo), no qual o pino de menor
potencial vai aterrado e o de maior potencial vai ligado a entrada não inversora de um amp op
(no caso usei o LM324 pois não necessita de fonte simétrica de alimentação). Como o ganho e
a relação de corrente nesse CI são medianos, ao invés de um único buffer, utilizei dois, por isso
a saída do primeiro amplificador entra no segundo, sendo dois estágios de ganho, controlados
pelos respectivos trimpots. A saída do amp op ’TERMOPAR’ é de onde você retira o sinal de ten-
são amplificado. Para o amplificador de ganho não inversor, mostrado na figura, temos que a
relação de ganho é dada como:
R f i xo
G anho = +1 (7)
R a j ust ável
G anho t ot al = G anho 1 ×G anho 2 (8)
Veja que o ganho de cada amplificador é a razão do resistor fixo (superior) e o resistor ajustável
(inferior), acrescido de um, no qual por padrão você pode adotar uns 10k para ambos. Quando
se possui vários estágios de ganho, o ganho final é a multiplicação entre ganhos individuais.
O código de exemplo já está autoexplicativo. Vamos agora fazer uma prática usando o conversor
MAX6675, com módulo pronto para termopar tipo K (de aprendizagem) e Arduino com a bibli-
oteca ’max6675.h’.
104
Figura 75: Código exemplo para termopar genérico - fonte: autor
105
Figura 76: Prática 17 - esquemático - fonte: autor
106
Figura 77: Prática 17 - código - fonte: autor
14.6 LM35
Este sensor é uma versão ’mini’ do termopar. O princípio de funcionamento é diferente mas a
operação é similar. Eles possui três pinos: Vcc, GND e sinal analógico, não necessitando de am-
plificação, opera de 0ºC a 100ºC e possui resolução de 10mV/1ºC. A seguir temos o esquemático
e código para operar o componente [23].
107
14.7 Prática 18 - LM35
108
14.8 DHT11
Este sensor mede temperatura ambiente (0ºC a 50ºC) e umidade relativa do ar (20% a 90%). Este
componente possui no mesmo invólucro um NTC e um medidor de umidade, conectados a um
microcontrolador de 8bits que envia o sinal para o Arduino. Apesar de 4 pinos, só utilizamos
3 deles, sendo: Vcc, GND e sinal. O pino de sinal é conectado ao pino analógico do Arduino
e devemos usar uma biblioteca para manipular o sensor. Como não se trata de uma biblioteca
oficial, mas criada pela comunidade, ela pode variar dependendo do modelo que você encontra,
então sempre confira o código de exemplo. Existem os modelo DHT11, DHT21 e DHT22. Neste
tópico utilizei o DHT11, mas você pode usar qualquer um deles, desde que mecha nas configu-
rações indicadas pela biblioteca [15].
109
14.10 MLX90614
Este sensor é um pouco diferente dos anteriores pois não necessita de contato direto. Ele é um
sensor que capta a radiação infravermelha do objeto. Também possui internamente um termis-
tor para aferir a temperatura ambiente, no qual sua faixa de operação varia de -40ºC a 120ºC. A
grande vantagem está na facilidade de uso, pois não é necessário contato, afere duas tempera-
turas distintas (corpo e ambiente) o que melhora a precisão e análise de dados e seu protocolo
de comunicação é I2C [17].
110
14.12 DS18B20
Este sensor é muito utilizado para medição de temperatura em ambientes líquidos pois possui
um invólucro a prova dágua, além de uma faixa de medição de -55ºC a 125ºC. Além disso, opera
com protocolo de comunicação 1-Wire, o que diminui muito a quantidade de pinos necessários
para seu funcionamento. Entre o terminal Vcc e o de sinal, deve-se instalar um resistor de 4,7k
em paralelo para garantir o pull up [16].
111
15
Sensores de Posição e
Presença
S ECTION
112
Figura 82: Rotina antibouncing - fonte: autor
O ruído mecânico do botão irá mudar o nível lógico que você quer aferir por um tempo muito
curto. Isso pode fazer com que seu programa interprete um nível lógico errado ou faça várias
aferições diferentes do mesmo pino. Para evitar isso, criamos 2 variáveis, uma auxiliar e uma
que queremos salvar o sinal vindo do botão. No exemplo, ’temp’ é a variável temporária e ’botao’
a variável final.
Você inicia a leitura digital do sinal normalmente, porém é necessário conferir depois de um
pequeno tempo (suficiente para o bouncing passar, mas que o sensor ainda esteja acionado) se
o sinal aferido continua sendo o mesmo. Caso o sinal aferido antes e depois do bouncing forem
iguais, então podemos salvar na variável final o dado colhido.
Na parte do hardware, podemos adicionar um capacitor (na ordem de nanofarads em paralelo
ao botão para reduzir o bouncing ainda mais.
Esses sensores podem ser do tipo NPN (envia nivel lógico alto no acionamento) ou PNP (envia
nível lógico baixo no acionamento), não necessitando de resistores de pull up ou pull down
(a não ser que indicado pelo fabricante). Existem diversos tipos, muitos usados na indústria,
porém o Arduino possui alguns módulos como o sensor touch capacitivo, que funciona igual os
outros sensores, só tem aparência diferente. Em resumo, este tipo de sensor sempre téra 3 pinos,
um para Vcc, GND e sinal.
113
Figura 83: Exemplos de sensores indutivos e capacitivos - fonte: diversos fabricantes
15.3 Óptico
Sensores ópticos funcionam de forma similar aos apresentados anteriormente nesta seção, po-
rém utilizam de emissores e receptores luminosos que enviam um sinal luminoso (normalmente
infravermelho) até o objeto. Para se identificar a presença, existem dois tipos, os que operam
com reflexão da luz e os que operam com passagem de luz.
Os que operam com reflexão enviam o sinal luminoso do emissor até o objeto e este reflete a
luz, sendo captada pelo receptor. Este tipo é indicado para objetos de cores metálicas ou de su-
perfícies reflexivas e que não absorvam o espectro de luz vermelho (não é indicado para objetos
escuros ou translúcidos/transparentes). Sua vantagem está no tamanho do sensor, já que no
mesmo invólucro possui o emissor de luz e o receptor, tendo tamanho reduzido. Quanto mais
reflexivo o objeto, maior a distância que podemos posicionar entre o sensor e o objeto [36].
Para os tipos que operam com passagem de luz é necessário o emissor separado do receptor,
isto porque o objeto tem que barrar a luz enviada do emissor para o receptor. Esse tipo de sen-
sor permite uma distância maior de separação entre suas partes (emissor/recepctor) e só não
é aconselhado contra objetos translúcidos/transparentes. Um sensor que veremos ainda nesta
seção é o encoder e normalmente ele opera com o mesmo princípio de funcionamento do sen-
sor luminoso com passagem de luz, porém com algumas adaptações.
114
Figura 84: Exemplo sensor luminoso reflexivo para Arduino - fonte: shield arduino
Figura 85: Exemplo sensor luminoso do tipo passagem de luz - fonte: desconhecido
Veja que o pino ’trigger’, do módulo, precisa receber um pulso ’HIGH’ (por 10us no mínimo) e
115
Figura 86: Funcionamento HC-SR04 - fonte: [Link]/blog
após isso, internamente o módulo envia 8 pulsos de 40kHz para excitar o emissor. A partir disso
o sinal sonoro é enviado e começamos a contar o o tempo. Esse tempo entre o envio da onda
sonora e o recebimento é dado pelo pino ’echo’ que fica em nível ’HIGH’ todo este período.
Logo, no Arduino, precisamos apenas enviar o pulso de trigger e verificar quanto tempo o echo
fica em nível alto. Como o tempo total é de envio e recebimento e queremos a distância até o
objeto, levamos em conta apenas o tempo de envio (basta dividir o tempo total por 2).
116
Figura 87: esquemático HC-SR04 - fonte: autor
Para esta prática, usamos a interrupção interna (escolhi o timer1, pino digital 2 do Arduino).
Pelo prino 13 enviamos o pulso digial de 10us e aguardamos a resposta do módulo ultrassônico.
quando ele enviar nível lógico alto no echo, significa que a onda sonora foi enviada e quando
esse pulso cair para nível lógico baixo, significa que a onda sonora foi recebida. Então o tempo
que o pino echo fica alto, é o tempo de envio e recebimento da onda, ou seja, duas vezes o tempo
que a onda leva para chegar ao objeto.
Fazendo uma interrupção por transição de borda, sabemos que toda vez que echo tem borda
de subida devemos começar a contagem do tempo e quando tem borda de descida devemos
parar a contagem. O Arduino, ao contrário de outros microcontroladores, possui uma função
que afere tempo: millis(), para milisegundos ou micros() (para microsegundos). Como o tempo
de envio é na ordem de microsegundos, usamos a função micros(). Salvando o tempo em que
começa e termina o envio do sinal echo, podemos calcular o tempo até o objeto e a distância.
Veja no código que a função ’ultrassom’ analisa a interrupção externa por borda de subida e des-
cida e para cada caso toma uma ação. Caso a borda seja de subida, temos o inicio da contagem
de tempo, caso seja de descida, temos o fim da contagem e processamento do algorítmo para
cálculo da distância e tempo. Tudo é mostrado no monitor serial. Na função ’LOOP’, a cada 1s
enviamos um novo pulso de trigger para o módulo, ou seja, acionamos ele.
Vale salientar que esse sensor é bem preciso e que a velocidade do som no ar interfere muito.
Neste caso, fica como desafio, você usar algum sensor de temperatura com o módulo HC-SR04 e
aferir com a variação da temperatura do ar a nova velocidade do som. Você verá como pequenas
variações de velocidade afetam muito o resultado final !
117
Figura 88: código HC-SR04 (1) - fonte: autor
118
15.6 Prática 22.2 - HC-SR04 - com biblioteca
Existem algumas bibliotecas que controlam esse módulo. Baixe a mais comum que é a ’Ultra-
sonic.h’. Se atente a pinagem do programa pois é diferente entre bibliotecas e do nosso código
anterior. A seguir temos um código de exemplo que faz a mesma coisa que o anterior (afere
distância e tempo até o objeto).
119
15.7 PIR
Este sensor é bem peculiar. Ele detecta radiação infravermelha dentro de um alcance de até 7m
porém o objeto precisa estar em movimento. Caso o mesmo esteja imóvel, o sensor não irá atuar.
Este sensor possui um trimpot para ajuste da sensibilidade e envia nível lógico alto quando de-
tecta algo [8]. Ele nada mais é do que um sensor luminosos porém, por ser ’diferentão’ do que
estamos acostumados a ver, irei mostrar o esquemático e o código (que são bem simples, nada
diferente do que já foi visto):
Figura 90: Acionamento de LED do Arduino com sensor PIR - fonte: autor
120
15.8 encoder
Encoderes são sensores de posicão extremamente precisos. Muito similares a potenciômetros
(devido a sua cosntrução mecânica) são facilmente confundidos com um, tanto que recebem a
errônea nomenclatura de potenciômetros digitais. Os mesmos podem ser do tipo rotativo (mais
comum) e linear, porém operam de forma totalmente diferente a de um potenciômetro. Os en-
coderes não são aparelhos resistivos, mas sim equipamentos que internamente possuem um
sistema de discos perfurados. Dependendo do alinhamento e posição desses discos, podemos
(por meio luminoso) ter ou não a passagem de luz. Podemos usar dessa técnica para definir
níveis lógicos, como por exemplo, 1 = iluminado e 0 = apagado. Como o mesmo possui um eixo
que rotaciona livremente, esses sinais luminosos que digitalizamos podem ser enviados sem li-
mite de giros. Com um simples circuito de optoacoplamento, podemos transformar esse sinal
luminoso num pulso elétrico ou sinal de tensão e com isso convertemos o giro mecânico em
sinais elétricos digitalizados, sem a limitação do manuseio do componente (como ocorre em
potenciômetros que tem um curso máximo de rotação). Para os equipamentos com desliza-
mento linear, ainda ocorre a limitação mecânica, mas a maioria são rotativos [27].
O princípio de funcionamento do encoder é o mesmo para o tipo rotativo e linear, porém como
vamos trabalhar nessa seção com um exemplo rotativo, irei me referir a ele especificamente.
Basicamente, um encoder possui um sistema de disco perfurado, no qual passa ou não luz. A
partir disso, um emissor luminoso do tipo passagem fica posicionado de um lado do disco e do
outro seu receptor. Nessa hora você precisa olhar o datasheet do componente, mas vamos supor
que ’1’ seja a luz passando e ’0’ a luz não passando. Dessa forma eu consigo converter os sinais
luminosos em sinais elétricos, já digitalizados e com alta precisão e velocidade [27].
121
Figura 92: encoder internamente - fonte: fabricantes diversos
Na figura 92 note que há um disco estriado, com pequenos furinhos, esse é o disco perfurado do
encoder. Alguns modelos podem vir sem esse disco, necessitando comprá-lo a parte.
Existem dois tipos principais de encoderes que são explicados a seguir
Este encoder é o mais fácil de se utilizar e também possui preço mais elevado. Ele já possui em
seu disco perfurado a sequência binária (ou outro código) para ser lido diretamente. Alguns mo-
delos, mais caros, já até apresentam um sistema de comunicação serial interno para facilitar o
envio de dados ao usuário.
O encoder possui uma resolução, ou seja, existe um ângulo mínimo a ser movimentado para que
ele detecte um deslocamento. Se você girar o eixo, verá que ele possui pequenos passos e quanto
maior a resolução dele, menor essa sensação de passos. No caso do absoluto, esses passos já in-
dicam qual a posição absoluta dele. Vamos supor que eu tenha um encoder com resolução de
8bits, isso implica que ele irá da contagem de 0 ao 255 (lembrando que será lido em binário, mas
eu estou convertendo para decimal). Como ele irá dar uma volta para ler todos esses bits, se
fizermos a divisão pelos 360º de giro, teremos uma resolução de aproximadamente 1,4º/bit ou
1,4º/passo. Então, se por exemplo, o seu encoder absoluto te indicar o valor 10, você só lerá o va-
lor 11 ou 9 se rotacionar em 1,4º o eixo, para a direita ou esquerda. No caso desse equipamento,
ele pode rotacionar tanto no sentido horário como antihorário, dessa forma (você precisa ver o
datasheet) sabendo se o código lido é maior ou menor que o anterior, podemos saber a posição
122
do eixo. Se analisarmos somente o tempo entre transição de informações, podemos saber a ve-
locidade de rotação. Quando ele executa uma volta completa, a contagem reinicia.
A grande vantagem do encoder absoluto está no fato dele já indicar o código pronto para você,
bastando apenas ler e comparar com o sinal anterior. Normalmente estamos acostumados a
lidar com código binário, mas no encoder, na maioria dos casos, é tratado o código gray, que é
uma adaptação do binário para que apenas 1 bit varie seu estado entre um número e outro. No
próximo tipo de encoder, você entenderá melhor a importância do código gray [27].
Figura 93: Exemplo de disco interno de encoder absoluto em código gray - fonte: Easy-
trom Labs
Veja na tabela da figura 93 que o código gray (e que indica a posição) varia apenas 1 bit por vez.
Este encoder é mais difícil de trabalhar que o anterior, porém seu custo é muito menor e neces-
sita de no máximo 3 pinos de sinal. Neste caso, possuímos o mesmo princípio do disco perfu-
rado, mas agora possuímos dois discos e que possuem furos igualmente espaçados. Entretando,
esses discos estão estrategicamente defasados entre si. Essa defasagem entre um disco e outro
é proposital para gerar uma defasagem de 90º entre o sinal de um disco e o sinal de outro disco.
Para facilitar a lógica, vamos supor que eu tenho o disco A e o disco B e que a posição inicial
deles é o 00.
Se eu rotacionar no sentido horário, por exemplo, o disco A irá enviar primeiro a informação da
mudança de nível lógico (de 0 para 1). Por sua vez, se eu rotacionar no sentido antihorário, o
disco B irá enviar essa informação de mudança de estado primeiro. Perceba que agora, como
não temos mais uma posição instantânea dada pelo código do encoder, precisamos avaliar a
mudança de nível lógico e quem mudou primeiro. No datasheet do componente é dado o grá-
fico de quadratura de sinais, no qual indica o sentido de rotação e qual disco muda de estado
primeiro. A figura 93 exemplifica o esquema de quadratura:
123
Figura 94: Exemplo de disco interno de encoder incremental - fonte: Easytrom Labs
sempre ser adaptadas para o datasheet do componente que você usar. Este encoder rotativo in-
cremental possui 5 pinos: Vcc, GND, SW, CLK e DT. O pino SW é um botão que envia nível lógico
baixo quando pressionado (sim, você pode pressionar o eixo desse encoder já que ele possui um
botão, e mesmo depois de 7 anos estudando elétrica eu também não sabia disso até fazer essa
apostila...), Os pinos CLK e DT são a mesma coisa dos pinos A e B que eu dei de exemplo anterior
[27].
Olhando o datasheet, ele irá indicar que se o pino CLK mudar primeiro seu estado, o sentido de
giro é horário. Se o pino DT mudar seu estado primeiro, o sentido de giro é antihorário. Uma
coisa que você tem que prestar atenção (e as vezes necessita de ensaio prático pois não fica claro
no datasheet) é com relação a mudança de posição do sinal do encoder em relação ao passo do
eixo. No caso do KY-040, ele envia 4 sinais diferentes para cada passo que o eixo dá. Esses sinais
por sua vez, estão em código gray, contando de 0 a 3 (4 sinais) [26]. Veja a figura 95 a seguir:
Figura 95: Operação por passo do encoder KY-040 - fonte: Easytrom Labs
Na figura 95 está representado os sinais que serão enviados pelos pinos CLK e DT quando mo-
vimentados no sentido horário ou antihorário. Esse encoder possui 20 passos, ou seja, para
cada passo, iremos rotacionar 18º. Porém, para cada passo, o encoder enviará esses 4 pulsos em
sequência!!!
Isso é uma coisa que confunde muito. Dependendo do encoder, para cada passo, ele irá enviar
124
um sinal apenas, então por exemplo: para o passo 1(18º), ele envia 00, para o passo 2 (36º), ele
envia 01, etc...
Porém, há encoderes que enviam os 4 sinais em sequência para um mesmo passo completo,
então no caso do KY-040, quando você der o passo 1(18º), ele envia: 00,01,11,10. Ai no passo
2 (36º) ele fará o mesmo, enviando: 00,01,11,10. Se você quiser aferir apenas 1 sinal, deve dar
1/4 de passo. Então, cuidado com esse princípio de funcionamento que varia de componente a
componente.
Agora, uma vez que você entendeu como funciona a transição dos sinais, perceba que a tabela
de sentido horário está defasada de 90º do sentido antihorário e uma opera na sequência oposta
da outra. Lembra que eu falei do código gray e que ele permite variar apenas 1bit por vez? en-
tão, essa é a vantagem aqui para definir qual o sentido de rotação também. Ao invés de termos
que aferir quem variou primeiro, podemos observar a sequência da tabela e como sabemos que
apenas 1bit varia por vez, podemos usar de interrupções que analisam o sinal toda vez que uma
mudança de estado ocorre! Então, como cada contagem é feita por sinal que variou, mas ape-
nas 1 bit varia por contagem, a interrupção identifica quando houve mudança na contagem e
analisando o dado atual e o anterior podemos comparar para dizer se o encoder rotacionou no
sentido horário ou antihorário. No seu esquemático, você define quem é o sinal A ou B. Para o
exemplo da próxima prática, utilizei CLK sendo A e DT sendo B, no qual uma interrupção ex-
terna analisa o A (CLK).
125
Figura 96: Prática 23.1 - esquemático - fonte: autor
126
Figura 97: Prática 23.1 - código (1ª parte) - fonte: autor
127
Figura 98: Prática 23.1 - código (2ª parte) - fonte: autor
128
15.10 Prática 23.2 - Encoder incremental com biblioteca
Vamos usar a biblioteca ’[Link]’. O esquemático é o mesmo da prática anterior. Para en-
tender a fundo a biblioteca e seus comandos, acesse [Link]
en/libraries/rotaryencoder/
129
15.11 Acelerômetros
Acelerômetros são sensores que consegue converter a intensidade da aceleração num valor de
tensão. Existem diversos métodos de fabricação, mas a maioria se baseia na construção de um
capacitor interno com a capacitância variável. Conforme o sensor é acelerado a distância entre
as placas dos capacitores varia e com isso podemos relacionar a deformação (distância) entre
as placas, com a aceleração gerada. Os acelerômetros podem medir acelerações nos três eixos
base e com a combinação desses dados podemos aferir rotações também. Alguns módulos já
vem com essas funções embutidas e prontas para uso, com comunicação I2C ou SPI, outros são
analógicos e recebemos apenas o sinal proporcional de tensão.
Quando você necessitar de um acelerômetro, escolha um que seja compatível com a sua aplica-
ção e que esteja dentro da faixa de aceleração desejada. Utilizar o componente para aferir uma
aceleração maior que a limite, pode danificá-lo [7].
Além disso, alguns acelerômetros possuem um giroscópio embutido. O giroscópio dará sempre
a referência da aceleração gravitacional. Assim fica mais fácil saber se estamos com uma acele-
ração no sentido de elevar ou descer o corpo, ou se essa aceleração está sendo na horizontal ou
em plano inclinado.
Além de capturar a aceleração, se usarmos métodos de controle, podemos aferir a variação da
velocidade e deslocamento do objeto também [19].
Nessa seção iremos trabalhar com dois tipos de acelerômetros: ADXL 335 e MPU 6050.
15.11.1 ADXL335
Este acelerômetro é totalmente analógico e avalia a aceleração nos três eixos (X,Y e Z). Não pos-
sui giroscópio nem protocolo de comunicação serial. Apesar de operar com 3,3V, o mesmo pos-
sui um regulador que permite alimentação de 5V pelo Arduino. Sua aceleração máxima é de 3G
(cada G equivale a uma aceleração gravitacional de 9,8m/s2̂) [7].
Sua sensibilidade é de 0,3V / G, tendo valor de base (0G) igual a 1,5V.
130
Figura 101: ADXL335 - fonte: diversos fabricantes
Por possuir uma alta sensibilidade porém baixa faixa de aferição (apenas 3G máximo), o ADXL335
é muito utilizado para aplicações de robótica no qual se deseja aferir a posição do objeto (ex: se
um robô está em pé, deitado, tombado,etc...). Veja que, por ser analógico e sem giroscópio, o
valor de tensão enviado pelos pinos Zout,Yout e Xout, irá alterar de acordo com a aceleração do
corpo e da gravidade. Se, por exemplo, estivermos com o sensor parado e o eixo Z paralelo a
vertical, o eixo Z estará sofrando aceleração gravitacional de 1G. Caso o sensor fique com o eixo
X na vertical, então quem irá mostrar um valor de tensão diferente será o eixo X, pois agora ele
que afere a aceleração gravitacional e não mais o eixo Z. Com essa lógica, podemos identificar a
posição do objeto no espaço. Também podemos aplicar outras lógicas ao mesmo sensor.
Nesta prática iremos ler os três pinos analógicos do sensor e aferir o valor de cada um no moni-
tor serial. Conforme você movimentar, o mesmo mostrará variações. Utilize dos valores aferidos
(ou uma faixa deles) para criar lógicas de posição (objeto tombado, objeto invertido, objeto pa-
rado, etc...).
131
Figura 102: Prática 24.1 - fonte: autor
15.11.3 MPU6050
Este acelerômetro é mais refinado que o anterior, possuindo comunicação I2C, módulo acelerô-
metro com giroscópio, conversor de 16bits e operando até 16G. Pode ser alimentado com 5V,
pois possui regulador no módulo para 3,3V.
132
Figura 103: MPU6050 - fonte: diversos fabricantes
Nesta prática iremos ler os valores da aceleração e rotação emprega sobre o módulo. Necessita-
mos da biblioteca ’Wire.h’ que já está apta a lidar com o módulo.
133
Figura 104: Prática 24.2 - esquemático - fonte: autor
Neste código inicializamos a biblioteca e definimos o endereço a ser lido. Depois para cada dado
aferido (aceleração em X,Y,Z, temperatura e aceleração rotacional), temos a declaração de variá-
veis e a inicialização do sensor. Como este sensor opera com 16bits, mas a função [Link], re-
cebe apenas 8bits por vez, usamos o comando ’«’ para realizar um deslocamento de 8bits. Desta
forma, lemos os primeiros 8bits MSB, deslocamos para esquerda e lemos os outros 8bits LSB,
vindos do sensor. Para realizar as duas leituas e guardar os valores na mesma variável, utilize a
sintaxe mostrada. O acelerômetro irá enviar em sequência as informações, como mostrado no
código.
134
Figura 105: Prática 24.2 - código - fonte: autor
135
16 Extensômetros
S ECTION
Extensômetros são dispositivos que podem aferir deformações mecânicas e relacionar a outras
grandezas físicas. Neste capítulo iremos nos focar a um tipo específico de extensômetro que é a
célula de carga.
136
Figura 106: Exemplo de célula de carga - fonte: fabricantes diversos
A seguir temos a equação geral da ponte. Veja que a tensão entre C e B é nula caso ambos os
divisores possuirem a mesma resistência:
R3 R4
VC B = ( − ) × V AD (11)
R1 + R3 R4 + R2
A tensão A e D é a da fonte de alimentação.
Se substituirmos um dos resistores por uma célula de carga, teremos uma tensão CB variável e
com isso podemos calcular o valor da resistência da célula de carga e correlacionar a deformação
mecânica.
∆R/R
K= (12)
∆L/L
137
K é a constante de deformação (e proporcionalidade) entre resistência e comprimento, desde
que o material esteja na fase elástica. A equação anterior relaciona a variação (delta) com o
valor inicial de referência. Perceba que o strain gauge selecionado deve estar na mesma região
elástica que o material aferido, ou seja, uma célula de carga para 100N não deve ser usara para
um material que sofrerá esforço de 200N !!!
16.4 HX711
Para facilitar nossa vida, existe um módulo amplificador de sinal chamado HX711. Nele é pos-
sível ligar as células de carga e aferir o valor de até 4 delas simultaneamente. Os dados já são
convertidos de analógicos para digital e enviados ao Arduino por comunicação serial. Neste
caso, precisamos apenas instalar a biblioteca ’HX711.h’ e efetuar a ligação correta do hardware.
Ao longe dessa seção iremos entender como usar melhor esse amplificador junto ao sensor [9].
138
Ela é composta internamente de 2 células de carga, por isso possui três fios. Lembre-se de que
a célula de carga é um tipo de resistor. A figura 110 exemplifica o diagrama interno com as
referidas cores para os fios (branco, preto e vermelho).
Os valores de resistência na figura são apenas simbólicos, porém a posição e coloração dos fios
são reais. Veja que podemos usar tanto uma célula de carga, como as duas para fazer a ponte de
wheatstone, porém elas se encontram no mesmo invólucro. Para a criação da ponte, podemos
usar 1, 2 ou 4 células de carga, que será o próximo tópico explorado.
Para não confundir os nomes, temos o nosso sensor de célula de carga de 50kg, que é o invólu-
cro metálico composto , ai sim, de duas células de carga que são os resistores. Como os nomes
confundem, eu vou chamar o sensor de 50kg de ’módulo de célula de carga’ e as células de carga
internas de ’resistores strain gauge’, então a gente sabe que, apesar de receberem nomes iguais,
eu tenho 1 módulo contendo 2 resistores internos,ok?
Veja na figura 111 os dois esquemáticos possíveis para formar a ponte, usando apenas 1 módulo
com 2 strain gauges. Podemos usar os dois strain gauges internos ou apenas um deles, depen-
dendo da configuração adotada e dos números de resistores auxiliares (R1,R2 ou R3) necessários.
139
Figura 111: esquemático para 1 módulo de célula de carga - fonte: autor
140
16.5.2 2 módulos de célula de carga, contendo 4 strain gauges
Neste caso, podemos usar apenas 2 strain gauges, um de cada módulo, ou podemos usar os 4
strain gauges dos 2 módulos. Veja a figura 112:
141
16.5.3 4 módulos de célula de carga, contendo 8 strain gauges
Neste caso teremos de aproveitar apenas 1 resistor strain gauge de cada módulo.
142
16.6 Prática 25 - lendo dados da célula de carga
Independente da configuração que você escolha, será necessário efetuar um processo de amos-
tragem vindo do HX711 que amplificou e processou os dados. A figura 114 exemplifica de ma-
neira simples como mostrar no monitor serial do arduino os dados aferidos. Existem outros
comandos vinculados a biblioteca, porém o intuito aqui é apenas familiarizar com o sensor.
Abrindo o monitor serial, vários valores, porém próximos serão mostrados. Para efetuar alguma
lógica é necessário criar uma relação entre os valores mostrados no monitor e a deformação
aferida. Neste caso, você pode criar um algorítmo de proporção linear a partir de algumas aferi-
ções feitas com diferentes pesos e valores aferidos ou pode usar comandos prontos da biblioteca
(necessário pesquisar a parte).
143
17 Motores
S ECTION
Motores são máquinas elétricas capazes de converter energia elétrica em energia mecânica ro-
tativa. Existem diversos tipos de motores com as mais diferentes aplicações, mas neste capítulo
iremos entender os três principais tipos usados em robótica: o motor DC universal, o motor de
passo e o servo motor.
144
Figura 115: Exemplo de motor DC - fonte: fabricantes diversos
Além disso,o nível de tensão ou a corrente drenada por esses motores, normalmente, é maior
que os níveis de operação do Arduino, sendo necessário uma interface de controle e alimen-
tação. Como esta apostila não é focada nisso, não irei me extender muito a este conceito do
hardware, porém irei dar exemplos de como integrar esses componentes. Para o acionamento
dos motores, podemos usar um relé, um transistor, mas o dispositivo mais comum é a ponte H.
A ponte H é composta, basicamente, de 4 transistores, dois do tipo NPN e dois do tipo PNP, no
qual de cada lado temos uma cascata PNP - NPN. No centro fica o motor. Quando enviamos sinal
alto para uma cascata e baixo para a outra, acionamos o motor para rotacionar em um sentido.
Caso a sequência seja invertida, o motor rotaciona no outro sentido. Se ambas as entradas de
sinal forem 0 ou 1 simultaneamente, então o motor fica parado, sendo no caso 0, energizado e
com resistência a rotação mecânica do eixo e no caso 1, sendo desenergizado e com eixo solto
??.
A ponte deve ser escolhida/projetada para suportar os parâmetros de operação e sobrecarga do
motor e em modelos mais modernos, possui sistemas optoacoplados ou CIs específicos que iso-
lam a entrada do Arduino, evitando a queima acidental do microcontrolador. Como você pode
perceber, basta enviar um sinal digital para acionar o motor, só que devido a sua característica
de linearidade e facilidade de uso, podemos usar um sinal PWM para controlar a velocidade do
145
Figura 117: Exemplo de acionamento da ponte H - fonte: adaptação blog eletrogate
motor.
Um modelo bem comum de ponte H para Arduino é a L298H, com capacidade para operar até 2
motores DC entre 6V a 35V, com potência máxima (dos dois somados) de 25W. Como controlam-
se 2 motores, teremos quatro entradas [11]. Olhando de cima p baixo a figura, os dois primeiro
pinos, das entradas, controlam o sentido de rotação do motor A e os outros dois do motor B,
como expliquei.
146
Como temos pinos de liga/desliga para o motor A e B (chamados de ATIVA MA e MB na figura),
se você deixar o jumper conectado, os motores sempre estarão prontos para serem acionados.
Caso você queira remover os jumpers e conectar um pino do Arduino para efetuar um controle
por PWM faça o seguinte:
• 2 - remova o jumper;
Figura 119: L298H com mesma fonte de alimentação para Arduino - fonte: autor
NAO RECOMENDO este método, pois efeitos de chaveamento dos motores podem elevar o ní-
vel de tensão muito rapidamente, mas sendo possível a queima do Arduino. Caso o Arduino
seja ligado a uma alimentação distinta do módulo, então você MANTEM O JUMPER, e NÃO IN-
TERLIGA o 5V com o 6-35V. Desta forma, o sinal recebido em 6-35V é rebaixado para 5V (do
147
regulador interno que é ligado pelo jumper) e fornece a alimentação de 5V para a placa e de 6-
35V ao motor. Apesar do módulo permitir até 35V, não é recomendado ultrapassar de 20V, pois
irá sobrecarregar o regulador interno.
Figura 120: L298H com fonte de alimentação distinta para Arduino - fonte: autor
Apesar do hardware, dessa ponte, ser um pouco mais trabalhoso de lidar, o acionamento é sim-
ples. Você já é capaz (depois de ter lido tudo nessa apostila) de acionar o motor tanto sem con-
trole de velocidade como com controle de velocidade, já que são sinais PWM e digitais simples.
Uma recomendação minha é: sempre teste a lógica em leds antes de passar para motores com o
módulo, pois caso você erre alguma coisa na lógica, saberá distinguir de uma montagem errada
do hardware. Os próximos dois tipos de motores eu terei de dar exemplos de código, já que são
mais "complexos".
148
Figura 121: exemplo motor de passo 28BYJ-48 para Arduino 5V - fonte: fabricantes di-
versos
A figura 121 ilustra o funcionamento básico de um motor de passo. Na prática, existem várias
bobinas que estão espaçadas entre si e recebendo o mesmo sinal de tensão, para em conjunto,
movimentar com precisão o eixo do motor (efetuar o passo), mas para o acionamento real, só
precisamos entender a figura a seguir:
Figura 122: metodologia básica para acionamento de motor de passo - fonte: autor
149
Figura 123: Acionamento meio passo - fonte: autor
Veja que para um acionamento de meio passo, triplicamos o número de acionamentos entre
bobinas. Enquanto que no passo completo (FULL STEP) acionamos a bobina A e desligamos as
outras, para depois acionar a bobina B e desacionar as outras, no meio passo (HALF STEP) de-
vemos inserir um acionamento intermediário, acionando A e B ao mesmo tempo. Desta forma,
conseguimos aumentar a precisão do passo e suavizar o movimento. Este método de aciona-
mento torna mais lento o acionamento, porém o torque [Link] efetuar uma volta com-
pleta, você precisa repetir o processo.
Existe o acionamento por micropasso, no qual cada bobina tem sua intensidade modulada por
PWM. Neste caso, por ser bem mais complexa a lógica, não entraremos em detalhes.
Também temos as formas construtivas dos motores de passo que são duas: Os motores uni-
polares e os bipolares.
Os motores bipolares não possuem uma derivação central na bobina que é aterrada, desta forma,
existem 2 conjuntos principais de bobinas, no qual o motor nos force acesso aos 4 terminais (2
de cada bobina). Para efetuar o acionamento, devemos energizar uma bobina em sequência da
outra, num sentido, e depois efetuar a mesma sequência, mas energizando a bobina com pola-
rização inversa. A figura a seguir explica isso de forma visual. Perceba que temos os terminais
A,B,C e D, no qual uma bobina tem terminais A e C e na outra terminais B e D. Desta forma aci-
onamos (no exemplo um full step mas a lógica do half step permanece) A,B,C e D, mas perceba
que quando acionamos A e mais pra frente C, estamos acionando a mesma bobina, porém com
polaridade diferente [29].
150
Figura 124: Exemplo motor bipolar - fonte: autor
Já o motor unipolar possui um conjunto principal de 2 bobinas com uma derivação central que é
aterrada. Você também pode imaginar como 4 conjuntos de bobinas, no qual cada bobina tem
um terminal aterrado. Alguns motores já possuem todos os aterramentos interligados, outros
possuem apenas um par aterrado, devido a corrente nominal ser maior. Neste motor a grande
vantagem é a lógica de acionamento mais simples, já que você só precisa enviar sinal em nível
lógico alto na bobina que deseja acionar e não ter que ficar raciocinando qual inverte o sentido
ou qual envia sinal direto. No final das contas, as sequências de acionamentos são iguais para
ambos os modelos (veja que no unipolar também é A,B,C e D), só que para o processo de apren-
dizado ele é mais simples de entender [29].
151
Figura 125: Exemplo motor unipolar - fonte: autor
152
17.4 Servo Motor
Servomotores são motores DC com um sistema de controle eletrônico acoplado. Desta forma,
o controlador que comanda o motor recebe sinais PWM no qual a frequência e duty cicle serão
aferidos e convertidos para um valor de ângulo a partir da referência inicial. Desta forma, os
servomotores possuem uma altíssima precisão, porém limitação no movimento, operando en-
tre ângulos máximos de 90º a 270º (alguns modelos mais sofisticados consegue exercer voltas
completas). Por possuírem um sistema de redução, possuem alto torque também, porém sua
velocidade é muito lenta comparada aos outros modelos. Para a prática dessa seção, iremos
usar o servo motor SG90, que opera em 5V e com baixa corrente, podendo ser alimentado pelo
Arduino. Como a interface de controle é dentro do motor, basta apenas enviarmos o sinal PWM
conhecendo seus parâmetros (vide: [Link]
SG90/1).
Este motor opera entre 0º a 180º, nos respectivos duty cicles de 0,6ms a 2,4ms, com valor mí-
nimo de incremento no duty cicle de 10us ou 0,01ms. Cada ciclo completo do PWM deve ter
20ms, o que fixa a velocidade de rotação. Como o pwm do Arduino não possui exatamente esse
período de operação, teremos de fazer manualmente o controle, porém você pode usar a bibli-
oteca ’Servo.h’ se quiser facilidade [29].
153
18 Referências
Referências Bibliográficas
S ECTION
154
[10] [Link]. Arduino Pinout. URL: [Link]
uno-pinout/.
[11] blog eletrogate. ponte H. URL: [Link]
de-uso-da-ponte-h-l298n/.
[12] Mundo da eletrônica. termopar. URL: [Link]
br/termopar-o-que-e-funcionamento-tipos-aplicacoes/.
[13] embarcados. SPI. URL: [Link]
155
[29] N1. Fritzgerald e N2. Kingsley e N3. Stephen D. Umans. Máquinas Elétricas. Vol. 1.
Mc Graw Hill, 7ªed, 2014.
156
Figura 126: Prática 26 - fonte: autor
157
Figura 127: Prática 27 - fonte: autor
158