2017년 8월 10일 목요일

7-Segment 카운터

아두이노로 7-Segment 카운터를 만들기 위해 아두이노 보드와 빵판(Bread Board)에 부품을 다음과 같이 조립했습니다.

Anode타입 세그먼트라서, Common 단자는 저항(220Ω)을 통해 5V 출력에 연결했습니다. 그리고 a~g까지의 단자는 리드선을 통해 2~8 포트에 연결되어 있습니다.

이렇게 연결하고 아두이노 전원을 넣으면, 7개의 lcd에 모두 불이 들어오게 됩니다. 초기에 모든 단자의 출력이 LOW이며, Anode타입이므로 불이 들어오게 되는 것이죠.

이제 이 세그먼트를 제어할 프로그램을 만들어야 합니다.

아두이노 스케치에서 처음 프로젝트를 만들면 다음과 같은 C 프로그램이 만들어집니다.

void setup()
{
}

void loop()
{
}

여기에는 main함수가 없지만, 내부에 다음과 같은 main함수가 숨어 있는 것입니다.

main()
{
    setup();
    while(1)
        loop();
}

즉, 최초에 setup()함수가 불리고 나서, loop()함수가 계속 호출되는 식이죠.
아무튼 최초 setup()함수에서는 우리가 사용할 핀(2~8)들에 대한 선언을 합니다. 기본적으로 C프로그램이므로 변수들도 자유롭게 선언할 수 있죠.

int pin[] = {2, 3, 4, 5, 6, 7, 8};
          // a, b, c, d, e, f, g

void setup()
{
  for(int k = 0; k < 7; ++k)
    pinMode(pin[k], OUTPUT);
}

void loop()
{
}

pinMode(int pinNo, int value);가 각 핀들의 기능을 선언하는 함수입니다. 루프를 돌면서 2번부터 8번까지의 핀들을 OUTPUT으로 선언하는 것이죠(물론 INPUT으로 선언하면 각종 센서로부터의 입력을 받을 수 있습니다).
다음에 loop()함수에서 각 세그먼트의 ONOFF를 제어해야 합니다.

int pin[] = {2, 3, 4, 5, 6, 7, 8};
           //a, b, c, d, e, f, g

void setup()
{
  for(int k = 0; k < 7; ++k)
    pinMode(pin[k], OUTPUT);
}

void loop()
{
    digitalWrite(pin[0], LOW); // a
    digitalWrite(pin[1], LOW); // b
    digitalWrite(pin[2], LOW); // c
    digitalWrite(pin[3], LOW); // d
    digitalWrite(pin[4], LOW); // e
    digitalWrite(pin[5], LOW); // f
    digitalWrite(pin[6], HIGH); // g
}

(Anode 타입이므로) High로 설정된 g led만 꺼져 0이 출력될 것입니다.
그런데 이런 식으로 일일이 코딩하느니, 테이블과 함수를 만드는 것이 낫겠죠.

int pin[] = {2, 3, 4, 5, 6, 7, 8};
           //a, b, c, d, e, f, g

byte pattern[10][7]
{
  { 0, 0, 0, 0, 0, 0, 1 }, // 0
  { 1, 0, 0, 1, 1, 1, 1 }, // 1
  { 0, 0, 1, 0, 0, 1, 0 }, // 2
  { 0, 0, 0, 0, 1, 1, 0 }, // 3
  { 1, 0, 0, 1, 1, 0, 0 }, // 4
  { 0, 1, 0, 0, 1, 0, 0 }, // 5
  { 0, 1, 0, 0, 0, 0, 0 }, // 6
  { 0, 0, 0, 1, 1, 1, 1 }, // 7
  { 0, 0, 0, 0, 0, 0, 0 }, // 8
  { 0, 0, 0, 0, 1, 0, 0 }  // 9
};

int digit = 0;

void setup()
{
  for(int k = 0; k < 7; ++k)
    pinMode(pin[k], OUTPUT);
}

void loop()
{
  Display(pattern[0]);
}

void Display(byte ptn[])
{
  for(int k = 0; k < 7; ++k)
    digitalWrite(pin[k], ptn[k]);
}

이렇게 해도 동일한 결과가 나옵니다(이 pattern 테이블과 Display함수는 다음에도 필요할때 복사해서 쓸 수 있습니다).

시간에 따라 숫자를 바꾸기 위해서는 delay(int millisec) 함수를 사용할 수 있습니다.

int pin[] = {2, 3, 4, 5, 6, 7, 8};
           //a, b, c, d, e, f, g

byte pattern[10][7]
{
  { 0, 0, 0, 0, 0, 0, 1 }, // 0
  { 1, 0, 0, 1, 1, 1, 1 }, // 1
  { 0, 0, 1, 0, 0, 1, 0 }, // 2
  { 0, 0, 0, 0, 1, 1, 0 }, // 3
  { 1, 0, 0, 1, 1, 0, 0 }, // 4
  { 0, 1, 0, 0, 1, 0, 0 }, // 5
  { 0, 1, 0, 0, 0, 0, 0 }, // 6
  { 0, 0, 0, 1, 1, 1, 1 }, // 7
  { 0, 0, 0, 0, 0, 0, 0 }, // 8
  { 0, 0, 0, 0, 1, 0, 0 }  // 9
};

int digit = 0;    // 이번에 출력할 숫자

void setup()
{
  for(int k = 0; k < 7; ++k)
    pinMode(pin[k], OUTPUT);
}

void loop()
{
  Display(pattern[digit]);
  delay(1000);      // 출력후 1초 기다림
  ++digit;          // 출력할 숫자 증가
  if(digit > 9)
    digit = 0;
}

void Display(byte ptn[])
{
  for(int k = 0; k < 7; ++k)
    digitalWrite(pin[k], ptn[k]);
}

7 Segment, Cathode, Anode

7 Segment란, 엘리베이터 등에서 흔히 볼 수 있는, 7개(정확히는 8개)의 발광다이오드(LCD)를 이용해 숫자를 표시할 수 있는 부품입니다.

그림 1

여러개의 LCD가 패턴을 만들고 있을 뿐 기본
적인 구조는 다음과 같습니다.

Cathod
Anode


공통단자가 전원선이냐 접지냐에 따라 Cathod형과 Anode형으로 나뉘며, 사용법도 약간의 차이가 있습니다.


아무튼, Anode형이든 Cathode형이든 공통단자는 그림 1에서 com에 해당하며, 나머지 선들은 다음과 같이 연결되어 있습니다.


이를테면, b와 c단자에 신호를 보내면 1이 표시되는 것이죠.

여기서 '신호를 보낸다'는 것에 Cathod와 Anode의 차이가 있습니다. Cathod는 접지에 공통단자가 연결되어 있으므로 전압이 가해졌을때(High 신호를 보낼 때) 빛이 납니다.
하지만 Anode형은 공통단자에 이미 전압이 가해져 있죠. Anode 단자에 High신호를 보내면(전압을 가하면) 공통단자의 전압과 상쇄되어 빛이 나지 않습니다. 즉 이 경우에는 Log신호를 보내야(전압을 가하지 않아야) 빛이 납니다.