#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <AccelStepper.h>
#include <Encoder.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define STEP_PIN 9
#define DIR_PIN 8
AccelStepper stepper(AccelStepper::DRIVER, STEP_PIN, DIR_PIN);
#define ENC_A 2 // Rotary encoder pin A
#define ENC_B 3 // Rotary encoder pin B
#define BTN_DIRECTION 4
#define BTN_START_STOP 5
#define POT_PIN A0 // Potentiometer connected to A0
Encoder encoder(ENC_A, ENC_B);
int turns = 5;
bool direction = true; // true = CW, false = CCW
bool running = false;
bool paused = false;
bool reversing = false;
long currentTurn = 0;
long lastEncoderPos = 0;
void setup() {
pinMode(BTN_DIRECTION, INPUT_PULLUP);
pinMode(BTN_START_STOP, INPUT_PULLUP);
stepper.setMaxSpeed(3300);
stepper.setAcceleration(100);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
updateDisplay();
}
void loop() {
handleSpeedAdjustment(); // Read potentiometer and set speed
handleEncoder(); // Handle rotary encoder input
if (digitalRead(BTN_DIRECTION) == LOW) {
if (!running) { // Allows direction change when stopped
direction = !direction;
updateDisplay();
} else if (paused) {
direction = !direction;
updateDisplay();
} else {
reverseWinding();
}
delay(200);
}
if (digitalRead(BTN_START_STOP) == LOW) {
if (!running) {
startWinding();
} else if (paused) {
resumeWinding();
} else {
pauseWinding();
}
delay(500);
}
if (running && !paused) {
stepper.run();
currentTurn = stepper.distanceToGo() / 200;
updateDisplay();
}
}
void handleEncoder() {
long newEncoderPos = encoder.read() / 4; // Adjust sensitivity
if (newEncoderPos != lastEncoderPos) {
int change = lastEncoderPos - newEncoderPos; // Reverse the direction
turns += change;
lastEncoderPos = newEncoderPos;
updateDisplay();
}
}
void handleSpeedAdjustment() {
int potValue = analogRead(POT_PIN); // Read potentiometer (0-1023)
float minSpeed = 1000; // Min speed in steps/sec (1 rotation/sec)
float maxSpeed = 1000; // Max speed in steps/sec (1000 RPM for 200-step motor)
float mappedSpeed = map(potValue, 0, 1023, minSpeed, maxSpeed);
stepper.setMaxSpeed(mappedSpeed);
stepper.setSpeed(direction ? mappedSpeed : -mappedSpeed);
}
void startWinding() {
running = true;
paused = false;
reversing = false;
stepper.setAcceleration(100);
stepper.move(turns * (direction ? 1 : -1) * 200);
updateDisplay();
}
void pauseWinding() {
paused = true;
stepper.setSpeed(0);
updateDisplay();
}
void resumeWinding() {
paused = false;
reversing = false;
updateDisplay();
}
void reverseWinding() {
if (paused) {
reversing = !reversing;
stepper.setSpeed(reversing ? (direction ? -500 : 500) : 0);
updateDisplay();
}
}
void updateDisplay() {
display.clearDisplay();
display.setCursor(0, 0);
display.print("Turns: ");
display.println(turns);
display.print("Current: ");
display.println(currentTurn);
display.print("Direction: ");
display.print(direction ? "CW " : "CCW ");
display.print(direction ? "\x10 " : "\x11 "); // Up arrow for CW, Down arrow for CCW
display.setTextColor(WHITE);
display.setCursor(0, 50);
display.print("Status: ");
if (running) {
if (paused) {
display.print("Paused");
} else {
display.print("Running");
}
} else {
display.print("Stopped");
}
display.display();
}