#include <Servo.h>
// 방향 enum (Arduino 커뮤니티 권장 방식)
enum Direction
{
    LEFT,
    MIDDLE,
    RIGHT
};
// CDS 센서 핀 설정 (3개 센서: 왼쪽 A0, 가운데 A1, 오른쪽 A2)
const int CDS_PINS[3] = {A0, A1, A2};
const int CDS_COUNT = 3;
// 서보모터 핀 설정
const int SERVO_PIN = 9;
// 서보모터 각도 설정 (각 방향에 대응: 왼쪽 0°, 가운데 90°, 오른쪽 180°)
const int ANGLES[3] = {0, 90, 180};
// 방향 문자열 (Arduino 권장 방식: const char 배열)
const char DIRECTION_STRINGS[3][10] = {"왼쪽", "중간", "오른쪽"};
// 센서 값 비교 임계값 (±5)
const int TOLERANCE = 5;
// 서보모터 흔들림 제스처 설정
const int SHAKE_INTERVAL = 200;      // 200ms마다 좌우 전환 (2개 센서 같을 때)
const int SHAKE_INTERVAL_SLOW = 700; // 700ms마다 좌우 전환 (3개 센서 모두 같을 때)
// 서보모터 상태 저장 (흔들림 제스처용)
int shake_angle_1 = 0;
int shake_angle_2 = 0;
int current_shake_state = 0;
int current_shake_interval = 200; // 현재 사용 중인 흔들림 간격
// 직렬 통신 설정
const int SERIAL_BAUD = 9600;
const int DEBUG_INTERVAL = 500; // 500ms마다 디버깅 정보 출력
Servo servo;
void setup()
{
    // 서보모터 초기화
    servo.attach(SERVO_PIN);
    // CDS 핀 설정 (입력)
    for (int i = 0; i < CDS_COUNT; i++)
    {
        pinMode(CDS_PINS[i], INPUT);
    }
    // 시리얼 통신 초기화 (디버깅용)
    Serial.begin(SERIAL_BAUD);
    Serial.println("CDS Servo Tracker started!");
    Serial.println("Tracking brightest light with 3 CDS sensors.");
}
void loop()
{
    // 각 CDS 센서 값 읽기
    int cds_values[3];
    for (int i = 0; i < CDS_COUNT; i++)
    {
        cds_values[i] = analogRead(CDS_PINS[i]);
    }
    // 가장 낮은 CDS 값 (빛이 가장 강한 센서) 찾기
    int min_index = 0;
    int min_value = cds_values[0];
    for (int i = 1; i < CDS_COUNT; i++)
    {
        if (cds_values[i] < min_value)
        {
            min_value = cds_values[i];
            min_index = i;
        }
    }
    // 가장 높은 CDS 값 (빛이 가장 약한 센서) 찾기
    int max_index = 0;
    int max_value = cds_values[0];
    for (int i = 1; i < CDS_COUNT; i++)
    {
        if (cds_values[i] > max_value)
        {
            max_value = cds_values[i];
            max_index = i;
        }
    }
    // 센서 값 범위 계산
    int value_range = max_value - min_value;
    // 판단 로직
    if (value_range <= TOLERANCE)
    {
        // 모든 센서 값이 거의 같음 (3개 모두 같음) - 0도와 180도를 왔다갔다 (0.7초 간격)
        shake_angle_1 = ANGLES[0];                    // 0도
        shake_angle_2 = ANGLES[2];                    // 180도
        current_shake_interval = SHAKE_INTERVAL_SLOW; // 0.7초 간격
        moveServoBidirectional();
    }
    else if (min_value >= 1018)
    {
        // 가장 강한 빛이 1023 근처 (±5 범위) - 혼란 제스처 (0.7초 간격)
        shake_angle_1 = ANGLES[0];                    // 0도
        shake_angle_2 = ANGLES[2];                    // 180도
        current_shake_interval = SHAKE_INTERVAL_SLOW; // 0.7초 간격
        moveServoBidirectional();
    }
    else if (max_value <= 10)
    {
        // 가장 약한 빛이 거의 0 근처 (±5 범위) - 혼란 제스처 (0.7초 간격)
        shake_angle_1 = ANGLES[0];                    // 0도
        shake_angle_2 = ANGLES[2];                    // 180도
        current_shake_interval = SHAKE_INTERVAL_SLOW; // 0.7초 간격
        moveServoBidirectional();
    }
    else
    {
        // 2개 센서가 같은 경우 판단
        if (abs(cds_values[0] - cds_values[1]) <= TOLERANCE)
        {
            // 왼쪽(0도)과 중간(90도)이 같음 → 오른쪽과 비교하여 더 강한 쪽으로 이동
            if (cds_values[2] < cds_values[0])
            {
                // 오른쪽이 더 강함 → 180도로 이동
                servo.write(ANGLES[2]);
            }
            else if (cds_values[2] > cds_values[0])
            {
                // 왼쪽/중간이 더 강함 → 0도와 90도 사이 흔들림
                shake_angle_1 = ANGLES[0];               // 0도
                shake_angle_2 = ANGLES[1];               // 90도
                current_shake_interval = SHAKE_INTERVAL; // 200ms 간격
                moveServoBidirectional();
            }
            else
            {
                // 3개 모두 같음
                shake_angle_1 = ANGLES[0];                    // 0도
                shake_angle_2 = ANGLES[2];                    // 180도
                current_shake_interval = SHAKE_INTERVAL_SLOW; // 0.7초 간격
                moveServoBidirectional();
            }
        }
        else if (abs(cds_values[1] - cds_values[2]) <= TOLERANCE)
        {
            // 중간(90도)과 오른쪽(180도)이 같음 → 왼쪽과 비교하여 더 강한 쪽으로 이동
            if (cds_values[0] < cds_values[1])
            {
                // 왼쪽이 더 강함 → 0도로 이동
                servo.write(ANGLES[0]);
            }
            else if (cds_values[0] > cds_values[1])
            {
                // 중간/오른쪽이 더 강함 → 90도와 180도 사이 흔들림
                shake_angle_1 = ANGLES[1];               // 90도
                shake_angle_2 = ANGLES[2];               // 180도
                current_shake_interval = SHAKE_INTERVAL; // 200ms 간격
                moveServoBidirectional();
            }
            else
            {
                // 3개 모두 같음
                shake_angle_1 = ANGLES[0];                    // 0도
                shake_angle_2 = ANGLES[2];                    // 180도
                current_shake_interval = SHAKE_INTERVAL_SLOW; // 0.7초 간격
                moveServoBidirectional();
            }
        }
        else if (abs(cds_values[0] - cds_values[2]) <= TOLERANCE)
        {
            // 왼쪽(0도)과 오른쪽(180도)이 같음 → 중간과 비교하여 더 강한 쪽으로 이동
            if (cds_values[1] < cds_values[0])
            {
                // 중간이 더 강함 → 90도로 이동
                servo.write(ANGLES[1]);
            }
            else if (cds_values[1] > cds_values[0])
            {
                // 왼쪽/오른쪽이 더 강함 → 0도와 180도 사이 흔들림
                shake_angle_1 = ANGLES[0];               // 0도
                shake_angle_2 = ANGLES[2];               // 180도
                current_shake_interval = SHAKE_INTERVAL; // 200ms 간격
                moveServoBidirectional();
            }
            else
            {
                // 3개 모두 같음
                shake_angle_1 = ANGLES[0];                    // 0도
                shake_angle_2 = ANGLES[2];                    // 180도
                current_shake_interval = SHAKE_INTERVAL_SLOW; // 0.7초 간격
                moveServoBidirectional();
            }
        }
        else
        {
            // 명확한 빛 방향 감지 - 해당 방향으로 이동
            servo.write(ANGLES[min_index]);
        }
    }
    // 디버깅: 500ms마다 센서 값과 상태 출력
    static unsigned long last_print_time = 0;
    if (millis() - last_print_time >= DEBUG_INTERVAL)
    {
        Serial.print("CDS값: ");
        Serial.print(cds_values[0]);
        Serial.print(", ");
        Serial.print(cds_values[1]);
        Serial.print(", ");
        Serial.print(cds_values[2]);
        Serial.print(" | ");
        // 범위 또는 비슷한 센서 정보 출력
        if (value_range <= TOLERANCE)
        {
            Serial.println("범위: 3개 모든 조도센서 값이 비슷합니다");
        }
        else if (min_value >= 1018)
        {
            Serial.println("범위: 빛이 너무 강해서 판단할 수 없습니다 (혼란 제스처)");
        }
        else if (max_value <= 10)
        {
            Serial.println("범위: 빛이 너무 약해서 판단할 수 없습니다 (혼란 제스처)");
        }
        else if (abs(cds_values[0] - cds_values[1]) <= TOLERANCE)
        {
            // 왼쪽과 중간이 같음
            if (cds_values[2] < cds_values[0])
            {
                Serial.println("범위: 오른쪽 조도센서 값이 강합니다");
            }
            else
            {
                Serial.println("범위: 왼쪽과 중간 조도센서 값이 비슷하고 강합니다");
            }
        }
        else if (abs(cds_values[1] - cds_values[2]) <= TOLERANCE)
        {
            // 중간과 오른쪽이 같음
            if (cds_values[0] < cds_values[1])
            {
                Serial.println("범위: 왼쪽 조도센서 값이 강합니다");
            }
            else
            {
                Serial.println("범위: 중간과 오른쪽 조도센서 값이 비슷하고 강합니다");
            }
        }
        else if (abs(cds_values[0] - cds_values[2]) <= TOLERANCE)
        {
            // 왼쪽과 오른쪽이 같음
            if (cds_values[1] < cds_values[0])
            {
                Serial.println("범위: 중간 조도센서 값이 강합니다");
            }
            else
            {
                Serial.println("범위: 왼쪽과 오른쪽 조도센서 값이 비슷하고 강합니다");
            }
        }
        else
        {
            // 3개 모두 다름
            if (min_index == 0)
            {
                Serial.println("범위: 왼쪽 조도센서 값이 가장 강합니다");
            }
            else if (min_index == 1)
            {
                Serial.println("범위: 중간 조도센서 값이 가장 강합니다");
            }
            else
            {
                Serial.println("범위: 오른쪽 조도센서 값이 가장 강합니다");
            }
        }
        last_print_time = millis();
    }
}
// 서보모터 좌우 흔들림 제스처 (설정된 두 각도 사이를 왔다갔다)
void moveServoBidirectional()
{
    static unsigned long last_shake_time = 0;
    static int shake_direction = 0; // 0: angle_1, 1: angle_2
    if (millis() - last_shake_time >= current_shake_interval)
    {
        if (shake_direction == 0)
        {
            servo.write(shake_angle_1);
            shake_direction = 1;
        }
        else
        {
            servo.write(shake_angle_2);
            shake_direction = 0;
        }
        last_shake_time = millis();
    }
}절대 이 배선도를 따라 전선을 연결하면 안됩니다.!
보드 망가집니다. ~
가상으로 움직임만 보여드려고 연결한 가짜 배선도입니다.