본문 바로가기
Arduino&RasberryPi/Arduino Uno

18. Arduino - 4자리 7 세그먼트 LED(1)

by Rosmary 2019. 11. 21.
728x90
반응형

***  4자리 7 세그먼트 LED의 동작과정에 대해 이해하기 위해서는 1자리 7 세그먼트 LED의 동작 과정에 익숙해져야한다. 따라서, 1자리 세그먼트에 대해 잘 모르시는 분들이라면, 여기를 눌러 세그먼트 LED 작동 방식에 대해 감을 잡은 뒤, 본 포스팅을 읽어주시기 바란다.

 

 

지난 포스팅에서는 1자리 7세그먼트 LED를 작동시키는 법에 대해 알아보았다. 이번에는 4자리를 표시할 수 있는 7 세그먼트 LED를 다루는 법에 대해 상세히 작성하고자...했으나, 너무 알아야 할 내용이 방대한 탓에, 포스팅을 나누어 진행하게 되었다...

 

4자리 7 세그먼트도 작동 방식은 1자리 부품과 별반 차이가 있지는 않다. 하지만, 제한된 핀으로 4자리를 각기 다르게 표시해야하는 특성 때문에, 코드가 조금 더 복잡하다. 필자는 몇 번의 실험을 통해, 사용되는 코드들을 조금 더 분석한 뒤 철저하게 분석된 글을 작성하고 싶었지만 byte 자료형을 자주 써오지 않았던터라, 이 부분에 대해서는 다음 표스팅이나 되어서야 내용을 정리할 수 있을 듯 하다.

 

우선, 4자리 7 세그먼트의 구성과 작동 방식 그리고 간단한 코드 작성까지만 알아보자.

 

 

 

1. 4자리 7 세그먼트 구성

 

4자리 7 세그먼트는 1자리 7 세그먼트와 외양면에서 큰 차이가 없다. 차이가 있다면, 숫자를 표시할 수 있는 LED가 4배 더 많다는 것과, Arduino 핀과 연결할 수 있는 단자가 2개 더 많다는 것이 전부다. 모양은 아래와 같이 생겼다.

 

 

12개의 단자는 아래위로 절반씩, 각각 6개가 배치되어 있다. 이 중 4개는, 각각의 7 세그먼트에 전원을 공급하는 공통 단자로 작동한다. 그 외의 단자는 한 자리 7 세그먼트와 마찬가지로, 각각의 LED를 지나온 전류가 빠져나가는 GND 핀과 연결된다. 자세한 단자의 상세도는 다음과 같다.

 

COM1부터 COM4까지 표시된 핀이, 각 자릿수에 전원을 공급하는(혹은 GND) 핀과 연결되는 단자다. COM1이 첫 자리를 구성하는 LEG Segment에 전원을 공급하며, COM2, 3, 4는 각각 두 번째 자리, 세 번째 자리, 네 번째 자리에서 사용하는 공통 단자라고 보면 된다.

 

1자리 7 세그먼트와 마찬가지로, 4자리 7 세그먼트 역시 공통 양극 모델과 공통 음극 모델로 종류가 나뉘는데, 이는 직접 회로를 연결하여 확인할 수 있다. 확인 방법은 여기를 눌러 볼 수 있다.

 

 

 

 

2. 작동 방식 및 코드 구성.

 

회로의 구성도를 보면 알겠지만, 각 자릿수에 해당하는 LED 전체에 불이 들어오도록 만드는 방법은 크게 어렵지 않다. 첫 자리만 불이 들어오게 하고 싶다면, COM1 단자와 연결된 핀만 전원을 공급하고, 나머지는 digitalWrite() 두 번째 인자 값을 0으로 만들어버리면 된다. COM2, COM3, COM4도 마찬가지.

 

각 자릿수마다 불이 잘 들어오는지 확인하기 위해, 1초마다 각 자릿수의 모든 세그먼트가 점등되었다가 꺼지도록 코드를 작성해 Arduino에 밀어넣어보자. 코드는 다음과 같다.

 

 

===================================

int firstsource = 10;
int secondsource= 11;
int thirdsource = 12;
int fourthsource= 13;

int a = 9;
int f = 8;
int b = 7;
int e = 6;
int d = 2;
int dp= 3;
int c = 4;
int g = 5;

void setup() {
  // put your setup code here, to run once:
  for(int i = 2; i <=13 ; i++)
  {
    pinMode(i, OUTPUT);
    digitalWrite(i, 1);
  }
}

void loop() {
  // put your main code here, to run repeatedly:
  show(1, 0);
  delay(1000);
  show(2,0);
  delay(1000);
  show(3,0);
  delay(1000);
  show(4,0);
  delay(1000);
}

void show(int digit, int segment)
{
  if(digit > 4) return 0;
  
  for(int i = 10; i <=13; i++)
  {
    digitalWrite(i, 0);
    if(i == digit + 9)
    {
      digitalWrite(i,1);
    }
  }

  for(int i = 2; i < 10; i++)
  {
    digitalWrite(i, 0);
  }
}

===========================

 

이전과 달리, show()라는 함수를 직접 만들어 코드를 작성했는데, 이 show라는 함수는 2개의 인자(자릿수, 표시할 숫자)를 가진다. 다만, 위의 코드에서는 자릿수마다 모든 세그먼트가 잘 점등되는지 확인하기 위해, 두 번째 인자는 모두 0으로 부여했다. 작동 결과는 아래와 같다.

 

 

하지만, 각 자릿수마다 서로 다른 숫자를 출력하고 싶다면... 초보의 입장에서는 고민이 된다. 각 세그먼트에 불이 들어오게 하기 위해서, 원래 32개의 단자가 필요함에도, 우리는 8개의 단자와 연결된 핀만 조절함으로써 이 문제를 해결해야 하기 때문이다. 만약 아래와 같이 코드를 작성하고 Arduino를 실행하면, 다음과 같이 모든 자릿수에서 동일한 세그먼트 LED가 동시에 점등되는 것을 볼 수 있을 것이다.

 

=============================

int firstsource = 10;
int secondsource= 11;
int thirdsource = 12;
int fourthsource= 13;

int a = 9;
int f = 8;
int b = 7;
int e = 6;
int d = 2;
int dp= 3;
int c = 4;
int g = 5;

void setup() {
  // put your setup code here, to run once:
  for(int i = 2; i <=13 ; i++)
  {
    pinMode(i, OUTPUT);
    digitalWrite(i, 1);
  }
  delay(1000);
}

void loop() {
  // put your main code here, to run repeatedly:
  for(int i = 2 ; i <= 9; i++)
  {
    digitalWrite(i, 0);
    delay(1000);
    setup();
  }

}

======================================

 

 

각기 서로 다른 숫자가 나타나도록 하는 방법은 의외로 간단하다. 각 자릿수를 표현하는 코드 사이에 아주 짧은 시간 동안 delay를 주는 것이다. 예를 들어, 7 세그먼트에 전원을 공급하는 핀이 10번부터 13번이므로,

 

================================

for(int i = 10; i<=13 ; i++)

{

   digitalWrite(i, 1);

   if(i==10)  digitalWrite(2, 0);

   else if(i==11) digitalWrite(5, 0);

   else if(i==12) digitalWrite(7, 0);

   else digitalWrite(8, 0);

   delay(5);

}

================================

 

와 같은 코드가 들어간다면, 각 자릿수는 각각 d, g, b, f에 해당하는 세그먼트만 점등될 것이다. 일종의 잔상 현상을 이용한 방법이라고 생각하면 된다. 위의 코드의 delay() 인자값을 변화하며, 4자리 7 세그먼트가 어떻게 동작하는지 보면, 이해가 빠를 것이다.

 

 

3. 숫자 표현 코드

 

숫자의 표현은 이전 포스팅에서 언급한 것과 비슷한 방식을 사용하면 된다. 선언한 show() 함수 내에, 두 번째 인자의 값에 따라 if/else 또는 switch문으로 해당 숫자를 표현하는 핀의 전기신호를 조작하는 코드를 넣어주면 된다. 실제로 작동도 잘 된다. 하지만, 필자가 Arduino에서 해당 포스팅의 내용을 그대로 사용하라고 하기가 꺼려지는 이유는, 코드가 경제적이지 않기 때문이다. 

 

다음은 필자가 0부터 9999까지 4자리 7 세그먼트에서 연속 출력되도록 작성한 코드다.

 

==========================================

int sourcePin[] = {10, 11, 12, 13};  //1, 2, 3, 4번째 전원 공급 핀
int led_segment[] = {9, 7, 4, 2, 6, 8, 5, 3};
int i, j;  

 

//  변수를 줄이고자 배열 형태로 핀을 재정의;


void setup ()
{
  for(i = 2; i <= 13; i++)
  {
    pinMode(i, OUTPUT);
    digitalWrite(i, 1);
  }
}

void loop ()
{
  for(int number = 0 ; number < 10000; number++)
  {
    calc(number);
    delay(5);
    setup();
  }
}

void calc (int value)
{
  if(value >=10000) return ;
  
  int first = value / 1000;
  int second = (value % 1000) / 100;
  int third = (value % 100) / 10;
  int fourth = (value %10);
  
  show(1, first);
  delay(5);
  show(2, second);
  delay(5);
  show(3, third);
  delay(5);
  show(4, fourth);
  delay(5);
}

void show (int digit, int segment)
{
  for(i=0; i<4; i++)
  {
    if(i == digit-1) digitalWrite(sourcePin[i],1);
    else  digitalWrite(sourcePin[i],0)  ;
  }

  if(segment == 0)
  {
    for(i = 0 ; i<=7 ; i++)
    {
      digitalWrite(led_segment[i], 0);
      if(i ==6) digitalWrite(led_segment[i], 1);
    }
  }
  else if(segment == 1)
  {
    for(i = 0 ; i<=7 ; i++)
    {
      digitalWrite(led_segment[i],1);
      if(i == 1 or i == 2) digitalWrite(led_segment[i],0);
    }
  }
  else if(segment == 2)
  {
    for(i = 0 ; i<=7 ; i++)
    {
      digitalWrite(led_segment[i],0);
      if(i == 2 or i == 5) digitalWrite(led_segment[i],1);
    }
  }
  else if(segment ==3)
  {
    for(i = 0 ; i<=7 ; i++)
    {
      digitalWrite(led_segment[i],0);
      if(i == 4 or i == 5 or i ==7) digitalWrite(led_segment[i],1);
    }
  }
  else if(segment ==4)
  {
    for(i = 0 ; i<=7 ; i++)
    {
      digitalWrite(led_segment[i],1);
      if(i==1 or i==2 or i == 5 or i == 6) digitalWrite(led_segment[i],0);
    }
  }
  else if(segment ==5)
  {
    for(i = 0 ; i<=7 ; i++)
    {
      digitalWrite(led_segment[i],0);
      if(i==1 or i==4) digitalWrite(led_segment[i],1);
    }
  }
  else if(segment ==6)
  {
    for(i = 0 ; i<=7 ; i++)
    {
      digitalWrite(led_segment[i],0);
      if(i==1) digitalWrite(led_segment[i],1);
    }
  }
  else if(segment ==7)
  {
    for(i = 0 ; i<=7 ; i++)
    {
      digitalWrite(led_segment[i],1);
      if(i==0 or i==1 or i==2) digitalWrite(led_segment[i],0);
    }
  }
  else if(segment ==8)
  {
    for(i = 0 ; i<=7 ; i++)
    {
      digitalWrite(led_segment[i],0);
    }
  }
  else if(segment ==9)
  {
    for(i = 0 ; i<=7 ; i++)
    {
      digitalWrite(led_segment[i],0);
      if(i==4 or i==7) digitalWrite(led_segment[i],1);
    }
  }
}

==========================================

 

< 꼭 시한폭탄 같다 >

 

 

show() 함수 내의 코드를 보면 알겠지만, 두 번째 인자에 따라 각기 다르게 동작하도록 만든 코드가 for문과 if 문에 떡칠이 되어, 상당히 복잡하다. 실제로 이 코드를 Arduino에 넣으면, 이 코드만으로도 Arduino 전체 용량의 6%를 차지한다...

 

인터넷 상에서 4자리 수를 표시하는 코드는, byte 자료형과 비트 연산자로 나타낸 자료가 가장 많이 보이는데, 필자가 비트 연산에 아직 익숙하지가 않아서인지 코드가 영 이해가 되지 않는다. 물론 시간을 들여서 코드를 분석한다면 이해할 수 있겠지만... 요즘따라 업무가 무척이나 바쁘다...(그래서인지 요즘 작성한 포스팅 글을 다시 읽으면 아주 개판...이다. 원래도 개판이었지만 ㅎㅎ)

 

따라서, 4자리 숫자를 byte와 비트 연산자로 나타내는 코드를 어느정도 분석할 수 있게 된다면, 다음 포스팅에서 관련 내용에 대해 이야기할 예정이다. 오늘은 간단하게 여기까지.

 

 

FIN.

 

 

반응형

댓글