Projetos

Metrônomo com Arduino

Eletrogate 6 de fevereiro de 2026

Introdução

Neste artigo, apresento um projeto de metrônomo com Arduino que explora duas abordagens distintas de controle de andamento, ambas voltadas à prática musical. A primeira utiliza controle analógico por potenciômetro, sem display, priorizando simplicidade e resposta imediata; a segunda emprega controle digital por botões com exibição precisa do valor de BPM em display.
Em ambas as versões, a geração do pulso rítmico é baseada no uso da função millis(), permitindo o controle preciso do tempo sem interrupções bloqueantes, aproximando a lógica computacional do funcionamento real de um metrônomo musical. A comparação entre essas abordagens evidencia como diferentes soluções de interface podem atender a necessidades musicais distintas, mesmo quando o objetivo funcional permanece o mesmo.

O Metrônomo

O metrônomo é um dispositivo utilizado para fornecer uma referência temporal regular, permitindo ao músico manter um andamento constante durante a execução musical. Sua função principal não é apenas “marcar o tempo”, mas auxiliar no desenvolvimento de aspectos fundamentais da performance, como precisão rítmica, estabilidade de andamento, coordenação motora e controle do pulso interno. Ao praticar com metrônomo, o músico aprende a relacionar sua execução a uma referência externa objetiva, reduzindo oscilações involuntárias de tempo e tornando o discurso musical mais consistente.
Na prática, o metrônomo marca pulsos regulares organizados a partir do conceito de BPM (batidas por minuto), que define quantas ocorrências desse pulso acontecem em um intervalo de um minuto. Cada batida corresponde a uma unidade temporal fixa — geralmente associada a uma figura rítmica, como a semínima — e serve como base para a organização do ritmo musical. Ao ajustar o BPM, o músico controla diretamente o andamento da execução, podendo estudar desde passagens em velocidades reduzidas até trechos em andamentos mais elevados, sempre mantendo uma referência temporal constante.

A Função millis()

A função millis() é um dos elementos centrais deste projeto, pois fornece a base de temporização utilizada para a geração do pulso rítmico do metrônomo. Ela retorna o tempo, em milissegundos, decorrido desde a inicialização do microcontrolador, permitindo que o programa acompanhe a passagem do tempo de forma contínua.
No contexto do metrônomo, a função millis() é utilizada para medir o intervalo entre batidas consecutivas. A cada pulso gerado, o instante atual é registrado e comparado com o tempo corrente do sistema. Quando a diferença entre esses valores atinge o intervalo correspondente ao andamento definido em BPM, um novo pulso é emitido.
// Lógica do metrônomo
  unsigned long agora = millis();
  
  if (tocando) {
    if (agora - ultimaBatida >= intervalo) {
      ultimaBatida = agora;

      // chame a função a ser realizada a cada atividade períodica ('tone' no caso do metrônomo)
    }
  }
Essa abordagem permite converter diretamente o conceito musical de batidas por minuto em um intervalo temporal em milissegundos, estabelecendo uma relação clara entre tempo musical e tempo computacional. Dessa forma, a função millis() atua como o relógio interno do sistema, sustentando o funcionamento do metrônomo independentemente da forma de controle adotada, seja por potenciômetro ou por botões com display.

Desenvolvimento

Metrônomo com controle analógico

Na versão de controle analógico, o ajuste de andamento é realizado por meio de um potenciômetro, que fornece um valor contínuo ao conversor analógico-digital (ADC) do microcontrolador. Esse valor é mapeado para uma faixa musicalmente útil de BPM, permitindo variações suaves de andamento, semelhantes ao comportamento de metrônomos mecânicos tradicionais. A interface é intencionalmente simples, dispensando o uso de display numérico, o que reduz a complexidade do sistema e favorece uma interação mais direta com o andamento musical.
Um LED é utilizado como indicação visual do pulso do metrônomo, oferecendo ao músico um segundo tipo de feedback durante a execução. Essa referência visual pode auxiliar na percepção do tempo, a combinação entre som e luz mantém a interface simples, ao mesmo tempo em que amplia as possibilidades de percepção do pulso.

Do ponto de vista do desenvolvimento, essa versão se destaca pela facilidade de adaptação e experimentação. Parâmetros como o valor mínimo e máximo de BPM podem ser ajustados diretamente no código, permitindo que o mesmo projeto seja adaptado a diferentes contextos musicais, níveis técnicos ou objetivos de estudo. Essa característica torna o metrônomo analógico uma ferramenta flexível, tanto para uso musical quanto para fins didáticos, ao evidenciar a relação direta entre código, comportamento do sistema e resultado musical.

 

// ---------- codigo 1 - 3.1 metronomo analogico

int bpm = 60;
int bpmMaximo = 120;
int bpmMinimo = 30;
bool tocando = false;
void atualizarIntervalo() { 
  intervalo = 60000 / bpm;
}

void loop() {
  // Leitura do potenciômetro e mapeamento para BPM
  int leituraPot = analogRead(potPin);
  bpm = map(leituraPot, 0, 1023, bpmMinimo, bpmMaximo);
  atualizarIntervalo();
}

Metrônomo com controle digital

Na versão de controle digital, o ajuste de andamento é realizado por meio de botões, permitindo a definição explícita e precisa do valor de BPM. Diferentemente do controle contínuo por potenciômetro, essa abordagem trabalha com valores discretos, incrementados ou decrementados de acordo com a interação do usuário. O valor atual de BPM é exibido em um display LCD, fornecendo uma referência visual objetiva e imediata do andamento selecionado.
Ao trabalhar com valores numéricos exatos, o músico pode retomar exercícios sempre no mesmo BPM, acompanhar progressões graduais de tempo (por exemplo, aumentar 5 ou 10 BPM por etapa) e documentar com clareza os parâmetros utilizados em sua rotina de prática. Nesse sentido, o metrônomo digital se aproxima da lógica dos metrônomos eletrônicos comerciais, nos quais a exatidão do valor de BPM é um elemento central.
// ---------- codigo 2 - 3.2 metronomo digital

void atualizarLCD() {
  lcd.setCursor(0, 1);
  lcd.print("BPM:");
  if (bpm < 100) lcd.print(" ");
  lcd.print(bpm);
  lcd.print(tocando ? " PLAY " : " PAUSE");
}

// Dentro do LOOP:
  // Ajuste de BPM
  if (botaoCima) {
    bpm += 10;
    if (bpm > bpmMaximo) bpm = bpmMaximo;
    atualizarLCD();
    delay(150); //debounce
  }
  else if (botaoBaixo) {
    bpm -= 10;
    if (bpm < bpmMinimo) bpm = bpmMinimo;
    atualizarLCD();
    delay(150); //debounce
  }
  else if (botaoDireita) {
    bpm += 1;
    if (bpm > bpmMaximo) bpm = bpmMaximo;
    atualizarLCD();
    delay(150); //debounce
  }
  else if (botaoEsquerda) {
    bpm -= 1;
    if (bpm < bpmMinimo) bpm = bpmMinimo;
    atualizarLCD();
    delay(150); //debounce
  }

  // Play / Pause
  if (botaoSelect && !ultimoEstadoSelect) {
    tocando = !tocando;
    atualizarLCD();

    if (!tocando) {
      digitalWrite(LEDdisplay, HIGH); // no pause, LED fica aceso
    }

    delay(150); //debounce
  }

  // Play / Pause
  if (botaoSelect && !ultimoEstadoSelect) {
    tocando = !tocando;
    atualizarLCD();
  }

Assim como na versão analógica, o metrônomo digital fornece feedback sonoro por meio de um buzzer e também oferece uma referência visual do pulso. Nesta implementação, a indicação visual é realizada utilizando o próprio LED integrado ao shield de display e botões, dispensando componentes externos adicionais. Esse LED é sincronizado com cada batida do metrônomo, funcionando como um indicador visual direto do pulso para o músico.

Aplicando o Fundamento

Antes de seguir, vale um convite ao leitor: use a imaginação. O objetivo central deste artigo não é apresentar um único tipo de metrônomo, mas explicar os fundamentos da criação de um metrônomo digital a partir da função millis(). Uma vez compreendida essa lógica básica de temporização, o mesmo princípio pode ser adaptado a diferentes projetos, interfaces e formas de visualização do pulso musical.
Como exemplo dessa flexibilidade, apresenta-se aqui uma adaptação do código do metrônomo analógico, na qual a indicação visual por LED é substituída pelo movimento de um servo motor, resultando em um metrônomo de referência pendular. Do ponto de vista musical, o conceito permanece o mesmo: a cada pulso definido pelo BPM, ocorre um evento periódico. O que muda é apenas a forma de apresentação desse evento ao músico.
// ---------- codigo 3 - 3.3 metronomo servo

// Config do Servo Motor
#include <Servo.h>
const int servo = 9;
Servo myservo; 
int direita = 100;
int esquerda = 80;
bool servoNaDireita = false;

void servo_direita(){
  myservo.write(direita);
}
void servo_esquerda(){
  myservo.write(esquerda);
}

// Dentro do LOOP:
// Acionamento por switch
  bool estadoPlayPause = digitalRead(botaoPlayPause);
  if (estadoPlayPause == LOW) {
    if (agora - ultimaBatida >= intervalo) {
      ultimaBatida = agora;

      tone(buzzerPin, 1000, 100); // bip

      // Movimento tipo pêndulo
      if (servoNaDireita) {
        servo_esquerda();
        servoNaDireita = false;
      } 
      else {
        servo_direita();
        servoNaDireita = true;
      }
    }
  }

Tecnicamente, essa adaptação exige modificações pontuais no código. A função responsável por acender o LED passa a controlar o movimento do servo, enquanto a lógica de acionamento por botão é substituída por uma chave do tipo switch. A estrutura de temporização baseada em millis() — núcleo do metrônomo — permanece inalterada, reforçando a ideia de que a lógica musical e temporal é independente da interface física escolhida.

Essa abordagem evidencia que compreender os fundamentos do funcionamento de um metrônomo é o ponto de partida para o desenvolvimento de diversas aplicações musicais. Ao dominar a relação entre tempo, BPM e eventos periódicos, torna-se possível transitar entre soluções simples ou mais elaboradas, reutilizando os mesmos conceitos em projetos distintos.

Diagramas

Controle Analógico

 

Controle Digital

 

Controle Analógico + Movimento pendular


Códigos completos

Controle analógico:

// Definição de Pinos

const int buzzerPin = 11;       // buzzer passivo
const int botaoPlayPause = 10; // botão
const int potPin = A0;         // potenciômetro
const int ledPin = 12;         // LED + resistor

// Configurações do Metrônomo
int bpm = 60;
int bpmMaximo = 120;
int bpmMinimo = 30;
bool tocando = false;

unsigned long ultimaBatida = 0;
unsigned long intervalo = 60000 / 60;

// Controle do LED
bool ledAtivo = false;
unsigned long tempoLed = 0;
const unsigned long duracaoLed = 50;

// Atualização do Intervalo
void atualizarIntervalo() { 
  intervalo = 60000 / bpm;
}

// Controle de Play e Pause
bool ultimoEstadoPlayPause = HIGH;

// ----- SETUP -----
void setup() {
  pinMode(buzzerPin, OUTPUT);
  pinMode(botaoPlayPause, INPUT_PULLUP);
  pinMode(potPin, INPUT);
  pinMode(ledPin, OUTPUT);

  digitalWrite(ledPin, LOW); // LED começa apagado
}

// ------ LOOP -----
void loop() {
  // Leitura do potenciômetro e mapeamento para BPM
  int leituraPot = analogRead(potPin);
  bpm = map(leituraPot, 0, 1023, bpmMinimo, bpmMaximo);
  atualizarIntervalo();

  // Botão PLAY / PAUSE
  bool estadoPlayPause = digitalRead(botaoPlayPause);
  if (estadoPlayPause == LOW && ultimoEstadoPlayPause == HIGH) {
    tocando = !tocando;
    delay(300); // debounce simples
  }
  ultimoEstadoPlayPause = estadoPlayPause;

  // Lógica do metrônomo
  unsigned long agora = millis();
  
  if (tocando) {
    if (agora - ultimaBatida >= intervalo) {
      ultimaBatida = agora;

      tone(buzzerPin, 1000, 100); // bip de 100 ms

      // LED pisca na batida
      digitalWrite(ledPin, HIGH);
      ledAtivo = true;
      tempoLed = agora;
    }
  }

  // Desliga o LED após o pulso
  if (ledAtivo && (agora - tempoLed >= duracaoLed)) {
    digitalWrite(ledPin, LOW);
    ledAtivo = false;
  }
}
Controle Digital
// Configurações do Display LCD Shield 16x2 com Teclado para Arduino
#include <LiquidCrystal.h> 
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
const int LEDdisplay = 10;    
const int botaoAnalogico = A0;

// Definição de Pinos
const int buzzerPin = 3; // Buzzer passivo

// Configurações do Metrônomo
int bpm = 60;
int bpmMaximo = 120;
int bpmMinimo = 30;
bool tocando = false;

unsigned long ultimaBatida = 0;
unsigned long intervalo = 60000 / 60;

// Controle do LED
bool ledApagadoNaBatida = false;
unsigned long tempoLed = 0;

// Atualização do LCD
void atualizarLCD() {
  lcd.setCursor(0, 1);
  lcd.print("BPM:");
  if (bpm < 100) lcd.print(" ");
  lcd.print(bpm);
  lcd.print(tocando ? " PLAY " : " PAUSE");
}

// Controle de Play e Pause
bool ultimoEstadoSelect = HIGH;

// ----- SETUP -----
void setup() {
  lcd.begin(16, 2);

  pinMode(buzzerPin, OUTPUT);
  pinMode(botaoAnalogico, INPUT);
  pinMode(LEDdisplay, OUTPUT);

  digitalWrite(LEDdisplay, HIGH); // LED começa aceso

  lcd.setCursor(0, 0);
  lcd.print("Metronomo");
  lcd.setCursor(0, 1);
  lcd.print("BPM:");
  lcd.print(bpm);
  lcd.print(" PAUSE");
}

// ------ LOOP -----
void loop() {
  // Leitura dos botões
  int leitura = analogRead(botaoAnalogico);

  bool botaoCima     = (leitura >= 100 && leitura < 200);
  bool botaoBaixo    = (leitura >= 200 && leitura < 400);
  bool botaoDireita  = (leitura >= 0   && leitura < 100);
  bool botaoEsquerda = (leitura >= 400 && leitura < 600);
  bool botaoSelect   = (leitura >= 600 && leitura < 800);

  // Ajuste de BPM
  if (botaoCima) {
    bpm += 10;
    if (bpm > bpmMaximo) bpm = bpmMaximo;
    atualizarLCD();
    delay(150); //debounce
  }
  else if (botaoBaixo) {
    bpm -= 10;
    if (bpm < bpmMinimo) bpm = bpmMinimo;
    atualizarLCD();
    delay(150); //debounce
  }
  else if (botaoDireita) {
    bpm += 1;
    if (bpm > bpmMaximo) bpm = bpmMaximo;
    atualizarLCD();
    delay(150); //debounce
  }
  else if (botaoEsquerda) {
    bpm -= 1;
    if (bpm < bpmMinimo) bpm = bpmMinimo;
    atualizarLCD();
    delay(150); //debounce
  }

  // Play / Pause
  if (botaoSelect && !ultimoEstadoSelect) {
    tocando = !tocando;
    atualizarLCD();

    if (!tocando) {
      digitalWrite(LEDdisplay, HIGH); // no pause, LED fica aceso
    }

    delay(150); //debounce
  }
  ultimoEstadoSelect = botaoSelect;

  // Lógica do metrônomo
  unsigned long agora = millis();
  intervalo = 60000 / bpm;

  if (tocando) {
    if (agora - ultimaBatida >= intervalo) {
      ultimaBatida = agora;

      tone(buzzerPin, 1000, 100);

      // LED apaga na batida
      digitalWrite(LEDdisplay, LOW);
      ledApagadoNaBatida = true;
      tempoLed = agora;
    }
  }

  // LED acende após a batida
  if (ledApagadoNaBatida && (agora - tempoLed >= 100)) {
    digitalWrite(LEDdisplay, HIGH);
    ledApagadoNaBatida = false;
  }
}

Controle Analógico + Pêndulo por servo motor

// Config do Servo Motor
#include <Servo.h>
const int servo = 9;
Servo myservo; 
int direita = 100;
int esquerda = 80;
bool servoNaDireita = false;

void servo_direita(){
  myservo.write(direita);
}
void servo_esquerda(){
  myservo.write(esquerda);
}

// Definição de Pinos
const int buzzerPin = 12;       // buzzer passivo
const int botaoPlayPause = 10; // switch
const int potPin = A0;         // potenciômetro

// Config do Metrônomo
int bpm = 60;
int bpmMaximo = 120;
int bpmMinimo = 30;
bool tocando = false;
unsigned long ultimaBatida = 0;
unsigned long intervalo = 60000 / 60;

// --------- SETUP ---------
void setup() {
  pinMode(buzzerPin, OUTPUT);
  pinMode(botaoPlayPause, INPUT_PULLUP);
  pinMode(potPin, INPUT);
  myservo.attach(servo);
}

// --------- LOOP ---------
void loop() {
  // Leitura do potenciômetro e mapeamento para BPM
  int leituraPot = analogRead(potPin);
  bpm = map(leituraPot, 0, 1023, bpmMinimo, bpmMaximo);
  intervalo = 60000 / bpm;;
  unsigned long agora = millis();

  // Acionamento por switch
  bool estadoPlayPause = digitalRead(botaoPlayPause);
  if (estadoPlayPause == LOW) {
    if (agora - ultimaBatida >= intervalo) {
      ultimaBatida = agora;

      tone(buzzerPin, 1000, 100); // bip

      // Movimento tipo pêndulo
      if (servoNaDireita) {
        servo_esquerda();
        servoNaDireita = false;
      } 
      else {
        servo_direita();
        servoNaDireita = true;
      }
    }
  }
  
}


Conclusão

Ao longo deste artigo, foi apresentado o conceito de metrônomo a partir de uma perspectiva musical e técnica, explicando como a lógica do pulso e do andamento pode ser traduzida para a lógica de programação por meio do uso da função millis(). Essa abordagem demonstra como um conceito musical abstrato — a organização do tempo em BPM — pode ser implementado de forma objetiva em um sistema embarcado, estabelecendo a base para o funcionamento de um metrônomo digital.
A partir desse fundamento, foram exploradas diferentes formas de aplicação do mesmo núcleo de funcionamento, evidenciando que, com pequenas alterações no código e na interface, é possível obter comportamentos e experiências distintas. As três implementações apresentadas neste artigo — controle analógico, controle digital e metrônomo pendular — mostram como a mesma lógica temporal pode ser reutilizada e adaptada a diferentes propostas.
Dessa forma, o estudo do metrônomo ultrapassa sua função tradicional e passa a atuar como ponto de partida para o desenvolvimento de novas aplicações musicais, reforçando a importância de compreender seus fundamentos antes de explorar soluções mais complexas ou especializadas.
Agradecemos pela leitura e nos vemos na próxima!

Referências

ARDUINO. Arduino Language Reference – millis().
Documentação oficial da função millis(), utilizada como base para a implementação da lógica de temporização dos projetos apresentados.
ARDUINO. Arduino UNO Rev3 – Documentação oficial.
Especificações técnicas e informações sobre o microcontrolador utilizado nos projetos.
WOKWI. Arduino Simulator.
Ambiente de simulação utilizado para testes, prototipagem e elaboração dos diagramas apresentados no artigo.
Disponível em: https://wokwi.com/
ALMADA, Carlos. Harmonia Funcional.
Rio de Janeiro: Lumiar, 2009.
Referência brasileira sobre organização do discurso musical, incluindo aspectos de tempo, pulso e estrutura, utilizados como base conceitual na abordagem musical do artigo.
MED, Bohumil. Teoria da Música.
Brasília: Musimed, 1996.
Obra amplamente adotada no ensino musical no Brasil, utilizada como referência para conceitos fundamentais de ritmo, métrica e andamento.

Sobre o Autor


Erwin de Mattos

 


Lista de Materiais

Eletrogate

6 de fevereiro de 2026

A Eletrogate é uma loja virtual de componentes eletrônicos do Brasil e possui diversos produtos relacionados à Arduino, Automação, Robótica e Eletrônica em geral.

Os comentários estão desativados.

Conheça a Metodologia Eletrogate e Lecione um Curso de Robótica nas Escolas da sua Região!

Eletrogate Robô

Assine nossa newsletter e
receba  10% OFF  na sua
primeira compra!