#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
// 핀 번호 정의
const int btnPins[] = {2, 3, 4, 5}; // 버튼 핀 배열
const int switchPins[] = {8, 9, 10, 11}; // 리미트스위치 핀 배열
const int up_motor_Pin = 6; // 모터 업 LED 핀
const int dw_motor_Pin = 7; // 모터 다운 LED 핀
const int up_move_Pin = 12;
const int dw_move_Pin = 13;
// 현재 엘리베이터 위치
int currentFloor = 1;
bool moving = false; // 엘리베이터 이동 중 여부를 나타내는 플래그
void setup() {
Serial.begin(9600);
lcd.init();
lcd.backlight();
// 입력 및 출력 핀 설정
for (int i = 0; i < 4; i++) {
pinMode(btnPins[i], INPUT); // 버튼 핀을 입력으로 설정
pinMode(switchPins[i], INPUT); // 스위치 핀을 입력으로 설정하고 내부 풀업 저항 사용
}
pinMode(up_motor_Pin, OUTPUT); // 모터 업 LED 핀을 출력으로 설정
pinMode(dw_motor_Pin, OUTPUT); // 모터 다운 LED 핀을 출력으로 설정
pinMode(up_move_Pin, OUTPUT); // 모터 업 LED 핀을 출력으로 설정
pinMode(dw_move_Pin, OUTPUT); // 모터 다운 LED 핀을 출력으로 설정
// 초기 LED 상태 설정
digitalWrite(up_motor_Pin, LOW); // 업 표시 LED 초기화
digitalWrite(dw_motor_Pin, LOW); // 다운 표시 LED 초기화
}
void loop() {
// 버튼 입력 확인
for (int i = 0; i < 4; i++) {
if (digitalRead(btnPins[i]) == HIGH) { // 버튼이 눌렸는지 확인
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Button:");
lcd.print(i+1);
lcd.print("Call");}
moveToFloor(i + 1); // 해당 층으로 이동
break;
}
}
// 엘리베이터 이동 중이 아닌 경우에만 스위치 입력 확인하여 현재 엘리베이터 위치 업데이트
if (!moving) {
for (int i = 0; i < 4; i++) {
if (digitalRead(switchPins[i]) == HIGH) { // 스위치가 감지되는 경우
{
// lcd.clear();
lcd.setCursor(9, 0);
lcd.print("S/W:");
lcd.print(i+1);
// lcd.print(" ON"); // 스위치에 해당하는 층수 출력
}
currentFloor = i + 1; // 현재 층 업데이트
delay(2000); // 바운스를 방지하기 위한 딜레이 500
break;
}
}
}
}
// 엘리베이터 이동 함수
void moveToFloor(int targetFloor) {
moving = true; // 엘리베이터 이동 중임을 나타내는 플래그 설정
if (targetFloor > currentFloor) // 목표 층이 현재 층보다 위에 있는 경우
{
digitalWrite(up_motor_Pin, HIGH); // 업 표시 LED 켜기
digitalWrite(dw_motor_Pin, LOW); // 다운 표시 LED 끄기
digitalWrite(up_move_Pin, HIGH); // 업 표시 LED on
// 엘리베이터를 위로 이동
while (currentFloor < targetFloor) { // 현재 층이 목표 층에 도달할 때까지 반복
if (digitalRead(switchPins[currentFloor]) == HIGH) { // 스위치 감지
currentFloor = currentFloor + 1; // 현재 층 업데이트
{
lcd.clear(); //LCD 화면 지우기
lcd.setCursor(0, 0);
lcd.print("Up move:");
lcd.print(currentFloor);
lcd.print("F");
}
delay(1000); // 각 층으로 이동하는 데 걸리는 시간 (리미트S/W 간격오차를 줄일수 있음)
}
}
} else if (targetFloor < currentFloor) { // 목표 층이 현재 층보다 아래에 있는 경우
digitalWrite(up_motor_Pin, LOW); // 업 표시 LED 끄기
digitalWrite(dw_motor_Pin, HIGH); // 다운 표시 LED 켜기
digitalWrite(dw_move_Pin, HIGH); // 업 표시 LED on
// 엘리베이터를 아래로 이동
while (currentFloor > targetFloor) { // 현재 층이 목표 층에 도달할 때까지 반복
if (digitalRead(switchPins[currentFloor - 2]) == HIGH) // 버튼 스위치 감지
{
currentFloor = currentFloor - 1; // 현재 층 업데이트
{
lcd.clear(); //LCD 화면 지우기
lcd.setCursor(0, 0);
lcd.print("Dn move:");
lcd.print(currentFloor);
lcd.print("F");
}
delay(1000); // 각 층으로 이동하는 데 걸리는 시간 (리미트S/W 간격오차를 줄일수 있음)
}
}
}
// 도착한 층에서 정지
digitalWrite(up_motor_Pin, LOW); // 업 모터 끄기
digitalWrite(dw_motor_Pin, LOW); // 다운 모터 끄기
digitalWrite(up_move_Pin, LOW); // 업 LED 끄기
digitalWrite(dw_move_Pin, LOW); // 다운 LED 끄기
{
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("STOP:");
lcd.print(currentFloor);
lcd.print("F");
lcd.setCursor(0, 1);
lcd.print("Motor OFF");
delay(5000); // 정지후 스위치 감지하기위한 딜레이 시간
}
moving = false; // 엘리베이터 이동 완료
}
}