#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Keypad.h>
#define CLK 2
#define DT 3
#define STEP_PIN 11
#define DIR_PIN 8
#define JOG_ESQ 14
#define JOG_DIR 15
#define SELECTOR_DIR 16
// Botão RESET
#define RESET_BTN 17
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
volatile long encoderPulses = 0;
volatile int lastCLKstate;
unsigned long startTime;
const int pulsesPerRevolution = 20;
const int stepsPerPulseBase = 160;
long lastDisplayedPulses = 0;
float espessuraDoFio = 1.00;
float passosPorPulso = 160 * 1.00;
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {4, 5, 6, 7};
byte colPins[COLS] = {9, 10, 12, 13};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
bool modoEdicao = false;
char bufferEdicao[4];
byte indexEdicao = 0;
// Controle do reset
unsigned long resetPressStart = 0;
bool resetTriggered = false;
void readEncoder() {
if (millis() - startTime < 300) return;
int currentState = digitalRead(CLK);
if (currentState == HIGH) {
if (digitalRead(DT) == LOW) encoderPulses++;
else encoderPulses--;
}
lastCLKstate = currentState;
}
void setup() {
Serial.begin(9600);
pinMode(CLK, INPUT_PULLUP);
pinMode(DT, INPUT_PULLUP);
lastCLKstate = digitalRead(CLK);
attachInterrupt(digitalPinToInterrupt(CLK), readEncoder, RISING);
pinMode(STEP_PIN, OUTPUT);
pinMode(DIR_PIN, OUTPUT);
pinMode(JOG_ESQ, INPUT_PULLUP);
pinMode(JOG_DIR, INPUT_PULLUP);
pinMode(SELECTOR_DIR, INPUT_PULLUP);
// Botão RESET
pinMode(RESET_BTN, INPUT_PULLUP);
Wire.begin();
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextSize(1); // Fonte menor
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Iniciando...");
display.display();
startTime = millis();
delay(800);
}
void lerTeclado() {
char tecla = keypad.getKey();
if (!tecla) return;
if (tecla == 'A' && !modoEdicao) {
modoEdicao = true;
indexEdicao = 0;
display.clearDisplay();
display.setCursor(0,0);
display.println("Editar fio:");
display.setCursor(0,30);
display.println("d.dd mm");
display.display();
return;
}
if (!modoEdicao) return;
if (tecla == '*') {
modoEdicao = false;
return;
}
if (tecla == '#' && indexEdicao == 3) {
int inteiro = bufferEdicao[0] - '0';
int dec = bufferEdicao[1] - '0';
int cent = bufferEdicao[2] - '0';
espessuraDoFio = inteiro + (dec * 0.1) + (cent * 0.01);
passosPorPulso = 160 * espessuraDoFio;
modoEdicao = false;
Serial.print("Espessura alterada: ");
Serial.println(espessuraDoFio, 2);
return;
}
if (tecla >= '0' && tecla <= '9') {
if (indexEdicao < 3) {
bufferEdicao[indexEdicao++] = tecla;
display.clearDisplay();
display.setCursor(0,0);
display.println("Editar fio:");
display.setCursor(0,30);
display.print(bufferEdicao[0]);
display.print('.');
display.print(bufferEdicao[1]);
display.print(bufferEdicao[2]);
display.println(" mm");
display.display();
}
}
}
// Checa o botão RESET: manter pressionado >= 3000 ms para zerar contadores
void checarReset() {
if (digitalRead(RESET_BTN) == LOW) {
if (resetPressStart == 0) resetPressStart = millis();
if (!resetTriggered && (millis() - resetPressStart >= 3000)) {
// Protege escrita enquanto a interrupção pode alterar encoderPulses
noInterrupts();
encoderPulses = 0;
interrupts();
lastDisplayedPulses = 0;
resetTriggered = true;
// Atualiza display imediatamente mostrando zeros
display.clearDisplay();
display.setCursor(0, 0);
display.println("Voltas:");
display.setCursor(0, 15);
display.print(0.00, 2);
display.setCursor(0, 30);
display.print("Esp: ");
display.print(espessuraDoFio, 2);
display.print(" mm");
display.setCursor(0, 45);
if (digitalRead(SELECTOR_DIR) == HIGH)
display.print("Direita");
else
display.print("Esquerda");
display.display();
Serial.println("Reset executado: contadores zerados.");
}
} else {
// botão solto: reinicia contagem
resetPressStart = 0;
resetTriggered = false;
}
}
void loop() {
lerTeclado();
checarReset();
// ============================================
// JOG ESQUERDA E DIREITA (manual)
// ============================================
if (digitalRead(JOG_ESQ) == LOW) {
digitalWrite(DIR_PIN, LOW);
digitalWrite(STEP_PIN, HIGH);
delayMicroseconds(500);
digitalWrite(STEP_PIN, LOW);
delayMicroseconds(500);
}
if (digitalRead(JOG_DIR) == LOW) {
digitalWrite(DIR_PIN, HIGH);
digitalWrite(STEP_PIN, HIGH);
delayMicroseconds(500);
digitalWrite(STEP_PIN, LOW);
delayMicroseconds(500);
}
// ============================================
// ATUALIZAR DIREÇÃO IMEDIATAMENTE
// ============================================
static int ultimaDirecao = -1;
int direcaoAtual = digitalRead(SELECTOR_DIR);
if (direcaoAtual != ultimaDirecao) {
ultimaDirecao = direcaoAtual;
display.clearDisplay();
display.setCursor(0, 0);
display.println("Voltas:");
display.setCursor(0, 15);
display.print(lastDisplayedPulses / (float)pulsesPerRevolution, 2);
display.setCursor(0, 30);
display.print("Esp: ");
display.print(espessuraDoFio, 2);
display.print(" mm");
display.setCursor(0, 45);
if (direcaoAtual == HIGH) display.print("Direita");
else display.print("Esquerda");
display.display();
}
// ============================================
// MOVIMENTO PELO ENCODER
// ============================================
long pulses;
noInterrupts();
pulses = encoderPulses;
interrupts();
if (pulses != lastDisplayedPulses) {
long diff = pulses - lastDisplayedPulses;
lastDisplayedPulses = pulses;
// Direção depende do seletor
if (digitalRead(SELECTOR_DIR) == HIGH)
digitalWrite(DIR_PIN, diff > 0 ? HIGH : LOW);
else
digitalWrite(DIR_PIN, diff > 0 ? LOW : HIGH);
int stepsToMove = abs(diff) * passosPorPulso;
for (int i = 0; i < stepsToMove; i++) {
digitalWrite(STEP_PIN, HIGH);
delayMicroseconds(500);
digitalWrite(STEP_PIN, LOW);
delayMicroseconds(500);
}
float revolutions = pulses / (float)pulsesPerRevolution;
display.clearDisplay();
display.setCursor(0, 0);
display.println("Voltas:");
display.setCursor(0, 15);
display.print(revolutions, 2);
display.setCursor(0, 30);
display.print("Esp: ");
display.print(espessuraDoFio, 2);
display.print(" mm");
display.setCursor(0, 45);
if (digitalRead(SELECTOR_DIR) == HIGH)
display.print("Direita");
else
display.print("Esquerda");
display.display();
}
}