attachInterrupt()

attachInterrupt(digitalPinToInterrupt(pino), funcao, modo)

Imagine que você precisa reagir na hora em que um botão é pressionado ou um sensor dispara, mas seu loop() está ocupado com outras coisas. A interrupção resolve isso: você pede pro Arduino "largar tudo" e rodar uma função sua no exato instante em que um pino muda de estado. É como um alarme que interrompe qualquer tarefa pra te avisar.

Sintaxe

attachInterrupt(digitalPinToInterrupt(pino), funcao, modo);

Parâmetros

  • pino: o pino que vai ser monitorado. No Uno, só os pinos 2 e 3 aceitam interrupção. Sempre embrulhe com digitalPinToInterrupt(pino) — é o jeito portátil e correto.
  • funcao: o nome da sua função que será chamada (a chamada ISR — Interrupt Service Routine). Ela não recebe argumentos nem retorna nada.
  • modo: quando disparar — RISING (subida de LOW pra HIGH), FALLING (descida de HIGH pra LOW), CHANGE (qualquer mudança) ou LOW (enquanto o pino estiver em LOW).

Retorno

Nada (void).

Exemplo

const byte pinoBotao = 2;
volatile int contador = 0;

void contar() {
  contador++;
}

void setup() {
  Serial.begin(9600);
  pinMode(pinoBotao, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(pinoBotao), contar, FALLING);
}

void loop() {
  Serial.println(contador);
  delay(500);
}

Notas e cuidados

  • No Uno, apenas os pinos 2 e 3 têm interrupção externa. No ESP32, quase todos os GPIOs servem (lembre que ele é 3,3 V — nunca aplique 5 V num pino dele).
  • A função da interrupção precisa ser curta e rápida: evite delay(), Serial.print() pesado e cálculos longos. Dentro dela o millis() não avança e o delay() nunca termina, porque ambos dependem de interrupções.
  • Qualquer variável compartilhada entre a ISR e o loop() deve ser declarada como volatile, senão o compilador pode "esquecer" de atualizá-la.

Quer aprender a usar isso em projetos reais, do zero?

Conhecer o Curso Maker