+1 500 000 produtos na nossa oferta
7000 encomendas enviadas diariamente
+300 000 clientes de 150 países
Data de publicação: 23-07-2021 Data de atualização: 16-04-2026 🕒 10 min de leitura
O dispositivo acabado é composto por blocos funcionais que geralmente podem ser usados várias vezes. Por exemplo, se estamos a construir um medidor de frequência com um microcontrolador – então, além do bloco amplificador –, vamos precisar quase dos mesmos componentes que para a construção de um temporizador. Referimo-nos a um microcontrolador com uma “envolvente” (resistências, condensadores, quartzo e outros), ecrã, botões e conectores. Obviamente, o contador de frequência não precisará de um relé para alterar o dispositivo externo e o temporizador do amplificador de entrada de banda larga, mas o núcleo continuará a ser o mesmo. Portanto, o segredo para o autodesenvolvimento de aplicações é compreender os princípios de funcionamento dos blocos funcionais individuais e depois combinar as suas funcionalidades.
Plataformas como a Arduino não exigem que o utilizador conheça o princípio de funcionamento dos componentes individuais. Basta conectar a placa-mãe ao módulo/capa de expansão e executar uma aplicação em funcionamento. Por outro lado, se não tivermos pelo menos um conhecimento básico dos componentes, então, em caso de problemas com o funcionamento do nosso dispositivo, estaremos condenados a vaguear pela escuridão. No entanto, quando procuramos componentes Arduino, na maioria das vezes esperamos um resultado rápido. É difícil conciliar tais expectativas com a necessidade de adquirir os conhecimentos adequados, porque basta introduzir alguns comandos para ver os primeiros resultados no ecrã, mas compreender porque é que isso acontece por vezes demora muito tempo.
Tendo em conta as discrepâncias descritas anteriormente, cada um dos artigos desta série será dividido em duas partes. No primeiro, mostraremos como conseguir o efeito. A segunda parte apresentará o modo de funcionamento de um determinado componente ou solução.
Começaremos com o módulo de ecrã LCD, porque, graças a ele, podemos ver o resultado do trabalho realizado mais rapidamente. Em seguida, analisaremos outros elementos da interface de utilizador e, depois, os sistemas externos selecionados: sensores e atuadores. Entretanto, também vamos familiarizar-nos com alguns truques e métodos de programação. E tudo isso com base na plataforma Arduino, que é económica e de fácil acesso e ainda lhe permitirá utilizar os conhecimentos adquiridos para construir dispositivos pré-fabricados ou protótipos.
A interface básica entre o microcontrolador e o utilizador é geralmente composta por um ecrã e um botão ou botões. Como facilmente adivinhará, o primeiro é usado para informar o utilizador das atividades do microcontrolador, ao passo que os botões, por vezes substituídos por uma tecla, podem ser usados para introduzir comandos ou dados. Vai encontrar na nossa oferta muitos ecrãs (incluindo os que têm um painel tátil), mas os ecrãs de caracteres com o controlador HD44780 tornaram-se, de certa forma, um padrão informal.
No primeiro exemplo de programação, usaremos uma placa Arduino UNO R3, uma placa de testes, um módulo LCD de caracteres com 2 linhas de 16 caracteres cada uma e alguns cabos de ligação. Naturalmente, isto é só uma sugestão: o ecrã pode ser conectado de qualquer forma, por exemplo, soldando-o à PCB. Aqui, foi utilizado o método que oferece a maior possibilidade de modificar e alterar o desenho da ligação.
Se o módulo de visualização tiver pinos dourados soldados, basta conectá-lo à placa de contacto. Depois conectamos o ecrã à placa Arduino UNO, conforme descrito na tabela 1.
Tabela 1. Ligações do ecrã de caracteres com a placa Arduino UNO
| N.º de contactos do ecrã | Nome do sinal de visualização | Nome do conector Arduino | Nome do sinal Arduino |
|---|---|---|---|
| 1 | VSS | Power | GND |
| 2 | VDD | Power | +5V |
| 3 | V0 | Power | GND |
| 4 | RS | Analog In | A4 (PC4) |
| 5 | R/W | Power | GND |
| 6 | E | Analog In | A5 (PC5) |
| 7 | DB0 | – | – |
| 8 | DB1 | – | – |
| 9 | DB2 | – | – |
| 10 | DB3 | – | – |
| 11 | DB4 | Analog In | A0 (PC0) |
| 12 | DB5 | Analog In | A1 (PC1) |
| 13 | DB6 | Analog In | A2 (PC2) |
| 14 | DB7 | Analog In | A3 |
| 15 (opcional) | LED+ | Power | 3.3V |
| 16 (opcional) | LED- | Power | GND |
Lembre-se de que, por exemplo, tendo a terra GND conectada a partir do conector de alimentação à placa de contactos, podemos fazer ligações dentro da placa de contactos e não temos de nos conectar ao conector de alimentação todas as vezes.
O uso do conector descrito como Power é necessário porque fornecerá energia ao ecrã. O conector Analogi In está montado mesmo ao lado, pelo que, por conveniência, se decidiu utilizar os pinos do microcontrolador disponíveis. No entanto, não se deixe enganar pelo nome: são necessárias saídas digitais para controlar o módulo de visualização, não as E/S analógicas. O conector chama-se Analog In porque tem entradas analógicas opcionais, que, não obstante, também podem ser configuradas para funcionar noutros modos, incluindo as saídas digitais. Assim, a entrada analógica A0 é a porta PC0, A1 - PC1, etc. (ver: Cabos do microcontrolador ATmega328PU).
Entre as muitas possibilidades de controladores de software disponíveis para Arduino, selecionámos uma biblioteca para controlar o funcionamento do ecrã LiquidCrystal. Depois de criar o esboço, vamos incluí-lo na primeira linha do programa com uma diretiva #include. Com o ecrã conectado ao microcontrolador da forma descrita anteriormente, pode começar a fazer o primeiro esboço de controlo do módulo de ecrã LCD.
Conectamos a placa Arduino à porta USB do nosso PC. No menu Arduino, escolha Arquivo e depois Novo (Ctrl+N). Aparecerá uma janela semelhante à da Figura 1. A palavra-chave void diz-nos que aqui será criada uma função que não devolverá nenhum valor. A palavra void é seguida do nome da função; a chave de abertura “{“ indica o seu início, e o símbolo de fecho “}” indica o seu final.
Ao criar um novo esboço, o ambiente Arduino informa sobre a necessidade de definir duas funções especiais: void setup (), que descreve a configuração do microcontrolador e que contém instruções realizadas uma vez aquando do início do programa, e void loop (), que contém atividades realizadas em loop infinito.
Figura 1. Nova janela de esboço para Arduino
Porque é que um programa de aplicação tem de ser executado em loop infinito? As aplicações do Windows ou do Linux são executadas sob controlo do sistema operativo. Se executamos a aplicação no Windows, uma vez finalizado o trabalho, volta ao lugar onde foi chamado e, como tal, com maior frequência, para mostrar a área de trabalho, a linha de comandos, etc. A partir desse momento, o sistema operativo assume o controlo do processador. O microcontrolador da placa Arduino UNO não tem nenhum sistema operativo carregado, pelo que o programador deve assegurar-se de que a aplicação é finalizada de forma segura. Isto pode ser feito apagando o microcontrolador (por exemplo, colocando-o em modo de suspensão) ou executando em loop as instruções para evitar a execução de instruções fora do intervalo de memória necessário. Isso pode ser feito na função void loop () ou por meio de outros métodos, sendo apresentado um exemplo em seguida.
Antes de mostrar informação no ecrã, devemos configurar o microcontrolador. Neste exemplo, só tem de configurar corretamente as saídas de controlo de ecrã.
No início do nosso esboço, incluímos uma biblioteca de funções de visualização:
#include <LiquidCrystal.h>
Depois, para nossa conveniência e legibilidade do programa, usando a diretiva #define, definimos os nomes dos pinos – saídas da porta C do microcontrolador:
//porta PC
#define pc0 A0
#define pc1 A1
#define pc2 A2
#define pc3 A3
#define pc4 A4
#define pc5 A5
Agora comunicamos ao microcontrolador a que pinos está conectado o ecrã. Para isso, é utilizada a função lcd (), na qual a lista de argumentos indica ao processador onde vai cada sinal. Ao substituir os pinos, mantenha a ordem correta:LiquidCrystal lcd(RS, Enable, D4, D5, D6, D7). Para criar uma lista de argumentos, usaremos a tabela 1, que contém uma lista de ligações entre o Arduino e o módulo de ecrã LCD.: LiquidCrystal lcd(pc4, pc5, pc0, pc1, pc2, pc3).
Agora deve tratar da configuração do modo de funcionamento dos pinos; deve configurá-los para que funcionem como saídas digitais. Esta configuração é armazenada na função void setup ():
pinMode(pc0, OUTPUT);
pinMode(pc1, OUTPUT);
pinMode(pc2, OUTPUT);
pinMode(pc3, OUTPUT);
pinMode(pc4, OUTPUT);
pinMode(pc5, OUTPUT);
Depois efetuamos a inicialização do ecrã, configurando o número de colunas e linhas e, num primeiro passo, limpando o ecrã. Depois da inicialização, o ecrã LCD deve estar em branco, mas, por uma questão de segurança e para um início adequado do trabalho, vale a pena seguir esta última indicação:
lcd.begin(16, 2);
lcd.clear();
No final, basta um comando para mostrar a mensagem:
lcd.print(“Hello!”);
Não pomos nenhum comando na função loop (). Depois de mostrar a mensagem, o programa simplesmente “girará” num loop infinito, desperdiçando tempo de CPU. Em princípio, seria possível neste ponto, por exemplo, entrar no modo de poupança de energia, porque, em todo o caso, a mensagem no ecrã não mudaria, mas seria necessária uma maior investigação de hardware, o que não é aconselhável nesta etapa.
O programa que mostra a mensagem “Hello!” está disponível nos materiais complementares deste texto. Se a descrição anterior e o resultado obtido forem satisfatórios, pode saltar a leitura do resto do texto. No próximo artigo, abordaremos operações um pouco mais avançadas em termos do conteúdo apresentado (que não apenas mostrar a mensagem).
Uma análise mais detalhada do tema deveria começar com a análise da estrutura do microcontrolador que está montado na placa Arduino, mas é um tema muito extenso. Portanto, primeiro analisaremos como funciona o módulo LCD.
São necessários conhecimentos básicos de chips de memória e chips digitais de um modo geral para compreender como controlar o módulo LCD. O conhecimento de termos como lógica alta, baixa, forma de onda, dados, 8 bits, byte, bit, flanco descendente e ascendente é essencial. Isto é necessário porque, do ponto de vista do manipulador, o módulo de visualização é visto como uma espécie de memória digital com a qual o microcontrolador pode comunicar bidirecionalmente. No entanto, de facto, o módulo de ecrã LCD tem o seu próprio microcontrolador (conforme mencionado no início, HD44780 ou semelhante), que não só recebe os dados a mostrar, como também executa os comandos relacionados com o funcionamento do módulo LCD e é compatível com o ecrã. Pelo facto de no sistema o microcontrolador integrado no módulo de visualização ter uma função autónoma estritamente especializada, tais sistemas são geralmente denominados escravos ou subordinados. O microcontrolador integrado na placa Arduino desempenha uma função de controlo superior. De um modo geral, estes sistemas são denominados mestres. Iremos deparar-nos muitas vezes com estes conceitos nas descrições de vários dispositivos conectados ao microcontrolador.
Voltemos ao básico por um momento. Nos circuitos CMOS – e a maioria dos circuitos integrados modernos utiliza esta tecnologia – o “1” lógico é pelo menos 95% da tensão de alimentação, e o “0” lógico é uma tensão menor ou igual a 0.3 V. Se o circuito do processador tiver uma fonte de alimentação incorporada, que costuma ser o caso de processadores mais complexos, o “1” lógico define-se em relação à fonte de alimentação interna. Também pode ser diferente – se o sistema CMOS tiver entradas compatíveis com os níveis TTL, então o “1” lógico é uma tensão superior a 2,4 V. Portanto, em caso de dúvida, vale a pena consultar a folha de dados do sistema específico. Poderá encontrá-la facilmente na Internet.
Uma alteração no nível lógico provoca uma alteração na tensão. Esta alteração ocorre a passos largos, ainda que ao longo do tempo. Quando o nível muda de “0” para “1” é um flanco ascendente, e quando muda de “1” para “0” é um flanco descendente. A duração da transição é denominada tempo de subida ou tempo de descida, respetivamente. Em geral, são apenas alguns nanossegundos, mas este não é necessariamente o caso.
Num microcontrolador, uma linha com o nível “0” ou “1” é denominada bit de dados. 8 dessas linhas formam um byte. Um microcontrolador AVR, como o Arduino UNO incorporado, tem uma palavra de dados de 8 bits, pelo que pode processar palavras de 1 byte, decimal de 0 a 255. Se o número for maior que 255, é necessário dividi-lo em “partes”, realizar uma operação e depois juntar o resultado. No entanto, não temos de nos preocupar com isso, porque o compilador Arduino fá-lo em segundo plano. Não obstante, deve ter em conta que quantos mais bits exigir uma determinada variável, mais tempo demorará a ser processada pelo microcontrolador.
Neste exemplo, o microcontrolador mestre controla o módulo de ecrã LCD com sinais de saída. Ao alterar os seus sinais de saída, controla os níveis lógicos nas entradas do módulo de visualização. Graças a isso, pode selecionar o momento de guardar os dados e a área de memória em que estes serão guardados:
Ao controlar o funcionamento do módulo de visualização de caracteres LCD, temos dois modos de funcionamento à nossa disposição, normalmente 8 bits e 4 bits. No primeiro, conectar o ecrã requer pelo menos 10 linhas de dados (RS, E, D0… D7). Do ponto de vista do controlador, este modo é muito eficaz se puder conectar um ecrã ao sistema host como memória num barramento de dados de 8 bits. O endereçamento do módulo de visualização estabelece a entrada de habilitação alta, baixa ou alta (consoante se trate de um comando ou de um dado para mostrar) em RS, coloca os dados no barramento e muda o nível a habilitar para baixo. Em alguns sistemas, o controlador simplifica bastante o processo.
No modo de 4 bits ainda usamos a palavra de 8 bits, mas só as entradas D4… D7 do módulo de visualização é que estão conectadas ao sistema host, e as palavras de dados de 8 bits são divididas em duas partes de 4 bits cada uma. Isto complica o programa de manutenção e dificulta a ligação do módulo de visualização ao sistema de supervisão, mas poupa 4 linhas GPIO do microcontrolador.
Nos manipuladores de módulos LCD simplificados que não utilizam as linhas R/W a priori, supõe-se que o módulo de visualização funciona corretamente. Estabelece-se um certo tempo pré-determinado, como a execução do comando de execução mais longa (geralmente cerca de 2 milissegundos), e, decorrido este tempo, supõe-se que o ecrã executou o comando ou mostrou um caracter e podem ser enviados dados posteriores. Regra geral, o microcontrolador integrado no módulo de visualização é mais rápido: só a execução do comando clear (limpeza de ecrã) demora até 2 milissegundos. Por outro lado, se, como neste exemplo, tivermos 2 linhas de 8 caracteres no ecrã, então não importa muito se enviamos 16 bytes em 32 milissegundos ou 100 microssegundos. Seja como for, nenhum utilizador conseguirá notar. Só não é assim quando se trata de ecrãs gráficos aos quais é transmitida uma quantidade muito maior de dados.
O Arduino não nos dá muita margem de manobra na hora de controlar o ecrã. O microcontrolador ATmega328 integrado no Arduino UNO não tem linhas de endereço externas, pelo que controlar o ecrã em modo de 8 bits com endereçamento como uma memória externa está fora de questão. No entanto, se usarmos uma porta GPIO, mais para controlar o sinal R/W, poderemos testar a bandeira de ocupado e ler o conteúdo dos registos e a memória do módulo LCD.
A função com o mesmo nome, ou seja, LiquidCrystal (), é utilizada para configurar o método de incluir o ecrã na biblioteca LiquidCrystal.h. A forma de incluir o ecrã é determinada pela função que chama à lista de argumentos:
O controlador HD44780 é um sistema universal, adaptado para suportar ecrãs LCD com um número variado de caracteres (colunas e linhas). Como resultado, depois de ligar a alimentação, o controlador “não sabe” que ecrã está conectado e deve ser configurado para o seu correto funcionamento. No Arduino, a função begin () é usada para isso, sendo os argumentos o número de colunas e o número de linhas. Por exemplo, a um ecrã com 2 linhas de 16 caracteres chamaríamos begin (16, 2).
O programa de exemplo também usa a função clear () para limpar o ecrã. É uma boa prática usá-lo primeiro, depois de iniciar o módulo LCD, porque podemos encontrar ecrãs que mostrem caracteres aleatórios depois da inicialização. Também usamos a função print (). Os seus argumentos são os dados a mostrar, como um número ou texto, e – no caso dos números – uma base, que para números decimais é “DEC”, binário “BIN”, hexadecimal “HEX”, octal “OCT”. A função print () encarrega-se de converter os números por nós, se for necessário mostrá-los em diferentes sistemas numéricos:
O ato de imprimir coloca os caracteres apresentados a partir da posição atual do cursor. Normalmente, depois do comando clear (), o cursor encontra-se no canto superior esquerdo do ecrã LCD.A biblioteca de funções LiquidCrystal.h contém muitas outras funções úteis, mas abordaremos como usá-las no próximo artigo. Para início, já aprendemos muito. É hora de um pequeno descanso.
A Transfer Multisort Elektronik (TME) é um dos maiores distribuidores globais de componentes eletrônicos, peças eletrotécnicas, equipamentos de oficina e automação industrial. O catálogo inclui mais de 1.500.000 de produtos de 1.300 fabricantes líderes. Os modernos centros logísticos da TME em Łódź e Rzgów (Polónia), com uma área total superior a 40.000 m², enviam quase 6.000 pacotes diariamente para clientes em mais de 150 países.
A TME também investe no desenvolvimento do conhecimento e das competências de jovens engenheiros e entusiastas da eletrónica através do projeto TME Education e apoia a comunidade tecnológica organizando a série de eventos TechMasterEvent, promovendo a inovação e a troca de experiências.