Apostila 2 — Curso Arduino Básico

ARDUINO BÁSICO

 

Módulo 2 – Programação Básica e Entradas Digitais

Aula 1 – Fundamentos da Programação no Arduino

 

Depois de conhecer a placa Arduino e aprender a montar os primeiros circuitos, chega o momento de compreender como transformar uma ideia em um conjunto de instruções que o microcontrolador seja capaz de executar. Programar significa justamente isso: criar uma sequência lógica de comandos que orienta o funcionamento do sistema. No caso do Arduino, a programação é baseada na linguagem C/C++, adaptada para facilitar o desenvolvimento de projetos eletrônicos e de automação.

Um programa de Arduino é chamado de Sketch e possui uma estrutura simples, composta principalmente pelas funções setup() e loop(). A função setup() é executada apenas uma vez quando a placa é ligada ou reiniciada. Nela são feitas as configurações iniciais, como definir quais pinos funcionarão como entrada ou saída e iniciar recursos como a comunicação serial. Já a função loop() é executada continuamente enquanto a placa estiver energizada, repetindo todas as instruções contidas em seu bloco. Essa organização facilita a leitura do código e ajuda o programador a separar as configurações iniciais das ações que devem ocorrer continuamente.

Para que o Arduino possa armazenar e manipular informações, utilizamos as variáveis. Uma variável pode ser comparada a uma caixa identificada por um nome, onde é possível guardar um valor que poderá ser utilizado ou alterado durante a execução do programa. Esse valor pode representar, por exemplo, a temperatura medida por um sensor, a intensidade da luz ambiente ou o estado de um botão. O uso correto das variáveis torna os programas mais organizados, flexíveis e fáceis de modificar.

Cada variável possui um tipo de dado, que determina qual tipo de informação poderá ser armazenada. Entre os tipos mais utilizados estão int, destinado aos números inteiros; float, utilizado para números com casas decimais; char, empregado para armazenar um único caractere; String, utilizada para textos; e bool, que trabalha apenas com dois valores possíveis: verdadeiro (true) ou falso (false). Escolher corretamente o tipo de dado contribui para um melhor aproveitamento da memória do microcontrolador e melhora o desempenho do programa.

Além das variáveis, existem as constantes. Diferentemente das variáveis, uma constante possui um valor fixo, que não pode ser alterado durante a execução do programa.

Elas são muito utilizadas para armazenar configurações permanentes, como o número do pino em que um LED está conectado. Essa prática torna o código mais organizado e reduz a possibilidade de alterações acidentais em informações importantes.

Outro elemento fundamental da programação são os operadores. Os operadores aritméticos permitem realizar cálculos, como soma, subtração, multiplicação e divisão. Já os operadores relacionais são utilizados para comparar valores, verificando, por exemplo, se dois números são iguais ou se um valor é maior que outro. Os operadores lógicos combinam diferentes condições para que decisões mais complexas possam ser tomadas durante a execução do programa. Esses recursos são indispensáveis para desenvolver aplicações capazes de responder às informações recebidas pelos sensores.

Durante a escrita dos programas, também é importante utilizar comentários. Eles são linhas de texto destinadas exclusivamente ao programador e não são executadas pelo Arduino. Os comentários servem para explicar a finalidade de determinadas instruções, facilitando futuras alterações e tornando o código mais compreensível para outras pessoas que venham a trabalhar no mesmo projeto. Em programas simples essa prática pode parecer dispensável, mas, à medida que os projetos crescem, ela se torna um importante recurso de organização.

Uma das boas práticas na programação consiste em utilizar nomes claros e objetivos para variáveis e funções. Em vez de utilizar identificadores genéricos, como "x" ou "a", é preferível escolher nomes que indiquem claramente sua finalidade, como temperatura, botaoLigado ou velocidadeMotor. Essa organização facilita tanto o desenvolvimento quanto a manutenção do código, reduzindo erros e tornando a leitura muito mais intuitiva.

Outro aspecto importante é realizar pequenos testes durante o desenvolvimento. Em vez de escrever um programa muito extenso antes de verificar seu funcionamento, recomenda-se implementar e testar cada etapa separadamente. Essa estratégia facilita a identificação de erros, reduz o tempo gasto com depuração e proporciona maior segurança durante a criação de novos projetos.

Ao concluir esta aula, o estudante compreenderá os principais fundamentos da programação aplicada ao Arduino, reconhecerá a função das variáveis, constantes, tipos de dados e operadores, entenderá a estrutura básica de um programa e estará preparado para desenvolver códigos cada vez mais organizados, eficientes e fáceis de manter.

Referências bibliográficas

BANZI, Massimo. Primeiros Passos com Arduino. São Paulo: Novatec.

MCROBERTS, Michael. Arduino Básico. São Paulo: Novatec.

MONK, Simon. Programação com Arduino: Começando com Sketches. Porto Alegre: Bookman.

BLOG DA ROBÓTICA. Fundamentos de Programação para Arduino.

OBSAT – Ministério da Ciência, Tecnologia e Inovação. Funções e Variáveis.

Instituto Federal Catarinense. Programação Aplicada a Microcontroladores.

Nerd Toolkit. Introdução a Variáveis e Constantes no Arduino.


Aula 2 – Estruturas de Decisão e Repetição

 

À medida que os projetos com Arduino se tornam mais elaborados, surge a necessidade de fazer com que a placa tome decisões e execute determinadas ações repetidamente. Imagine, por exemplo, um sistema de irrigação que só deve ligar quando o solo estiver seco ou um semáforo que alterna automaticamente entre as luzes verde, amarela e vermelha. Para resolver situações como essas, a programação utiliza estruturas de decisão e estruturas de repetição, recursos que tornam os programas mais inteligentes, organizados e eficientes. Esses conceitos fazem parte da base da lógica de programação e são amplamente utilizados em projetos de automação e robótica.

As estruturas de decisão permitem que o Arduino escolha entre diferentes ações de acordo com uma condição. A mais utilizada é a instrução if, que executa um bloco de comandos somente quando determinada condição é verdadeira. Por exemplo, um sensor de luminosidade pode informar ao Arduino que o ambiente está escuro; nesse caso, o programa poderá acender automaticamente uma lâmpada. Caso a condição não seja atendida, o programa simplesmente continuará sua execução normalmente.

Quando é necessário definir uma ação alternativa, utiliza-se a estrutura if...else. Ela permite estabelecer dois caminhos possíveis: um para quando a condição for verdadeira e outro para quando for falsa. Um exemplo simples é o controle de um ventilador. Se a temperatura ultrapassar um valor definido, o ventilador será ligado; caso contrário, permanecerá desligado. Essa estrutura torna o código mais claro e evita o uso de várias verificações independentes.

Em situações que envolvem diversas possibilidades, pode ser mais adequado utilizar o comando switch...case. Diferentemente do if, que avalia expressões lógicas, o switch compara o valor de uma variável com diferentes opções previamente definidas. Esse recurso é bastante útil quando um mesmo programa precisa executar rotinas distintas

conforme o modo de operação selecionado pelo usuário ou conforme comandos recebidos por um teclado, controle remoto ou comunicação serial.

Além de tomar decisões, muitos programas precisam repetir determinadas ações continuamente. Para isso existem as estruturas de repetição, também conhecidas como laços ou loops. Elas evitam a repetição desnecessária de comandos, tornando os programas menores, mais organizados e fáceis de manter. Em vez de escrever várias vezes a mesma instrução para acender um LED, por exemplo, basta utilizar um laço de repetição para que essa tarefa seja executada automaticamente quantas vezes forem necessárias.

O laço for é indicado quando já se conhece antecipadamente o número de repetições que será realizado. Ele utiliza uma variável de controle, responsável por acompanhar cada repetição até que uma condição de parada seja alcançada. Essa estrutura é bastante utilizada para criar sequências de LEDs, realizar contagens ou percorrer conjuntos de dados armazenados em memória. Sua sintaxe compacta facilita a leitura do código e reduz a possibilidade de erros.

Já o laço while é utilizado quando não se sabe exatamente quantas vezes uma ação deverá ser repetida. Nesse caso, o bloco de comandos continuará sendo executado enquanto determinada condição permanecer verdadeira. Um exemplo é a leitura contínua de um sensor até que um valor específico seja alcançado. Como o while depende diretamente da condição estabelecida, é importante garantir que essa condição possa ser modificada durante a execução do programa, evitando laços infinitos que impedem o funcionamento adequado do sistema.

Outro comando muito utilizado é a função delay(), responsável por interromper temporariamente a execução do programa durante um intervalo de tempo definido em milissegundos. Embora seja extremamente simples de utilizar, o delay() bloqueia completamente a execução das demais instruções enquanto a pausa estiver ativa. Em projetos pequenos isso normalmente não representa um problema, mas em aplicações mais complexas pode impedir a leitura de sensores ou atrasar respostas importantes do sistema.

Para contornar essa limitação, a programação do Arduino oferece a função millis(), que retorna o tempo decorrido desde que a placa foi ligada. Diferentemente do delay(), ela permite controlar o tempo sem interromper a execução do restante do programa. Dessa forma, o Arduino pode realizar várias tarefas simultaneamente, como monitorar sensores, atualizar um display e

controlar o tempo sem interromper a execução do restante do programa. Dessa forma, o Arduino pode realizar várias tarefas simultaneamente, como monitorar sensores, atualizar um display e controlar motores ao mesmo tempo. O uso de millis() é considerado uma boa prática em projetos que exigem maior desempenho e capacidade de resposta.

Como atividade prática desta aula, pode-se desenvolver um pequeno semáforo utilizando três LEDs. O programa deverá utilizar estruturas de repetição para manter o funcionamento contínuo do sistema e estruturas de decisão para controlar situações específicas, como um modo de manutenção acionado por um botão. Essa atividade permite observar, na prática, como diferentes estruturas de programação trabalham em conjunto para resolver um problema real.

Ao concluir esta aula, o estudante compreenderá quando utilizar as estruturas if, else, switch, for e while, reconhecerá as diferenças entre delay() e millis() e será capaz de desenvolver programas mais organizados, eficientes e preparados para aplicações de automação e robótica.

Referências bibliográficas

BANZI, Massimo. Primeiros Passos com Arduino. São Paulo: Novatec.

MCROBERTS, Michael. Arduino Básico. São Paulo: Novatec.

MONK, Simon. Programação com Arduino: Começando com Sketches. Porto Alegre: Bookman.

OLIVEIRA, Marcelo Eduardo de. Introdução à Robótica Educacional com Arduino – Hands On!. Prefeitura de Santo André.

Instituto Federal Catarinense. Programação Aplicada a Microcontroladores.

TreinaWeb. Estruturas condicionais e de repetição.

Blog da Robótica. Fundamentos de Programação para Arduino.


Aula 3 – Entradas Digitais

 

Uma das características mais importantes do Arduino é sua capacidade de interagir com o ambiente ao seu redor. Para isso, a placa recebe informações de sensores, botões e interruptores por meio das chamadas entradas digitais. Esses dispositivos permitem que o Arduino identifique eventos simples, como um botão pressionado, uma chave acionada ou um sensor que detectou movimento. A partir dessas informações, o programa pode tomar decisões e controlar diferentes componentes eletrônicos, tornando os projetos interativos e inteligentes.

As entradas digitais trabalham com apenas dois estados possíveis: HIGH (nível lógico alto) e LOW (nível lógico baixo). De forma simplificada, esses estados representam as respostas "ligado" ou "desligado", "verdadeiro" ou "falso". Essa simplicidade torna a leitura das entradas digitais bastante eficiente e

adequada para dispositivos que possuem apenas duas condições de funcionamento, como botões, chaves fim de curso, sensores magnéticos e sensores de presença digitais.

Antes de utilizar um pino como entrada, é necessário configurá-lo corretamente utilizando a função pinMode(). Quando um pino é definido como INPUT, ele passa a receber sinais provenientes dos componentes conectados. Outra possibilidade é utilizar o modo INPUT_PULLUP, que ativa internamente um resistor de pull-up, eliminando, em muitos casos, a necessidade de instalar um resistor externo. Essa configuração simplifica bastante a montagem dos circuitos e é amplamente utilizada em projetos com botões.

Depois que o pino foi configurado, o Arduino realiza a leitura utilizando a função digitalRead(). Essa função verifica o estado lógico presente na entrada e retorna apenas um dos dois valores possíveis: HIGH ou LOW. Com base nesse resultado, o programa pode executar diferentes ações, como acender um LED, emitir um som em um buzzer, movimentar um servo motor ou iniciar outra rotina previamente programada.

Um dos componentes mais utilizados para demonstrar o funcionamento das entradas digitais é o botão de pressão (push button). Quando pressionado, ele altera o estado elétrico do circuito, permitindo que o Arduino identifique a ação do usuário. Esse princípio está presente em inúmeros equipamentos eletrônicos do dia a dia, como elevadores, controles remotos, teclados, eletrodomésticos e sistemas de automação residencial.

Durante a utilização de entradas digitais, um problema bastante comum é o chamado estado flutuante (floating). Isso acontece quando um pino permanece sem uma referência elétrica definida. Nessas condições, o Arduino pode interpretar sinais aleatórios, fazendo com que o programa registre comandos inexistentes. Para evitar esse comportamento, utilizam-se resistores de pull-up ou pull-down, responsáveis por manter o pino em um estado lógico estável quando nenhum botão estiver sendo pressionado.

O modo INPUT_PULLUP tornou-se bastante popular justamente porque utiliza um resistor interno existente no próprio microcontrolador. Nessa configuração, o pino permanece normalmente em nível lógico HIGH e passa para LOW quando o botão é pressionado e conectado ao GND. Embora essa lógica seja inversa em relação à utilizada com resistores pull-down, ela reduz a quantidade de componentes necessários e simplifica a montagem dos projetos.

Outro fenômeno importante é o chamado debounce. Os

contatos mecânicos de um botão não fecham de forma perfeitamente instantânea; ao serem pressionados, podem oscilar rapidamente entre ligado e desligado durante alguns milissegundos. Como o Arduino executa milhares de instruções por segundo, ele pode interpretar essas oscilações como vários acionamentos consecutivos. Para evitar esse problema, utiliza-se o debounce, que pode ser implementado por meio de componentes eletrônicos ou por programação, filtrando essas pequenas oscilações antes de considerar o botão realmente pressionado.

Uma boa prática consiste em testar cada entrada digital individualmente antes de integrar vários componentes em um mesmo projeto. O uso do Monitor Serial facilita esse processo, permitindo visualizar em tempo real as mudanças entre os estados HIGH e LOW. Dessa forma, eventuais problemas de ligação, configuração ou programação podem ser identificados rapidamente, reduzindo o tempo gasto na depuração do sistema.

Como atividade prática desta aula, o aluno poderá montar um circuito simples em que um botão controla o acionamento de um LED. Inicialmente, o LED permanecerá apagado e será aceso apenas enquanto o botão estiver pressionado. Em seguida, o projeto poderá ser ampliado para que cada acionamento alterne o estado do LED entre ligado e desligado, permitindo explorar tanto a leitura das entradas digitais quanto as estruturas condicionais estudadas anteriormente.

Ao concluir esta aula, o estudante compreenderá o funcionamento das entradas digitais, saberá configurar corretamente os pinos utilizando INPUT e INPUT_PULLUP, utilizará a função digitalRead() para ler o estado de botões e sensores, compreenderá a importância dos resistores de pull-up e do debounce e estará preparado para desenvolver sistemas capazes de interagir com o ambiente por meio de dispositivos de entrada.

Referências bibliográficas

BANZI, Massimo. Primeiros Passos com Arduino. São Paulo: Novatec.

MCROBERTS, Michael. Arduino Básico. São Paulo: Novatec.

MONK, Simon. Programação com Arduino: Começando com Sketches. Porto Alegre: Bookman.

Projeto Robótica Educacional. Arduino – Entradas e Saídas Digitais.

Arduino Get Started. Referência da função digitalRead() em português.

Universidade Federal do Rio Grande do Sul. Introdução ao Arduino.

Universidade Federal de Santa Catarina. Programação Básica em Arduino.

  

Estudo de Caso – Módulo 2

O sistema de controle da estufa escolar

 

Uma escola técnica decidiu desenvolver um pequeno projeto de automação

técnica decidiu desenvolver um pequeno projeto de automação para uma estufa utilizada nas aulas de Ciências. A proposta era simples: instalar um botão que permitisse ligar e desligar manualmente um sistema de ventilação representado por um LED. O projeto serviria como base para futuras aplicações envolvendo sensores de temperatura e umidade.

A equipe responsável, formada por alunos iniciantes, iniciou a programação utilizando as estruturas de decisão aprendidas em sala de aula. O programa verificava constantemente se o botão havia sido pressionado e, quando isso acontecia, alterava o estado do LED. A montagem parecia correta e o código compilava sem apresentar erros.

Durante os primeiros testes, porém, surgiu um comportamento inesperado. Ao pressionar o botão apenas uma vez, o LED ligava e desligava diversas vezes em sequência. Em outros momentos, o LED mudava de estado sem que ninguém tocasse no botão. Além disso, quando decidiram acrescentar uma sequência de piscadas para indicar que o sistema estava ativo, perceberam que o botão demorava a responder enquanto o programa executava longos períodos de espera com a função delay(). Esses problemas são comuns em projetos com entradas digitais e normalmente estão relacionados ao efeito de bounce (debounce), ao uso de entradas flutuantes e ao bloqueio causado por atrasos prolongados.

Depois de analisar cuidadosamente o projeto, os alunos identificaram três causas principais. A primeira era a ausência de um resistor de pull-up ou pull-down, deixando a entrada digital em estado flutuante e sujeita a interferências elétricas. A segunda estava relacionada ao fenômeno conhecido como debounce: ao ser pressionado, o botão produzia pequenas oscilações mecânicas que o Arduino interpretava como vários acionamentos consecutivos. Por fim, o uso excessivo da função delay() fazia com que o programa interrompesse temporariamente todas as demais tarefas, reduzindo a capacidade de resposta do sistema.

Para solucionar o primeiro problema, os estudantes configuraram o pino do botão utilizando o modo INPUT_PULLUP, aproveitando o resistor interno do próprio Arduino e eliminando o estado flutuante da entrada. Em seguida, implementaram uma rotina de debounce, permitindo que o programa considerasse apenas pressionamentos realmente estáveis do botão. Por fim, substituíram parte dos atrasos baseados em delay() por uma lógica utilizando a função millis(), permitindo que o Arduino continuasse monitorando o botão enquanto outras

tarefas eram executadas. Essas mudanças tornaram o sistema muito mais confiável e responsivo.

Após as correções, o botão passou a responder corretamente, acionando o LED apenas uma vez a cada pressionamento. A equipe percebeu que pequenos detalhes de programação e configuração podem fazer grande diferença no desempenho de um projeto. Mais importante do que simplesmente fazer um circuito funcionar é compreender por que ele funciona e como evitar comportamentos inesperados.

Erros comuns observados

  • Utilizar entradas digitais sem resistores de pull-up ou pull-down.
  • Ignorar o efeito de debounce dos botões.
  • Fazer comparações lógicas incorretas nas estruturas if e else.
  • Criar laços de repetição que impedem a execução de outras tarefas.
  • Utilizar delay() em excesso, bloqueando a resposta do programa.
  • Não testar o funcionamento de cada parte do código antes de integrar todo o sistema.

Como evitar esses problemas

  • Configurar entradas digitais utilizando INPUT_PULLUP quando apropriado.
  • Implementar técnicas de debounce por software ou hardware.
  • Dividir o programa em pequenas etapas e testar cada uma separadamente.
  • Utilizar nomes claros para variáveis e organizar o código em funções.
  • Empregar millis() quando o projeto exigir execução simultânea de várias tarefas.
  • Utilizar o Monitor Serial para acompanhar os valores das entradas durante os testes e facilitar a identificação de falhas.

Lições aprendidas

O desenvolvimento desse projeto mostrou que a programação de sistemas embarcados depende tanto da lógica do código quanto da correta configuração do hardware. Estruturas de decisão bem planejadas, laços de repetição utilizados de forma adequada e uma leitura confiável das entradas digitais são fundamentais para construir sistemas seguros e estáveis. Ao adotar boas práticas desde os primeiros projetos, o estudante desenvolve uma base sólida para trabalhar futuramente com sensores, atuadores e aplicações mais complexas de automação e robótica.

Voltar