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으로 올릴지 결정할께요. 될 수 있으면 가상시뮬레이터로 한번 제작해서 보여드리는 방향으로 할께요.
7세그먼트 몰라서 숫자써서 하나하나 찾아낸 노가다의 추억ㅋㅋㅋ
한가지 재밌는 사실은 4-Digit 7-Segment Display이 3x3x3 led cube, 키패드 등의 부품과 동일한 원리로 동작해요.
하나의 원리를 깨우치면 나중에 다른 부품들을 응용할 때 꽤 유용하게 활용할 수 있는 것 같아요.
아 그렇군요. 4.7 은 같은 줄 알았는데 다른 것들도 같은 원리라니 신기합니다. ^^ 하핳핳핳. 다음에 또 기회 있을 때 재밌는 거 만들어봐야겠네요. codingman 님 감사합니다. 멋진 걸 배웠네요.ㅎㅎㅎㅎ
여기에, 74hc595 칩을 이용하여 8개 핀을 3핀으로 줄일 수 있고요. 12 or 16 출력 신호를 만들어내는 칩을 이용하면 이름이 막 떠오르지 않지만 이용하면 더 재밌는 것을 만들 수 있어요.
나중에 도전해 보세요.
칩이 달라지면 그런 것도 할 수 있군요. 3핀으로 줄일 수 있는지는 몰랐는데요. 음. ㅇ_ㅇ 12, 16출력이라 오호. 신기해요.
대개 LED를 다량 연결할 때 칩들을 많이 이용하는 것 같아요. 저도 칩네임이 잘 기억 안나지만 칩 몇개만 연결해서 표현하면 수십개의 LED를 제어할 수 있어서 효율적인 면에서 칩을 많이 사용하더군요.
유튜브 같은 LED로 표현한 작품들을 보시면 아마 많이 보실 수 있을꺼에요.
Congratulations @codingman! You have completed some achievement on Steemit and have been rewarded with new badge(s) :
Click on the badge to view your Board of Honor.
If you no longer want to receive notifications, reply to this comment with the word
STOPTo support your work, I also upvoted your post!
Do not miss the last post from @steemitboard!
Participate in the SteemitBoard World Cup Contest!
Collect World Cup badges and win free SBD
Support the Gold Sponsors of the contest: @good-karma and @lukestokes
(jjangjjangman 태그 사용시 댓글을 남깁니다.)
호출에 감사드립니다! 즐거운 스티밋하세요!
짱짱맨! 방문에 감사합니다.
C compiler는 어떤걸 사용하시나요?
아두이노 통합개발환경(IDE)를 이용해서 프로그램을 이식하네요.