#include <EEPROM.h> // EEPROM 사용을 위한 라이브러리
#include <Wire.h> // i2C 통신을 위한 라이브러리
#include <LiquidCrystal_I2C.h> // LCD 2004 I2C용 라이브러리
int CLK = 2; // 로터리 엔코더의 CLK를 연결한 핀
int DT = 3; // 로터리 엔코더의 DT를 연결한 핀
int SW = 4; // 로터리 엔코더의 SW를 연결한 핀
int RED_PIN = 5; // 빨간색 LED 연결핀번호
int GREEN_PIN = 6; // 초록색 LED 연결핀번호
int BLUE_PIN = 9; // 파란색 LED 연결핀번호
int led_onoff=1;
static int oldCLK = LOW; // CLK 핀의 값을 저장하는 변수
static int oldDT = LOW; // DT 핀의 값을 저장하는 변수
LiquidCrystal_I2C lcd(0x27,20,4); // 접근주소: 0x3F or 0x27
int RED,GREEN,BLUE;
int INTERVAL,DURATION;
int currb=HIGH,lastb=HIGH;
int mr,mg,mb,mi,md,mcur;
char buf[20];
int mode=0; // 0=normal, 1=setup
int menu=0; // 0=RED, 1=GREEN, 2=BLUE, 3=INTV, 4=DUR, 5=END
void setup()
{
initsetting();
loadsetting();
lcd.init(); // LCD 초기화
lcd.backlight(); // 백라이트 켜기
pinMode(CLK, INPUT_PULLUP); // CLK를 내장 풀업 저항을 사용하는 입력으로 설정
pinMode(DT, INPUT_PULLUP); // DT를 내장 풀업 저항을 사용하는 입력으로 설정
pinMode(SW, INPUT_PULLUP); // SW를 내장 풀업 저항을 사용하는 입력으로 설정
//attachInterrupt(digitalPinToInterrupt(SW), rotbutton, LOW);
attachInterrupt(digitalPinToInterrupt(DT), rotdial, CHANGE);
}
void loop()
{
if ((millis()/100)%(INTERVAL+DURATION)<DURATION) led_onoff=1; else led_onoff=0;
currb=debounceButton(currb);
if (mode==0 && currb==LOW && lastb==HIGH) {
lcd.clear(); mode=1; mcur=0; mr=RED; mg=GREEN; mb=BLUE; mi=INTERVAL; md=DURATION;
}
else if (mode==1 && currb==LOW && lastb==HIGH && mcur!=5) {
lcd.clear(); mode=2; menu=mcur;
}
else if (mode==1 && currb==LOW && lastb==HIGH && mcur==5) {
lcd.clear();
lcd.setCursor(0,2); sprintf(buf,"STORING SETTING ."); lcd.print(buf); delay(500);
lcd.setCursor(0,2); sprintf(buf,"STORING SETTING .."); lcd.print(buf); delay(500);
lcd.setCursor(0,2); sprintf(buf,"STORING SETTING ..."); lcd.print(buf); delay(500);
savesetting(); mode=0;
}
else if (mode==2 && currb==LOW && lastb==HIGH) {
lcd.clear(); mode=1;
}
lcdshow();
ledlight();
lastb=currb;
}
boolean debounceButton(boolean state)
{
boolean stateNow=digitalRead(SW);
if (state!=stateNow) {
delay(10);
stateNow=digitalRead(SW);
}
return stateNow;
}
void ledlight()
{
if (led_onoff==1) {
analogWrite(RED_PIN, 255-RED);
analogWrite(GREEN_PIN, 255-GREEN);
analogWrite(BLUE_PIN, 255-BLUE);
}
else {
analogWrite(RED_PIN, 255);
analogWrite(GREEN_PIN, 255);
analogWrite(BLUE_PIN, 255);
}
}
void lcdshow()
{
if (mode==0) {
lcd.setCursor(0,0);
sprintf(buf,"==RGB LED LIGHTING==");
lcd.print(buf);
lcd.setCursor(0,1);
sprintf(buf,"R:%3d G:%3d B:%3d ",RED,GREEN,BLUE);
lcd.print(buf);
lcd.setCursor(0,2);
sprintf(buf," INTERVAL:%2d.%d(sec) ",INTERVAL/10,INTERVAL%10);
lcd.print(buf);
lcd.setCursor(0,3);
sprintf(buf," DURATION:%2d.%d(sec) ",DURATION/10, DURATION%10);
lcd.print(buf);
}
if (mode==1){
lcd.setCursor(0,0);
sprintf(buf,"<<<CHANGE SETTING>>>");
lcd.print(buf);
lcd.setCursor(0,1);
sprintf(buf,"%cRED %cGREEN ",mcur==0?'>':' ',mcur==1?'>':' ');
lcd.print(buf);
lcd.setCursor(0,2);
sprintf(buf,"%cBLUE %cINTERVAL ",mcur==2?'>':' ',mcur==3?'>':' ');
lcd.print(buf);
lcd.setCursor(0,3);
sprintf(buf,"%cDURATION %cEXIT ",mcur==4?'>':' ',mcur==5?'>':' ');
lcd.print(buf);
}
if (mode==2){
switch (menu) {
case 0:
lcd.setCursor(0,0);
sprintf(buf,"<<<CHANGE SETTING>>>");
lcd.print(buf);
lcd.setCursor(0,2);
sprintf(buf," %3d",mr);
lcd.print(buf);
lcd.setCursor(0,3);
sprintf(buf," RED INTENSITY");
lcd.print(buf);
break;
case 1:
lcd.setCursor(0,0);
sprintf(buf,"<<<CHANGE SETTING>>>");
lcd.print(buf);
lcd.setCursor(0,2);
sprintf(buf," %3d",mg);
lcd.print(buf);
lcd.setCursor(0,3);
sprintf(buf," GREEN INTENSITY");
lcd.print(buf);
break;
case 2:
lcd.setCursor(0,0);
sprintf(buf,"<<<CHANGE SETTING>>>");
lcd.print(buf);
lcd.setCursor(0,2);
sprintf(buf," %3d",mb);
lcd.print(buf);
lcd.setCursor(0,3);
sprintf(buf," BLUE INTENSITY");
lcd.print(buf);
break;
case 3:
lcd.setCursor(0,0);
sprintf(buf,"<<<CHANGE SETTING>>>");
lcd.print(buf);
lcd.setCursor(0,2);
sprintf(buf," %2d.%d",mi/10,mi%10);
lcd.print(buf);
lcd.setCursor(0,3);
sprintf(buf," BLINK INTERVAL");
lcd.print(buf);
break;
case 4:
lcd.setCursor(0,0);
sprintf(buf,"<<<CHANGE SETTING>>>");
lcd.print(buf);
lcd.setCursor(0,2);
sprintf(buf," %2d.%d",md/10,md%10);
lcd.print(buf);
lcd.setCursor(0,3);
sprintf(buf," BLINK DURATION");
lcd.print(buf);
break;
}
}
}
void loadsetting()
{
RED=EEPROM.read(1);
GREEN=EEPROM.read(2);
BLUE=EEPROM.read(3);
INTERVAL=EEPROM.read(4);
DURATION=EEPROM.read(5);
}
void initsetting()
{
if (EEPROM.read(0)!=101) {
EEPROM.update(0,101);
EEPROM.update(1,255);
EEPROM.update(2,255);
EEPROM.update(3,255);
EEPROM.update(4,10);
EEPROM.update(5,10);
}
}
void savesetting()
{
RED=mr; EEPROM.update(1,RED);
GREEN=mg; EEPROM.update(2,GREEN);
BLUE=mb; EEPROM.update(3,BLUE);
INTERVAL=mi; EEPROM.update(4,INTERVAL);
DURATION=md; EEPROM.update(5,DURATION);
}
void rotdial() {
if (mode==0) return;
int direct = 0; // 방향을 0으로 초기화
int newCLK = digitalRead(CLK); // 현재 CLK 값을 저장하는 변수
int newDT = digitalRead(DT); // 현재 DT 값을 저장하는 변수
if (newCLK != oldCLK) { // CLK 값이 변한 경우
if (oldCLK == LOW) { // LOW에서 HIGH로 변한 경우
direct = -1*(oldDT * 2 - 1); // DT 값을 이용해 direct 값 변경
}
}
oldCLK = newCLK; // oldCLK 갱신
oldDT = newDT; // oldDT 갱신
if (mode==1) {
mcur+=direct; if (mcur>5) mcur=0; if (mcur<0) mcur=5; return;
}
switch (menu) {
case 0: mr+=5*direct; if (mr>255) mr=0; if(mr<0) mr=255; break;
case 1: mg+=5*direct; if (mg>255) mg=0; if(mg<0) mg=255;break;
case 2: mb+=5*direct; if (mb>255) mb=0; if(mb<0) mb=255;break;
case 3: mi+=direct; if (mi>100) mi=0; if(mi<0) mi=100;break;
case 4: md+=direct; if (md>100) md=0; if(md<0) md=100;break;
}
}
/*
void rotbutton() {
if (mode==0) {
lcd.clear(); mode=1; menu=0; mr=RED; mg=GREEN; mb=BLUE; mi=INTERVAL; md=DURATION;
}
if (mode==1) {
lcd.clear(); menu=menu+1;
}
}
*/