🎤 Medindo o barulho da galera
"O primeiro olho do robô" — Desenvolva um programa que captura áudio do microfone, calcula intensidade sonora simulada e gera alertas personalizados com memes paranaenses.
🎤📊🤣
Códigos BNCC
EM13CNT104 - Avaliar limites e potencialidades das tecnologias de captura de áudio
EM13MAT503 - Interpretar e representar dados sonoros em gráficos simples
EM13LGG702 - Utilizar diferentes linguagens para produção de sentido (memes como linguagem)
Competências Gerais
Competência 2 - Exercitar curiosidade intelectual
Competência 7 - Argumentar com base em dados
Etapas da Aula (100 minutos)
| Etapa | Tempo | Atividade |
|---|---|---|
| Abertura | 10 min | Desafio: "Quanto barulho tem na nossa sala?" estimativa coletiva. |
| Conceituação | 15 min | Explicar decibéis (dB) e como o computador "escuta" (PCM, amostragem). |
| Codificação | 40 min | Implementar o código de captura de áudio e decisões com memes (em duplas). |
| Teste prático | 20 min | Criar diferentes níveis de barulho (sussurro, conversa, grito, palmas). Registrar no CSV. |
| Fechamento | 15 min | Gerar gráfico dos últimos 10 registros. Debater: "O robô reagiu certo?" |
🎤 Nível de som simulado
0.0 dB
📢 Mensagem do Robô:
Materiais
- Notebook Colab da aula anterior
- Microfones (embutidos no Chromebook ou headsets)
- Caixa de som (para gerar barulho controlado)
Adaptações para inclusão
- Alunos com deficiência auditiva podem usar o recurso de "vibração do Chromebook" ou focar na parte visual do gráfico
- Para alunos com TDAH: sessões curtas de codificação com pausas
# ===================================================================
# Robô Fofoqueiro - Sensor de Som Irreverente
# ===================================================================
# Objetivo: Simular um sensor de som (KY-038) usando o microfone real,
# medindo níveis de intensidade sonora em decibéis simulados,
# emitindo alertas quando o volume ultrapassa 75 dB e
# salvando logs em CSV para análise gráfica.
# Alunos: [A SER PREENCHIDO]
# Orientadora: Gisele Nunes
# Data : 2026
# ===================================================================
# -*- coding: utf-8 -*-
# Importa a biblioteca pyaudio para capturar áudio do microfone em tempo real.
import pyaudio
# Importa numpy para operações matemáticas com arrays (cálculo de RMS, etc.).
import numpy as np
# Importa time para possíveis delays ou marcações de tempo.
import time
# Importa threading para executar tarefas em paralelo (não usado diretamente aqui,
# mas mantido para expansões futuras como captura contínua).
import threading
# Importa csv para salvar os dados das medições em formato de planilha.
import csv
# Importa datetime para gerar timestamps precisos de cada medição.
from datetime import datetime
# Importa matplotlib para gerar gráficos de barras com o histórico de medições.
import matplotlib.pyplot as plt
# Importa clear_output do IPython para limpar a saída do notebook Colab.
from IPython.display import clear_output
# ===== CONFIGURAÇÃO INICIAL =====
# No Colab, é necessário instalar as bibliotecas com:
# !pip install pyaudio keyboard matplotlib numpy
# !apt-get install portaudio19dev
# ===== FUNÇÃO PRINCIPAL =====
def medidor_fofoqueiro():
"""
Função que simula o sensor KY-038 usando o microfone real.
Captura 3 segundos de áudio, calcula a intensidade sonora (RMS),
converte para uma escala simulada de 0 a 120 dB e retorna o nível,
um status de alerta e uma mensagem de meme conforme o volume.
Retorna:
tuple: (decibeis_simulados, alerta, mensagem_meme)
"""
# Define a duração da captura de áudio em segundos.
DURACAO = 3
# Define a taxa de amostragem (44.1 kHz é qualidade de CD).
TAXA_AMOSTRAGEM = 44100
# Define o tamanho do buffer (quantos samples por leitura).
TAMANHO_BUFFER = 1024
# Cria uma instância do objeto PyAudio para gerenciar o microfone.
audio = pyaudio.PyAudio()
# Abre um stream de áudio para captura (input=True significa microfone).
stream = audio.open(
format=pyaudio.paInt16, # Formato 16 bits por sample.
channels=1, # Mono (um canal).
rate=TAXA_AMOSTRAGEM, # Taxa de amostragem definida.
input=True, # Modo captura.
frames_per_buffer=TAMANHO_BUFFER # Tamanho de cada bloco de leitura.
)
# Mensagem informativa para o usuário.
print("🎤 Gravando 3 segundos de áudio...")
# Lista para armazenar os frames (blocos) de áudio capturados.
frames = []
# Calcula quantos blocos serão necessários para preencher DURACAO segundos.
# Ex: 44100 samples/s / 1024 samples/bloco * 3 s = ~129 blocos.
for _ in range(0, int(TAXA_AMOSTRAGEM / TAMANHO_BUFFER * DURACAO)):
# Lê um bloco de dados do microfone.
data = stream.read(TAMANHO_BUFFER)
# Converte os bytes lidos em um array numpy de inteiros de 16 bits.
dados_audio = np.frombuffer(data, dtype=np.int16)
# Adiciona o bloco convertido à lista de frames.
frames.append(dados_audio)
# Para o stream de áudio para liberar o microfone.
stream.stop_stream()
# Fecha o stream.
stream.close()
# Termina a instância do PyAudio.
audio.terminate()
# Concatena todos os frames em um único array numpy de áudio.
audio_data = np.concatenate(frames)
# CÁLCULO DA INTENSIDADE SONORA (RMS - Root Mean Square)
# RMS é uma média quadrática que representa a potência do sinal.
# Quanto maior o RMS, mais alto o volume.
rms = np.sqrt(np.mean(audio_data**2))
# Valor máximo possível para um sinal int16 (2^15 = 32768).
max_rms = 32768
# Converte o RMS para uma escala simulada de decibéis (0 a 120 dB).
# Um RMS de 0 resulta em 0 dB, um RMS de 32768 resulta em 120 dB.
decibeis = (rms / max_rms) * 120
# Garante que o valor não ultrapasse os limites de 0 a 120 dB.
decibeis = min(120, max(0, decibeis))
# EMOJI CONFORME VOLUME (faixas de intensidade)
# Quanto maior o dB, mais "barulhento" é o emoji escolhido.
if decibeis < 20:
emoji = "🔇🤫" # Silêncio absoluto.
elif decibeis < 40:
emoji = "🤫" # Sussurro.
elif decibeis < 60:
emoji = "🗣️" # Conversa normal.
elif decibeis < 80:
emoji = "📢" # Gritaria moderada.
elif decibeis < 100:
emoji = "🔊" # Muito alto.
else:
emoji = "💀📢" # Extremamente alto (alerta máximo).
# MENSAGEM MEME POR NÍVEL (texto humorístico para cada faixa)
# Define também a variável alerta (True se ultrapassar 75 dB).
if decibeis < 40:
mensagem = "🤫 silêncio absoluto... até assusta"
alerta = False
elif decibeis < 60:
mensagem = "🗣️ papinho normal, nada de mais"
alerta = False
elif decibeis < 80:
mensagem = "📢 TÁ FICANDO BOM! logo logo viro fofoqueiro"
alerta = True
elif decibeis < 100:
mensagem = "🔊 CALA A BOCA! vou piscar o LED vermelho"
alerta = True
else:
mensagem = "💀 INFERNO ACÚSTICO! vou chamar a diretora robô"
alerta = True
# Alerta também é ativado separadamente se dB > 75 (redundante, mas seguro).
alerta = decibeis > 75
# Exibe um resumo formatado com emoji, valor em dB e mensagem.
print("\n" + "="*50)
print(f"Nível atual: {emoji}")
print(f"Decibéis simulados: {decibeis:.1f} dB")
print(f"📢 {mensagem}")
print("="*50)
# Retorna uma tupla com os três valores de interesse.
return (decibeis, alerta, mensagem)
# ===== FUNÇÃO PARA SALVAR LOG EM CSV =====
def salvar_log(decibeis, mensagem, arquivo="log_fofoqueiro.csv"):
"""
Salva uma medição em um arquivo CSV.
Cria o cabeçalho se o arquivo estiver vazio.
Parâmetros:
decibeis: float - valor medido em dB.
mensagem: str - mensagem de meme associada.
arquivo: str - nome do arquivo CSV (padrão: log_fofoqueiro.csv).
"""
# Gera um timestamp com data e hora atuais no formato ANO-MÊS-DIA HORA:MINUTO:SEGUNDO.
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# Abre o arquivo em modo de adição ('a' = append).
# newline='' evita linhas em branco extras no Windows.
# encoding='utf-8' garante caracteres especiais (emoji, acentos).
with open(arquivo, mode='a', newline='', encoding='utf-8') as file:
writer = csv.writer(file)
# Move o ponteiro para o final do arquivo para verificar se está vazio.
file.seek(0, 2)
# Se o arquivo estiver vazio (tell() retorna 0), escreve o cabeçalho.
if file.tell() == 0:
writer.writerow(["Timestamp", "Decibeis (dB)", "Mensagem"])
# Escreve a linha com os dados da medição atual.
writer.writerow([timestamp, f"{decibeis:.1f}", mensagem])
# Confirma o salvamento com uma mensagem.
print(f"💾 Log salvo: {timestamp} - {decibeis:.1f} dB")
# ===== FUNÇÃO PARA MOSTRAR GRÁFICO =====
def mostrar_grafico(arquivo="log_fofoqueiro.csv"):
"""
Lê o arquivo CSV de log e gera um gráfico de barras com as últimas 10 medições.
Barras verdes para dB <= 75 (seguro) e vermelhas para dB > 75 (alerta).
Parâmetros:
arquivo: str - nome do arquivo CSV (padrão: log_fofoqueiro.csv).
"""
try:
# Tenta abrir o arquivo CSV para leitura.
with open(arquivo, 'r', encoding='utf-8') as file:
leitor = csv.reader(file)
# Pula o cabeçalho (primeira linha).
cabecalho = next(leitor)
# Listas para armazenar os dados.
timestamps = []
decibeis = []
contador = 0
# Percorre todas as linhas do CSV.
for linha in leitor:
timestamps.append(linha[0]) # Primeira coluna: timestamp.
decibeis.append(float(linha[1])) # Segunda coluna: dB (converte para float).
contador += 1
# Pega apenas os últimos 10 registros (ou menos se houver menos de 10).
ultimos = min(10, contador)
timestamps = timestamps[-ultimos:]
decibeis = decibeis[-ultimos:]
# Cria uma figura com tamanho de 12 polegadas de largura por 6 de altura.
plt.figure(figsize=(12, 6))
# Define as cores das barras: verde se dB <= 75, vermelho se > 75.
cores = ['green' if db <= 75 else 'red' for db in decibeis]
# Cria o gráfico de barras com as cores definidas e transparência 0.7.
barras = plt.bar(range(len(decibeis)), decibeis, color=cores, alpha=0.7)
# Adiciona uma linha horizontal pontilhada no limite de 75 dB (alerta).
plt.axhline(y=75, color='orange', linestyle='--', linewidth=2, label='Limite de Alerta (75 dB)')
# Rótulo do eixo X.
plt.xlabel('Medições (mais recente na direita)', fontsize=12)
# Rótulo do eixo Y.
plt.ylabel('Decibéis Simulados (dB)', fontsize=12)
# Título do gráfico em negrito.
plt.title('📊 Histórico do Robô Fofoqueiro - Últimas Medições', fontsize=14, fontweight='bold')
# Define os rótulos do eixo X como os timestamps, rotacionados 45 graus.
plt.xticks(range(len(timestamps)), timestamps, rotation=45, ha='right')
# Define os limites do eixo Y de 0 a 120 dB.
plt.ylim(0, 120)
# Adiciona uma grade leve (alpha=0.3 = 30% opaco).
plt.grid(True, alpha=0.3)
# Adiciona a legenda da linha de alerta.
plt.legend()
# Adiciona os valores numéricos acima de cada barra.
for i, (barra, db) in enumerate(zip(barras, decibeis)):
altura = barra.get_height()
# Posiciona o texto 2 unidades acima da barra, centralizado.
plt.text(barra.get_x() + barra.get_width()/2., altura + 2, f'{db:.0f}dB', ha='center', va='bottom', fontsize=9)
# Ajusta o layout automaticamente para evitar cortes.
plt.tight_layout()
# Exibe o gráfico.
plt.show()
print(f"📈 Gráfico mostrado com os últimos {ultimos} registros!")
except FileNotFoundError:
# Se o arquivo não existir, exibe uma mensagem amigável.
print("⚠️ Ainda não há dados para mostrar. Faça algumas medições primeiro!")
except Exception as e:
# Captura qualquer outro erro e exibe uma mensagem genérica.
print(f"❌ Erro ao gerar gráfico: {e}")
# ===== LOOP PRINCIPAL =====
def main():
"""
Função principal que controla o fluxo do programa:
- Exibe o cabeçalho com arte ASCII.
- Executa medições em loop até o usuário pressionar 'q'.
- Salva logs e exibe gráfico ao final.
"""
# Exibe um cabeçalho estilizado com arte ASCII e instruções.
print("""
╔══════════════════════════════════════════════════════════╗
║ ║
║ 🤖 ROBÔ FOFOQUEIRO - VERSÃO PARANÁENSE 🤖 ║
║ ║
║ "Bora medir o barulho da galera!" ║
║ "Égua, que gritaria danada!" ║
║ ║
║ Pressione 'q' a qualquer momento para sair ║
║ ║
╚══════════════════════════════════════════════════════════╝
""")
# Contador de quantas medições foram realizadas.
contador_medicoes = 0
# Lista para armazenar todos os valores de dB para cálculo de estatísticas.
historico_dB = []
try:
# Loop infinito controlado pelo usuário.
while True:
# Incrementa o contador de medições.
contador_medicoes += 1
# Exibe o número da medição atual.
print(f"\n🔁 Medição #{contador_medicoes}")
# Chama a função que captura o áudio e retorna os valores.
dB, alerta, mensagem = medidor_fofoqueiro()
# Salva a medição no arquivo CSV.
salvar_log(dB, mensagem)
# Adiciona o valor de dB à lista de histórico.
historico_dB.append(dB)
# Se o alerta estiver ativado (dB > 75), exibe mensagem de destaque.
if alerta:
print("🚨 ALERTA! 🚨")
print("🔴🔴🔴 PASSOU DOS 75 dB! TÁ MUITO ALTO! 🔴🔴🔴")
# Pergunta ao usuário se deseja continuar ou sair.
comando = input("\nPressione ENTER para nova medição ou 'q' para sair: ")
# Se o usuário digitar 'q' (maiúsculo ou minúsculo), interrompe o loop.
if comando.lower() == 'q':
break
except KeyboardInterrupt:
# Captura o Ctrl+C no terminal e exibe mensagem amigável.
print("\n\n🛑 Programa interrompido pelo usuário!")
# Exibe um resumo estatístico ao final do programa.
print("\n" + "="*50)
print("📊 RESUMO DO ROBÔ FOFOQUEIRO")
print("="*50)
print(f"Total de medições realizadas: {contador_medicoes}")
# Só exibe estatísticas se houver pelo menos uma medição.
if historico_dB:
print(f"Maior nível registrado: {max(historico_dB):.1f} dB")
print(f"Menor nível registrado: {min(historico_dB):.1f} dB")
print(f"Média dos níveis: {sum(historico_dB)/len(historico_dB):.1f} dB")
# Gera o gráfico final com todas as medições.
print("\n📊 Gerando gráfico final com todo o histórico...")
mostrar_grafico()
# Mensagem de encerramento.
print("\n✅ Programa encerrado com sucesso!")
print("🙏 Valeu por usar o Robô Fofoqueiro - Tchê!")
# Verifica se o script está sendo executado diretamente (não importado como módulo).
if __name__ == "__main__":
# Exibe instruções de instalação antes de iniciar o programa.
print("⚠️ IMPORTANTE: Execute no terminal do Colab:")
print("!pip install pyaudio keyboard matplotlib numpy")
print("!apt-get install portaudio19dev")
# Aguarda o usuário pressionar ENTER após instalar as bibliotecas.
input("\nPressione ENTER após instalar as bibliotecas...")
# Chama a função principal para iniciar o programa.
main()
Checklist de avaliação - Aluno
- Código funcional que captura som e exibe dB?
- Log CSV gerado com sucesso?
- Gráfico plotado ao final com as últimas 10 medições?
- Participação na discussão sobre "O robô reagiu certo?"
- Testou diferentes níveis de barulho (sussurro, conversa, grito, palmas)?
- Os memes e alertas personalizados aparecem corretamente?
Simulação de Coleta de Dados
Clique no botão abaixo para simular uma coleta de dados com diferentes níveis de som:
Critérios de Avaliação
- Código funcional que captura som e exibe dB
- Log CSV gerado com sucesso
- Gráfico plotado ao final
- Participação na discussão
Plano de Aula - Docente
Título: "Medindo o barulho da galera: o primeiro olho do robô"
Códigos BNCC: EM13CNT104, EM13MAT503, EM13LGG702 | RCP - Paraná: Física - Ondulatória, Matemática - Tratamento da Informação
Duração: 2 aulas (100 minutos)
Materiais: Notebook Colab, microfones, caixa de som
Dicas de mediação
- Abertura (10min): Desafio "Quanto barulho tem na nossa sala?" - estimativa coletiva
- Conceituação (15min): Explique decibéis (dB) e como o computador "escuta" (PCM, amostragem)
- Codificação (40min): Implemente o código em duplas, incentive comentários irreverentes
- Teste prático (20min): Organize estações: sussurro, conversa, grito, palmas
- Fechamento (15min): Gere o gráfico e debata "O robô reagiu certo?"
Kit do Professor
Códigos RCP - Paraná
Física - Ondulatória - Relacionar frequência e intensidade sonora com aplicações práticas
Matemática - Tratamento da Informação - Construir e interpretar gráficos de dados coletados