#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// Set up the I2C LCD display (address, columns, rows)
LiquidCrystal_I2C lcd(0x27, 16, 2);

const int encoderPinA = 2; // Encoder pin A
const int encoderPinB = 3; // Encoder pin B
const int buttonPin = 4; // Button pin

const int stepPins[4] = {8, 9, 10, 11}; // Stepper motor step pins
const int dirPins[4] = {12, 13, 14, 15}; // Stepper motor direction pins

const char* motorNames[4] = {"Base", "Shoulder", "Elbow", "Wrist"};

volatile long encoderPos = -2;
long prevEncoderPos = 0;
int encoderState;
int lastEncoderState;
int activeMotor = 0; // Currently active motor

bool buttonState;
bool lastButtonState;

const float stepAngle = 1.8; // Step angle of the stepper motor

void setup() {
  pinMode(encoderPinA, INPUT_PULLUP);
  pinMode(encoderPinB, INPUT_PULLUP);
  pinMode(buttonPin, INPUT_PULLUP);

  for (int i = 0; i < 4; i++) {
    pinMode(stepPins[i], OUTPUT);
    pinMode(dirPins[i], OUTPUT);
  }

  encoderState = readEncoder();
  lastEncoderState = encoderState;
  lastButtonState = digitalRead(buttonPin);

  // Initialize the LCD
  lcd.init();
  lcd.backlight();
  lcd.clear();
  updateLCD();
}

void loop() {
  encoderState = readEncoder();
  buttonState = digitalRead(buttonPin);

  if (buttonState != lastButtonState) {
    if (buttonState == LOW) {
      activeMotor = (activeMotor + 1) % 4; // Switch to the next motor
      updateLCD();
    }
    delay(5); // Debounce delay
  }

  if (encoderState != lastEncoderState) {
    if (encoderState > lastEncoderState) {
      digitalWrite(dirPins[activeMotor], HIGH); // Clockwise
      encoderPos++;
    } else {
      digitalWrite(dirPins[activeMotor], LOW); // Counterclockwise
      encoderPos--;
    }

    digitalWrite(stepPins[activeMotor], HIGH);
    delayMicroseconds(500); // Adjust delay for desired stepper motor speed
    digitalWrite(stepPins[activeMotor], LOW);
    delayMicroseconds(500); // Adjust delay for desired stepper motor speed

    lastEncoderState = encoderState;
  }

  lastButtonState = buttonState;
}

int readEncoder() {
  int pinAVal = digitalRead(encoderPinA);
  int pinBVal = digitalRead(encoderPinB);

  if (pinAVal && !pinBVal) {
    return 1;
  } else if (pinAVal && pinBVal) {
    return 2;
  } else if (!pinAVal && pinBVal) {
    return 3;
  } else {
    return 0;
    }
}

float getAngle() {
return encoderPos * stepAngle;
}

void updateLCD() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(motorNames[activeMotor]);
lcd.print(" Motor");

lcd.setCursor(0, 1);
lcd.print("Pos: ");
lcd.print(getAngle(),1);
lcd.print((char)223); // Degree symbol
}
A4988
A4988
A4988
A4988