[아두이노] 4-Digit 7-Segment Display 시계 만들기
[아두이노] 4-Digit 7-Segment Display 시계 만들기
- 온라인 가상시뮬레이터 : https://www.tinkercad.com
- 참고 :
[아두이노] 4-Digit 7-Segment Display 제어
[아두이노] 시간 millis() 함수로 시계 코딩
지난 시간에 4-Digit 7-Segment Display을 사용하는 방법을 실험 하였습니다. 오늘은 지난시간에 만든 회로도와 기본소스를 기반으로 아두이노 시계를 실제 만들어 보겠습니다.
1. 4-Digit 7-Segment Display 회로도
- 준비물 : 4-Digit 7-Segment Display 1개, 스위치버턴 1개, 아두이노우노
- 내용 : 4-Digit 7-Segment Display 부품의 핀 번호 순서에 맞게 아두이노우노에 연결하고, 스위치 버턴은 2번핀에 연결하시오.
- 참조 : [아두이노] 4-Digit 7-Segment Display 제어
지난 시간의 회로도와 동일합니다.
2. 시계 코딩
시간을 참조 Post에 가셔서 사전 학습 해주세요.
1) 시간 구하기
시간은 시리얼통신으로 입력을 받을 경우를 가정해서 시간을 구해 볼까요.
if(Serial.available()){
String inString = Serial.readStringUntil('\n');
}
inString에 시간 문자열을 읽습니다.
int index1 = inString.indexOf(':');
int index2 = inString.indexOf(':',index1+1);
int index3 = inString.length();
hour = inString.substring(0, index1).toInt();
min = inString.substring(index1+1,index2).toInt();
sec = inString.substring(index2+1,index3).toInt();
위와 같이 코딩해서 hour, min, sec 구하게 됩니다. 지난시간에 설명을 다했기 때문에 간단히 넘어 갑니다.
timer0_millis = ((long)hour*3600+min*60+sec)*1000;
hour, min, sec 값을 초로 변환하여 timer0_millis 변수에 저장하면 타이머는 입력된 시간을 기준으로 돌아가게 됩니다. 즉, 입력된 시간에서 타이머 시간이 흐른다고 보시면 됩니다.
readTime = millis()/1000; sec = readTime%60; min = (readTime/60)%60; hour = (readTime/(60*60))%24;
readTime 변수에는 millis()함수에서 읽은 타이머 시간값을 1000으로 나눈 몫 값을 저장하기 때문에 입력된 시간을 기준으로 1초 단위로 값이 변화가 일어 나겠죠. 입력시간을 기준으로 흐르는 시간값을 hour, min, sec값으로 다시 구하면 현재 시간을 구할 수 있게 됩니다.
이 값을 4-Digit 7-Segment Display로 출력하면 실제 아두이노 시계가 완성 됩니다.
2) 시간 타이머리셋 지정
24시간을 기준으로 시간을 리셋 시킬 예정입니다. 그러면 어떻게 코딩해야 할까요.
if(millis()>=86400000){ //타이머 리셋
timer0_millis=0;
}
if문으로 1day는 24시간이고 이 시간은 "60x60x24" 가 됩니다. 여기에 1초(1000)을 곱해주면 86400000의 타이머 시간값이 만들어 집니다. 이 시간이 되면 timer0_millis=0으로 리셋 시키면 24시간 단위로 타이머는 처음부터 다시 돌게 됩니다.
3) 인터럽트 스위치버턴 활용
지난시간에 인터럽트 스위치버턴을 추가했는데 그러면 이 스위치버턴을 그냥 두기가 아쉬워서 어떤 기능을 넣을까 고민하다가 시간 표시를 제어하는 스위치버턴으로 변경해 보았습니다.
void switchFn(){
state=!state;
}
스위치 버턴이 눌러지면 state 변수가 반전이 일어나게 했습니다.
if(state==true){ //12시 or 24시 출력모드
hour = hour%12;
}
이렇게 수정했습니다. 현재 시간 hour를 12시 기준으로 출력할 것인지 24시 기준으로 출력할 건지를 스위치버턴으로 제어하는 기능을 추가 했네요.
4) 종합소스
이제 지난시간의 소스에다가 위 설계 코딩을 삽입하면 아래와 같이 완성 됩니다.
//a,b,c,d,e,f,g 상태값
const byte segValue[10][7] = {
{1,1,1,1,1,1,0}, //0
{0,1,1,0,0,0,0}, //1
{1,1,0,1,1,0,1}, //2
{1,1,1,1,0,0,1}, //3
{0,1,1,0,0,1,1}, //4
{1,0,1,1,0,1,1}, //5
{1,0,1,1,1,1,1}, //6
{1,1,1,0,0,0,0}, //7
{1,1,1,1,1,1,1}, //8
{1,1,1,1,0,1,1} //9
};
const byte segPin[8]={7,3,A3,A1,A0,6,A4,A2}; //사용핀{a,b,c,d,e,f,g,dp} 순서대로임
const byte digitPin[4] = {8,5,4,A5}; //segment 위치 핀
const byte interruptPin = 2;//인터럽트핀
boolean state = false;//시간 출력형식 지정
extern volatile unsigned long timer0_millis; //타이머변수
unsigned long readTime; //현재타이머시간
int hour, min, sec;
void setup() {
Serial.begin(9600);
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), switchFn, FALLING);
for(int i=0;i<10;i++){
pinMode(segPin[i], OUTPUT);
}
for(int j=0;j<4;j++){
pinMode(digitPin[j], OUTPUT);
digitalWrite(digitPin[j], HIGH);
}
}
void loop() {
if(Serial.available()){ //입력시간 읽기
String inString = Serial.readStringUntil('\n');
int index1 = inString.indexOf(':');
int index2 = inString.indexOf(':',index1+1);
int index3 = inString.length();
hour = inString.substring(0, index1).toInt();
min = inString.substring(index1+1,index2).toInt();
sec = inString.substring(index2+1,index3).toInt();
timer0_millis = ((long)hour*3600+min*60+sec)*1000; //입력시간 초변환
}
if(millis()>=86400000){ //타이머 리셋
timer0_millis=0;
}
readTime = millis()/1000; //현재시간 읽기
sec = readTime%60;
min = (readTime/60)%60;
hour = (readTime/(60*60))%24;
if(state==true){ //12시 or 24시 출력모드
hour = hour%12;
}
segOutput(3,min%10,0); //min 1의 자리
segOutput(2,min/10,0); //min 10의 자리
segOutput(1,hour%10,1); //hour 1의 자리
segOutput(0,hour/10,0); //hour 10의 자리
}
//12시 or 24시 출력 변경
void switchFn(){
state=!state;
}
//LED 초기화
void segClear(){
for(int i=0;i<8;i++){
digitalWrite(segPin[i], LOW);
}
}
//LED 출력
void segOutput(int d, int Number, int dp){
segClear();
digitalWrite(digitPin[d], LOW);
for(int i=0;i<7;i++){
digitalWrite(segPin[i], segValue[Number][i]);
}
digitalWrite(segPin[7], dp);
delayMicroseconds(1000);
digitalWrite(digitPin[d], HIGH);
}
3. 결과
1) 분/초 출력
숫자를 4개 뿐이 출력을 못하기 때문에 간단히 시간이 흐르는 것을 확인 할 수 있게 출력 숫자는 분/초로 세팅했습니다.
segOutput(3,sec%10,0); //min 1의 자리 segOutput(2,sec/10,0); //min 10의 자리 segOutput(1,min%10,1); //min 1의 자리 segOutput(0,min/10,0); //min 10의 자리
입력은 정상적으로 시간 "23:59:50"을 입력할 때는 내부적으로 시간은 정확하게 흘러갑니다. 여기서, 출력은 분/초만 표시될 뿐이죠
분/초만 아래와 같이 출력되어 정상적으로 시간이 흘러가네요.
2) 시/분 출력
종합 소스에 시/분 코딩을 그대로 실험한 결과입니다. 출력은 시/분만 출력됩니다.
segOutput(3,min%10,0); //min 1의 자리 segOutput(2,min/10,0); //min 10의 자리 segOutput(1,hour%10,1); //hour 1의 자리 segOutput(0,hour/10,0); //hour 10의 자리
입력은 시간 "23:59:10"을 입력했습니다.

결과는 아래의 동영상에 보시면 "23:59"만 출력됩니다. 내부적으로 초는 계속 흘러가고 있습니다. 인터럽트 스위치버턴을 누르면 12시 기준으로 시간을 표시되고 다시 누르면 23시 기준으로 시간이 표시 되는 실험 결과를 보실 수 있을 꺼에요. 그리고 24시가 되면은 "00:00"으로 리셋되는 것 까지 보실 수 있을 꺼에요.
마무리
4-Digit 7-Segment Display 부품 밖에 없어서 안타깝게 6자리 시간 표시를 못했네요. 그러다보니 분/초 아니면 시/분으로 표시할 수 밖에 없었고 결과 동영상으로는 표현의 한계가 있었네요.
개별 7-Segment가 2개 있으면 추가로 연결해서 표시 할 수 있었겠지만 한개뿐이라 연결을 포기 했습니다. 아무튼 이런식으로 아두이노 시계를 만들 수 있다는 것을 보여드리는 걸로 정리를 할까 합니다. Stepper Motor로 시계를 표시하고 싶은데 4-Digit 7-Segment Display가 post 주제에서 나중에 응용편으로 기회가 된다면 그때 보여드릴게요. 주제에 맞게 post를 하기 위해서 그 실험은 생략하도록 하겠습니다.
가상시뮬레이터에서 6개 7-Segment를 이용해서 확실히 시계를 만들어서 보여드릴까 고민 좀 해보겠습니다. 여러분들은 실제 제작을 안하더라고 가상시뮬레이터에서 동일한 실험이 체험할 수 있게 귀찮은 회로선 연결을 해야하지만 한번 생각해보고 다음 post으로 올릴지 결정할께요. 될 수 있으면 가상시뮬레이터로 한번 제작해서 보여드리는 방향으로 할께요.
'IOT > 아두이노' 카테고리의 다른 글
| [아두이노] 6-Digit 7-Segment Display 시계 리모콘 제어 (0) | 2019.06.19 |
|---|---|
| [아두이노] 4-Digit 7-Segment Display 가상시뮬레이터 실험 (1) | 2019.06.18 |
| [아두이노] 4-Digit 7-Segment Display 제어 (1) | 2019.06.14 |
| [아두이노] 2-Digit 7-Segment Display (0) | 2019.06.13 |
| [아두이노] 시간 millis() 함수로 시계 코딩 (0) | 2019.06.07 |






