Quem trabalha com máquinas operatrizes ou oficinas em geral sabe como é útil ter uma leitura precisa da velocidade de rotação do equipamento. Recentemente, desenvolvi um projeto para instalar um sensor Hall e um display de 7 segmentos no meu torno mecânico usando um Arduino Nano.
A grande vantagem dessa implementação é que o circuito ganhou dupla função:
1. Modo F001 (Tacômetro / RPM): Mede as rotações por minuto em tempo real.
2. Modo F002 (Contador de Voltas): Conta o número total de voltas acumuladas, ideal para tarefas de precisão como enrolamento de fios, bobinas e transformadores.
Como Funciona o Circuito
O sensor Hall fica posicionado no eito/árvore do torno para detectar a passagem de um pequeno ímã. Cada passagem aciona uma interrupção digital no pino D2 do Arduino Nano, garantindo que nenhum pulso seja perdido, mesmo em altas velocidades.
O painel conta com um display de 7 segmentos de 4 dígitos (gerenciado pela biblioteca SevSeg) e dois botões de controle:
- Botão SET (pino A4): Alterna entre as funções F001 (RPM) e F002 (Contador de Voltas), exibindo a indicação da função escolhida no display por 2 segundos.
- Botão RESET (pino A5): Zera a contagem de voltas quando o sistema está no modo F002.
Aplicações Práticas
- Uso em Usinagem: Acompanhar a rotação exata ajuda a selecionar a velocidade de corte adequada para diferentes materiais e ferramentas.
- Uso como Rebobinadora: O modo contador facilita imensamente o enrolamento de bobinas, pequenos transformadores e motores de forma precisa sem precisar contar manualmente.
Código Completo para Arduino Nano
(NOVO) Código disponível para download em: https://github.com/aobatroz/rpmcounter-4digit-display
Abaixo está o código-fonte desenvolvido. Para compilá-lo, certifique-se de ter a biblioteca SevSeg instalada na sua IDE do Arduino:
#include <SevSeg.h>
SevSeg sevseg;
#define MAX_WAIT_FREQ 2000
const byte ledPin = 13;
const byte interruptPin = 2; // contador de pulso (Sensor Hall)
const byte setButtonPin = A4; // botao set
const byte resetButtonPin = A5; // botao reset
const byte digitPins[] = {A0, 3, 4, 5}; // pinos dos digitos do display
const byte segmentPins[] = {6, 7, 8, 9, 10, 11, 12, 13}; // pinos dos segmentos
unsigned long interruptCount = 0; // Contador de interrupcoes
unsigned long rpmCount = 0;
double rps = 0;
unsigned long lastPulse = millis();
unsigned long interval = 0;
unsigned long refreshTime = millis();
unsigned int mode = 0;
unsigned int functionMode = 1; // 1 para F001 (RPM), 2 para F002 (Contador)
bool forceDisplayValue = false;
void interruptFunction()
{
interval = millis() - lastPulse;
lastPulse = millis();
interruptCount++; // Incrementa o contador de interrupcoes
}
void displayFunctionMode()
{
char buffer[5];
snprintf(buffer, sizeof(buffer), "F00%d", functionMode); // Formata a string F00X
sevseg.setChars(buffer); // Exibe no display
for (unsigned long start = millis(); millis() - start < 2000;) { // Exibe por 2 segundos
sevseg.refreshDisplay();
}
sevseg.blank(); // Apaga o display
sevseg.refreshDisplay();
}
void setup()
{
Serial.begin(9600);
const byte numDigits = 4;
bool resistorsOnSegments = 0;
pinMode(interruptPin, INPUT_PULLUP);
pinMode(setButtonPin, INPUT_PULLUP);
pinMode(resetButtonPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), interruptFunction, RISING);
sevseg.begin(COMMON_CATHODE, numDigits, digitPins, segmentPins, resistorsOnSegments);
sevseg.setBrightness(10);
displayFunctionMode();
}
void F001()
{
// Calculando rps (rotacoes por segundo)
rps = 0;
if (interval > 0 && (millis() - lastPulse) < MAX_WAIT_FREQ) // ignora leituras muito lentas
{
rps = 1000.0 / interval;
}
if ((millis() > refreshTime))
{
Serial.println(rps);
sevseg.setNumber(rps * 60); // Converte RPS para RPM
refreshTime = millis() + 200;
}
}
void F002()
{
static unsigned long lastInterruptCount = -1;
if (digitalRead(resetButtonPin) == LOW)
{
interruptCount = 0; // Reseta o contador
}
if ((lastInterruptCount != interruptCount) || forceDisplayValue)
{
lastInterruptCount = interruptCount;
Serial.println(interruptCount);
sevseg.setNumber(interruptCount);
forceDisplayValue = false;
}
}
void loop()
{
// Alterna o modo ao pressionar o botao SET
if (digitalRead(setButtonPin) == LOW)
{
functionMode = (functionMode % 2) + 1; // Alterna entre 1 e 2
displayFunctionMode(); // Exibe o modo por 2 segundos
forceDisplayValue = true;
delay(200); // Debounce
}
if (functionMode == 1)
{
F001();
}
else if (functionMode == 2)
{
F002();
}
sevseg.refreshDisplay();
}
Se você gostou da ideia, pretende aplicar em alguma máquina aí da sua oficina ou tem sugestões de melhorias no código, deixe seu comentário!

