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

Servo myServo;
String inputString = ""; // String to hold incoming serial data
boolean stringComplete = false; // Whether the string is complete
int potPin = A0; // Analog pin connected to potentiometer
int buttonPin = 2; // Digital pin connected to pushbutton
int leds[10] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; // Digital pins connected to LEDs

// Define LCD properties (columns, rows)
LiquidCrystal_I2C lcd(0x27, 16, 2);

// Define mode variables
enum ControlMode { SerialControl, PotControl };
ControlMode mode = SerialControl;

void setup() {
  Serial.begin(9600);
  myServo.attach(9); // Assuming the servo is connected to pin 9
  pinMode(buttonPin, INPUT_PULLUP); // Set button pin as input with internal pull-up resistor
  for (int i = 0; i < 10; i++) {
    pinMode(leds[i], OUTPUT); // Set LED pins as output
  }
  lcd.init(); // Initialize the LCD
  lcd.backlight(); // Turn on backlight
  lcd.setCursor(0, 0);
  lcd.print("Servo: ");
  lcd.setCursor(0, 1);
  lcd.print("Mode: Serial");
}

void loop() {
  if (digitalRead(buttonPin) == LOW) {
    // Button is pressed, switch mode
    switchMode();
  }
  
  if (mode == SerialControl) {
    processSerialInput(); // Process serial input
  } else {
    controlServo(); // Control servo based on potentiometer input
  }
}

void processSerialInput() {
  if (Serial.available() > 0) {
    char inChar = Serial.read(); // Read incoming character

    if (inChar == '\n') { // If newline character is received
      stringComplete = true; // Set string complete flag
    } else { // Otherwise, append character to inputString
      inputString += inChar;
    }
  }

  if (stringComplete) { // If the string is complete
    if (inputString == "H" || inputString == "h") {
      myServo.write(0); // Move servo to 0 degrees
      delay(100); // Add a delay for servo stabilization
      Serial.println("Servo moved to 0 degrees");
      displayAngle(0);
      updateBarGraph(0);
    } else if (inputString == "F" || inputString == "f") {
      myServo.write(180); // Move servo to 180 degrees
      delay(100); // Add a delay for servo stabilization
      Serial.println("Servo moved to 180 degrees");
      displayAngle(180);
      updateBarGraph(180);
    } else {
      int angle = inputString.toInt(); // Convert inputString to integer
      if (angle >= 0 && angle <= 180) { // Ensure angle is within valid range
        myServo.write(angle); // Move servo to specified angle
        delay(100); // Add a delay for servo stabilization
        Serial.print("Servo moved to ");
        Serial.print(angle);
        Serial.println(" degrees");
        displayAngle(angle);
        updateBarGraph(angle);
      } else { // If angle is out of range, print error message
        Serial.println("Invalid angle. Angle must be between 0 and 180 degrees.");
      }
    }
    inputString = ""; // Clear the input string
    stringComplete = false; // Reset the string complete flag
  }
}

void controlServo() {
  // Read potentiometer value and map it to servo angle
  int potValue = analogRead(potPin); // Read potentiometer value (0-1023)
  int servoAngle = map(potValue, 0, 1023, 0, 180); // Map potentiometer value to servo angle
  myServo.write(servoAngle); // Move servo to the mapped angle
  delay(100); // Add a delay for servo stabilization
  displayAngle(servoAngle);
  updateBarGraph(servoAngle);
}

void switchMode() {
  if (mode == SerialControl) {
    mode = PotControl;
    Serial.println("Switched to Pot Control Mode");
    lcd.setCursor(0, 1);
    lcd.print("Mode: Pot    "); // Display current control mode
  } else {
    mode = SerialControl;
    Serial.println("Switched to Serial Control Mode");
    lcd.setCursor(0, 1);
    lcd.print("Mode: Serial "); // Display current control mode
  }
  delay(200); // Delay to debounce button
}

void displayAngle(int angle) {
  lcd.setCursor(7, 0);
  lcd.print("   "); // Clear previous servo angle value
  lcd.setCursor(7, 0);
  lcd.print(angle); // Display current servo angle
}

void updateBarGraph(int angle) {
  int numLeds = map(angle, 0, 180, 0, 10); // Map servo angle to number of LEDs
  for (int i = 0; i < 10; i++) {
    digitalWrite(leds[i], i < numLeds ? HIGH : LOW); // Turn on LEDs up to the mapped number
  }
}
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
servo1:GND
servo1:V+
servo1:PWM
pot1:GND
pot1:SIG
pot1:VCC
lcd1:GND
lcd1:VCC
lcd1:SDA
lcd1:SCL
btn1:1.l
btn1:2.l
btn1:1.r
btn1:2.r
bargraph1:A1
bargraph1:A2
bargraph1:A3
bargraph1:A4
bargraph1:A5
bargraph1:A6
bargraph1:A7
bargraph1:A8
bargraph1:A9
bargraph1:A10
bargraph1:C1
bargraph1:C2
bargraph1:C3
bargraph1:C4
bargraph1:C5
bargraph1:C6
bargraph1:C7
bargraph1:C8
bargraph1:C9
bargraph1:C10