Aula 01 - Plataforma Arduino, Arquitetura do Hardware e Primeiros Códigos


1. O Ecossistema Arduino e a Computação Física

A plataforma Arduino surgiu em 2005 no Interaction Design Institute Ivrea (Itália) como um projeto de hardware e software livres (Open-Source Hardware/Software) concebido para democratizar o acesso à computação física e ao controle embarcado.

Embora amplamente reconhecida como uma ferramenta de prototipagem rápida, a arquitetura do Arduino Uno R3 baseia-se em um microcontrolador industrial padrão — o Atmel AVR ATmega328P — e obedece aos mais rigorosos conceitos da engenharia eletrônica: barramentos de alimentação com proteção contra sobrecorrente, conversores de nível lógico, temporização a cristal piezoelétrico e gravação em memória não-volátil sem necessidade de hardware de gravação proprietário dedicado.


2. Engenharia de Hardware da Placa Arduino Uno R3

2.1 Subsistema de Alimentação e Proteção Elétrica

A placa Uno R3 possui três alternativas para suprimento de energia:

  1. Alimentação via Cabo USB (): Fornecida diretamente pela porta USB do computador hospedeiro. O circuito inclui um termistor PTC rearmável (PolySwitch) que limita a corrente em , protegendo as portas USB do computador contra curtos-circuitos acidentais na protoboard;
  2. Jack P4 de Alimentação Externa (): Conector fêmea de centro positivo () que aceita fontes de corrente contínua não-reguladas de (limites extremos: ). Um diodo Schottky em série protege contra inversão acidental de polaridade;
  3. Regulador Linear LDO (Low Dropout): O circuito integrado NCP1117ST50 reduz a tensão de entrada para regulados para alimentar o microcontrolador. Uma segunda linha linear fornece (até ) para alimentar sensores modernos de baixa tensão;
  4. Circuito de Comutação Automática de Fonte: Um comparador operacional (LM358) monitora a tensão : se (isto é, ), um MOSFET canal P corta a alimentação da porta USB, priorizando a fonte externa e evitando correntes reversas danosas ao computador.

2.2 O Conversor USB-Serial e o Auto-Reset

Em placas Arduino genuínas e clones de primeira linha, a interface USB não é um conversor dedicado estático (como o antigo FT232RL ou o econômico CH340G), mas sim um segundo microcontrolador RISC completo — o ATmega16U2 — programado com firmware USB CDC (Communications Device Class):

  • O ATmega16U2 traduz pacotes virtuais USB em pulsos seriais UART nos pinos D0 (RX) e D1 (TX);
  • O Sinal DTR de Auto-Reset: Na linha DTR (Data Terminal Ready), há um capacitor cerâmico em série de conectado ao pino RESET do ATmega328P. Quando a IDE do Arduino abre a porta serial para efetuar o upload do código, a descida de DTR gera um pulso negativo que reseta o ATmega328P no instante exato, iniciando o Bootloader sem necessidade de intervenção física humana no botão de reset.

3. O Microcontrolador ATmega328P e o Papel do Bootloader

O coração operacional da placa é o microcontrolador Atmel ATmega328P em encapsulamento DIP de 28 pinos:

  • Arquitetura Harvard RISC avançada com 131 instruções de máquina;
  • Frequência de operação fixada em por um cristal oscilador de quartzo externo acoplado a dois capacitores cerâmicos de carga de ;
  • Ciclo de Máquina: Diferentemente do PIC que divide o clock por 4, a arquitetura AVR executa a maioria das instruções em um único ciclo de clock puro ():

3.1 Mecanismo de Auto-Programação (Self-Programming)

Tradicionalmente, microcontroladores exigiam programadores externos (como USBasp, PICkit ou JTAG) que aplicavam protocolos seriais síncronos nos pinos SPI com o chip em reset.

O Bootloader Optiboot (instalado de fábrica no topo da Flash, endereços a ):

  1. É executado imediatamente após qualquer evento de Reset;
  2. Pisca rapidamente o LED do pino D13 e escuta a porta serial a por cerca de ;
  3. Se receber o caractere de sincronismo do protocolo STK500 vindo da IDE, entra em modo de gravação: recebe os blocos binários compilados via UART e utiliza a instrução de hardware SPM (Store Program Memory) para reescrever as páginas da Flash;
  4. Se nenhum dado for recebido no timeout, o Optiboot salta para o endereço e executa imediatamente o código do usuário residente na memória.

4. Estrutura Canônica do Código e Compilação em C++

Diferentemente de programas C clássicos para desktop que possuem uma função main() linear que retorna zero ao término da execução, o framework Arduino converte o sketch (.ino) internamente em um código fonte padrão que roda em um laço perpétuo (bare-metal superloop):

// Arquivo interno da biblioteca Arduino Core (main.cpp):
#include <Arduino.h>
 
int main(void) {
    init();          // Inicializa temporizadores internos Timer0 para millis() e ADC
    initVariant();
    
    setup();         // Executa a função de inicialização do usuário (1 única vez)
    
    for (;;) {
        loop();      // Executa iterativamente em loop infinito
        if (serialEventRun) serialEventRun();
    }
    return 0;
}

4.1 A Função setup()

Executada exatamente uma vez quando a placa é ligada ou resetada. Destina-se à configuração estática de hardware:

  • Definição da direção de pinos GPIO (pinMode);
  • Inicialização de barramentos de comunicação (Serial.begin, Wire.begin, SPI.begin);
  • Configuração de timers, interrupções externas e calibração de sensores.

4.2 A Função loop()

Executada ciclicamente em repetição infinita enquanto a placa estiver energizada. Contém a lógica de controle principal:

  • Leitura de sensores analógicos e digitais;
  • Processamento algorítmico e máquinas de estados;
  • Atualização das saídas de controle (relés, PWM de motores, displays).

5. Abstração de Alto Nível vs. Acesso Direto a Registradores

A biblioteca padrão do Arduino fornece funções de alto nível que priorizam a portabilidade e facilidade de aprendizado, mas que introduzem sobrecarga de processamento (overhead) devido a pesquisas em tabelas e verificações de segurança:

5.1 O Registrador PINx como Alternador de Hardware (Hardware Toggle)

Uma característica singular da arquitetura Atmel AVR é que escrever o bit lógico no registrador de leitura PINx faz com que o hardware inverta instantaneamente (toggle) o estado do pino correspondente no registrador de saída PORTx em um único ciclo de máquina ():


6. Diagrama Arquitetural Consolidado

O diagrama técnico vetorial a seguir ilustra a topologia física da placa Arduino Uno R3, destacando os subsistemas de regulação de alimentação, o conversor serial ATmega16U2, a pinagem do microcontrolador ATmega328P e a comparação com os registradores nativos DDRB/PORTB:

Arquitetura Arduino Uno R3 e ATmega328P


7. Exercícios Resolvidos e Aplicações em Concursos

Exercício 1 (Petrobras - Engenharia Eletrônica / CESGRANRIO)

Enunciado: Deseja-se conectar um LED vermelho de sinalização industrial ao pino digital D13 de uma placa Arduino Uno R3 operando com . Os parâmetros ópticos do LED fornecidos pelo catálogo são: queda de tensão direta sob corrente nominal direta .

  1. Calcule o valor exato do resistor limitador de corrente a ser colocado em série com o LED.
  2. Selecione o valor comercial normalizado na série E24 imediatamente superior para operar de forma conservadora e calcule a corrente real de trabalho resultante.
  3. Determine a dissipação de potência nominal no resistor limitador e no pino de saída do microcontrolador.

Resolução Passo a Passo:

  1. Cálculo do Resistor Limitador Teórico: Aplicando a Lei de Ohm na malha fechada do pino de saída:

  2. Seleção Comercial e Corrente Real: Na série comercial normalizada E24 (), os valores próximos são . Adotando o valor comercial padrão superior de : Como (limite seguro do pino GPIO do ATmega328P), o circuito opera com excelente brilho e durabilidade térmica infinita.

  3. Dissipação de Potência:

    • No resistor limitador de : Um resistor convencional de filme de carbono de () opera com ampla folga.
    • Potência fornecida pelo pino D13 do microcontrolador:


Exercício 2 (Marinha do Brasil - Corpo de Engenheiros)

Enunciado: Um engenheiro de controle necessita gerar uma onda quadrada com frequência de exatamente em um pino digital de uma placa Arduino Uno R3 operando com clock de .

  1. Demonstre formalmente por que é matematicamente impossível gerar essa frequência utilizando a função padrão digitalWrite(pin, val).
  2. Escreva o trecho de código em linguagem C/C++ utilizando manipulação direta de registradores nativos do ATmega328P para sintetizar a onda de com duty cycle simétrico de .

Resolução Técnica Analítica:

  1. Limitação da Função digitalWrite:

    • Para sintetizar uma onda quadrada de , o período total deve ser:
    • Cada semiperíodo (tempo em nível alto e tempo em nível baixo) deve durar rigorosamente:
    • Em um clock de (), correspondem a:
    • A função digitalWrite() consome internamente cerca de de clock () para decodificar tabelas de portas e desabilitar PWMs. Duas chamadas consecutivas consom mais de (), limitando a frequência máxima de chaveamento em cerca de . Logo, atingir via digitalWrite() é fisicamente impossível!
  2. Código Otimizado em Registradores Nativos: Para consumir exatamente 8 ciclos por semiperíodo:

    • 1 ciclo para inverter o pino via registrador PINB;
    • 7 ciclos de atraso gerados por instruções de máquina NOP (No Operation - 1 ciclo cada) ou loops calibrados:
void setup() {
    DDRB |= (1 << 5);      // Configura pino D13 (PB5) como saída digital (1 ciclo)
}
 
void loop() {
    while (1) {
        PINB = (1 << 5);   // Inverte o estado de D13 (1 ciclo de máquina)
        __asm__ __volatile__ (
            "nop\n\t"      // 1 ciclo
            "nop\n\t"      // 1 ciclo
            "nop\n\t"      // 1 ciclo
            "nop\n\t"      // 1 ciclo
            "nop\n\t"      // 1 ciclo
        );                 // Salto incondicional do loop consome 2 ciclos (Total = 1 + 5 + 2 = 8 ciclos!)
    }
}

Com em nível alto e em nível baixo: A onda de é gerada com precisão de cristal de quartzo!