코딩교육-아두이노

아두이노 디지털 핀 (4자리 숫자 7-세그먼트 게소드 제어) - Arduino Digtal Pin - 4 Digit Seven-Segment Cathode Control

carrotweb 2022. 1. 31. 19:49
728x90
반응형

4자리 숫자 7-세그먼트 (7-Segment)는 1자리 숫자 7-세그먼트 (7-Segment)를 4개를 결합한 것입니다. 28개의 세그먼트와 4개 도트로 구성되어 숫자(0부터 9999까지)나 문자를 표시할 수 있는 디지털 출력 모듈입니다.

1자리 숫자 7-세그먼트과 동일하게 양극(VCC)을 공통 핀으로 갖는 에노드형(Common Anode type)과 음극(GND)을 공통 핀으로 갖는 게소드형(Common Cathode Type)등 2가지 타입이 있습니다.

제가 가지고 있는 4자리 숫자 7-세그먼트는 음극(GND)을 공통 핀으로 갖는 게소드형(Common Cathode type)입니다.

 

1자리 숫자 7-세그먼트는 도트를 포함하여 8개의 숫자 핀(a, b, c, d, e, f, g, dp)과 2개의 GND로 되어 있었습니다.

만약 1자리 숫자 7-세그먼트를 4개로 연결한다면 40개의 핀으로 구성되어 연결할 디지털 핀이 많아야 합니다. 아두이노 우노 보드는 디지털 핀이 14개로 연결할 수 없습니다.

그래서 4자리 숫자 7-세그먼트는 1자리 숫자 7-세그먼트과 동일하게 숫자를 표현하기 위해 도트를 포함하여 8개의 숫자 핀(a, b, c, d, e, f, g, dp)과 각 숫자 자리마다 LED에 불을 켜거나 끌 수 있게 제어하는 자리 순서 핀(O1, O2, O3, O4)으로 구성되어 있었습니다. 즉, 숫자의 자리 순서를 제어함으로써 40개의 핀 수를 12개의 핀으로 줄일 수 있었습니다. 그러나 여러 자리에 동시에 숫자를 표현할 수 없게 되었습니다.

 

4자리 숫자 7-세그먼트에서 숫자를 표시하기 위해서는 자리 순서부터 설정해야 합니다.

자리 순서를 설정하기 위해서는 지정할 자리 순서 핀에만 디지털 신호(LOW)를 주고 나머지는 디지털 신호(HIGH)를 주면 됩니다. 한 번에 하나의 자리만 설정하여 제어할 수 있습니다.

그리고 숫자 핀(a, b, c, d, e, f, g, dp)에 디지털 신호(HIGH)를 주어 숫자를 표시합니다.

예를 들어, 3번째 자리에 1을 표현한다면 O3 자리 순서 핀에 LOW주고 나머지 자리 순서 핀에 HIGH를 줍니다. 그리고 1을 표현하기 위해 a핀과 c핀에 HIGH를 주어 LED에 불이 켜지게 합니다.

만약, 4자리에 숫자를 다 표현하고 싶다면 숫자를 표시할 자리 순서 핀과 숫자 핀에 디지털 신호를 반복적으로 주어야 합니다. 그 이유는 실제로는 한 번에 하나의 자리에만 숫자가 표시되기 때문에 모든 자리에 숫자가 보이게 하기 위해서는 연속적으로 반복해서 호출해야 합니다. 그러면 사람의 눈에는 착시현상으로 동시에 표시되는 것처럼 보입니다.

디지털 핀 출력 제어 - 4자리 숫자 7-Segment LED 숫자 0 표시

1. 4자리 숫자 7-세그먼트를 브레드보드에 꼽습니다.

상하로 점프 와이어와 연결하기 위해 4자리 숫자 7-세그먼트의 상단 핀을 g열 2, 3, 4, 5, 6, 7에 하단 핀을 e열 2,3,4,5,6,7에 꼽습니다.

 

2. 숫자 핀(a, b, c, d, e, f, g, dp)에 220옴 저항을 연결하기 위해 M-M 점퍼 와이어를 꼽습니다.

a: j열 3번과 14번에 흰색 M-M 점퍼 와이어

f: j열 4번과 15번에 녹색 M-M 점퍼 와이어

b: j열 7번과 16번에 빨간색 M-M 점퍼 와이어

e: a열 2번과 17번에 흰색 M-M 점퍼 와이어

d: a열 3번과 18번에 파란색 M-M 점퍼 와이어

dp: a열 4번과 19번에 주황색 M-M 점퍼 와이어

c: a열 5번과 20번에 녹색 M-M 점퍼 와이어

g: a열 6번과 21번에 빨간색 M-M 점퍼 와이어

 

3. 숫자 핀(a, b, c, d, e, f, g, dp)관 연결된 M-M 점퍼 와이어에 220옴 저항을 꼽습니다.

a: h열 14번과 e열 14번에 220옴 저항

f: h열 15번과 e열 15번에 220옴 저항

b: h열 16번과 e열 16번에 220옴 저항

e: a열 17번과 f열 17번에 220옴 저항

d: a열 18번과 f열 18번에 220옴 저항

dp: a열 19번과 f열 19번에 220옴 저항

c: a열 20번과 f열 20번에 220옴 저항

g: a열 21번과 f열 21번에 220옴 저항

 

4. 아두이노 우노 보드와 연결하기 위해 M-M 점퍼 와이어를 꼽습니다. 이전 1자리 숫자 7-세그먼트와 동일한 색을 사용하였습니다.

a: b열 14번에 흰색 M-M 점퍼 와이어

f: b열 15번에 녹색 M-M 점퍼 와이어

b: b열 16번에 회색 M-M 점퍼 와이어

e: i열 17번에 주황색 M-M 점퍼 와이어

d: i열 18번에 빨간색 M-M 점퍼 와이어

dp: i열 19번에 파랑색 M-M 점퍼 와이어

c: i열 20번에 보라색 M-M 점퍼 와이어

g: i열 21번에 노란색 M-M 점퍼 와이어

 

5. 자리 순서 핀(O1, O2, O3, O4)과 아두이노 우노 보드와 연결하기 위해 M-M 점퍼 와이어를 꼽습니다.

O1: i열 2번에 검은색 M-M 점퍼 와이어

O2: i열 5번에 갈색 M-M 점퍼 와이어

O3: i열 6번에 주황색 M-M 점퍼 와이어

O4: b열 7번에 빨간색 M-M 점퍼 와이어

 

6. 아두이노 우노 보드에 4자리 숫자 7-세그먼트의 8개 숫자 핀(a, b, c, d, e, f, g, dp)과 연결된 M-M 점퍼 와이어를 디지털 핀에 연결합니다. 이전 1자리 숫자 7-세그먼트와 동일한 색을 사용하였습니다.

숫자 핀(a, b, c, dp, f, g, e, d)

2: 흰색 M-M 점퍼 와이어

3: 회색 M-M 점퍼 와이어

4: 보라색 M-M 점퍼 와이어

5: 파란색 M-M 점퍼 와이어

6: 녹색 M-M 점퍼 와이어

7: 노란색 M-M 점퍼 와이어

8: 주황색 M-M 점퍼 와이어

9: 빨간색 M-M 점퍼 와이어

자리 순서 핀(O1, O2, O3, O4)

10: 검은색 M-M 점퍼 와이어

11: 갈색 M-M 점퍼 와이어

12: 주황색 M-M 점퍼 와이어

13: 빨간색 M-M 점퍼 와이어

 

이전 1자리 숫자 7-세그먼트 소스코드를 복사하여 사용합니다.

// 디지털 핀(a, b, c, dp, f, g, e, d)
byte ledPins[] = {2, 3, 4, 5, 6, 7, 8, 9};
byte pinCount = 8;

// 숫자 0~9
byte segmentDigit[11][8] = {
  {1, 1, 1, 0, 1, 0, 1, 1}, // 0
  {0, 1, 1, 0, 0, 0, 0, 0}, // 1
  {1, 1, 0, 0, 0, 1, 1, 1}, // 2
  {1, 1, 1, 0, 0, 1, 0, 1}, // 3
  {0, 1, 1, 0, 1, 1, 0, 0}, // 4
  {1, 0, 1, 0, 1, 1, 0, 1}, // 5
  {1, 0, 1, 0, 1, 1, 1, 1}, // 6
  {1, 1, 1, 0, 0, 0, 0, 0}, // 7
  {1, 1, 1, 0, 1, 1, 1, 1}, // 8
  {1, 1, 1, 0, 1, 1, 0, 1}, // 9
  {0, 0, 0, 1, 0, 0, 0, 0} // dot
};

// 영어문자 A, b, c, d, E, F
byte segmentAlphabet[6][8] = {
  {1, 1, 1, 0, 1, 1, 1, 0}, // A
  {0, 0, 1, 0, 1, 1, 1, 1}, // b
  {1, 0, 0, 0, 1, 0, 1, 1}, // C
  {0, 1, 1, 0, 0, 1, 1, 1}, // d
  {1, 0, 0, 0, 1, 1, 1, 1}, // E
  {1, 0, 0, 0, 1, 1, 1, 0} // F
};

void segmentDigitWrite(byte digit) {
  for (byte pinIndex = 0; pinIndex < pinCount; pinIndex++) {
    digitalWrite(ledPins[pinIndex], segmentDigit[digit][pinIndex]);
  }
}

void segmentAlphabetWrite(byte digit) {
  for (byte pinIndex = 0; pinIndex < pinCount; pinIndex++) {
    digitalWrite(ledPins[pinIndex], segmentAlphabet[digit][pinIndex]);
  }
}

void loop() {
  for (byte index = 0; index < 11; index++) {
    segmentDigitWrite(index);
    delay(1000);
  }
}

7. 전역에 1차원 배열로 자리 순서 핀(O1, O2, O3, O4)를 제어하기 위해 디지털 핀 번호를 선언합니다. (O1: 10, O2: 11, O3: 12, O4: 13)

// 자리 순서 핀(O1, O2, O3, O4)
byte orderPins[] = {10, 11, 12, 13};
byte orderCount = 4;

 

8. 지정된 자리 순서에 숫자를 표시하기 위한 함수를 선언합니다.

void segmemntOrderDigitWrite(byte order, byte digit) {
  // 잔상제거
  for (byte pinIndex = 0; pinIndex < pinCount; pinIndex++) {
    digitalWrite(ledPins[pinIndex], LOW);
  }
  for (byte orderIndex = 0; orderIndex < orderCount; orderIndex++) {
    digitalWrite(orderPins[orderIndex], orderIndex == order ? LOW : HIGH);
  }
  segmentDigitWrite(digit);
}

잔상 제거를 위해 8개 핀(a, b, c, d, e, f, g, dp)에 LOW를 주는 이유는 4자리 숫자 7-세그먼트의 8개 핀(a, b, c, d, e, f, g, dp)을 공동으로 사용하기 때문에 자리 순서 핀에 LOW를 주는 순간에 지정된 자리에 이전의 숫자가 표시됩니다. 그래서 지정된 자리에 숫자를 표시하기 전에 8개 핀(a, b, c, d, e, f, g, dp)에 LOW로 설정해야 합니다.

9. setup() 함수에서 for문을 이용하여 자리 순서 핀의 모드를 출력 모드로 설정하고 HIGH로 초기화합니다.

void setup() {
  for (int pinIndex = 0; pinIndex < pinCount; pinIndex++) {
    pinMode(ledPins[pinIndex], OUTPUT);
  }
  for (int orderIndex = 0; orderIndex < orderCount; orderIndex++) {
    pinMode(orderPins[orderIndex], OUTPUT);
    digitalWrite(orderPins[orderIndex], HIGH);
  }
  segmemntOrderDigitWrite(3, 0);
}

 

10. 이전 loop() 함수 내의 내용은 지웁니다.

void loop() {
}

 

11. 컴파일하고 업로드합니다. 잠시 후 4자리 숫자 7-세그먼트의 LED에 불이 들어오면서 숫자 0이 표시됩니다.

 

 

디지털 핀 출력 제어 - 4자리 숫자 7-Segment LED 숫자 1234 표시

1. 4자리 숫자를 표시하기 위한 함수를 선언합니다.

4자리 숫자를 표현하기 위해서는 일단위, 십 단위, 백 단위, 천 단위 숫자를 분리하고 단위 별로 숫자가 표시되게 segmemntOrderDigitWrite()함수를 호출합니다.

void segmemntOrderDigitWrite(int digit) {
  int units = digit % 10;
  int tens = (digit / 10) % 10;
  int hundreds = (digit / 100) % 10;
  int thousands = (digit / 1000) % 10;

  segmemntOrderDigitWrite(3, units);
  if (digit >= 10) {
    segmemntOrderDigitWrite(2, tens);
  }
  if (digit >= 100) {
    segmemntOrderDigitWrite(1, hundreds);
  }
  if (digit >= 1000) {
    segmemntOrderDigitWrite(0, thousands);
  }
}

 

2. 전역 변수에 숫자를 표시 하기 위한 변수를 선언하고 1234를 초기 데이터로 설정합니다.

int number = 1234;

 

3. loop() 함수에segmemntOrderDigitWrite() 함수를 호출합니다.

void loop() {
  segmemntOrderDigitWrite(number);
}

만약, loop() 함수에서 segmemntOrderDigitWrite()함수를 호출하지 않고 setup() 함수에서 segmemntOrderDigitWrite()함수를 호출했다면 천 단위에만 1이 표시됩니다. 그 이유는 위에서 언급했던 것처럼 한 번에 한자리의 숫자만 표시되기 때문에 반복적으로 호출되지 않으면 제일 마지막에 호출한 자리의 숫자만 표시되게 됩니다.

4. 컴파일하고 업로드합니다. 잠시 후 1234가 표시됩니다.

 

이전 segmemntOrderDigitWrite() 함수에서 잔상 제거를 위해 8개 핀(a, b, c, d, e, f, g, dp)에 LOW를 주었습니다. 만약에 8개 핀(a, b, c, d, e, f, g, dp)에 LOW를 주지 않고 처리한다면 다음처럼 잔상과 겹처져서 나타나게 됩니다.

 

다음 처럼 잔상 제거도 없고 delay() 함수가 짧게 처리되었다면 위처럼 잔상이 겹치지는 않지만 잔상이 나오는 것을 확인할 수 있습니다.

void segmemntOrderDigitWrite(byte order, byte digit) {
  for (byte orderIndex = 0; orderIndex < orderCount; orderIndex++) {
    digitalWrite(orderPins[orderIndex], orderIndex == order ? LOW : HIGH);
  }
  segmentDigitWrite(digit);
  delay(5);
}

 

 

디지털 핀 출력 제어 - 4자리 숫자 7-Segment LED 숫자 카운트

1. 전역 변수에 이전 시간을 저장하는 변수를 선언하고 number를 0으로 초기화합니다.

unsigned long oldTime = 0;
int number = 0;

 

2. loop() 함수에서 0.1 초마다 number를 증가시키고 숫자를 표시합니다. number가 10,000이 되면 0으로 초기화한다.

void loop() {
  unsigned long currentTime = millis();
  if (currentTime - oldTime > 100) {
    number++;
    if (number == 10000) {
      number = 0;
    }
    oldTime = currentTime;
  }
  segmemntOrderDigitWrite(number);
}

깜빡거림을 최소화하기 위해서는 delay()가 없어야 합니다. 그 이유는 delay() 함수가 호출되면 4자리 숫자 7-세그먼트는 마지막에 호출한 단위의 숫자만 표시됩니다. 그래서 loop() 함수가 delay() 없이 계속 돌면서 0.1초마다 숫자를 증가시키기 위해서 Time의 millis() 함수를 사용합니다.

 

전체 소스입니다.

// 디지털 핀(a, b, c, dp, f, g, e, d)
byte ledPins[] = {2, 3, 4, 5, 6, 7, 8, 9};
byte pinCount = 8;

// 숫자 0~9
byte segmentDigit[11][8] = {
  {1, 1, 1, 0, 1, 0, 1, 1}, // 0
  {0, 1, 1, 0, 0, 0, 0, 0}, // 1
  {1, 1, 0, 0, 0, 1, 1, 1}, // 2
  {1, 1, 1, 0, 0, 1, 0, 1}, // 3
  {0, 1, 1, 0, 1, 1, 0, 0}, // 4
  {1, 0, 1, 0, 1, 1, 0, 1}, // 5
  {1, 0, 1, 0, 1, 1, 1, 1}, // 6
  {1, 1, 1, 0, 0, 0, 0, 0}, // 7
  {1, 1, 1, 0, 1, 1, 1, 1}, // 8
  {1, 1, 1, 0, 1, 1, 0, 1}, // 9
  {0, 0, 0, 1, 0, 0, 0, 0} // dot
};

// 자리 순서 핀(O1, O2, O3, O4)
byte orderPins[] = {10, 11, 12, 13};
byte orderCount = 4;

unsigned long oldTime = 0;
int number = 0;

void segmentDigitWrite(byte digit) {
  for (byte pinIndex = 0; pinIndex < pinCount; pinIndex++) {
    digitalWrite(ledPins[pinIndex], segmentDigit[digit][pinIndex]);
  }
}

void segmemntOrderDigitWrite(byte order, byte digit) {
  // 잔상제거
  for (byte pinIndex = 0; pinIndex < pinCount; pinIndex++) {
    digitalWrite(ledPins[pinIndex], LOW);
  }
  for (byte orderIndex = 0; orderIndex < orderCount; orderIndex++) {
    digitalWrite(orderPins[orderIndex], orderIndex == order ? LOW : HIGH);
  }
  segmentDigitWrite(digit);
}

void segmemntOrderDigitWrite(int digit) {
  int units = digit % 10;
  int tens = (digit / 10) % 10;
  int hundreds = (digit / 100) % 10;
  int thousands = (digit / 1000) % 10;

  segmemntOrderDigitWrite(3, units);
  if (digit >= 10) {
    segmemntOrderDigitWrite(2, tens);
  }
  if (digit >= 100) {
    segmemntOrderDigitWrite(1, hundreds);
  }
  if (digit >= 1000) {
    segmemntOrderDigitWrite(0, thousands);
  }
}

void setup() {
  for (int pinIndex = 0; pinIndex < pinCount; pinIndex++) {
    pinMode(ledPins[pinIndex], OUTPUT);
  }
  for (int orderIndex = 0; orderIndex < orderCount; orderIndex++) {
    pinMode(orderPins[orderIndex], OUTPUT);
    digitalWrite(orderPins[orderIndex], HIGH);
  }
  segmemntOrderDigitWrite(3, 0);
}

void loop() {
  unsigned long currentTime = millis();
  if (currentTime - oldTime > 100) {
    number++;
    if (number == 10000) {
      number = 0;
    }
    oldTime = currentTime;
  }
  segmemntOrderDigitWrite(number);
}

millis()함수

millis() 함수는 아두이노 보드에서 프로그램이 시작한 후부터 밀리초를 반환합니다.

(단, millis()함수는 약 50일이 지나면 오버플로우가 발생하여 0으로 돌아갑니다.)

loop() 함수에서 millis() 함수를 이용해 현재 밀리초를 받고 이전에 저장한 밀리초와 연산하여 0.1초가 지났는지 비교합니다. 0.1초가 지났으면 number를 증가시킵니다. 그리고 현재 밀리초를 저장합니다.

3. 컴파일하고 업로드합니다. 잠시 후 0부터 0.1초마다 숫자가 무한 증가합니다.

 

728x90
반응형