Programação com Arduino – Parte 2

Interface com Hardware

Na primeira parte do artigo sobre como programar arduino, abordamos apenas questões de desenvolvimento de software. As funções, bibliotecas, estruturas de decisão e loops, são ferramentas usadas no seu código para implementar a lógica que você precisa.

Mas temos também o hardware!

O Arduino possui uma série de bibliotecas e funções já prontas para acessar as configurações do microcontrolador e manipular as interfaces de hardware. É a existência dessas bibliotecas e funções que encapsulam toda a complexidade do microcontrolador o grande responsável pela facilidade de se aprender e programar o Arduino.

Algumas coisas acabam se repetindo em todo programa. Configurar I/Os digitais e analógicos, estabelecer um canal de comunicação serial e gerar/ler sinais PWM são conceitos básicos que você sempre vai precisar para a maioria de suas aplicações. Pensando nisso, vamos entender como isso é feito nessa sessão.

I/Os digitais

O arduino possui 14 inputs/Outputs digitais. Esses I/Os são usados para ler e gerar sinais de natureza digital, isto é, sinais que assumem apenas dois estados: alto (5 V/3.3V) ou baixo (GND).

Antes de usar um pino digital você deve configurá-lo como entrada ou saída. Por padrão os pinos são configurados como entrada, mas é uma boa prática de programação deixar isso explícito em seu código.

As funções que você vai usar para configurar, ler e setar um pino digital são:

void pinMode()

Usada para configurar os pinos como entrada ou saída. A sua sintaxe de utilização é a seguinte:

  • pinMode(pino, modo);

Em que pino é o número do I/O digital que você quer configurar e modo pode ser INPUT, INPUT_PULLUP e OUTPUT. Por exemplo, para configurar o pino treze como saída digital, você deve escrever:

  • EX:  pinMode(13, OUTPUT)

int digitalRead()

Função utilizada para ler o estado de um pino digital. Nesse caso, é necessário que você tenha configurado o pino como entrada. A sintaxe dessa função é:

  • digitalRead(pino);

Em que pino é o número do pino digital que se deseja ler. Por exemplo, se você quer saber se o pino 13 está em nível alto ou baixo, você deve escrever a seguinte linha de código:

  • X = digitalRead(13);

Nesse caso, a variável x deve ser declarada de antemão. Ela é responsável por receber o valor correspondente ao estado do pino ( 1 se estiver em nível alto e 0 se estiver em GND).

void digitalWrite()

Por fim, a função para escrever no pino, ou como se diz, “setar” o pino para um determinado nível lógico. A sintaxe de utilização é a seguinte:

  • digitalWrite(pino, valor);

Pino é o número do pino que você quer “setar”. Valor pode ser HIGH ou LOW. Assim, caso você precise colocar o pino 13 em nível lógico alto (5V), você deve escrever o seguinte:

  • digitalWrite(13, HIGH);

Lembre-se que para usar essa função o pino deve estar configurado como saída. Um exemplo clássico de utilização dos I/Os digitais é led blink, um firmware simples focado em fazer um led piscar. Veja o programa abaixo:

Exemplo: Led Blink

Led

Exemplo Arduino Led Blink. Fonte: Arduino Oficial

Neste código, na função de inicialização nós configuramos o pino 13 como uma saída digital.

Já no loop infinito, é chamada a função digitalWrite(13, High), responsável por atribuir nível alto ao pino 13 , ou seja, o led  ligado ao pino 13 é ativado. Logo em seguida é chamada a função delay(1000), que pausa a execução do loop por mil milissegundos, isto é, por um segundo.

Depois de aguardar esse tempo, a função digitalWrite() é novamente chamada, mas dessa vez para atribuir nível lógico baixo ao pino 13, ou seja, para desligar o led ligado ao pino 13. Por fim, novamente a função delay(1000) é chamada para fazer mais uma pausa de um segundo.

I/Os analógicos

Os canais analógicos são 6. Essas entradas são utilizadas para fazer a leitura de sinais analógicos, ou seja, sinais cujo nível de tensão varia continuamente entre 0 e VCC (geralmente 5 ou 3.3V).

Esses inputs estão ligados ao conversor A/D do ATmega328. O conversor A/D é um circuito interno ao MCU responsável por converter as grandezas analógicas aplicadas aos inputs em um valor digital com o qual o processador possa trabalhar. O conversor A/D do Arduino UNO possui resolução de 10 bits. Isso significa que um sinal que varia de 0 a VCC em termos analógicos, ao ser convertido para digital, será um valor que varia de 0 a 1024. Sendo que cada unidade dessa faixa de 0 a 1024 corresponde a VCC/1024.

Caso a tensão de referência seja 5V. Cada unidade dessa faixa de 0 a 1024 corresponderá a 4,88 mV. Para você entender melhor como funcionam os conversores A/D e como saber se a resolução do seu conversor é adequada à sua aplicação, veja o nosso post sobre conversores A/D: “Arduino e conversores A/D”.

Para trabalhar com os inputs analógicos você vai utilizar as seguintes funções:

  • analogReference(tipo)

Essa função é usada para definir a tensão de referência do conversor A/D. A sua sintaxe é:

  • analogReference(tipo);

Em que tipo define as configurações possíveis do canal A/D. São elas:

  • DEFAULT: a tensão padrão para conversão é a de alimentação da placa. Geralmente esses valores são 5V  ou 3.3 V
  • INTERNAL: Referência interna de 1.1V no Atmega168 e Atmega328, e 2.56 V no ATmega8;
  • INTERNAL1V1: Referência de 1.1V, apenas no Arduino Mega;
  • INTERNAL2V56: Referência interna de 5.6 V, somente no Arduino Mega;
  • EXTERNAL: Referência de tensão aplicada no pino AREF (entre 0 e 5V).

Para configurar o conversor A/D para operar com tensão externa do AREF por exemplo, você deve escrever o seguinte:

  • analogReference(EXTERNAL);

A outra função utilizada é:

  • int analogRead(pino)

Essa função é utilizada para ler o valor de uma das entradas analógicas. A sua sintaxe é a seguinte:

  • Valor_sensor = analogRead(pino);

Valor_sensor é uma variável qualquer para armazenar o valor lido. O parâmetro pino é número do input que você quer ler. Por exemplo, se você quiser armazenar o valor do canal analógico 1, você deve escrever:

  • Valor_sensor = analogRead(1);

Exemplo sensor analógico:

No exemplo abaixo vemos como é feito a leitura de um sensor analógico. Esse sensor poderia ser um thermistor para medir temperatura, um potenciômetro, um sensor de luminosidade e qualquer outro cujo sinal de saída seja analógico.

Exemplo sensor analógico com Arduino: Fonte: Arduino Oficial

Na função void Setup() nós configuramos o pino 13 como saída digital e a tensão de referência do conversor A/D para DEFAULT, ou seja, a tensão de alimentação da placa.

No loop infinito nós usamos a função analogRead(); para ler o valor do sensor, que nesse caso está localizado no pino A0 (também poderia ter sido atribuído valor 0).

Após ler o valor do sensor, o pino 13 é ativado, e logo depois é chamado um delay cujo valor de espera é o valor lido do sensor. Ou seja, o tempo de espera depende do valor lido do sensor. Depois do primeiro delay, o pino 1 é desativado e um novo delay é chamado.

Esse programa nada mais faz do que acender e desligar o led ligado ao pino 13 variando o tempo de espera de acordo com o sinal do sensor.

Comunicação serial

A comunicação serial, conhecida pela sigla UART, é um recurso muito interessante fazer um canal de comunicação entre a placa e o computador ou entre o microcontrolador e outros módulos, como dispositivos GSM, GPS, dentre outros.

No nosso post “Comunicação serial com Arduino: Saiba tudo”, explicamos em detalhe o funcionamento desse módulo.

Aqui apresentamos as principais funções para usar o canal serial do Arduino UNO. Na placa, você pode ver que há um pino digital com nome RX, e um outro pino com nome TX. Esses são os dois pinos utilizados na comunicação serial.

As funções que você irá utilizar para estabelecer comunicação serial são:

  • Serial.begin() : É utilizada para configurar a taxa de comunicação e outros parâmetros. É a primeira função que deve ser chamada
  • Serial.available() : Essa função retorna a quantidade de bytes disponíveis no buffer de leitura. Pode ser útil para descobrir se há algum dado no buffer para ser lido ou não.
  • Serial.read() : Faz a leitura do byte mais recente do buffer de leitura.
  • Serial.print() : Escreve uma determinada palavra em código ASCII na porta serial.
  • Serial.println() : Mesma coisa que a anterior, mas acrescenta ao final da palavra um caractere de quebra de linha (/n).
  • Serial.write() : Escreve um byte na porta serial

A IDE do Arduino possui um terminal serial que pode ser usado para visualizar o recebimento e envio de dados para a placa. Para acessar esse terminal serial, clique no ícone Serial Monitor ou acesse o menu Tools -> Serial Monitor.

A janela do terminal tem a cara a seguir:

Terminal serial do arduino

PWM

A técnica de PWM, cuja abreviação em inglês significa Pulse Width Modulation, é uma técnica usada para variar o valor médio de uma forma de onda periódica. A ideia básica do PWM é manter a frequência de uma onda quadrada fixa e variar o tempo que o sinal fica em nível lógico alto.

Ou seja, o tempo que o sinal fica ativado varia. Esse tempo é chamado de Duty Cycle, e é variando esse tempo que é possível fazer o valor médio variar proporcionalmente.

O Arduino Uno possui pinos específicos para saídas PWM.Esses pinos são indicados pelo caractere ‘~’ na frente de seu número. A função utilizada para gerar um sinal PWM é a AnalogWrite, veja sua sintaxe abaixo:

  • analogWrite(Pino_PWM, valor);

Pino_PWM correspondente ao pino no qual o PWM será aplicado. Valor é o Duty Cycle a ser aplicado ao sinal PWM. Esse valor deve estar entre 0 a 255, sendo 0 um duty cycle de 0% e 255 um Duty Cycle de 100%.

No nosso post “Dominando PWM no Arduino” explicamos em detalhe os conceitos por trás do PWM, suas aplicações mais comuns e como mudar as configurações padrão de frequência do microcontrolador Atmel do Arduino Uno.

Programando!

Vamos fazer agora um exemplo de aplicação para você treinar os conhecimentos obtidos. Esse exemplo será um pouco diferente. Nós não vamos mostrar nenhum código, até porque tudo que você vai precisar, as funções e estruturas de programação, já foram mostradas nos exemplos anteriores.

Aqui no nosso exemplo, nós vamos descrever a aplicação e apenas apresentar a estrutura lógica do programa. Você é quem terá que implementar no seu Arduino substituindo as descrições lógicas pelas funções e códigos necessários, conforme você aprendeu nesse post. E aí, está animado?! Para entrar no mundo Arduino tem que estar!

Vamos começar.

Desafio

Nossa aplicação é a seguinte:

“Controlar o brilho de um led, usando como sinal de controle a temperatura ambiente. Além disso, a temperatura ambiente deve ser exibida no terminal do computador.”

Descrição das necessidades da aplicação:

Da descrição do nosso desafio sabemos o seguinte:

  • Temos que controlar o brilho de um led. Isso significa que temos que aplicar um sinal de tensão variável nos terminais do led. Em outras palavras, temos que usar uma saída PWM para variar a tensão de ativação do led.
  • O brilho do led deve ser proporcional à temperatura ambiente. Ou seja, teremos que ler um sensor para saber a temperatura ambiente. Isso significa que vamos usar um dos canais analógicos para fazer a leitura do sinal de um sensor de temperatura.
  • É necessário exibir no terminal do PC o valor da temperatura lido com o Arduino. Isso significa que vamos ter que usar o canal serial do Arduino para enviar o valor lido de temperatura para o PC e exibir em um terminal serial, por exemplo, o terminal da própria IDE do Arduino.
  • Do ponto de vista lógico, o problema não exige grandes elaborações. Temos basicamente que monitorar continuamente um sensor de temperatura, e baseado nas variações que forem percebidas pelo sensor, vamos ajustar o Duty Cycle de um PWM aplicado a um LED e também enviar os dados de temperatura para o PC via porta serial.

Algoritmo

Vamos desenhar um algoritmo de como seria essa aplicação. Nós já conhecemos a estrutura base de todo programa Arduino, que são as funções void Setup() e void Loop().  Na imagem abaixo você pode ver o passo a passo de coomo deve ficar a sua função void Setup().

Passo a passo void setup()

Agora o algoritmo de como deve ficar a função Void Loop().

Passo a passo função void loop()

E aí, agora está fácil né?! Volte aos tópicos anteriores do texto, identifique quais funções usar e escreva seu código. Qualquer dúvida que você tiver entre em contato conosco. E não esqueça de conferir nossos outros posts sobre PWM, comunicação serial e conversores A/D. Deixe o seu comentário!

Avaliações: 5.0. de 1 voto.
Por favor, aguarde...
Vitor Vidal
Vitor Vidal
Engenheiro eletricista, mestrando em eng. elétrica e apaixonado por eletrônica, literatura, tecnologia e ciência. Divide o tempo entre pesquisas na área de sistemas de controle, desenvolvimento de projetos eletrônicos e sua estante de livros.
  • EVDS ELÉTRICA

    Gostei,muito bem explicado.

    Faça sua avaliação.
    Por favor, aguarde...
    • Vitor

      Olá, EVDS Elétrica!

      Obrigado pelo comentário!

      Abraços!

      Faça sua avaliação.
      Por favor, aguarde...