#include <Servo.h>
#include <ezButton.h>
/* ========================================
   핀 연결 배선도
   ========================================
   아두이노 R4 WiFi 보드 핀 배치:
   버튼 1 (오른쪽 회전)  -> 2번 핀 (디지털 입력, 내부 풀업 저항 사용)
   버튼 2 (왼쪽 회전)   -> 3번 핀 (디지털 입력, 내부 풀업 저항 사용)
   서보모터             -> 9번 핀 (PWM 출력)
   서보모터 접선:
   - 빨강: 5V
   - 검정: GND
   - 노랑: 9번 핀
   버튼 접선 (내부 풀업 저항 사용):
   - VCC: 아두이노 5V (필요 없음, 내부 풀업 사용)
   - 한쪽: 2번 핀 또는 3번 핀
   - 다른쪽: GND
   버튼 동작: 누르면 LOW, 놓으면 HIGH (풀업 저항)
   ======================================== */
// 핀 정의
const int BUTTON_RIGHT_PIN = 2; // 버튼 1 (오른쪽, 내부 풀업)
const int BUTTON_LEFT_PIN = 3;  // 버튼 2 (왼쪽, 내부 풀업)
const int SERVO_PIN = 9;        // 서보모터
// 서보모터 각도 범위
const int SERVO_CENTER_ANGLE = 90; // 중앙 위치
// 서보 이동 방향 상수
const int DIRECTION_RIGHT = 1; // 오른쪽
const int DIRECTION_LEFT = -1; // 왼쪽
const int DIRECTION_STOP = 0;  // 정지
// 타이밍 제어 상수
const unsigned long SERVO_MOVE_DURATION = 50;  // 서보 이동 시간(ms) - 50ms마다 1도씩
const unsigned long BUTTON_DEBOUNCE_TIME = 50; // 버튼 디바운싱(ms)
const int SERVO_SPEED = 1;                     // 연속 이동시 매 루프마다 증감 각도(도)
const int SERVO_MIN_ANGLE = 0;                 // 서보 최소 각도
const int SERVO_MAX_ANGLE = 180;               // 서보 최대 각도
// ezButton 객체 생성 (내부 풀업 저항 사용)
ezButton button_right(BUTTON_RIGHT_PIN);
ezButton button_left(BUTTON_LEFT_PIN);
// 서보모터 객체
Servo servo_motor;
// 상태 변수
unsigned long last_update_time = 0; // 마지막 업데이트 시간
int current_servo_angle = 90;       // 현재 서보 각도 (초기값: 90도)
int servo_direction = 0;            // 서보 이동 방향 (1: 오른쪽, -1: 왼쪽, 0: 정지)
void setup()
{
    // 직렬 통신 초기화 (디버깅용)
    Serial.begin(9600);
    // ezButton 초기화 (내부 풀업 저항 사용)
    button_right.setDebounceTime(BUTTON_DEBOUNCE_TIME);
    button_left.setDebounceTime(BUTTON_DEBOUNCE_TIME);
    // 서보모터 초기화
    servo_motor.attach(SERVO_PIN);
    servo_motor.write(SERVO_CENTER_ANGLE);
    Serial.println("Setup complete!");
    Serial.println("Button - Servo Motor Control with ezButton Library");
    Serial.println("Right Button (Pin 2): Move Right");
    Serial.println("Left Button (Pin 3): Move Left");
}
void loop()
{
    // ezButton 상태 업데이트 (반드시 호출)
    button_right.loop();
    button_left.loop();
    // 버튼 상태에 따라 방향 결정
    if (isButtonRightPressed())
    {
        servo_direction = DIRECTION_RIGHT;
    }
    else if (isButtonLeftPressed())
    {
        servo_direction = DIRECTION_LEFT;
    }
    else
    {
        servo_direction = DIRECTION_STOP;
    }
    // 서보 각도 업데이트
    updateServoAngle();
}
// 오른쪽 버튼 누름 확인
boolean isButtonRightPressed()
{
    return (button_right.getState() == LOW);
}
// 왼쪽 버튼 누름 확인
boolean isButtonLeftPressed()
{
    return (button_left.getState() == LOW);
}
// 서보 각도 업데이트 (연속 이동)
void updateServoAngle()
{
    unsigned long current_time = millis();
    unsigned long time_diff = current_time - last_update_time;
    // 매 50ms마다 업데이트 (1도씩 이동)
    if (time_diff < SERVO_MOVE_DURATION)
    {
        return;
    }
    last_update_time = current_time;
    // 방향에 따라 각도 증감
    if (servo_direction == DIRECTION_RIGHT)
    {
        if (current_servo_angle < SERVO_MAX_ANGLE)
        {
            current_servo_angle += SERVO_SPEED;
            Serial.print("Moving RIGHT -> Current angle: ");
            Serial.println(current_servo_angle);
        }
        else
        {
            current_servo_angle = SERVO_MAX_ANGLE;
        }
    }
    else if (servo_direction == DIRECTION_LEFT)
    {
        if (current_servo_angle > SERVO_MIN_ANGLE)
        {
            current_servo_angle -= SERVO_SPEED;
            Serial.print("Moving LEFT -> Current angle: ");
            Serial.println(current_servo_angle);
        }
        else
        {
            current_servo_angle = SERVO_MIN_ANGLE;
        }
    }
    // 서보 위치 업데이트
    servo_motor.write(current_servo_angle);
}