아두이노 메가 2560으로 만드는 조절 가능 카운트다운 타이머
부품 및 소모품
| 부품 |
수량 |
비고 |
| 아두이노 메가 2560 |
1 |
타 아두이노 보드도 사용 가능 |
| 4자리 7세그먼트 디스플레이 |
1 |
공통 양극/음극 확인 필요 |
| 푸시 버튼 |
4 |
시작/정지, 시간 증가/감소용 |
| 부저 |
1 |
알람음용 |
| 점퍼 와이어 |
21 |
|
| 브레드보드 (풀사이즈) |
1 |
|
프로젝트 소개
4자리 7세그먼트 디스플레이의 가장 자연스러운 활용 예인 카운트다운 타이머를, 코드 수정 없이 버튼만으로 시간을 설정할 수 있게 만들었습니다. 기존 프로젝트들은 코드를 고쳐야 시간을 바꿀 수 있어 실용적이지 않았습니다.
제공된 코드에는 범용적으로 쓸 수 있는 PrintNumber() 함수가 포함되어 있어, 다른 7세그먼트 프로젝트에서도 0~9999 숫자를 지정된 시간 동안 표시하는 데 활용할 수 있습니다. (멀티플렉싱으로 한 자리씩 빠르게 스위칭하여 표시)
버튼 기능
- 버튼 1 (핀 13): 타이머 시작/일시정지 (설정 모드 진입/종료)
- 버튼 2 (핀 12): 카운트다운 중 취소/리셋
- 버튼 3 (핀 16): 설정 모드에서 시간 감소 (길게 누르면 가속)
- 버튼 4 (핀 17): 설정 모드에서 시간 증가 (길게 누르면 가속)
회로도

세그먼트 핀: A~G → D2~D8, 자릿수 선택 핀: D6, D9, D10, D11 (PWM), 부저: D15
전체 소스 코드
#include
int digit_pin[] = {6, 9, 10, 11}; // 왼쪽부터 오른쪽 자릿수 PWM 핀
int speakerPin = 15;
#define DIGIT_ON LOW
#define DIGIT_OFF HIGH
int segA = 2, segB = 3, segC = 4, segD = 5, segE = A0, segF = 7, segG = 8;
int button1 = 13, button2 = 12, button3 = 16, button4 = 17;
int countdown_time = 60; // 기본 60초
struct struct_digits { int digit[4]; };
void setup() {
pinMode(segA, OUTPUT); pinMode(segB, OUTPUT); pinMode(segC, OUTPUT);
pinMode(segD, OUTPUT); pinMode(segE, OUTPUT); pinMode(segF, OUTPUT); pinMode(segG, OUTPUT);
for (int i = 0; i < 4; i++) pinMode(digit_pin[i], OUTPUT);
pinMode(speakerPin, OUTPUT);
pinMode(button1, INPUT_PULLUP); pinMode(button2, INPUT_PULLUP);
pinMode(button3, INPUT_PULLUP); pinMode(button4, INPUT_PULLUP);
}
void playTone(int tone, int duration) {
for (long k = 0; k < duration * 1000L; k += tone * 2) {
digitalWrite(speakerPin, HIGH); delayMicroseconds(tone);
digitalWrite(speakerPin, LOW); delayMicroseconds(tone);
}
}
void lightNumber(int numberToDisplay) {
#define SEGMENT_ON HIGH
#define SEGMENT_OFF LOW
switch (numberToDisplay) {
case 0: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_ON); digitalWrite(segE, SEGMENT_ON); digitalWrite(segF, SEGMENT_ON); digitalWrite(segG, SEGMENT_OFF); break;
case 1: digitalWrite(segA, SEGMENT_OFF); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_OFF); digitalWrite(segE, SEGMENT_OFF); digitalWrite(segF, SEGMENT_OFF); digitalWrite(segG, SEGMENT_OFF); break;
case 2: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_OFF); digitalWrite(segD, SEGMENT_ON); digitalWrite(segE, SEGMENT_ON); digitalWrite(segF, SEGMENT_OFF); digitalWrite(segG, SEGMENT_ON); break;
case 3: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_ON); digitalWrite(segE, SEGMENT_OFF); digitalWrite(segF, SEGMENT_OFF); digitalWrite(segG, SEGMENT_ON); break;
case 4: digitalWrite(segA, SEGMENT_OFF); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_OFF); digitalWrite(segE, SEGMENT_OFF); digitalWrite(segF, SEGMENT_ON); digitalWrite(segG, SEGMENT_ON); break;
case 5: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_OFF); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_ON); digitalWrite(segE, SEGMENT_OFF); digitalWrite(segF, SEGMENT_ON); digitalWrite(segG, SEGMENT_ON); break;
case 6: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_OFF); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_ON); digitalWrite(segE, SEGMENT_ON); digitalWrite(segF, SEGMENT_ON); digitalWrite(segG, SEGMENT_ON); break;
case 7: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_OFF); digitalWrite(segE, SEGMENT_OFF); digitalWrite(segF, SEGMENT_OFF); digitalWrite(segG, SEGMENT_OFF); break;
case 8: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_ON); digitalWrite(segE, SEGMENT_ON); digitalWrite(segF, SEGMENT_ON); digitalWrite(segG, SEGMENT_ON); break;
case 9: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_ON); digitalWrite(segE, SEGMENT_OFF); digitalWrite(segF, SEGMENT_ON); digitalWrite(segG, SEGMENT_ON); break;
case 10: digitalWrite(segA, SEGMENT_OFF); digitalWrite(segB, SEGMENT_OFF); digitalWrite(segC, SEGMENT_OFF); digitalWrite(segD, SEGMENT_OFF); digitalWrite(segE, SEGMENT_OFF); digitalWrite(segF, SEGMENT_OFF); digitalWrite(segG, SEGMENT_OFF); break;
}
}
void SwitchDigit(int digit) {
for (int i = 0; i < 4; i++) {
digitalWrite(digit_pin[i], (i == digit) ? DIGIT_ON : DIGIT_OFF);
}
}
struct struct_digits IntToDigits(int n) {
struct struct_digits dig;
int zeros = 0, d;
for (int i = 0; i < 4; i++) {
d = n / pow(10, 3 - i);
zeros += d;
n -= d * pow(10, 3 - i);
dig.digit[i] = (zeros != 0 || i == 3) ? d : 10; // 10 = blank
}
return dig;
}
void PrintNumber(int n, int time) {
struct struct_digits dig = IntToDigits(n);
for (int i = 0; i <= time / 20; i++) {
if (digitalRead(button2) == LOW) return; // 취소 버튼
for (int j = 0; j < 4; j++) {
SwitchDigit(j);
lightNumber(dig.digit[j]);
delay(5);
}
}
}
bool Countdown(int n, int del) {
for (int q = n; q > 0; q--) {
PrintNumber(q, del);
if (digitalRead(button2) == LOW) return false;
}
PrintNumber(0, 0);
playTone(1519, 1000); // 알람음
return true;
}
void reset() {
int pressed3 = 0, pressed4 = 0;
struct struct_digits dig = IntToDigits(countdown_time);
while (digitalRead(button1) == HIGH) { // 버튼1 누르면 시작
for (int j = 0; j < 4; j++) { SwitchDigit(j); lightNumber(dig.digit[j]); delay(5); }
if (digitalRead(button3) == LOW) { // 시간 감소
if (pressed3 == 0 || pressed3 > 30) { if (countdown_time > 0) countdown_time--; dig = IntToDigits(countdown_time); }
pressed3++;
} else if (digitalRead(button4) == LOW) { // 시간 증가
if (pressed4 == 0 || pressed4 > 30) { if (countdown_time < 9999) countdown_time++; dig = IntToDigits(countdown_time); }
pressed4++;
}
if (digitalRead(button3) == HIGH) pressed3 = 0;
if (digitalRead(button4) == HIGH) pressed4 = 0;
}
}
void loop() {
reset(); // 설정 모드
while (!Countdown(countdown_time, 962)) { reset(); } // 카운트다운 실행, 취소 시 재설정
while (digitalRead(button2) == HIGH) {}; // 버튼2 눌러야 다음 라운드
}
활용 팁
PrintNumber(숫자, 표시시간_ms) 함수를 다른 프로젝트에서 재사용 가능
- 공통 음극 디스플레이 사용 시
SEGMENT_ON/OFF 및 DIGIT_ON/OFF 로직 반전 필요
- 버튼에 풀업 저항 사용 (INPUT_PULLUP), 누르면 LOW