UC00670 · Programação de microcontroladores
Aulify · Componente Tecnológica

Efetuar a programação de microcontroladores

Arduino, registos, GPIO, sensores, atuadores, interrupções e depuração
UC00670 · 50 horas · 4,5 pontos Nível 4 · TSCR · Ano 3
Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Resultados de aprendizagem

  1. Escrever o código de programação de um microcontrolador.
  2. Interligar botões, sensores, motores e relés.
  3. Ensaiar e depurar o programa e o circuito.
Liga o software ao mundo físico: ler temperatura, acender luzes, mover motores. A base do IoT e da automação.
Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Plano

  1. O microcontrolador e a sua arquitetura
  2. Instruções, ambiente de desenvolvimento e fluxogramas
  3. Estrutura do programa: tipos, variáveis, funções
  4. Entradas e saídas digitais, ADC e PWM
  5. Sensores e atuadores
  6. Interrupções, temporização e protocolos
  7. Depuração e projeto integrado
Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores
Bloco 1 · O microcontrolador

Um computador num chip

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Microcontrolador contra microprocessador

Microcontrolador (µC) Microprocessador (µP)
CPU, RAM, Flash e I/O num chip Só CPU; o resto é externo
Tarefa dedicada Uso geral (PC)
Baixo consumo e custo Alto desempenho
Corre firmware Corre sistema operativo
Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Plataformas e como escolher

Plataforma Núcleo Lógica
Arduino UNO (ATmega328P) AVR 8 bits, 16 MHz 5 V
ESP32 32 bits, Wi-Fi e Bluetooth 3,3 V
STM32 ARM Cortex-M 3,3 V
Raspberry Pi Pico (RP2040) 2 núcleos Cortex-M0+ 3,3 V

Escolher por: pinos, comunicação, tensão, memória, consumo, custo.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Especificar antes de programar

Três partes: entradas, saídas, regras com números.

Exemplo, rega automática:

  • Entrada: humidade do solo (A0).
  • Saída: relé da bomba (pino 7), LED de estado.
  • Regra: abaixo de 30 % liga a bomba 10 s; no máximo 1 vez por hora; leitura fora da gama desliga e sinaliza erro.

"Regar quando estiver seco" não se programa. "Abaixo de 30 %" já se programa e testa.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Diagrama de blocos do ATmega328P

 Flash (32 KB) --> CPU: contador de programa
                   32 registos R0..R31 <--> ALU
 SRAM (2 KB)  <--> SREG (flags)
 EEPROM (1 KB)         |
                barramento de 8 bits
 Portas B,C,D | Timers 0,1,2 | ADC | UART | I2C | SPI
  • Arquitetura Harvard: programa e dados em barramentos separados.
  • Periféricos configuram-se por registos.
Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

ALU e registo de estado

A ALU soma, subtrai e faz lógica sobre registos de 8 bits. O SREG guarda as flags: C, Z, N, V, S, H, T, I.

Exemplo · 200 + 100 em 8 bits

  • 1100 1000 + 0110 0100 = 1 0010 1100
  • O registo guarda 0010 1100 = 44; o nono bit vai para C = 1.

Num uint8_t o resultado em C também é 44.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

As três memórias

Memória Tamanho Volátil Guarda
Flash 32 KB Não Programa
SRAM 2 KB Sim Variáveis e pilha
EEPROM 1 KB Não Calibrações, contadores
  • EEPROM: cerca de 100 000 escritas por célula (folha de características).
  • Pilha cresce para baixo, heap para cima; se se cruzam, comportamento imprevisível.
Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Pinagem do Arduino UNO

Pino Função
D0, D1 UART (RX, TX), partilhados com a USB
D2, D3 Interrupções INT0, INT1
D3, 5, 6, 9, 10, 11 PWM
D10 a D13 SPI (SS, MOSI, MISO, SCK)
A4, A5 I²C (SDA, SCL)
D13 LED da placa

Portas: D0 a D7 = D, D8 a D13 = B, A0 a A5 = C.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Limites elétricos

  • Funcionamento a 5 V; nível alto a partir de cerca de 0,6 × Vcc, baixo até cerca de 0,3 × Vcc.
  • Corrente por pino: recomendada ~20 mA, máximo absoluto 40 mA.
  • Há também um limite para a corrente total do chip.
3,3 V não tolera 5 V. ESP32 e outras: usar divisor (1 kΩ + 2 kΩ dá 5 × 2/3 ≈ 3,3 V) ou conversor de níveis.
Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores
Bloco 2 · Instruções e ambiente

Do código ao chip

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Do C ao código máquina

C/C++ (sketch) -> avr-gcc -> código máquina (.hex) -> Flash
assembly       -> assembler -> código máquina

Instruções AVR (RISC, ~130):

  • Transferência: LDI, MOV, LD, ST, IN, OUT
  • Aritméticas: ADD, SUB, INC, DEC
  • Lógicas: AND, OR, EOR
  • Bits: SBI, CBI
  • Salto: CP, BRNE, RJMP, RET
Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Modos de endereçamento

Modo Exemplo
Registo direto MOV R16, R17
Imediato LDI R16, 0x05
Direto à memória LDS R16, 0x0100
Indireto LD R16, X
Pós-incremento LD R16, X+
Com deslocamento LDD R16, Y+5
Memória de programa LPM R16, Z
Relativo RJMP etiqueta
Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Registos DDR, PORT e PIN

Registo Função
DDRx Direção: 1 saída, 0 entrada
PORTx Nível de saída (ou pull-up se entrada)
PINx Leitura do pino
void setup() {
  DDRB  |= (1 << DDB5);    // pino 13 como saída
  PORTB |= (1 << PORTB5);  // HIGH
}
void loop() {
  PORTB ^= (1 << PORTB5);  // inverte
  delay(500);
}
Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Operações bit a bit

Objetivo Expressão
Pôr a 1 reg |= (1 << n)
Pôr a 0 reg &= ~(1 << n)
Inverter reg ^= (1 << n)
Testar reg & (1 << n)

Exemplo · bits 2 e 5 a 1 com PORTB = 0100 0001:

  • máscara 0010 0100
  • 0100 0001 OU 0010 0100 = 0110 0101 (0x65)

0b1011 0100 = 0xB4 = 180.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Ambientes de desenvolvimento (IDE)

Ferramenta Características
Arduino IDE 2 Oficial, simples, monitor série
PlatformIO (VS Code) Profissional, Git, depuração, platformio.ini
Wokwi, Tinkercad Simuladores, sem hardware

A linguagem: C/C++ para Arduino; MicroPython em RP2040 e ESP32 (mais fácil, mais pesado).

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Configurar a plataforma

  1. Instalar o IDE e, se necessário, o suporte da placa.
  2. Ligar a placa por USB (driver CH340 nos clones).
  3. Escolher placa e porta.
  4. Testar com Blink.
  5. Abrir o Monitor Série com o mesmo baud rate.
Regista as versões do IDE, da placa e das bibliotecas. No PlatformIO ficam no platformio.ini.
Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Instalar bibliotecas

Formas de instalar:

  1. Gestor de Bibliotecas (recomendado).
  2. Ficheiro .zip.
  3. lib_deps no PlatformIO.
#include <Servo.h>
Servo braco;

Incluídas com o IDE: Servo, Wire, SPI, EEPROM, LiquidCrystal, Stepper.

Uma biblioteca para AVR pode não funcionar em ESP32. Ler as placas suportadas.
Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores
Bloco 3 · O programa

Fluxogramas, tipos e funções

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Fluxogramas: simbologia

Símbolo Forma Uso
Terminal Oval Início e fim
Processo Retângulo Ação
Decisão Losango Sim ou não
Entrada/saída Paralelogramo Ler, mostrar
Subrotina Retângulo com barras Chamar função
Conector Círculo Continuação

Norma: ISO 5807.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Fluxograma · termóstato com histerese

( Início ) -> [ Configurar pinos e Serial ]
   +-> [ Ler t ]
   |     < t > 26 ? > Sim -> [ Ligar ventoinha ]
   |         Não
   |     < t < 24 ? > Sim -> [ Desligar ventoinha ]
   |         Não
   |   [ Mostrar t ] -> [ Esperar 2 s sem bloquear ] --+
   +--------------------------------------------------+

Entre 24 e 26 o estado mantém-se: é a histerese.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Anatomia de um sketch

#include <Servo.h>            // bibliotecas
const int PINO_LED = 13;      // constantes e globais

void setup() {                // UMA vez
  pinMode(PINO_LED, OUTPUT);
}
void loop() {                 // para sempre
  piscar(3);
  delay(2000);
}
void piscar(int vezes) { /* ... */ }

Comentar o porquê, não o óbvio.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Tipos de dados (AVR)

Tipo Bytes Gama
bool 1 true ou false
byte / uint8_t 1 0 a 255
int 2 -32 768 a 32 767
unsigned int 2 0 a 65 535
long 4 cerca de ±2,1 mil milhões
unsigned long 4 0 a 4 294 967 295
float 4 ~7 algarismos

Noutras placas int tem 4 bytes: usar uint8_t, int16_t, uint32_t.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Exemplo · overflow de um int

T (°C) = leitura × 500 / 1024 (LM35, 5 V, ADC 10 bits; graus inteiros)

int leitura = 66;
int graus = leitura * 500 / 1024;          // ERRADO
long graus2 = (long)leitura * 500 / 1024;  // certo
  • 66 × 500 = 33 000 passa 32 767 e dá a volta: -32 536.
  • -32 536 / 1024 = -31.
  • Certo: 33 000 / 1024 = 32.

Converter o operando, não o resultado.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Variáveis e operadores

Tipo Vive
Global Todo o programa
Local Só na função
static local Mantém o valor entre chamadas
volatile Pode mudar numa interrupção

Operadores: + - * / %, == != < > <= >=, && \|\| !, & \| ^ ~ << >>.

if (x = 5) atribui 5: a condição é sempre verdadeira. Usar ==.
Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Funções e modularidade

float lerTemperatura() {
  int leitura = analogRead(A0);
  float tensao = leitura * 5.0 / 1024.0;
  return tensao * 100.0;           // LM35
}
void aplicarControlo(float t) {
  digitalWrite(LED_ALERTA, t > 30.0 ? HIGH : LOW);   // LED de aviso
}

Uma função, uma responsabilidade. O loop() só orquestra.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores
Bloco 4 · Entradas e saídas

Digital, analógico e PWM

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Saída digital e LED

pinMode(9, OUTPUT);
digitalWrite(9, HIGH);   // 5 V
digitalWrite(9, LOW);    // 0 V

R = (Vcc - Vf) / I

Exemplo · LED vermelho: Vf ≈ 2,0 V, I = 15 mA.

  • R = 3 / 0,015 = 200 Ω, normalizado 220 Ω
  • I real = 3 / 220 = 13,6 mA
  • P = 220 × 0,0136² = 0,041 W
Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Entrada digital: pull-up

Configuração Repouso Premido
Pull-up (botão a GND) HIGH LOW
Pull-down (botão a Vcc) LOW HIGH
pinMode(2, INPUT_PULLUP);
bool premido = (digitalRead(2) == LOW);

Pino sem nada ligado flutua e lê ruído.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Ressalto (debounce)

Contactos mecânicos saltam durante alguns ms: o µC lê vários toques.

// bloqueante (só em exemplos)
if (digitalRead(BTN) == LOW) {
  delay(20);
  if (digitalRead(BTN) == LOW) { /* válido */ }
}

Melhor: versão com millis(), que só aceita a mudança depois de 30 ms estáveis. Ou filtro RC em hardware.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Exemplo · botão que liga e desliga

bool ledLigado = false;
int anterior = HIGH;

void loop() {
  int atual = digitalRead(BTN);
  if (anterior == HIGH && atual == LOW) {  // flanco
    ledLigado = !ledLigado;
    digitalWrite(LED, ledLigado);
    delay(30);
  }
  anterior = atual;
}

Reage à mudança, não ao nível. Sem anterior, o LED piscaria enquanto o dedo estivesse no botão.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

O conversor ADC

10 bits: 1024 níveis (0 a 1023) entre 0 V e Vref.

tensão = leitura × Vref / 1024

Referência Valor
DEFAULT 5 V
INTERNAL 1,1 V (típico; 1,0 a 1,2 V na folha de características)
EXTERNAL tensão em AREF

Resolução com 5 V: 4,88 mV. Com 1,1 V: 1,07 mV.

Conversão: cerca de 104 µs (~9600 leituras/s).

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Exemplo · LM35 e resolução

LM35: 10 mV/°C. A 25 °C, 250 mV.

Vref mV por nível °C por nível leitura a 25 °C
5 V 4,88 0,49 51
1,1 V 1,07 0,107 232

analogReference(INTERNAL); dá cerca de 4,5 vezes mais resolução, mas só mede até 1,1 V (110 °C no cálculo; confirmar a gama da variante do LM35 usada). Valores nominais: a referência real mede-se e calibra-se.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

PWM: saída pseudo-analógica

O pino liga e desliga depressa; a fração ligada é o duty cycle.

analogWrite(pino, valor), valor 0 a 255, duty = valor / 255.

  • Pinos PWM: 3, 5, 6, 9, 10, 11.
  • ~490 Hz (3, 9, 10, 11) e ~980 Hz (5, 6).
  • Duty 25 % dá 1,25 V médios; 50 %, 2,5 V; 75 %, 3,75 V.
  • Servo usa o Timer1 e inutiliza o PWM em 9 e 10.
Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores
Bloco 5 · Sensores e atuadores

Ler e agir no mundo

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Divisor de tensão e LDR

Vcc -- [ LDR ] --+-- A0
                 |
              [10 kΩ]
                 |
                GND

Vout = Vcc × Rfixa / (Rfixa + Rsensor)

Condição R LDR Vout leitura
Muita luz 1 kΩ 4,55 V ~931
Normal 10 kΩ 2,50 V 512
Escuro 100 kΩ 0,45 V ~93
Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Exemplo · NTC de 10 kΩ

NTC (B = 3950) a Vcc, 10 kΩ a GND. Leitura 754.

  1. R = 10 000 × (1024/754 - 1) = 3580 Ω
  2. 1/T = 1/298,15 + ln(3580/10000)/3950
  3. ln(0,358) = -1,0275 → 1/T = 0,003094 → T = 323,2 K
  4. 50,0 °C

Valores R0 e B vêm da folha de características do NTC.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

HC-SR04: distância por eco

Pulso de 10 µs no TRIG; o ECHO fica HIGH durante a ida e volta.

distância = tempo × 0,0343 / 2 (cm, µs)

Exemplo: 5830 µs → 5830 × 0,0343 = 199,97 → 100 cm.

unsigned long d = pulseIn(ECHO, HIGH, 30000UL);
if (d == 0) return -1.0;     // sem eco
return d * 0.0343 / 2.0;
Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Outros sensores e calibração

  • PIR: HIGH ao detetar; tempo de estabilização depois de ligar.
  • Fim de curso: pull-up e debounce.
  • MQ-x: aquecimento e calibração; não é detetor certificado.
  • Humidade do solo: calibrar com dois pontos.

Calibrar: dois pontos de referência → map → constrain → comparar com um instrumento fiável.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Atuadores: o pino comanda, não alimenta

Pino: ~20 mA. Ordens de grandeza das cargas:

  • LED com resistência: 10 a 20 mA, ligação direta
  • Relé (bobina): dezenas de mA, transístor ou módulo
  • Motor DC pequeno: centenas de mA, transístor ou ponte H
  • Motor de passo: driver dedicado
  • Fitas de LED, bombas: amperes, MOSFET ou relé

Fonte própria e massa comum.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Exemplo · transístor para um relé

Bobina 70 mA, Vpino 5 V, Vbe ≈ 0,7 V.

Ganho mínimo hFE: o da folha de características do transístor (aqui assumimos 100).

  1. Ganho forçado 10: Ib = 70 / 10 = 7 mA
  2. Rb = (5 - 0,7) / 0,007 = 614 Ω
  3. Normalizado 560 Ω: Ib = 4,3 / 560 = 7,7 mA (menos de 20 mA)
+V -- [CARGA] -- C
pino -- [Rb] -- B  NPN
                E -- GND (comum)
Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Cargas indutivas e alimentação

Motores e relés geram picos ao cortar a corrente.

  • Díodo de roda livre em antiparalelo (1N4007 ou 1N4148).
  • Fonte dimensionada para a corrente de arranque.
  • GND comum entre Arduino e fonte.
  • Não alimentar motores a partir da USB.
  • Condensador junto à carga contra quedas e reinícios.
230 V só com circuito sem tensão, módulos adequados e habilitação. Nas aulas, carga de baixa tensão.
Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Servomotor

PWM de 50 Hz (período 20 ms); a largura do impulso é a posição (~1 a 2 ms).

#include <Servo.h>
Servo s;
void setup() { s.attach(9); }
void loop() {
  s.write(0);   delay(1000);
  s.write(180); delay(1000);
}

Por omissão 0° = 544 µs e 180° = 2400 µs; 90° = 1472 µs. Fonte própria, massa comum.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Motor DC e ponte H

IN1 IN2 Motor
LOW LOW Parado
HIGH LOW Sentido 1
LOW HIGH Sentido 2
void motor(int v) {            // -255 a 255
  digitalWrite(IN1, v > 0);
  digitalWrite(IN2, v < 0);
  analogWrite(ENA, abs(v));
}

motor(150) ≈ 59 % de duty. Parar antes de inverter.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Motor de passo

1,8° por passo → 360 / 1,8 = 200 passos por volta.

Driver (A4988): STEP e DIR; micropasso 1/16 = 3200 passos/volta.

Exemplo · 60 rpm:

  • 1 volta/s = 200 passos/s
  • intervalo = 1/200 = 5 ms
  • com 1/16: 3200 passos/s → ~312 µs
A4988: alimentação própria para o motor, limite de corrente regulado e massa comum. Nunca ligar nem desligar o motor com o driver alimentado. Só baixa tensão.
Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores
Bloco 6 · Interrupções e comunicação

Reagir a tempo

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Sondagem contra interrupção

  • Polling: o programa pergunta a cada volta. Se o loop() é lento, o evento perde-se.
  • Interrupção: o hardware pára a CPU, corre a ISR e retoma.
loop() ... ----[evento]----> ISR() ----> volta ao mesmo ponto

UNO: pinos 2 (INT0) e 3 (INT1). Modos: LOW, CHANGE, RISING, FALLING.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Escrever uma ISR

volatile unsigned int toques = 0;
void contar() { toques++; }

void setup() {
  pinMode(2, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(2), contar, FALLING);
}
void loop() {
  noInterrupts();
  unsigned int copia = toques;   // leitura atómica
  interrupts();
}

Regras: ISR curta; sem delay() (o millis() não avança lá dentro); variáveis partilhadas volatile; debounce comparando millis() com o último evento.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

millis() em vez de delay()

const unsigned long INTERVALO = 1000;
unsigned long ultimo = 0;

void loop() {
  unsigned long agora = millis();
  if (agora - ultimo >= INTERVALO) {
    ultimo = agora;
    // tarefa periódica
  }
}

millis() volta a zero ao fim de 49,7 dias (2³² ms). A subtração funciona na mesma: 200 - 4 294 967 000 = 496 ms.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Temporizadores e modo CTC

Timer0 (8 bits), Timer1 (16 bits), Timer2 (8 bits). Prescaler 1, 8, 64, 256, 1024 no Timer0 e no Timer1; o Timer2 tem ainda 32 e 128.

O Timer0 dá o millis(): 16 MHz / 64 / 256 → overflow a cada 1,024 ms.

OCR1A = f_clk / (prescaler × f) - 1

Exemplo · 1 Hz, prescaler 256: 16 000 000 / 256 = 62 500; OCR1A = 62 499.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

UART e Monitor Série

Assíncrona, TX e RX, velocidade combinada. Trama 8N1 = 10 bits por byte.

Exemplo · 9600 baud: Valor: 1023\r\n = 13 bytes → 130 bits → 130/9600 = 13,5 ms.

Serial.begin(9600);
if (Serial.available() > 0) { char c = Serial.read(); }

Velocidade diferente no Monitor = carateres estranhos.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

I²C

Dois fios: SDA (A4) e SCL (A5), pull-ups, mestre e vários escravos de 7 bits.

Dispositivo Endereço comum
LCD com PCF8574 0x27 ou 0x3F
DS3231 0x68
BME280 0x76 ou 0x77
Wire.beginTransmission(addr);
if (Wire.endTransmission() == 0) { /* presente */ }
Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

SPI, 1-Wire e comparação

Protocolo Fios Velocidade Uso
UART 2 Média Depuração, GPS
I²C 2 Média Sensores, ecrãs, RTC
SPI 4 + CS Alta SD, TFT, rádio
1-Wire 1 Baixa DS18B20

SPI no UNO: MOSI 11, MISO 12, SCK 13, SS 10.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Wi-Fi e Internet das Coisas

[sensor] -> [ESP32] --Wi-Fi--> [broker MQTT] -> [painel]
  • HTTP: pedido e resposta.
  • MQTT: publicar e subscrever por tópicos; leve.

Cuidados: sem palavras-passe no código partilhado, ligação cifrada quando possível, firmware atualizado, não expor sem necessidade.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores
Bloco 7 · Depuração e projeto

Ensaiar, depurar, integrar

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Três tipos de erro

Tipo Quando Exemplo
Sintático Ao compilar Falta de ;
Lógico Corre mal = em vez de ==
De execução Corre, mas falha depois Overflow, SRAM, delay

A linha reportada pelo compilador pode estar depois do erro real.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Depurar com o Monitor Série

  1. Imprimir valores brutos (ADC, estado do pino).
  2. Marcas de fluxo: "entrei em X".
  3. Serial Plotter para ver o sinal ao longo do tempo.
  4. Etiquetar: Serial.print("T="); Serial.println(t);
  5. Remover as mensagens no fim (ocupam tempo e SRAM).

Num simulador (Wokwi, Tinkercad) vê-se o estado dos pinos sem risco.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Depuradores e breakpoints

Um depurador controla a execução no próprio µC:

  • Pontos de pausa (breakpoints)
  • Passo a passo: step over, step into, step out
  • Watch de variáveis, pilha de chamadas, registos

Depurador de hardware: SWD ou JTAG nos ARM (ST-LINK no STM32); debugWIRE ou JTAG em alguns AVR (UNO precisa de sonda externa).

O Arduino IDE 2 e o PlatformIO integram-no nas placas que o suportam.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Depurar o circuito

Sintoma Verificar
Nada acontece Alimentação, cabo de dados, placa e porta
Botão lê sempre o mesmo Pull-up, GND, pino
ADC sempre 0 ou 1023 Pino, divisor, massa comum
Leitura a tremer Fios longos, alimentação
Placa reinicia com o motor Fonte própria, díodo, massa comum

Método: um periférico de cada vez, mudar uma coisa por vez.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Plano de ensaios

N.º Condição Esperado
1 20 °C Relé desligado
2 Sobe a 27 °C Relé liga
3 Desce a 25 °C Relé continua ligado
4 Desce a 23 °C Relé desliga
5 Sensor desligado Relé desliga e sinaliza erro

Os casos de fronteira são os que mais revelam erros.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Padrão ler, decidir, atuar

SENSOR -> DECISÃO (programa) -> ATUADOR
   ^                                |
   +----------- mundo físico <------+

Histerese em código:

const int RELE = 7;
const int RELE_ATIVO = LOW;   // módulo ativo a LOW; se for a HIGH, trocar

if (!ventoinha && t > LIGA)    ventoinha = true;
if (ventoinha  && t < DESLIGA) ventoinha = false;
digitalWrite(RELE, ventoinha ? RELE_ATIVO : !RELE_ATIVO);
Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Máquina de estados: alarme

            botão               PIR deteta
DESARMADO --------> ARMADO --------------> DISPARADO
    ^                 ^                        |
    +-----------------+---- botão -------------+
enum Estado { DESARMADO, ARMADO, DISPARADO };
switch (estado) {
  case DESARMADO: /* ... */ break;
  case ARMADO:    /* ... */ break;
  case DISPARADO: tone(BUZZER, 1000); break;
}
Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

EEPROM e organização do projeto

#include <EEPROM.h>
EEPROM.get(0, limiar);
if (limiar < 0 || limiar > 1023) {
  limiar = 512;
  EEPROM.put(0, limiar);
}

update e put só escrevem se o valor mudou.

Projeto: cabeçalho, constantes, funções pequenas, loop() curto, F("..."), esquema atualizado, registo de ensaios, Git.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Erros comuns

  • Entrada a flutuar; esquecer a lógica invertida.
  • = em vez de ==.
  • Divisão inteira e overflow de int.
  • Motor ou relé direto no pino; sem díodo de roda livre.
  • delay() longo.
  • ISR demorada ou sem volatile.
  • Baud rate diferente; placa e porta erradas.
  • 5 V num pino de 3,3 V.
  • Sensor sem calibração.
  • Escrever na EEPROM a cada volta.
Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores

Síntese

  • µC = CPU + Flash + SRAM + EEPROM + periféricos.
  • Especificar, desenhar o fluxograma, depois programar.
  • Cuidado com tipos: overflow e divisão inteira.
  • Pull-up, debounce, ADC (V = L × Vref / 1024), PWM.
  • Potência: transístor, driver ou relé, fonte própria, GND comum, flyback.
  • millis(), interrupções e timers.
  • UART, I²C, SPI, Wi-Fi.
  • Depurar: Serial, simulador, multímetro, depurador.
  • Ler, decidir, atuar, com plano de ensaios.
Aulify · Componente Tecnológica · Cursos Profissionais
UC00670 · Programação de microcontroladores
Aulify · UC00670 · Fim

Software a mexer no mundo real.

geral@aulify.pt
Aulify · Componente Tecnológica · Cursos Profissionais

NOTAS DO PROFESSOR - Os três verbos são as três realizações do referencial: escrever, interligar, depurar. - Pergunta: onde há microcontroladores em casa? Máquina de lavar, comando da garagem, contador. - Analogia: o microcontrolador é um computador sem ecrã que vive dentro das coisas.

NOTAS DO PROFESSOR - O µC é um sistema completo; o µP precisa de companhia. - Erro comum: dizer que o Arduino é um microcontrolador. O Arduino é a placa; o ATmega328P é o µC. - Analogia: o µC é uma cozinha pequena pronta a usar; o µP é só o fogão.

NOTAS DO PROFESSOR - A escolha parte dos requisitos, não da moda. - Pergunta: que placa para uma sonda de solo com Wi-Fi e bateria? ESP32. - Exemplo: painel com 40 LED e 12 botões precisa de 52 pinos; o UNO não chega, o Mega sim.

NOTAS DO PROFESSOR - Uma regra sem número não é testável. - Pergunta à turma: que regra falta? O que acontece se o sensor se desligar? - Exemplo: o termóstato com dois limiares (26 e 24 graus) em vez de um.

NOTAS DO PROFESSOR - Os periféricos trabalham em paralelo com a CPU. - Erro comum: achar que o programa corre na SRAM. Corre da Flash. - Analogia: a CPU é o chefe; os periféricos são funcionários com a sua secretária (registos).

NOTAS DO PROFESSOR - O resultado guardado é 44, e a flag C avisa do excesso. - Pergunta: porque é importante escolher bem o tipo de dados? - Analogia: o conta-quilómetros que volta a zero depois do máximo.

NOTAS DO PROFESSOR - SRAM é a memória escassa. 2 KB acaba depressa com Strings. - Erro comum: escrever na EEPROM em cada volta do loop. - Exemplo: um texto com F() fica na Flash e poupa SRAM.

NOTAS DO PROFESSOR - Cada pino acumula funções; não as usar em simultâneo. - Erro comum: ligar algo aos pinos 0 e 1 e não conseguir carregar o sketch. - Exemplo: um servo usa o Timer1 e tira o PWM aos pinos 9 e 10.

NOTAS DO PROFESSOR - Os valores exatos vêm sempre da folha de características. - Pergunta: um LED com 20 mA e outro com 20 mA no mesmo chip, está tudo bem? Somar. - Exemplo: sensor de 5 V ligado a um ESP32 sem adaptação destrói o pino.

NOTAS DO PROFESSOR - O assembly serve para perceber o que o processador faz, não para programar tudo. - Pergunta: porque uma linha de C pode demorar mais do que uma instrução? - Analogia: C é a receita, assembly é cada gesto na cozinha.

NOTAS DO PROFESSOR - O modo diz onde está o operando. - Exemplo resolvido: LDI R16,5; LDI R17,3; ADD R16,R17 dá R16 = 8. - Erro comum: confundir imediato (valor na instrução) com direto (endereço na instrução).

NOTAS DO PROFESSOR - pinMode e digitalWrite escrevem estes registos por baixo. - Pergunta: o pino 13 é que bit de que porta? PB5. - Exemplo: manipulação direta é muito mais rápida do que digitalWrite.

NOTAS DO PROFESSOR - Uma máscara muda só os bits escolhidos. - Erro comum: PORTB = (1 << 5) apaga todos os outros bits. - Exemplo: limpar o bit 6 com PORTB &= ~(1 << 6) dá 0010 0101.

NOTAS DO PROFESSOR - Um IDE reúne editor, compilador, carregador e monitor. - Pergunta: quando escolher o PlatformIO? Vários projetos, Git, várias placas. - Exemplo: aula sem material, começar no Wokwi.

NOTAS DO PROFESSOR - Placa e porta erradas explicam a maioria dos casos de não carrega. - Erro comum: cabo USB só de carga, sem dados. - Exemplo: um projeto que compilava deixa de compilar com outra versão de biblioteca.

NOTAS DO PROFESSOR - Bibliotecas poupam tempo mas ocupam memória e têm versões. - Erro comum: instalar duas bibliotecas com o mesmo nome de ficheiro. - Exemplo: DHT sensor library para o DHT22.

NOTAS DO PROFESSOR - Cada decisão tem duas saídas rotuladas. - Erro comum: usar losango sem rotular Sim e Não. - Exemplo: o loop() é um ciclo infinito, não tem Fim.

NOTAS DO PROFESSOR - A histerese evita o relé a comutar dezenas de vezes por minuto. - Pergunta: o que se passa a 25 graus? Depende do estado anterior. - Exemplo: um termóstato de casa tem um intervalo de meio grau ou um grau.

NOTAS DO PROFESSOR - setup corre ao ligar ou no reset; loop repete. - Erro comum: declarar variáveis dentro de loop esperando que mantenham o valor. - Exemplo: o piscar(3) é uma função de uma só responsabilidade.

NOTAS DO PROFESSOR - O tamanho depende da arquitetura. - Pergunta: que tipo para millis()? unsigned long. - Exemplo: double no UNO tem 4 bytes, igual a float.

NOTAS DO PROFESSOR - A conversão tem de acontecer antes da multiplicação. - Erro comum: (long)(leitura * 500) converte tarde de mais. - Exemplo: o termómetro que dá temperaturas negativas num dia quente.

NOTAS DO PROFESSOR - Preferir const a #define. - Erro comum: usar = em vez de == numa condição. - Exemplo: o compilador avisa; ler os avisos.

NOTAS DO PROFESSOR - Código modular testa-se por partes. - Pergunta: onde pôr o debounce? Numa função própria. - Exemplo: reutilizar lerTemperatura() noutro projeto.

NOTAS DO PROFESSOR - Sem resistência o LED e o pino ficam em risco. - Pergunta: porque se escolhe o valor normalizado acima? Para não exceder a corrente. - Exemplo: LED verde, 2,1 V, 10 mA dá 290 Ω, normalizado 330 Ω.

NOTAS DO PROFESSOR - Com pull-up a lógica fica invertida. - Erro comum: esquecer a inversão e o LED fica aceso em repouso. - Exemplo: INPUT_PULLUP dispensa a resistência externa.

NOTAS DO PROFESSOR - O µC é rápido demais para um contacto mecânico. - Erro comum: delay(500) como debounce, que bloqueia tudo. - Analogia: uma bola que bate várias vezes no chão antes de parar.

NOTAS DO PROFESSOR - Detetar o flanco é a ideia central. - Pergunta: o que acontece se tirarmos a variável anterior? - Exemplo: contador de peças numa linha de montagem usa o mesmo princípio.

NOTAS DO PROFESSOR - Resolução é Vref a dividir por 1024. - Exemplo: leitura 768 a 5 V dá 3,75 V. - Erro comum: usar 1023 ou 1024 e achar que muda tudo. A diferença é inferior a 0,1 %.

NOTAS DO PROFESSOR - Menor Vref, maior resolução, menor gama. - Pergunta: e se a temperatura puder passar dos 110 graus? Não usar a referência de 1,1 V. - Exemplo: estufa com LM35 e referência interna.

NOTAS DO PROFESSOR - PWM não é tensão analógica real, mas muitas cargas comportam-se como se fosse. - Exemplo: analogWrite(9, 64) dá duty de 25,1 %. - Pergunta: PWM alimenta um motor? Não, só comanda um driver.

NOTAS DO PROFESSOR - Sensores resistivos precisam de um divisor para o ADC. - Erro comum: trocar o LDR com a resistência e inverter o sentido sem notar. - Exemplo: luz exterior acende se analogRead(A0) < 200.

NOTAS DO PROFESSOR - A relação é exponencial, não linear. - Pergunta: o que acontece com uma tolerância de 5 por cento? Muda o resultado. - Exemplo: confirmar com um termómetro de referência.

NOTAS DO PROFESSOR - O timeout evita ficar preso à espera de um eco que não vem. - Pergunta: porque dividir por 2? O som vai e volta. - Exemplo: 2915 µs dá 50 cm.

NOTAS DO PROFESSOR - Mostrar primeiro o valor bruto do ADC. - Erro comum: assumir que a fórmula da folha serve para todos os exemplares. - Exemplo: seco 820, imerso 350.

NOTAS DO PROFESSOR - O pino comanda, não alimenta. - Pergunta: porque o aluno que ligou o motor ao pino queimou a placa? - Exemplo: ESP32 e relé: o módulo traz transístor e díodo.

NOTAS DO PROFESSOR - Rb alta demais deixa o transístor fora de saturação. - Erro comum: ligar o relé sem resistência de base. - Exemplo: com 10 kΩ, Ib seria 0,43 mA e o relé não fecharia bem.

NOTAS DO PROFESSOR - O flyback protege o transístor e o µC. - Pergunta: placa a reiniciar quando o motor arranca? Alimentação separada. - Exemplo: o módulo de relé já traz o díodo, a montagem à mão não.

NOTAS DO PROFESSOR - A biblioteca esconde o PWM. - Pergunta: a que pulso corresponde 90 graus? 1472 microssegundos. - Exemplo: braço robótico com vários servos precisa de fonte própria.

NOTAS DO PROFESSOR - A ponte H inverte a polaridade; o PWM controla a velocidade. - Erro comum: inverter o sentido de repente. - Exemplo: L298N, L293D ou TB6612.

NOTAS DO PROFESSOR - Sem sensor a posição mantém-se se o motor não perder passos. - Pergunta: e se for 120 rpm? 2,5 ms entre passos. - Exemplo: impressoras 3D e CNC.

NOTAS DO PROFESSOR - Eventos curtos e críticos pedem interrupção. - Pergunta: um sensor de fluxo envia pulsos de 1 ms, polling serve? Depende do loop. - Exemplo: encoder de um motor.

NOTAS DO PROFESSOR - ISR curta: altera uma variável e sai. - Erro comum: delay() ou Serial.print dentro da ISR. - Exemplo: o int de 16 bits lê-se em 2 passos; uma interrupção a meio corrompe.

NOTAS DO PROFESSOR - Sempre a subtração, nunca agora >= ultimo + intervalo. - Erro comum: usar int para guardar millis(). - Analogia: o relógio da cozinha em vez de ficar parado diante do forno.

NOTAS DO PROFESSOR - Os timers são periféricos independentes da CPU. - Pergunta: com prescaler 1024, qual o OCR1A para 1 Hz? 15 624. - Exemplo: prescaler 64 e OCR1A = 24 999 dão 10 Hz.

NOTAS DO PROFESSOR - Enviar muito e depressa bloqueia o programa. - Erro comum: carateres estranhos, baud rate diferente. - Exemplo: subir para 115200 reduz o tempo por byte.

NOTAS DO PROFESSOR - Dois dispositivos com o mesmo endereço colidem. - Pergunta: como descobrir os endereços ligados? Programa de varrimento. - Exemplo: ecrã LCD e RTC no mesmo barramento.

NOTAS DO PROFESSOR - Escolher pelo número de pinos, velocidade e dispositivos. - Pergunta: cartão SD em que protocolo? SPI. - Exemplo: vários DS18B20 num só fio.

NOTAS DO PROFESSOR - Segurança é parte do projeto, não um extra. - Erro comum: deixar a palavra-passe do Wi-Fi no repositório público. - Exemplo: sonda de solo que publica a humidade de hora a hora.

NOTAS DO PROFESSOR - Cada tipo tem a sua ferramenta de deteção. - Pergunta: compila, logo está certo? Não. - Exemplo: contador int que passa de 32 767 ao fim de 9 horas.

NOTAS DO PROFESSOR - Serial é a ferramenta mais comum, mas também altera o tempo. - Pergunta: o bug desaparece quando se acrescenta um print? Pode ser tempo. - Exemplo: o Plotter mostra ruído no ADC a olho.

NOTAS DO PROFESSOR - Consultar a documentação da placa antes de comprar a sonda. - Pergunta: o UNO tem depuração por USB? Não, precisa de sonda externa. - Exemplo: ESP32 e Pico com sonda de baixo custo.

NOTAS DO PROFESSOR - Muitos erros de programa são erros de ligação. - Erro comum: mexer em três coisas e já não saber o que corrigiu. - Exemplo: multímetro para confirmar 5 V no sensor.

NOTAS DO PROFESSOR - Escrever o resultado esperado antes de ensaiar. - Pergunta: que caso falta? Arranque com a carga já ligada. - Exemplo: acrescentar colunas Obtido e Aprovado.

NOTAS DO PROFESSOR - O mundo físico fecha o ciclo. - Pergunta: o que acontece com um só limiar? O relé comuta rápido. - Exemplo: termóstato, rega, alarme, estufa.

NOTAS DO PROFESSOR - Cada case: o que fazer e quando sair. - Erro comum: tratar os modos com muitos booleanos soltos. - Exemplo: acrescentar o estado ATRASO de saída sem tocar nos outros.

NOTAS DO PROFESSOR - A EEPROM aguenta um número limitado de escritas. - Pergunta: guardar a cada segundo? Não; só quando muda. - Exemplo: calibração do sensor guardada para sobreviver a um corte.

NOTAS DO PROFESSOR - Estes são os erros de prova e de laboratório. - Pergunta: qual destes já cometeram? - Exemplo: pedir a cada grupo para identificar um erro num código dado.

NOTAS DO PROFESSOR - Voltar aos três resultados de aprendizagem. - Pergunta: que parte tiveram mais dificuldade? Orientar o estudo. - Exemplo: ligar a síntese ao mini-projeto.