/*
RPMStepper com Controle por Potenciômetro e Display OLED
Este programa permite controlar a velocidade de um motor de passo através
de um potenciômetro conectado ao pino A0 e exibe as informações atuais
em um display OLED SSD1306.
Características:
- Controle de velocidade (0-100 RPM) via potenciômetro
- Exibição da velocidade atual e direção no display OLED
- Botão para alternar direção (conectado ao pino 2)
- Botão para parada de emergência (conectado ao pino 7)
*/
#include "RPMStepper.h"
#include <Wire.h>
#include <Adafruit_GFX.h> // Biblioteca gráfica core
#include <Adafruit_SSD1306.h> // Biblioteca específica para display SSD1306
// Definições do display OLED
#define SCREEN_WIDTH 128 // Largura do OLED em pixels
#define SCREEN_HEIGHT 64 // Altura do OLED em pixels
#define OLED_RESET -1 // Pino de reset (-1 se compartilhar o reset do Arduino)
#define SCREEN_ADDRESS 0x3C // Endereço I2C do display (pode ser 0x3D para alguns displays)
// Definições dos pinos do motor
#define PULSE_PIN 3 // Pino conectado ao STEP do driver
#define DIR_PIN 4 // Pino conectado ao DIR do driver
#define ENABLE_PIN 6 // Pino conectado ao ENABLE do driver
// Definições dos pinos de controle
#define POT_PIN A0 // Potenciômetro para controle de velocidade
#define DIR_BTN_PIN 2 // Botão para alternar direção
#define STOP_BTN_PIN 8 // Botão para parada de emergência
// Passos por revolução do motor
#define STEPS_PER_REV 200
// RPM máximo (valor máximo do potenciômetro)
#define MAX_RPM 100
// Cria os objetos
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
RPMStepper motor(PULSE_PIN, DIR_PIN, ENABLE_PIN, STEPS_PER_REV);
// Variáveis globais para controle
bool motorEnabled = true; // Estado de ativação do motor
float targetRPM = 0; // RPM alvo baseado no potenciômetro
bool isClockwise = true; // Direção do motor
unsigned long lastPotRead = 0; // Último momento de leitura do potenciômetro
unsigned long lastDisplayUpdate = 0; // Último momento de atualização do display
// Variáveis para debounce dos botões
bool lastDirBtnState = HIGH;
bool lastStopBtnState = HIGH;
unsigned long lastDirBtnDebounce = 0;
unsigned long lastStopBtnDebounce = 0;
unsigned long debounceDelay = 50; // Tempo de debounce em ms
void setup() {
Serial.begin(115200);
Serial.println("Iniciando RPMStepper com Controle OLED");
// Configuração dos pinos dos botões
pinMode(DIR_BTN_PIN, INPUT_PULLUP); // Botão de direção com pull-up interno
pinMode(STOP_BTN_PIN, INPUT_PULLUP); // Botão de parada com pull-up interno
// Inicializa o display OLED
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("Erro ao inicializar SSD1306"));
for(;;); // Loop infinito em caso de falha
}
// Configurações iniciais do display
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println(F("Inicializando..."));
display.display();
delay(1000);
// Configura o motor
motor.setAcceleration(30); // Aceleração de 30 RPM por segundo
motor.enable(); // Ativa o motor
// Exibe tela inicial
updateDisplay();
}
void loop() {
// Lê o potenciômetro a cada 100ms para evitar flutuações
if (millis() - lastPotRead > 100) {
int potValue = analogRead(POT_PIN);
// Mapeia o valor do potenciômetro (0-1023) para RPM (0-MAX_RPM)
targetRPM = map(potValue, 0, 1023, 0, MAX_RPM * 100) / 100.0;
motor.setRPM(targetRPM);
lastPotRead = millis();
}
// Verifica o botão de direção com debounce
int dirBtnReading = digitalRead(DIR_BTN_PIN);
if (dirBtnReading != lastDirBtnState) {
lastDirBtnDebounce = millis();
}
if ((millis() - lastDirBtnDebounce) > debounceDelay) {
if (dirBtnReading == LOW && lastDirBtnState == HIGH) {
// Botão de direção foi pressionado
isClockwise = !isClockwise; // Inverte a direção
motor.setDirection(isClockwise);
Serial.print("Direção alterada para: ");
Serial.println(isClockwise ? "Horário" : "Anti-horário");
}
}
lastDirBtnState = dirBtnReading;
// Verifica o botão de parada de emergência com debounce
int stopBtnReading = digitalRead(STOP_BTN_PIN);
if (stopBtnReading != lastStopBtnState) {
lastStopBtnDebounce = millis();
}
if (digitalRead(STOP_BTN_PIN)) {
// Botão de parada foi pressionado
if (motorEnabled) {
Serial.println("Parada de emergência acionada!");
motor.emergencyStop();
motorEnabled = false;
} else {
Serial.println("Motor reativado!");
motor.enable();
motorEnabled = true;
}
}
lastStopBtnState = stopBtnReading;
// Executa o motor (deve ser chamado continuamente)
motor.run();
// Atualiza o display a cada 200ms
if (millis() - lastDisplayUpdate > 200) {
updateDisplay();
lastDisplayUpdate = millis();
}
}
// Função para atualizar as informações no display OLED
void updateDisplay() {
display.clearDisplay();
// Título
display.setTextSize(1);
display.setCursor(0, 0);
display.println(F("RPMStepper Controller"));
display.drawLine(0, 9, display.width(), 9, SSD1306_WHITE);
// Informações do Motor
display.setTextSize(1);
display.setCursor(0, 12);
display.print(F("Status: "));
if (motorEnabled) {
display.println(motor.getCurrentRPM() > 0 ? F("RODANDO") : F("PARADO"));
} else {
display.println(F("DESATIVADO"));
}
// RPM Atual
display.setTextSize(2);
display.setCursor(0, 24);
display.print(motor.getCurrentRPM(), 1);
display.print(F(" RPM"));
// RPM Alvo
display.setTextSize(1);
display.setCursor(0, 42);
display.print(F("Alvo: "));
display.print(targetRPM, 1);
display.println(F(" RPM"));
// Direção
display.setCursor(0, 52);
display.print(F("Direcao: "));
display.println(isClockwise ? F("HORARIO") : F("ANTI-HOR"));
// Desenha uma pequena barra de progresso para RPM
int barWidth = map(int(motor.getCurrentRPM()), 0, MAX_RPM, 0, SCREEN_WIDTH - 2);
display.drawRect(0, SCREEN_HEIGHT - 7, SCREEN_WIDTH, 7, SSD1306_WHITE);
if (barWidth > 0) {
display.fillRect(1, SCREEN_HEIGHT - 6, barWidth, 5, SSD1306_WHITE);
}
display.display();
}