Programação para Arduino by Veca
Programação para Arduino by Veca
Introdução
O objetivo deste tutorial é apresentar, de uma forma simples e rápida, o básico de
programação para que você possa começar a utilizar o Arduino em seus projetos, sem
ter que ler muitos livros ou artigos sobre programação. O tema "desenvolvimento de
software" como um todo é muito abrangente, então vamos focar apenas nos conceitos
que são importantes para Arduino e sistemas embarcados em geral.
Existem muitas outras coisas para se aprender na parte de software que não vamos
abordar aqui. No final do artigo nós colocamos links que você pode seguir para aprender
conceitos mais avançados ou conceitos de software que não são muito utilizados na
programação de sistemas embarcados.
Vamos começar explicando como funciona um computador (lembre-se que o Arduino é,
no fundo, um computador).
Computador
Um computador é, de forma simplificada, uma máquina que processa instruções.
Essas instruções são processadas no "cérebro" do computador, que se
chama microprocessador. Todo computador possui pelo menos um microprocessador.
O Arduino, por exemplo, nada mais é do que um computador muito pequeno, e ele
utiliza um microprocessador do modelo ATmega. Alguns microprocessadores, como o
ATmega, também são chamados de microcontroladores.
Programa de Computador
Um programa de computador, ou software, é uma sequência de instruções que são
enviadas para o computador. Cada tipo de microprocessador (cérebro) entende
um conjunto de instruções diferente, ou seja, o seu próprio "idioma". Também
chamamos esse idioma de linguagem de máquina.
As linguagens de máquina são, no fundo, as únicas linguagens que os computadores
conseguem entender, só que elas são muito difíceis para os seres humanos
entenderem. É por isso nós usamos uma coisa chamada linguagem de programação.
No caso de sistemas como o Arduino (os chamados sistemas embarcados), o software
que roda no microprocessador é também chamado de firmware.
Linguagem de Programação
Nós seres humanos precisamos converter as nossas idéias para uma forma que os
computadores consigam processar, ou seja, a linguagem de máquina. Os computadores
de hoje (ainda) não conseguem entender a linguagem natural que nós usamos no dia a
dia, então precisamos de um outro "idioma" especial para instruir o computador a fazer
as tarefas que desejamos. Esse "idioma" é uma linguagem de programação, e na
verdade existem muitas delas.
Essas linguagens de programação também são chamadas de linguagens de
programação de alto nível. A linguagem de programação utilizada no Arduino é a
linguagem C++ (com pequenas modificações), que é uma linguagem muito tradicional e
conhecida. Essa é a linguagem que utilizaremos ao longo deste tutorial.
Para converter um programa escrito em uma linguagem de alto nível para linguagem de
máquina, nós utilizamos uma coisa chamada compilador. A ação de converter um
programa para linguagem de máquina é chamada compilar. Para compilar um
programa, normalmente se utiliza um ambiente de desenvolvimento (ou IDE, do
inglês Integrated Development Environment), que é um aplicativo de computador que
possui um compilador integrado, onde você pode escrever o seu programa e compilá-lo.
No caso do Arduino, esse ambiente de desenvolvimento é o Arduino IDE.
O texto contendo o programa em uma linguagem de programação de alto nível também
é conhecido como o código fonte do programa.
Algoritmo (Programa)
Um algoritmo, ou simplesmente programa, é uma forma de dizer para um computador
o que ele deve fazer, de uma forma que nós humanos conseguimos entender
facilmente. Os algoritmos normalmente são escritos em linguagens de programação de
alto nível. Isso se aplica a praticamente qualquer computador, inclusive o Arduino, onde
um algoritmo também é conhecido como sketch. Para simplificar, a partir de agora nós
vamos nos referir aos algoritmos, programas ou sketches simplesmente como
"programas".
Um programa é composto de uma sequência de comandos, normalmente escritos em
um arquivo de texto. Para este tutorial, vamos usar como base os comandos do
programa mais simples do Arduino, o Blink, que simplesmente acende e apaga um
LED, e vamos destrinchá-lo ao longo do tutorial. Veja abaixo o código fonte do Blink:
void setup() {
pinMode(led, OUTPUT);
void loop() {
digitalWrite(led, HIGH);
delay(1000);
digitalWrite(led, LOW);
delay(1000);
Variável
Uma variável é um recurso utizado para armazenar dados em um programa de
computador. Todo computador possui algum tipo de memória, e uma variável
representa uma região da memória usada para armazenar uma determinada
informação. Essa informação pode ser, por exemplo, um número, um caractere ou uma
sequência de texto. Para podermos usar uma variável em um programa Arduino, nós
precisamos fazer uma declaração de variável, como por exemplo:
int led;
Nesse caso estamos declarando uma variável do tipo int chamada led . Em seguida
nós falaremos mais sobre o tipo de dado de uma variável.
Tipo de Dado
O tipo de dado de uma variável significa, como o próprio nome diz, o tipo de informação
que se pode armazenar naquela variável. Em muitas linguagens de programação, como
C++, é obrigatório definir o tipo de dado no momento da declaração da variável, como
vimos na declaração da variável led acima. No caso dos módulos Arduino que usam
processador ATmega, os tipos mais comuns de dados que utilizamos são:
Para conhecer todos os tipos de dado suportados pelo Arduino, veja a seção "Data
Types" nessa página.
Atribuição
Atribuir um valor a uma variável significa armazenar o valor nela para usar
posteriormente. O comando de atribuição em C++ é o = . Para atribuírmos o valor 13 à
variável led que criamos acima, fazemos assim:
led = 13;
O objetivo dessa linha de código é dizer que o pino 13 do Arduino será utilizado para
acender o LED, e armazenar essa informação para usar depois ao longo do programa.
Os valores fixos usados no programa, como o valor 13 acima, são chamados
de constantes, pois, diferentemente das variáveis, o seu valor não muda.
Operador
Um operador é um conjunto de um ou mais caracteres que serve para operar sobre
uma ou mais variáveis ou constantes. Um exemplo muito simples de operador é o
operador de adição, o + . Digamos que queremos somar dois números e atribuir a uma
variável x . Para isso, fazemos o seguinte:
x = 2 + 3;
Operadores aritméticos:
o + : adição ("mais")
o - : subtração ("menos")
o * : multiplicação ("vezes")
o / : divisão ("dividido por")
Operadores lógicos:
o && : conjunção ("e")
o || : disjunção ("ou")
o == : igualdade ("igual a")
o != : desigualdade ("diferente de")
o ! : negação ("não")
o > : "maior que"
o < : "menor que"
o >= : "maior ou igual a"
o <= : "menor ou igual a"
Operadores de atribuição:
o = : atribui um valor a uma variável, como vimos acima.
Ao longo do desenvolvimento dos seus projetos, aos poucos você se familiarizará com
todos esses operadores. Para uma lista completa, veja essa página da Wikipedia.
Função
Uma função é, em linhas gerais, uma sequência de comandos que pode ser reutilizada
várias vezes ao longo de um programa. Para criar uma função e dizer o que ela faz, nós
precisamos fazer uma declaração de função. Veja como uma função é declarada no
nosso programa de exemplo:
void setup() {
pinMode(led, OUTPUT);
Aqui estamos declarando uma função com o nome setup() . O que ela faz é executar os
comandos de uma outra função pinMode() . A ação de executar os comandos de função
previamente declarada é denominada chamada de função. Nós não precisamos
declarar a função pinMode() porque ela já é declarada automaticamente no caso do
Arduino.
Chamada de Função
Chamar uma função significa executar os comandos que foram definidos na sua
declaração. Uma vez declarada, uma função pode ser chamada várias vezes no mesmo
programa para que seus comandos sejam executados novamente. Para chamarmos a
nossa função setup() , por exemplo, nós usaríamos o seguinte comando:
setup();
No entanto, no caso do Arduino, nós não precisamos chamar a função setup() , porque
ela é chamada automaticamente. Quando compilamos um programa no Arduino IDE, ele
chama a função setup() uma vez e depois chama a função loop() repetidamente até
que o Arduino seja desligado ou reiniciado.
Valor de Retorno
A palavra chave que vem antes do nome da função na declaração define o tipo do valor
de retorno da função. Toda vez que uma função é chamada, ela é executada e devolve
ou retorna um determinado valor - esse é o valor de retorno, ou
simplesmente retorno da função. O valor de retorno precisa ter um tipo, que pode ser
qualquer um dos tipos de dados citados anteriormente. No caso da nossa
função setup() , o tipo de retorno é void , o que significa que a função não retorna
nada.
Para exemplificar, vamos criar uma função que retorna alguma coisa, por exemplo um
número inteiro. Para retornar um valor, nós utilizamos o comando return :
int f() {
return 1;
Quando chamada, a função f() acima retorna sempre o valor 1 . Você pode usar o
valor de retorno de uma função para atribuí-lo a uma variável. Por exemplo:
x = f();
Após declarar a função f() e chamar o comando de atribuição acima, a variável x irá
conter o valor 1 .
Parâmetros
Um outro recurso importante de uma função são os parâmetros. Eles servem para
enviar algum dado para a função quando ela é chamada. Vamos criar por exemplo uma
função que soma dois números:
return a + b;
}
Aqui acabamos definir uma função chamada soma() , que aceita dois números inteiros
como parâmetros. Nós precisamos dar um nome para esses parâmetros, e nesse caso
escolhemos a e b . Esses parâmetros funcionam como variável que você pode usar
dentro da função. Sempre que chamarmos a função soma() , precisamos fornecer esses
dois números. O comando return a + b; simplesmente retorna a função com a soma
dos dois números. Vamos então somar 2 + 3 e atribuir o resultado para uma variável x :
x = soma(2, 3);
Comentários
Um comentário é um trecho de texto no seu programa que serve apenas para explicar
(documentar) o código, sem executar nenhum tipo de comando no programa. Muitas
vezes, os comentários são usados também para desabilitar comandos no código. Nesse
caso, dizemos que o código foi comentado.
Na linguagem C++, um comentário pode ser escrito de duas formas:
/*
*/
/*
*/
/*
Esta função é chamada apenas uma vez, quando o Arduino é ligado ou reinicia
do.
*/
void setup() {
/*
*/
void loop() {
Estruturas de Controle
Estruturas de controle são blocos de instruções que alteram o fluxo de execução do
código de um programa. Com elas é possível fazer coisas como executar comandos
diferentes de acordo com uma condição ou repetir uma série de comandos várias vezes,
por exemplo.
A seguir nós veremos algumas das estruturas de controle mais comuns usadas nas
linguagens de programação em geral. Vamos também modificar o nosso programa de
teste para exemplificar melhor como essas estruturas funcionam.
While
O while é uma estrutura que executa um conjunto de comandos repetidas vezes
enquanto uma determinada condição for verdadeira. While em inglês quer dizer
"enquanto", e pronuncia-se "uái-ou". Ele segue o seguinte formato:
while(condição) {
...
Vamos então fazer uma modificação no nosso programa para exemplificar melhor como
o while funciona. O nosso objetivo agora é fazer o LED piscar três vezes, depois
esperar cinco segundos, piscar mais três vezes e assim por diante. Nós vamos mudar o
conteúdo da função loop() para o seguinte:
while(i < 3) {
Primeiro nós declaramos uma variável i . Essa variável vai contar quantas vezes o LED
já piscou desde o início do programa ou desde a última pausa de cinco segundos. Nós
vamos inicializar essa variável com zero porque no início da função loop() o LED ainda
não piscou nenhuma vez sob essas condições.
Em seguida nós inserimos o comando while , que deve ser seguido de
uma condição definida entre parênteses. Enquanto essa condição for verdadeira, todo
o bloco de comandos entre os caracteres { e } é executado repetidamente. No caso
do nosso programa, enquanto o número de "piscadas" do LED (representado pela
variável i ) for menor do que três, nós continuamos a executar os comandos que fazem
o LED piscar. Isso é representado pela expressão i < 3 dentro dos parênteses.
Entre os caracteres { e } nós colocamos o código que faz o LED piscar, como
anteriormente, mas não podemos nos esquecer de somar 1 à variável que conta o
número de "piscadas". Isso é feito na seguinte linha de código:
Após esses passos, chegamos ao final da função loop() , e como já sabemos, ela é
chamada novamente pelo sistema do Arduino. Isso reinicia o ciclo, executando os
passos acima indefinidamente.
Rode o programa modificado com as instruções acima no seu Arduino e tente variar o
número de "piscadas" e o número
For
Agora que nós já aprendemos o comando while, fica muito fácil aprender o
comando for, pois ele é quase a mesma coisa. Vamos modificar o conteúdo da
função loop() como fizemos acima, porém usando o for no lugar do while :
int i;
A primeira modificação que fizemos foi declarar a variável i sem inicializá-la com o
valor 0 . Nós podemos fazer isso porque o comando for fará isso para a gente. Ele
segue o seguinte formato:
...
Podemos então verificar que o for nada mais é do que um while acrescido de um
comando de inicialização e um comando de finalização. Para o nosso programa de
teste, esses comandos são, respectivamente:
If
O if é uma das estruturas mais básicas de programação em geral. If significa "se" em
inglês, e é exatamente isso que ele faz: ele verifica uma expressão e, apenas se ela
for verdadeira, executa um conjunto de comandos. Em linguagem natural, ele executa
uma lógica do tipo: "se isso for verdadeiro, então faça aquilo"
Para ilustrar, vamos modificar o nosso programa de exemplo para que ele faça a mesma
coisa que fizemos com o while e o for acima, porém vamos fazer isso usando um if ,
que segue o seguinte formato:
if(condição) {
...
int i = 0;
void loop() {
if(i == 3) {
}
Aqui a lógica é um pouco diferente: nós vamos manter a função loop() piscando o LED
como no programa original, porém vamos inserir uma espera adicional de 5 segundos
após cada 3 piscadas. Para isso, criamos uma variável i fora da função loop() ; ela
precisa ser declarada de fora da função para poder reter o seu valor entre cada
execução da função loop() . Chamamos isso de variável global. Quando a variável é
declarada dentro do corpo da função, ela não retém o valor etnre cada execução, sendo
reiniciada a cada vez que a função é re-executada. Chamamos isso de variável local.
Nós usaremos então essa variável global i para contar, novamente, o número de
vezes que o LED acendeu e apagou. Na declaração da variável, nós a inicializamos com
o valor 0 para indicar que o LED não acendeu nenhuma vez ainda. A
função loop() então começa a ser executada, acendendo e apagando o LED. Para
contar o número de vezes que o LED piscou, nós adicionamos a seguinte linha de
código:
A partir daí a função loop() continua sendo chamada e o ciclo se inicia novamente.
If-Else
O if-else, também conhecido como if-then-else, pode ser visto como uma extensão do
comando if . Else em inglês significa "caso contrário", e ele faz exatamente o que o
nome diz: "se isso for verdadeiro, então faça aquilo, caso contrário, faça outra coisa".
Ele segue o seguinte formato:
if(condição) {
...
} else {
...
Para exemplificar, vamos usar o programa do for que mostramos acima, mas vamos
dessa vez fazer o LED acender e apagar quatro vezes antes de dar uma pausa de cinco
segundos. Depois vamos fazer com que na terceira de cada uma dessas quatro
"piscadas", o LED acenda por um período mais curto. Dentro da função loop() ,
teremos o seguinte:
int i;
if(i == 2) {
} else {
Bibliotecas
As coisas que aprendemos nas seções anteriores são importantes para implementar a
lógica do seu programa no Arduino, mas normalmente você vai querer fazer mais coisas
além de apenas acender um LED. Quando se faz tarefas mais complexas ou se utiliza
algum outro circuito conectado ao seu Arduino, um recurso muito importante são
as bibliotecas.
Uma biblioteca é basicamente composta de código fonte adicional que você adiciona ao
seu projeto por meio do comando include. Vejamos como adicionar, por exemplo, uma
biblioteca para controle de um display de cristal liquido (LCD):
#include <LiquidCrystal.h>
Uma biblioteca do Arduino se apresenta normalmente como uma ou mais classes que
possuem funções, os métodos, para acionar dispositivos, configurá-los ou executar
alguma outra tarefa. Continuando com o exemplo do display de cristal líquido, para usá-
lo no seu programa, primeiro é preciso inicializá-lo. O que fazemos nesse caso é criar
um objeto para acessar o LCD (tecnicamente isso se chama instanciar um objeto).
Vejamos como isso é feito:
lcd.begin(16, 2);
Normalmente esse método begin() é chamado de dentro da função setup() , ou seja,
durante a inicialização do programa. Os parâmetros do método begin() , nesse caso,
correspondem ao número de colunas e o número de linhas do LCD, respectivamente.
Feitos esses passos, já podemos escrever texto no LCD. Fazemos isso usando o
método print() do objeto lcd , sempre que precisarmos ao longo do programa:
lcd.print("Oi!");