⬤ Iniciante

🔔 Campainha — Buzzer Passivo

⏱️ 30 min 🧩 Buzzer Passivo — Pino D8

Exercícios

📌 Pinagem na placa de interface

Módulo Conector Interface Pino Arduino Notas
🔔 Buzzer Passivo BUZZ D8 Suporta tone() — frequência controlada por software
ℹ️
Funções essenciais: tone(pino, frequência) gera um som contínuo à frequência indicada (em Hz). tone(pino, frequência, duração) toca durante duração milissegundos e pára sozinho. noTone(pino) pára imediatamente qualquer som. Nenhuma destas funções bloqueia o loop() quando usada com duração.

🔊 Buzzer Ativo vs Buzzer Passivo

✅ Passivo (Kit C)

  • Frequência variável — controlada por software com tone()
  • Permite melodias, escalas musicais e sons complexos
  • Som depende inteiramente do sketch Arduino
  • Precisa de sinal PWM — não basta ligar e desligar
  • Sem sinal → silêncio total

⚠️ Ativo (não incluído)

  • Frequência fixa — tom único interno, não programável
  • Funciona com simples digitalWrite(HIGH)
  • Só serve para bips simples — sem melodias
  • Tem oscilador interno — mais fácil mas menos versátil
  • Distingue-se pelo autocolante no cimo ou pela pinagem (2 pinos vs 3)
💡
Como distinguir: Sem código no Arduino, liga o buzzer directamente entre 5V e GND. Se soar → ativo. Se ficar em silêncio → passivo. O Kit C inclui o passivo, que é muito mais versátil para domótica educacional.

🎵 Notas Musicais e Frequências

A função tone() recebe a frequência em Hz. Estas são as notas da 4.ª oitava — as mais usadas em melodias simples:

Dó 262 Hz C4
Ré 294 Hz D4
Mi 330 Hz E4
Fá 349 Hz F4
Sol 392 Hz G4
Lá 440 Hz A4
Si 494 Hz B4
Dó' 523 Hz C5
🎼
Dica de organização: define as frequências como constantes no topo do sketch para o código ficar legível. Por exemplo: #define DO 262, #define RE 294, #define MI 330 — depois usa tone(BUZZER, DO, 300) em vez de tone(8, 262, 300).

Exercício 1 — Primeiro bip

Toca um bip simples ao iniciar. Confirma que o buzzer está a funcionar e a ligação está correcta.

ex1_buzzer_bip.ino
#define BUZZER 8

void setup() {
  pinMode(BUZZER, OUTPUT);

  // 3 bips de confirmação ao arrancar
  for (int i = 0; i < 3; i++) {
    tone(BUZZER, 1000, 150);  // 1000 Hz durante 150 ms
    delay(300);                // Pausa entre bips
  }
}

void loop() {
  // Toca bip a cada 2 segundos
  tone(BUZZER, 800, 100);
  delay(2000);
}
💡
Frequências úteis para alertas: Sons agudos (1000–3000 Hz) são mais audíveis e penetrantes — bons para alarmes. Sons graves (200–400 Hz) são mais suaves — bons para confirmações e notificações. Experimenta vários valores para encontrar o tom certo para cada situação da tua casa.

Exercício 2 — Padrões de alerta

Cada evento da casa inteligente tem o seu padrão sonoro característico. Sons diferentes comunicam informações diferentes ao utilizador — sem precisar de olhar para o ecrã.

Confirmação
2 bips curtos · porta aberta confirmada, LED ligado
Atenção
3 bips espaçados · PIR detetou movimento, LDR escuro
Alarme Gás
Bips rápidos contínuos · MQ-2 detetou gás
Campainha
Toque musical (Dó–Lá) · botão da porta premido
Encerramento
Escala descendente · sistema pronto / desativado
ex2_buzzer_padroes.ino
#define BUZZER 8

// Padrão: 2 bips curtos de confirmação
void bipsConfirmacao() {
  tone(BUZZER, 1200, 80);  delay(160);
  tone(BUZZER, 1200, 80);  delay(100);
}

// Padrão: 3 bips de atenção
void bipsAtencao() {
  for (int i = 0; i < 3; i++) {
    tone(BUZZER, 880, 150);
    delay(350);
  }
}

// Padrão: alarme de gás — bips rápidos contínuos
void alarmeGas() {
  for (int i = 0; i < 8; i++) {
    tone(BUZZER, 1500, 80);
    delay(120);
  }
}

// Padrão: toque da campainha (dois tons)
void campainha() {
  tone(BUZZER, 523, 300);  // Dó5
  delay(380);
  tone(BUZZER, 440, 400);  // Lá4
  delay(480);
}

// Padrão: escala descendente de encerramento
void encerramento() {
  int notas[] = { 523, 440, 392, 330, 262 };
  for (int i = 0; i < 5; i++) {
    tone(BUZZER, notas[i], 200);
    delay(260);
  }
}

void setup() {
  pinMode(BUZZER, OUTPUT);
  Serial.begin(9600);
  Serial.println("Envia 1-5 pelo Monitor Serie para ouvir os padroes.");
}

void loop() {
  if (Serial.available()) {
    char c = Serial.read();
    if      (c == '1') bipsConfirmacao();
    else if (c == '2') bipsAtencao();
    else if (c == '3') alarmeGas();
    else if (c == '4') campainha();
    else if (c == '5') encerramento();
  }
}

Exercício 3 — Melodia: Escala de Dó

Toca a escala de Dó completa (Dó–Ré–Mi–Fá–Sol–Lá–Si–Dó) usando um array de notas e durações. Este padrão com arrays é a base para qualquer melodia mais complexa.

ex3_buzzer_escala.ino
#define BUZZER 8

// Frequências das notas — oitava 4
#define DO  262
#define RE  294
#define MI  330
#define FA  349
#define SOL 392
#define LA  440
#define SI  494
#define DO5 523
#define SIL 0    // Pausa (silêncio)

// Array com as notas da escala (0 = pausa)
int escala[] = { DO, RE, MI, FA, SOL, LA, SI, DO5 };

// Duração de cada nota em milissegundos
int duracoes[] = { 300, 300, 300, 300, 300, 300, 300, 600 };

int numNotas = 8;

void tocarMelodia(int notas[], int durs[], int n) {
  for (int i = 0; i < n; i++) {
    if (notas[i] == SIL) {
      noTone(BUZZER);          // Pausa
    } else {
      tone(BUZZER, notas[i], durs[i]);
    }
    delay(durs[i] + 30);     // +30ms de separação entre notas
  }
  noTone(BUZZER);
}

void setup() {
  pinMode(BUZZER, OUTPUT);
}

void loop() {
  tocarMelodia(escala, duracoes, numNotas);
  delay(2000);  // Pausa entre repetições
}
🎵
Para músicas conhecidas: Procura as partituras em notação numérica (cifra) e converte cada nota para a sua frequência Hz. O silêncio entre notas (delay(durs[i] + 30)) é importante — sem ele as notas fundem-se e perdem-se as separações.

Exercício 4 — Campainha da porta com botão

Ao premir o botão toca o toque musical da campainha e acende os LEDs por 2 segundos. Simula com fidelidade uma campainha de porta real.

ex4_buzzer_campainha.ino
#define BUZZER      8
#define BOTAO       4
#define LED_BRANCO  5
#define LED_AMARELO 6

void tocarCampainha() {
  // Toque clássico: Dó5 longo + Lá4 longo
  tone(BUZZER, 523, 320);  delay(400);
  tone(BUZZER, 440, 480);  delay(560);
  // Repetição mais suave
  tone(BUZZER, 523, 200);  delay(280);
  tone(BUZZER, 440, 300);  delay(380);
  noTone(BUZZER);
}

void setup() {
  pinMode(BOTAO,      INPUT_PULLUP);
  pinMode(BUZZER,     OUTPUT);
  pinMode(LED_BRANCO, OUTPUT);
  pinMode(LED_AMARELO,OUTPUT);
  Serial.begin(9600);
}

void loop() {
  if (digitalRead(BOTAO) == LOW) {  // Botão premido
    Serial.println("Campainha! Alguem na porta.");

    // Liga LEDs para sinalizar visualmente
    digitalWrite(LED_BRANCO,  HIGH);
    digitalWrite(LED_AMARELO, HIGH);

    tocarCampainha();             // Toca o som

    delay(2000);                    // LEDs ficam ligados 2s
    digitalWrite(LED_BRANCO,  LOW);
    digitalWrite(LED_AMARELO, LOW);

    delay(300);                     // Anti-bounce
  }
}

Exercício 5 — Alarme integrado com sensores

O buzzer reage a vários sensores com sons diferentes: PIR toca atenção, gás MQ-2 dispara alarme urgente. O LCD mostra o estado. Cada evento tem a sua identidade sonora.

ex5_buzzer_alarme_integrado.ino
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

#define BUZZER   8
#define PIR      2
#define MQ2_ANA  A1
#define LED_BRANCO 5

#define LIMIAR_GAS  500

LiquidCrystal_I2C lcd(0x27, 16, 2);

// ── Sons de alerta ──────────────────────────

void somMovimento() {
  // 3 bips espaçados — atenção moderada
  for (int i = 0; i < 3; i++) {
    tone(BUZZER, 880, 120);
    delay(250);
  }
}

void somAlarmeGas() {
  // Bips rápidos alternados — urgência máxima
  tone(BUZZER, 1500, 80); delay(110);
  tone(BUZZER, 1000, 80); delay(110);
  tone(BUZZER, 1500, 80); delay(110);
  tone(BUZZER, 1000, 80); delay(110);
}

// ── Setup ───────────────────────────────────

void setup() {
  pinMode(PIR,        INPUT);
  pinMode(BUZZER,     OUTPUT);
  pinMode(LED_BRANCO, OUTPUT);

  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0); lcd.print("Sistema pronto");
  lcd.setCursor(0, 1); lcd.print("MQ2 a aquecer..");
  delay(30000);          // Aquecimento MQ-2
  lcd.clear();
}

// ── Loop principal ──────────────────────────

void loop() {
  int  gas = analogRead(MQ2_ANA);
  bool mov = (digitalRead(PIR) == HIGH);

  // ── Prioridade 1: Alarme de gás (mais urgente)
  if (gas > LIMIAR_GAS) {
    digitalWrite(LED_BRANCO, HIGH);
    lcd.setCursor(0, 0); lcd.print("!! ALARME GAS !!");
    lcd.setCursor(0, 1); lcd.print("Gas: ");
    lcd.print(gas); lcd.print("     ");
    somAlarmeGas();

  // ── Prioridade 2: Movimento detetado
  } else if (mov) {
    digitalWrite(LED_BRANCO, HIGH);
    lcd.setCursor(0, 0); lcd.print("Movimento!      ");
    lcd.setCursor(0, 1); lcd.print("PIR ativo       ");
    somMovimento();
    delay(3000);              // Mantém LED 3s após deteção
    digitalWrite(LED_BRANCO, LOW);

  // ── Estado normal
  } else {
    noTone(BUZZER);
    digitalWrite(LED_BRANCO, LOW);
    lcd.setCursor(0, 0); lcd.print("Casa: OK        ");
    lcd.setCursor(0, 1); lcd.print("Gas: ");
    lcd.print(gas); lcd.print("     ");
    delay(500);
  }
}
ℹ️
Hierarquia de prioridades: O código verifica primeiro o gás (mais perigoso), depois o movimento. Assim, se ambos ocorrerem em simultâneo, o alarme de gás tem sempre prioridade e toca o seu som mais urgente. Este padrão de if / else if / else em cascata é fundamental para qualquer sistema de domótica com múltiplos sensores.

🏆 Desafios