아두이노 레시피

아두이노 레시피 : 7세그먼트 - 초중급편

arduinochef 2025. 2. 26. 18:45

# Recipe 18. LED 정복하기 시리즈 : 7-Segment

HACKADAY by Dan Maloney

안녕하세요~ 아두이노셰프입니다. 이번 주는 LED에 대해서 다루고 있는데요. 오늘은 조금 특별한 LED를 들고 왔습니다. 바로 ‘7-세그먼트’입니다. 이름은 조금 생소할 수 있지만, 한 번쯤은 봤을법한 흔하게 사용되는 표시장치입니다. 7개의 LED획으로 이루어져서 7-세그먼트라는 이름이 붙었고요, 각각의 LED를 온오프 해서 숫자나 문자를 나타낼 수 있는 친구예요. 원리랄 게 없습니다. 그냥 LED 7개를 모아둔 거니까요.ㅎㅎ 그런데 숫자나 문자를 나타내려면 7개의 LED 중 특정 LED만 켜고 꺼야 하는데 어떻게 할 수 있을까요? 물론 라이브러리로 쉽게 할 수 있지만, 오늘은 라이브러리 없이 해보려고요. 그래야 원리를 이해할 수 있겠죠? (코드가 조금 어려울 수 있습니다.)

오늘은 다섯 번째 시간, ‘’ 7-세그먼트’입니다.

오늘의 재료 Ingredient


<메인 재료>

7-세그먼트

<그 외 재료>

아두이노 우노

브레드보드

200Ω 저항(8개)

수-수 점퍼케이블(9개)


메이킹 방법 Steps

Step 1. 선 연결하기 Wiring

세그먼트의 핀번호를 참고해 주세요!

a. A, B, C, D, E, F, G순대로 아두이노의 2,3,4,5,6,7,8번에 연결할 거예요.

b. 200Ω 저항을 이용해서 아두이노와 연결해 주세요.

(반드시 저항을 이용해서 연결해 주세요! 200Ω 사용을 권장합니다.)

c. 세그먼트의 8번과 3번은 공통핀입니다. 모든 LED와 연결되어 있어요. 3번 핀을 아두이노의 5v에 연결해 주세요.

d. 이번 레시피에서는 세그먼트의 DP(5번) 핀은 사용하지 않을 겁니다.

(조금 복잡하죠?ㅠㅠ 그림을 참고해서 연결해 주세요!)

- - - - - - - - - -

Step 2. 아두이노 코드 Code review

여러분의 요리가 훨씬 간편해질 수 있도록, 숙성이 필요한 코드는 언제나 제가 준비할게요ㅎㅎ

세그먼트에 숫자 1을 표시해 볼게요.

//방법1
void setup()
{
 for(int x=2; x<9; x++){
   pinMode(x, OUTPUT);
   digitalWrite(x,HIGH);
   }
}
void loop()
{
  digitalWrite(2,1);
  digitalWrite(3,0);
  digitalWrite(4,0);
  digitalWrite(5,1);
  digitalWrite(6,1);
  digitalWrite(7,1);
  digitalWrite(8,1);
}
//방법2
int one[7] = {1,0,0,1,1,1,1}; //숫자1 LED배열
int two[7] = {0,0,1,0,0,1,0}; //숫자2 LED배열
int three[7] = {0,0,0,0,1,1,0}; //숫자3 LED배열
int four[7] = {1,0,0,1,1,0,0}; //숫자4 LED배열
int five[7] = {0,1,0,0,1,0,0}; //숫자5 LED배열

void setup()
{
for(int x=2; x<9; x++){
  pinMode(x, OUTPUT);
   digitalWrite(x,HIGH);
   }
}
void loop()
{
  for(int x=2; x<9; x++){
   if(one[x-2] == 0){
    digitalWrite(x,LOW); //만약 캐소드 공통 세그먼트라면 HIGH로 바꾸어서 업로드해주세요.
   }
   else{
    digitalWrite(x,HIGH); //만약 캐소드 공통 세그먼트라면 LOW로 바꾸어서 업로드해주세요.
   }
  }

}

Step 3. 동작시키기 Working

● 코드를 아두이노 우노에 업로드해 주세요.

● 코드를 하나씩 업로드하여 동작시켜 보세요. 숫자가 잘 표시되나요?

●코드"if(one [x-2] == 0)"이 부분의 'one'을 'two', 'three', 'four', 'five'로 바꾸어서 업로드해 보세요. 어떻게 출력되나요?

Q. 세그먼트의 불이 들어오지 않아요.

LED에 극성이 있는 것처럼, 세그먼트는 총 두 가지 종료가 있습니다.

캐소드 공통 타입과 에노드 공통 타입.

캐소드 공통타입은 세그먼트의 각 LED핀에 +가 연결되어야 켜지는 세그먼트입니다.

공통핀인 3번과 8번에는 GND가 연결되어야겠죠.

따라서 코드에 digitalWrite(pin, HIGH);를 해줘야 켜집니다.

반대로 에노드 공통타입은 세그먼트의 각 LED에 -가 연결되어야 켜지는 세그먼트입니다.

공통핀에는 5v(+)가 연결되어야 하는 세그먼트죠.

따라서 코드에 digitalWrite(pin, LOW);를 해줘야 켜집니다.

저의 예재코드는 에노드 공통타입을 기준으로 작성되었습니다.

만약 불이 안 들어온다면 사용하는 세그먼트가 '캐소드 공통 타입'임으로

세그먼트의 3 번핀(공통핀)을 GND로 바꿔서 연결해 주고,

코드의 digitalWrite함수의 HIGH신호를 LOW신호로 바꾸어야 제대로 켜집니다.


코드의 동작 알고리즘

알고리즘은 쉬운 말로 ‘진행절차’라고 할 수 있습니다.

코드가 어떻게 동작되는지 알아볼까요?

오늘은 자료구조 중 리스트 배열에 대해서 잠시 배워볼까 해요.

자료구조란 자료를 저장하는 방식, 구조를 말합니다.

예를 들어,

데이터로서 정수 1,2,3,4,5를 저장하고 싶다고 할게요.

그럼 아두이노에서 int a=1;, int b=2;...

이런 식으로 일일이 데이터를 저장해야 할까요?

만약 10개, 아니 100개가 넘는 데이터를 저장하고 나중에 불러오고 싶다면요?

지금처럼 변수를 모두 선언하고 이름을 모두 기억해야 할까요?

그렇지 않겠죠ㅋㅋㅋ

이런 식으로 데이터를 저장할 때는 자료구조를 사용해서 간단히 나타낼 수 있어요.

여러 자료구조들 중에서 리스트에 대해서 설명드릴게요.

'리스트' (LIST)

말 그대로 데이터를 리스트처럼 일렬로 저장하는 겁니다.

조금 더 자세히 얘기하면

위의 그림처럼 일렬로 칸을 만들어놓고

그 칸 안에 데이터를 저장하는 방식이에요.

그리고 칸의 위치를 인덱스라고 합니다.

인덱스가 바로, 값이 저장되어 있는 위치인 거죠.

이 인덱스를 이용해서 데이터를 읽거나 쓸 수 있습니다.

어떻게 사용하는지 바로 보여드릴게요.

 

int list[5] = {1,2,3,4,5};

Serial.println(list[0]); //시리얼모니터에 '1'이 출력될거에요.

위의 코드처럼 데이터의 타입(ex. int정수)과 리스트의 이름을 선언하고

대괄호에 저장할 데이터 수를 적어주면 돼요. [5]처럼요.

그리고 중괄호{} 안에 데이터를 , 로 구분해서 넣어주면 된답니다.

원하는 데이터를 꺼낼 때는

리스트의 이름[인덱스번호]

이렇게 호출하면 됩니다.

(인덱스는 0부터 시작해요.)

예제처럼, 데이터 1을 불러오고 싶으면

list [0] 이렇게 하면 됩니다.

만약 2를 불러오고 싶으면 list [1]

5라면 list [4]

이렇게 값을 가져올 수 있죠.

리스트에 대해서 조금은 감이 잡히나요?


우리가 리스트를 배운 이유가 있습니다.

문자를 세그먼트에 출력하려면 리스트를 사용하는 것이 효과적이기 때문이에요.

바로 알아볼까요?

세그먼트의 LED를 켜는 코드는 어렵지 않아요.

그냥 LED를 켜는 것과 같으니까요.(digitalWrite 함수만 사용)

하지만 우리가 원하는 것은

숫자 1을 표시하는 거니까

LED획의 위치에 따라 켤지 말지를 결정해야 된다는 거죠.

아래 그림을 보실까요?

그림처럼 해당 획 위치의 LED를 켜주어야 문자모양이 나타납니다.

자, 일단 무식하게 해 보죠.

일단 세그먼트의 위치는 위의 a부터 시작해서 시계방향 순서입니다.

아두이노핀들도 같은 순서로 연결했으니 a를 아두이노 D2번, 마지막 g를 D8번으로 하면 되겠군요.

그림처럼 1을 표시하려면 b, c만 켜고 나머지는 모두 꺼야 합니다.

이렇게요.

digitalWrite(2,1);

digitalWrite(3,0);

digitalWrite(4,0);

digitalWrite(5,1);

digitalWrite(6,1);

digitalWrite(7,1);

digitalWrite(8,1);

(LOW와 HIGH대신 0,1을 적어도 됩니다. 같은 디지털을 의미하니까요.)

사용한 7 세그먼트는 에노드 공통타입이어서 LOW신호를 줘야 켜집니다.

어때요?

뭔가... 숫자 1 하나 출력하는 건데, 코드가 7줄이나 되죠?

for함수로 해볼까 해도,

D3, D4번을 제외하고 모두 HIGH신호를 주어야 하니...

IF처럼 조건문도 아니고 단순히 는 안 되겠네요.

그래서 여기에 리스트가 필요한 겁니다.

먼저 저기 코드에서 1을 표시하기 위한 HIGH, LOW신호들만 모아볼게요.

1,0,0,1,1,1,1

오 이걸 리스트로 저장해 볼까요?

int one [7] = {1,0,0,1,1,1,1};

저기 one이라는 리스트는 1이라는 숫자를 표시하기 위한 세그먼트의 위치값이 되겠군요.

이렇게 하면 숫자별로 하나씩 적을 필요가 없겠어요.

for함수로 반복시키고

리스트의 인덱스 번호대로

HIGH, LOW신호를 주면

우리가 원하는 숫자가 표시되겠죠?

(조금 어렵나요?ㅎㅎ)

바로 이렇게요!

int one[7] = {1,0,0,1,1,1,1}; //숫자1 LED배열
//중간생략
for(int x=2; x<9; x++){
   if(one[x-2] == 0){
    digitalWrite(x,LOW);
   }
   else{
    digitalWrite(x,HIGH);
   }
  }

for함수로 led 수만큼 반복시키면서

'리스트[인덱스]' 값이 0이라면

그대로 LOW를 출력하고

아니라면 HIGH를 출력하면 되겠죠.

one [x-2]라고 한 이유는

변수 x의 시작값을 2로 한 이유가 아두이노핀 번호 때문인데,

그대로 집어넣으면

리스트의 첫 시작인 0부터가 아니라 2부터 시작하잖아요.

그래서 x-2라고 해서

LED와 인덱스의 값이 매칭되도록 했어요.

아직 헷갈린다면 for문과 if문 조건 x에 숫자를 직접 대입해 보면서

반복문을 천천히 머릿속으로 실행해 보는 것도 좋은 방법이에요

x가 2일 때는 one [0]인데,

one [0]이 값 1이니까

if문의 조건과 맞지 않아서 D2번은 HIGH신호가 출력되겠구나.

x가 3일 때는 one [1]인데,

one [1]이 값 0이니까

if문의 조건과 맞아서 D3번은 LOW신호가 출력되겠구나.

이렇게요.

이런 식으로 각 숫자의 신호값을 리스트로 만들면

간단하게 어떤 숫자든지 출력할 수 있답니다~

 

for문과 if문이 아직 헷갈리시는 분들은
이전 LED 레시피들을 참고해 주세요~~

리스트는 유용하니까 앞으로도 많이 사용할 거예요.
아직 헷갈려도 괜찮습니다!


오늘은 조금 길었네요ㅎㅎ

수고하셨습니다!