// 5 button LCD and Stepper
// https://wokwi.com/projects/399421219902241793
// 
// modified from https://wokwi.com/projects/396715020656032769

#include <LiquidCrystal.h>
#include <AccelStepper.h>

// Define the pins for the LCD
const int rs = 8, en = 9, d4 = 4, d5 = 5, d6 = 6, d7 = 7, backlightPin = 10;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

// Define the pin for the analog input
const int buttonPin = A0;

// Define the pins for the stepper motor driver
const int stepPin = 11;
const int dirPin = 12;

// Create a new instance of the AccelStepper class
AccelStepper stepper(1, stepPin, dirPin);

long currentValue = 0; // Stores the current value entered by the user
int currentDirection = 1; // Stores the current direction of the stepper motor (1: forward, -1: backward)
int defaultSpeed = 1000; // Default speed of the stepper motor

unsigned long lastActivityTime = 0; // Stores the time of the last activity in the secret menu
const unsigned long timeoutDuration = 10000; // Timeout duration (in milliseconds) for the secret menu

void setup() {
  // Set up the LCD
  lcd.begin(16, 2);

  // Set up the backlight pin for PWM
  pinMode(backlightPin, OUTPUT);
  analogWrite(backlightPin, 128); // Set backlight intensity to 50%

  // Set up the stepper motor
  stepper.setMaxSpeed(defaultSpeed); // Set the maximum speed of the stepper motor
  stepper.setAcceleration(200);

  // Print the initial value, direction, and default speed on the LCD
  printValueAndDirection();

  // Initialize Serial communication
  Serial.begin(115200);
}

void loop() {
  // Read analog input to determine the button state
  static int last = -1;
  int buttonState = analogRead(buttonPin);
  if (buttonState != last) {
    last = buttonState;
    // Print raw ADC reading to the serial console
    Serial.println(buttonState);

    switch (buttonState) {
      case 0 ... 49: // Right button
        handleRightButton();
        break;
      case 300 ... 400: // Up button
        handleUpButton();
        break;
      case 100 ... 150: // Down button
        handleDownButton();
        break;
      case 500 ... 620: // Left button
        handleLeftButton();
        break;
      case 720 ... 830: // Select button
        handleSelectButton();
        break;
      default: // No button press
        break;
    }

  }
  // Run the stepper motor
  stepper.run();
}

// Function to handle the right button press
void handleRightButton() {
  // Handle the right button press
  currentDirection = 1;
  printValueAndDirection();
}

// Function to handle the up button press
void handleUpButton() {
  // Handle the up button press
  incrementCurrentValue();
}

// Function to handle the down button press
void handleDownButton() {
  // Handle the down button press
  decrementCurrentValue();
}

// Function to handle the left button press
void handleLeftButton() {
  // Handle the left button press
  currentDirection = -1;
  printValueAndDirection();
}

// Function to handle the select button press
void handleSelectButton() {
  lcd.setCursor(13, 0);
  lcd.print("RUN");
  moveStepper(currentValue * currentDirection); // Move the stepper motor
  lcd.setCursor(13, 0);
  lcd.print("   ");
}

// Function to increment the value
void incrementCurrentValue() {
  currentValue++;
  if (currentValue > 9999) {
    currentValue = 0; // Wrap around if the value exceeds 9999
  }
  printValueAndDirection();
}

// Function to decrement the value
void decrementCurrentValue() {
  currentValue--;
  if (currentValue < 0) {
    currentValue = 9999; // Wrap around if the value goes below 0
  }
  printValueAndDirection();
}

// Function to print the value and direction on the LCD
void printValueAndDirection() {
  lcd.clear();
//  lcd.setCursor(0, 0);
  lcd.print("Pocet kroku/steps");
  lcd.setCursor(0, 1);
  if (currentDirection == 1) {
    lcd.print("   ");
    lcd.print(currentValue);
    lcd.print(" >>");
  } else {
    lcd.print("<< ");
    lcd.print(currentValue);
    lcd.print("   ");
  }
}

// Function to move the stepper motor
void moveStepper(long steps) {
  // Set the direction based on the sign of steps
  if (steps >= 0) {
    stepper.setSpeed(defaultSpeed); // Set the speed of the stepper motor
    stepper.move(steps); // Move the motor forward by 'steps' steps
  } else {
    stepper.setSpeed(-defaultSpeed); // Set the speed of the stepper motor (negative for reverse direction)
    stepper.move(steps); // Move the motor backward by 'steps' steps
  }
}
uno:A5.2
uno:A4.2
uno:AREF
uno:GND.1
uno:13
uno:12
uno:11
uno:10
uno:9
uno:8
uno:7
uno:6
uno:5
uno:4
uno:3
uno:2
uno:1
uno:0
uno:IOREF
uno:RESET
uno:3.3V
uno:5V
uno:GND.2
uno:GND.3
uno:VIN
uno:A0
uno:A1
uno:A2
uno:A3
uno:A4
uno:A5
lcd1:VSS
lcd1:VDD
lcd1:V0
lcd1:RS
lcd1:RW
lcd1:E
lcd1:D0
lcd1:D1
lcd1:D2
lcd1:D3
lcd1:D4
lcd1:D5
lcd1:D6
lcd1:D7
lcd1:A
lcd1:K
btn1:1.l
btn1:2.l
btn1:1.r
btn1:2.r
btn2:1.l
btn2:2.l
btn2:1.r
btn2:2.r
btn3:1.l
btn3:2.l
btn3:1.r
btn3:2.r
btn4:1.l
btn4:2.l
btn4:1.r
btn4:2.r
btn5:1.l
btn5:2.l
btn5:1.r
btn5:2.r
Buttons to AnalogBreakout
chip1:IN1
chip1:IN2
chip1:IN3
chip1:IN4
chip1:IN5
chip1:GND
chip1:VCC
chip1:OUT
A4988
drv1:ENABLE
drv1:MS1
drv1:MS2
drv1:MS3
drv1:RESET
drv1:SLEEP
drv1:STEP
drv1:DIR
drv1:GND.1
drv1:VDD
drv1:1B
drv1:1A
drv1:2A
drv1:2B
drv1:GND.2
drv1:VMOT
stepper1:A-
stepper1:A+
stepper1:B+
stepper1:B-
+
-
CW>>>
<<<CCW
Enter
vcc1:VCC
gnd1:GND