Acender a luz batendo palmas não é novidade, mas não deixa de ser uma coisa muito interessante de usar e aprender a criar. Principalmente pros preguiçosos… Ou pra quem gosta de automação. Portanto, vamos aprender a base de como fazer um sistema para acender uma lâmpada batendo palmas.

Pretendo focar na parte da captação do som e não no acendimento da lâmpada em si. Portanto, para ter uma boa noção para criar o projeto completo, recomendo que leia o post que ensina a usar relé (acionar lâmpada) com o Arduino.


Informações base

Para criar esse projeto, vou utilizar um sensor de som, também chamado de microfone. No caso, uma plaquinha que contem um microfone com um comparador(imagem abaixo).

modulo microfone

Essa plaquinha contem 4 pinos:

  • 2 pinos de alimentação:  Vcc (+) e GND (G)
  • 1 pino de leitura analógica: Esse pino te permite ler as ondas sonoras diretamente. O sensor transforma a intensidade das ondas sonoras em tensões de 0 a 5V
  • 1 pino para leitura digital: Esse pino manda um sinal de nível alto se uma determina intensidade do som for atingida

Normalmente, os módulos com microfone semelhantes ao da imagem, possuem apenas o pino de leitura digital.

Basicamente, o pino de leitura analógica pega o sinal direto do microfone. Isto é, o microfone sendo conectado diretamente na alimentação juntamente com um resistor. Já o pino de leitura digital pega o sinal de um comparador. Este comparador emite sinal de nível alto se um certo nível de tensão no microfone for atingido e este nível é regulado no potenciômetro (componente azul na placa).

Para esse projeto, é possível utilizar um microfone separadamente. A diferença é que, no projeto, a leitura será feita no pino digital. Porém, para fazer a lógica com leitura analógica não muda muita coisa.


Captação das palmas

A ideia do projeto é acender um LED (simbolizando uma lâmpada) ao bater palmas duas vezes em sequência. Como o microfone está atuando como um sensor de intensidade sonora, basta avaliar se o sinal lido apresenta dois picos de intensidade que estão em sequência. Isto é, se dois sons de alta intensidade sonora foram detectados um na sequência do outro.

Observação importante: sem utilizar algum tipo de amplificador, pode ser que o microfone não capte um bater de palmas a um distância considerável (mais de 30cm-1m). Portanto, se deseja aplicar essa ideia para grandes distâncias, adicione um amplificador ao microfone. A distância que funcionou muito bem no meu caso foi cerca de 10cm.

Para a leitura digital:

gráfico da leitura digital

Para a leitura analógica:

gráfico da leitura analógica

É importante observar a alguns detalhes:

  • Vamos estipular que o tempo máximo que um som de alta intensidade pode durar é 200 ms
  • Vamos definir um tempo máximo de 700 ms entre cada bater de palmas
  • O sistema funciona pra qualquer sinal sonoro de alta intensidade, não só bater palmas

Os tempos acima foram determinados experimentalmente.

Sendo assim, basta detectar um sinal de nível alto (no caso da leitura digital), verificar se ele tem até no máximo 200ms de duração, esperar até no máximo 700ms para o próximo bater de palmas e então acionar a lâmpada. Para o caso da leitura digital, é só verificar se o valor lido está acima do valor limite para detecção.


Circuito

Como dito anteriormente, vamos utilizar um microfone e um LED (simboliza a lâmpada).

circuito com microfone ligado ao Arduino

A ligação é simples: ligue o negativo do LED no GND e, em série, ligue um resistor de 220Ω. O positivo do LED tem que ser ligado no pino digital 2 do Arduino. Para o microfone, ligue o Vcc no 5v, o GND no GND e o pino para leitura digital no pino D3 do Arduino.

Para a leitura analógica do microfone, é só ligar em qualquer um dos pinos analógicos (A0-A5).


Programação

Informações importantes

Para fazer a detecção do tempo que a onda fica em nível alto, ou em baixo utilizei variáveis auxiliares juntamente com a função delayMicroseconds. Esse método é mais simples de entender e não atrapalha o funcionamento do programa. A solução alternativa é utilizar o método que ensinei neste post, mas não é necessário.

Dividi a amostragem do som em 3 estágios:

  • Primeira onda
    • Se estagio1 (variável auxiliar) estiver desativado, verifica se apareceu algum sinal de nível alto e ativa a variável estagio1
    • Se estagio1 estiver ativa, verifica se a onda foi para nível baixo e ativa estagio2
  • Segunda onda
    • Se estagio2 estiver ativo e um sinal de nível alto foi percebido, ativa estagio3
    • Se estagio3 estiver ativo, verifica se a onda foi para nível baixo e: troca o estado do LED (acende ou apaga) e volta o programa pra etapa 0 (desativa estagio1, estagio2 e estagio3)

Para ler o valor digital do microfone, utilizei uma variável chamada “valor”. Então, para fazer o mesmo código, porém com leitura analógica, é só trocar a lógica da variável valor. De modo que, quando a leitura analógica for maior que X (intensidade sonora quando bate palma), então basta ativar a variável “valor”.

Código

Leia os comentários para entender o código por completo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#define led 2 //Define led como sendo o pino 2
#define micro 3 //Define micro como sendo o pino 3

bool valor=false; //Variavel para leitura do microfone

// Variaveis para ajudar na captação do bater de palmas
bool estagio1=false;
bool estagio2=false;
bool estagio3=false;

// Variaveis para fazer a função do tempo limite da onda em alta e baixa
int a;
int b;

void setup() {
  pinMode(led, OUTPUT); //Configura LED como saída
  pinMode(micro, INPUT); //Configura o microfone como entrada
 
  digitalWrite(led, LOW); //Começa com o LED apagado
}

void loop() {
  valor = digitalRead(micro);//Le o pino digital
 
  // Teste do primeiro bater de palmas
  if(valor==true && estagio1 == false){ //Primeiro testa se o pino esta em alta
    estagio1=true; //Ativa uma variavel auxiliar
    a=0; //Volta o temporizador para 0
  }
 
  // Agora testa se o pino que estava em alta abaixou
  if(valor==false && estagio1 == true && estagio2==false){
    estagio2=true; //Ativa a segunda variavel auxiliar
    a=0;
  }
 
  // Testa se o tempo em alta da primeira onda ultrapassou 200ms
  if(estagio1==true && estagio2==false){
    // Essa parte adiciona + 1 à variavel 'a' enquanto a onda esta em nivel alto; se a onda continuar em nivel alto por 200ms, o programa volta pro inicio
    delay(1);
    a++;
    if(a>200){
      estagio1=false; //Manda o programa voltar pra etapa 0
    }
  }

  // Testa se o tempo em alta da primeira onda ultrapassou 700ms
  if(estagio2==true){
    // Essa parte adiciona + 1 a variavel 'a' enquanto a onda esta em nivel baixo (etapa 2 true e etapa 3 false); se a onda continuar em nivel baixo por 200ms, o programa volta pro inciio
    if(estagio3 == false){
      delay(1);
      a++;
      if(a>700){
        estagio1=false; //Manda o programa voltar pra etapa 0
        estagio2=false;
      }
    }
 
    // Se a variavel 'a' chegar no minimo a 70ms (tempo em baixa) o programa pode começar a verificação da segunda onda
    // Esse tempo de 70us serve para o programa nao confundir vibrações que ocorrem em intervalos de tempo muito pequenos
    if(a>70){
      //Teste do segundo bater de palmas
      if(valor==true && estagio2 == true && estagio3 == false){ //Testa se o pino foi pra alta (observe que o estagio2== true é redundante, mas vou manter para facilitar o entendimento)
        estagio3=true; //Ativa a terceira variavel auxiliar
        b=0;//Volta o temporizador b para 0
      }

      // Agora testa se o pino que estava em alta abaixou (neste caso testa se ocorreu o bater de palmas duas vezes
      if(valor==false && estagio3 == true){
        digitalWrite(led, !digitalRead(led));//Inverte o sinal do LED
        estagio1=false; //Volta o programa voltar pra etapa 0
        estagio2=false;
        estagio3=false;
        delay(1000); //Cria um delay ate a proxima amostragem para nao misturar os dados
      }

      // Testa se o tempo em alta da segunda onda ultrapassou 200ms
      if(estagio3==true){
        // Esta parte adiciona + 1 a variavel 'b' enquanto a onda (segunda) esta em nivel alto; se a onda continuar em nivel alto por 200ms, o programa volta pro inicio
        delay(1);
        b++;
        if(b>200){
          estagio1=false; // Se sim, manda o programa voltar pra etapa 0
          estagio2=false;
          estagio3=false;
        }
      }
    }
  }

  delayMicroseconds(1/44100*1000000);//Delay de 44Khz (frequencia comum para gravação de audio)
}