#include <Wire.h>
#include <Keypad.h>
#include <Adafruit_SSD1306.h>
#include <AccelStepper.h>
#define OLED_WIDTH 128
#define OLED_HEIGHT 64
#define OLED_ADDR 0x3C // OLED I2C address
Adafruit_SSD1306 display(OLED_WIDTH, OLED_HEIGHT);
#define dirPin 10 // Direction pin for the stepper motor.
#define stepPin 9 // Step pin for the stepper motor.
#define motorInterfaceType 1
#define beep 11 // Buzzer pin
AccelStepper stepper = AccelStepper(motorInterfaceType, stepPin, dirPin);
volatile long CtaEnc = 0; // Position relative to the target (encoder count).
int Vmax = 255; // Maximum PWM value.
int Vmin = 20; // Minimum PWM value without stopping the motor.
int Vprom = 195; // Average speed.
int Fvel = 0; // Speed reduction factor.
int Steps = 0; // Number of steps to move.
int Repetitions = 0; // Number of times to repeat the movement.
int MotorDirection = 1; // Motor direction (1 for forward, -1 for backward).
int MotorSpeed = 100; // Motor speed percentage (0 to 100%).
int BlinkDelay = 500; // Delay for blinking effect.
byte col = 42; // Column for display.
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1', '2', '3', '@'},
{'4', '5', '6', '§'},
{'7', '8', '9', 'é'},
{'*', '0', '#', 'D'}
};
byte colPins[COLS] = {A3, A2, A1, A0}; // Column pins.
byte rowPins[ROWS] = {6, 5, 4, 3}; // Row pins.
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
char key;
boolean entryComplete;
boolean isSettingSteps = true; // Flag to switch between setting steps, repetitions, speed, and position.
boolean isSettingReps = false; // Flag to set repetitions.
boolean isSettingSpeed = false; // Flag to set speed.
boolean isSettingPos = false; // Flag to set position.
boolean startMotor = false; // Flag to start the motor.
unsigned long lastBlinkTime = 0; // For handling the blink effect.
boolean blinkState = false; // For controlling blinking.
void setup() {
pinMode(beep, OUTPUT); // Initialize buzzer pin
stepper.setMaxSpeed(1000);
stepper.setAcceleration(500);
display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);
display.setTextSize(1); // Use smaller text size
display.setTextColor(WHITE);
display.clearDisplay();
display.setCursor(0, 0);
display.print("Set Steps:");
display.display();
delay(100);
}
void loop() {
readKeypad(); // Handle keypad input.
updateDisplay(); // Update the display with current values and blinking effect.
if (startMotor) {
executeSteps(); // Start motor only when flag is set.
startMotor = false; // Reset the flag after starting the motor.
}
}
void updateDisplay() {
display.clearDisplay();
display.setTextSize(1); // Use smaller text size
unsigned long currentTime = millis();
if (currentTime - lastBlinkTime >= BlinkDelay) {
lastBlinkTime = currentTime;
blinkState = !blinkState; // Toggle blink state.
}
if (isSettingSteps) {
display.setCursor(0, 0);
display.print(blinkState ? "> Steps: " : " Steps: ");
display.print(Steps);
} else {
display.setCursor(0, 0);
display.print(" Steps: ");
display.print(Steps);
}
if (isSettingReps) {
display.setCursor(0, 10);
display.print(blinkState ? "> Reps: " : " Reps: ");
display.print(Repetitions);
} else {
display.setCursor(0, 10);
display.print(" Reps: ");
display.print(Repetitions);
}
if (isSettingSpeed) {
display.setCursor(0, 20);
display.print(blinkState ? "> Speed: " : " Speed: ");
display.print(MotorSpeed);
display.print("%");
} else {
display.setCursor(0, 20);
display.print(" Speed: ");
display.print(MotorSpeed);
display.print("%");
}
if (isSettingPos) {
display.setCursor(0, 30);
display.print(blinkState ? "> Pos: " : " Pos: ");
display.print(stepper.currentPosition());
} else {
display.setCursor(0, 30);
display.print(" Pos: ");
display.print(stepper.currentPosition());
}
display.setCursor(0, 40);
display.print("Dir: ");
display.print(MotorDirection == 1 ? "Forward" : "Backward");
display.display();
}
void readKeypad() {
key = keypad.getKey();
if (key) {
tone(beep, 4000, 10); // Sound buzzer when a key is pressed.
if (isDigit(key)) {
// Process numeric input based on the current mode.
int digit = key - '0';
if (isSettingSteps) {
Steps = Steps * 10 + digit;
} else if (isSettingSpeed) {
MotorSpeed = MotorSpeed * 10 + digit;
MotorSpeed = constrain(MotorSpeed, 0, 100); // Limit speed to 0-100%.
} else if (isSettingReps) {
Repetitions = Repetitions * 10 + digit;
} else if (isSettingPos) {
stepper.setCurrentPosition(stepper.currentPosition() + digit);
}
} else if (key == '#') {
// Switch between Steps, Reps, Speed, and Position.
if (isSettingSteps) {
isSettingSteps = false;
isSettingReps = true;
} else if (isSettingReps) {
isSettingReps = false;
isSettingSpeed = true;
} else if (isSettingSpeed) {
isSettingSpeed = false;
isSettingPos = true;
} else if (isSettingPos) {
isSettingPos = false;
isSettingSteps = true;
}
} else if (key == 'D') {
// Start motor when 'D' is pressed.
startMotor = true;
} else if (key == 'é') {
// Enter Speed setting mode.
isSettingSteps = false;
isSettingReps = false;
isSettingSpeed = true;
} else if (key == '@') {
// Toggle motor direction.
MotorDirection = -MotorDirection;
} else if (key == '*') {
// Handle delete function.
if (isSettingSteps && Steps > 0) {
Steps /= 10;
} else if (isSettingReps && Repetitions > 0) {
Repetitions /= 10;
} else if (isSettingSpeed && MotorSpeed > 0) {
MotorSpeed /= 10;
}
}
}
}
void executeSteps() {
stepper.setMaxSpeed(map(MotorSpeed, 0, 100, 0, 1000)); // Map motor speed percentage to actual speed value.
for (int i = 0; i < Repetitions; i++) {
stepper.setCurrentPosition(0);
stepper.moveTo(Steps * MotorDirection);
while (stepper.distanceToGo() != 0) {
stepper.run();
}
delay(1000); // Delay between repetitions.
}
}