Aula 02 - Entradas e Saídas Digitais, Debounce de Botões e Modulação PWM
1. Modos de Operação dos Pinos Digitais (GPIO)
O microcontrolador ATmega328P na placa Arduino Uno R3 disponibiliza 14 pinos digitais de uso geral numerados de D0 a D13 (além de permitir que os 6 pinos analógicos A0 a A5 sejam reconfigurados como pinos digitais D14 a D19).
A função nativa pinMode(pin, mode) configura a arquitetura interna do circuito de entrada/saída através de três modos canônicos:
2. Circuitos de Polarização de Entradas: Pull-Up vs. Pull-Down
Para que uma chave mecânica (push-button) ou sensor digital forneça níveis de tensão unívocos e imunes a espúrios, o circuito deve ser obrigatoriamente referenciado a um potencial fixo quando a chave estiver aberta:
2.1 A Vantagem de Engenharia do INPUT_PULLUP
A ativação do resistor de pull-up interno por firmware (pinMode(pin, INPUT_PULLUP)) dispensa componentes passivos externos na placa de circuito impresso:
- A chave é conectada diretamente entre o pino do Arduino e a linha de terra (GND);
- Quando o operador pressiona o botão, o pino é aterrado, resultando na leitura lógica
LOW(); - Quando o botão é solto, o resistor interno puxa a tensão de volta para , lendo
HIGH().
3. O Repique Mecânico (Contact Bounce) e o Algoritmo de Debounce
Quando os contatos metálicos internos de uma chave mecânica fecham ou abrem, a elasticidade dos materiais condutores faz com que as lâminas colidam e vibrem durante um intervalo de .
Durante essa transição mecânica, a tensão elétrica oscila dezenas de vezes entre e . Como a UCP do ATmega328P executa de instruções por segundo, um único toque humano de botão seria erroneamente contabilizado como pulsos consecutivos!
3.1 Eliminação do Repique com a Função Não-Bloqueante millis()
A função de temporização do sistema millis() retorna o número acumulado de milissegundos decorridos desde que a placa foi ligada através de um contador de 32 bits alimentado por interrupções do Timer0. Ela atinge estouro (overflow) apenas após de operação ininterrupta.
O algoritmo profissional de Debounce Não-Bloqueante com Detecção de Borda implementa-se sem paralisar a UCP:
const uint8_t PINO_BOTAO = 2;
const uint8_t PINO_LED = 13;
uint8_t estado_botao_anterior = HIGH;
uint8_t estado_led = LOW;
unsigned long ultimo_tempo_debounce = 0;
const unsigned long DELAY_DEBOUNCE = 50; // Janela de filtro de 50 ms
void setup() {
pinMode(PINO_BOTAO, INPUT_PULLUP);
pinMode(PINO_LED, OUTPUT);
digitalWrite(PINO_LED, estado_led);
}
void loop() {
uint8_t leitura_atual = digitalRead(PINO_BOTAO);
// 1. Detecta transição de borda (Mudança de estado no pino físico)
if (leitura_atual != estado_botao_anterior) {
ultimo_tempo_debounce = millis(); // Reinicia o cronômetro de filtro
}
// 2. Se a leitura permaneceu estável por tempo superior à janela de repique:
if ((millis() - ultimo_tempo_debounce) > DELAY_DEBOUNCE) {
// Se a tecla foi efetivamente pressionada (borda de descida em Active-Low):
static uint8_t estado_estabilizado = HIGH;
if (leitura_atual != estado_estabilizado) {
estado_estabilizado = leitura_atual;
if (estado_estabilizado == LOW) {
estado_led = !estado_led; // Inverte o estado do LED (Toggle)
digitalWrite(PINO_LED, estado_led);
}
}
}
estado_botao_anterior = leitura_atual;
}4. Modulação por Largura de Pulso (PWM) no Arduino Uno
O microcontrolador ATmega328P não possui conversores digital-analógicos (DAC) verdadeiros em seus pinos de saída. Para produzir tensões contínuas variáveis capazes de regular o brilho de lâmpadas ou a velocidade de motores, emprega-se a Modulação por Largura de Pulso (PWM - Pulse Width Modulation).
A função padrão da API do Arduino é:
Onde valor é um número inteiro de 8 bits variando de (saída permanentemente em , de Duty Cycle) até (saída permanentemente em , de Duty Cycle).
4.1 Cálculo da Tensão Média Contínua ()
A tensão média equivalente aplicada à carga corresponde à área sob a curva do pulso retangular dividida pelo período total :
Para uma carga com constante de tempo elétrica ou mecânica muito superior ao período do sinal PWM (, como o enrolamento indutivo de um motor ou a inércia térmica de um filamento), a carga responde puramente ao valor médio .
5. Mapeamento de Pinos PWM e Frequências dos Temporizadores
Na placa Arduino Uno R3, apenas 6 pinos digitais possuem hardware conectado aos temporizadores internos para geração autônoma de PWM (indicados na serigrafia da placa pelo símbolo til ~):
| Pinos PWM Arduino | Temporizador AVR Associado | Modo de Operação PWM | Frequência de Chaveamento () | Aplicações Recomendadas |
|---|---|---|---|---|
| D5 e D6 | Timer0 (8 bits) | Fast PWM | Dimerização de LEDs (Sem flicker visível) | |
| D9 e D10 | Timer1 (16 bits) | Phase-Correct PWM | Controle de velocidade de motores CC | |
| D3 e D11 | Timer2 (8 bits) | Phase-Correct PWM | Cargas térmicas e drivers de potência |
IMPORTANT
Conflitos Críticos entre Bibliotecas e Timers:
- O Timer0 também gera a base de tempo para as funções vitais
millis(),micros()edelay(). Alterar o prescaler do Timer0 descalibrará todos os relógios de software da placa!- A biblioteca padrão de servo motores
<Servo.h>assume o controle exclusivo do Timer1. Portanto, ao invocarmeu_servo.attach(pin), o PWM nativo por hardware dos pinos D9 e D10 deixa de funcionar!- A função de geração de áudio
tone()utiliza o Timer2, desabilitando o PWM dos pinos D3 e D11.
6. Diagrama Arquitetural Consolidado
O diagrama técnico vetorial a seguir sintetiza a topologia física de entradas digitais com chave push-button e resistor de pull-up, o comparativo temporal do repique mecânico contra o filtro de software com millis() e o conjunto de formas de onda PWM com cálculo das frequências de chaveamento de e :
7. Exercícios Resolvidos e Aplicações em Concursos
Exercício 1 (Petrobras - Engenharia Eletrônica / CESGRANRIO)
Enunciado: Deseja-se controlar a potência térmica de uma resistência de aquecimento em um processo de secagem laboratorial através de um sinal PWM gerado pelo pino digital D6 de uma placa Arduino Uno. O sistema de controle proporcional calcula que o processo requer exatamente de potência ativa média entregue à carga.
- Calcule o valor inteiro de 8 bits a ser fornecido como parâmetro para a função
analogWrite(6, valor). - Determine a tensão média contínua entregue à resistência de aquecimento ().
- Calcule o período exato em microssegundos do sinal PWM gerado no pino D6 e o tempo em que o sinal permanece em nível lógico alto () durante cada ciclo.
Resolução Passo a Passo:
-
Cálculo do Parâmetro de 8 Bits: Como a resolução de 8 bits possui passos discretos de fundo de escala: O comando executado no sketch é
analogWrite(6, 173). -
Cálculo da Tensão Média Real: Com o valor inteiro : Tensão média resultante:
-
Período e Tempo em Nível Alto (): O pino D6 é controlado pelo Timer0 operando em modo Fast PWM com prescaler de 64: Período total do sinal: Tempo em nível alto ():
Exercício 2 (Marinha do Brasil - Corpo de Engenheiros)
Enunciado: Analise tecnicamente os impactos sobre a arquitetura de um sistema microcontrolado em tempo real ao substituir o controle temporal baseado na função delay() por uma máquina de estados finitos estruturada com a função millis(). Demonstre por que a função millis() não sofre descalibração ou deriva quando executada concorrentemente com outras tarefas no laço loop().
Resolução Técnica Estruturada:
- Impactos da Substituição de
delay()pormillis():- Eliminação do Bloqueio da CPU (Non-Blocking Execution): A função
delay(N)força o microcontrolador a rodar em um loop estéril de contagem de ciclos por milissegundos, impedindo a amostragem de qualquer outro pino de entrada, recepção de comandos de parada de emergência ou atualização de displays; - Viabilização de Pseudo-Multitarefa Cooperativa: Com
millis(), o processador compara a marca temporal atual com marcas armazenadas em variáveis estáticas (if (millis() - t_ant >= delta_t)). Se o tempo ainda não venceu, a UCP salta a rotina em fração de microssegundo e executa imediatamente outras dezenas de rotinas no mesmo ciclo doloop(), atingindo operação paralela virtual.
- Eliminação do Bloqueio da CPU (Non-Blocking Execution): A função
- Imunidade a Deriva (Drift) e Independência de Software:
- A contagem de
millis()não depende do tempo de execução do código de software: ela é incrementada por uma Rotina de Serviço de Interrupção de Hardware do Timer0 (TIMER0_OVF_vect) disparada a cada estouro do temporizador (a cada ); - O hardware do Timer0 conta pulsos de cristal de quartzo independentemente de o software estar ocupado com cálculos matemáticos complexos ou ocioso;
- Um algoritmo de correção fracionária embutido na ISR do núcleo Arduino compensa o desvio residual de adicionando periodicamente uma unidade à variável global contadora de milissegundos, mantendo a precisão temporal idêntica à precisão física do cristal de quartzo piezoelétrico.
- A contagem de