#include <LiquidCrystal.h>
#include <DMXSerial.h>
// LCD 핀 연결 (RS, E, D4, D5, D6, D7)
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
// 스위치 핀 번호
const int minusButton = 2;
const int plusButton = 3;
const int confirmButton = 4;
const int setupButton = 5;
// 포텐셔미터 핀 번호
const int potentiometerPin = A1;
// RS485 제어 핀
const int rs485ControlPin = 6;
// DMX 어드레스 설정 변수
int ones = 0; // 1의 자리
int tens = 0; // 10의 자리
int hundreds = 0; // 100의 자리
int digitIndex = 0;
bool setupMode = false;
unsigned long setupButtonPressTime = 0;
void setup() {
// LCD 초기화
lcd.begin(16, 2);
lcd.print("DMX TESTER Rev.1");
// 스위치 핀 설정
pinMode(minusButton, INPUT_PULLUP);
pinMode(plusButton, INPUT_PULLUP);
pinMode(confirmButton, INPUT_PULLUP);
pinMode(setupButton, INPUT_PULLUP);
// RS485 제어 핀 설정
pinMode(rs485ControlPin, OUTPUT);
digitalWrite(rs485ControlPin, HIGH); // 송신 모드
// DMX 송신 초기화
DMXSerial.init(DMXController);
// 현재 DMX 어드레스 표시
int potValue = analogRead(potentiometerPin);
displayAddress(potValue);
}
void loop() {
// 포텐셔미터 값 읽기
int potValue = analogRead(potentiometerPin);
int potPercent = map(potValue, 0, 1023, 0, 255); // DMX 신호 값으로 변환
// 4번 스위치가 눌렸을 때
if (digitalRead(setupButton) == LOW) {
if (setupButtonPressTime == 0) {
setupButtonPressTime = millis(); // 버튼이 눌린 시각 기록
} else if (millis() - setupButtonPressTime > 2000) {
// 2초 이상 눌렸을 때 어드레스를 000으로 설정
ones = 0;
tens = 0;
hundreds = 0;
setupMode = false;
lcd.noBlink();
lcd.setCursor(0, 0);
lcd.print("!! Addr Reset !!");
displayAddress(potValue);
delay(1000); // 1초간 메시지 표시
lcd.setCursor(0, 0);
lcd.print("DMX TESTER Rev.1");
setupButtonPressTime = 0; // 시간 리셋
}
} else {
if (setupButtonPressTime != 0 && millis() - setupButtonPressTime <= 2000) {
// 2초 이하로 눌렸을 때 SETUP 모드로 전환
setupMode = true;
digitIndex = 0;
lcd.setCursor(0, 0);
lcd.print("**Set Address** ");
blinkDigit(digitIndex);
delay(500); // 디바운스 처리
}
setupButtonPressTime = 0; // 시간 리셋
}
displayAddress(potValue); // 포텐셔미터 값을 함께 출력
// DMX 신호 발신
int dmxAddress = hundreds * 100 + tens * 10 + ones;
if (dmxAddress > 0 && dmxAddress <= 512) {
DMXSerial.write(dmxAddress, potPercent);
}
// SETUP 모드에서 값 설정
if (setupMode) {
if (digitalRead(plusButton) == LOW) {
incrementDigit();
delay(300); // 디바운스 처리
}
if (digitalRead(minusButton) == LOW) {
decrementDigit();
delay(300); // 디바운스 처리
}
if (digitalRead(confirmButton) == LOW) {
confirmDigit();
delay(300); // 디바운스 처리
}
}
}
void displayAddress(int potValue) {
int address = hundreds * 100 + tens * 10 + ones;
// 포텐셔미터 값을 퍼센티지로 변환
int potPercent = map(potValue, 0, 1023, 0, 100);
lcd.setCursor(0, 1);
lcd.print("Add:");
if (address < 100) lcd.print('0');
if (address < 10) lcd.print('0');
lcd.print(address);
lcd.print(" / Val:");
if (potPercent == 100) {
lcd.print("FL");
} else {
lcd.print(potPercent);
lcd.print("%");
}
lcd.print(" "); // 남은 공간을 빈칸으로 채움
// 커서 깜빡임 설정
if (setupMode) {
blinkDigit(digitIndex);
} else {
lcd.noBlink();
}
}
void blinkDigit(int index) {
// 각 자리수 위치에 따른 커서 위치 설정
int positions[] = {6, 5, 4}; // 1, 10, 100의 자리 위치
lcd.setCursor(positions[index], 1);
lcd.blink();
}
void incrementDigit() {
switch (digitIndex) {
case 0:
ones = (ones + 1) % 10;
break;
case 1:
tens = (tens + 1) % 10;
break;
case 2:
if (hundreds < 5) {
hundreds = (hundreds + 1) % 6;
} else {
hundreds = 5; // 512를 넘지 않기 위해 5까지만 설정
}
break;
}
int potValue = analogRead(potentiometerPin);
displayAddress(potValue);
}
void decrementDigit() {
switch (digitIndex) {
case 0:
ones = (ones + 9) % 10;
break;
case 1:
tens = (tens + 9) % 10;
break;
case 2:
if (hundreds > 0) {
hundreds = (hundreds + 5) % 6; // 0~5까지만 설정 가능
}
break;
}
int potValue = analogRead(potentiometerPin);
displayAddress(potValue);
}
void confirmDigit() {
digitIndex++;
if (digitIndex > 2) {
setupMode = false;
lcd.noBlink();
lcd.setCursor(0, 0);
lcd.print(" Confirm! ");
delay(1000); // 1초간 Confirm 메시지 표시
lcd.setCursor(0, 0);
lcd.print("DMX TESTER Rev.1");
int potValue = analogRead(potentiometerPin);
displayAddress(potValue);
}
}