/*
1층 각도를 180
2층 각도를 90
3층 각도를 0 으로 하겠습니다.
*/
/*
리팩토링 요소들
1. 버튼 핀 번호를 배열로 만들어서 for문으로 처리( 완료 )
2. 층 수를 배열로 만들어서 for문으로 처리 ( 완료 )
3. 코드 주석 다시 정리 ( 완료 )
4. 버튼의 디바운스 처리 ( 없는 가정하에 보류 )
5. 각 층 버튼 처리 의 비슷한 부분을 함수로 묶어서 처리( 완료 )
6. 시리얼 출력문 정리 ( 완료 )
7. 서보모터 연결 및 해제를 State Machine으로 처리 ( 보류 )
8. 시스템 시작시 층을 1층으로 초기화 하지 말고 현재 층을 읽을 수 있는 코드로 변경을 생각 해볼 것( 완료 )
9. 변수 이름 수정 (F -> floor_difference) ( 완료 )
10. delay()를 사용하지 않고 millis()를 사용해서 시간을 계산해서 처리( 보류 )
11. loop() 함수를 작게 만들기 위해서 함수로 분리 , 예를 들어 void check_button() , void move_elevator() 등등 ( 완료 )
12. setup ( )함수와 loop ( ) 함수 위치를 맨 뒤로 변경 ( 완료 )
*/
/*
2차 리팩토링을 통해서 코드 줄을 더욱 줄이고 코드 가독성을 높이는 작업을 진행 합니다.
*/
#include <Servo.h>
Servo servo;
// 시작의 현재 층을 랜덤 함수를 이용해서 결정 합니다.
int current_floor;
int target_floor;
int floor_difference;
// 엘리베이터 1, 2, 3 층에 맞게 각도 값을 배열로 선언
const int SERVO_ANGLE[3] = {180, 90, 0}; // 1층 180 , 2층 90 , 3층 0
// 버튼 핀 번호 , 배열로 만듭니다.
const int FLOOR_BUTTON_PIN[3] = {2, 3, 4}; // 1층 , 2층 , 3층
// 초기 층을 랜덤하게 이동시켜주는 함수
void randomStartFloor()
{
// 랜덤한 층 번호를 생성합니다.
int floor = random(3);
// 층 번호가 1, 2, 3 중 하나인지 확인합니다.
while (floor == 0)
{
floor = random(3);
}
// 현재 층을 랜덤한 층으로 설정합니다.
target_floor = floor;
}
// 엘리베이터 부분 별도 함수로 처리
void move(int target_floor)
{
// 현재 위치 층과 목표 층의 차이를 계산합니다.
floor_difference = abs(target_floor - current_floor);
// 서보모터를 회전 시킵니다.
if (target_floor == 1)
{
servo.write(180);
}
else if (target_floor == 2)
{
servo.write(90);
}
else if (target_floor == 3)
{
servo.write(0);
}
delay(1000 * floor_difference); // 층 수 차이 * 1초 곱한 시간만큼 대기
current_floor = target_floor;
}
// 버튼 부분 별도 함수로 처리 , 디바운스가 없는 가정하에
void checkButton()
{
// 각 층의 버튼 핀의 상태를 확인 합니다.
for (int i = 0; i < 3; i++)
{
if (digitalRead(FLOOR_BUTTON_PIN[i]) == LOW)
{
target_floor = i + 1;
break;
}
}
}
// 디버깅용 시리얼 출력 함수
void debergingPrintSerial()
{
Serial.print("C_floor: ");
Serial.print(current_floor);
Serial.print(" T_floor: ");
Serial.print(target_floor);
Serial.print(" Btn 1: ");
Serial.print(digitalRead(FLOOR_BUTTON_PIN[0]));
Serial.print(" Btn 2: ");
Serial.print(digitalRead(FLOOR_BUTTON_PIN[1]));
Serial.print(" Btn 3: ");
Serial.println(digitalRead(FLOOR_BUTTON_PIN[2]));
}
void setup()
{
Serial.begin(9600);
// random 시드를 사용해서 랜덤 값을 생성 합니다.
randomSeed(micros());
// 시작시 랜덤한 층으로 초기화 합니다.
randomStartFloor();
// 서보모터를 9번 핀에 연결 및 동작 준비시킵니다.
servo.attach(9);
// 시작시 move( ) 함수를 사용해서 무작위 층으로 엘레베이터를 이동 시킵니다.
move(target_floor);
// 버튼 모드선언을 핀번호 배열을 이용해서 for문으로 처리
for (int i = 0; i < 3; i++)
{
pinMode(FLOOR_BUTTON_PIN[i], INPUT_PULLUP);
}
}
void loop()
{
// 버튼을 누르면 목표 층을 변경 합니다.
checkButton();
// 현재 층과 목표 층이 다르면 엘리베이터를 이동 시킵니다.
if (current_floor != target_floor)
{
move(target_floor);
}
// debergingPrintSerial(); // 디버깅용 시리얼 출력 함수 , 필요할때만 쓰세요
}