Mostrando postagens com marcador Sensor Hall. Mostrar todas as postagens
Mostrando postagens com marcador Sensor Hall. Mostrar todas as postagens

domingo, 29 de setembro de 2024

Como transformar um torno em tacômetro e contador de voltas com Arduino e Sensor Hall

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!