4-Digit 7-Segment Display 제어(아두이노)

in #kr-arduino6 years ago (edited)

4-Digit 7-Segment Display 제어(아두이노)



지난시간에 2-Digit 7-Segment Display(애노드형)을 가상시뮬레이터에서 실험 했었습니다. 오늘은 실제로 4-Digit 7-Segment Display로 숫자를 출력해보는 실험을 해보겠습니다. 4-Digit 7-Segment Display 부품은 캐소드형이고 지난시간에 일부 변수값과 상태값은 전부 반전된 형태로 표현해야 하기 때문에 회로도를 만들고나서 코딩을 할 때 혼동하지 말고 주의해서 코딩하시기 바랍니다.

1. 4-Digit 7-Segment Display(캐소드형)


4-Digit 7-Segment Display 부품은 아래 이미지와 같습니다. 대충 그렸는데 썩 마음에 들지 않네요.

내부 회로도를 살펴보면 지난 시간에 애노드형 2-Digit 7-Segment Display 회로도를 보셨을 꺼에요. 오늘은 실제 사용되는 4-Digit 7-Segment Display 부품은 캐소드형으로 아래와 같은 회로도로 구성되어 있습니다.

4개의 7-Segment가 a,b,c,d,e,f,g,dp 핀을 공유하고 제어는 D1, D2, D3, D4로 각 D핀을 개방함으로써 해당 7-Segment에 숫자나 문자를 출력하게 됩니다.

캐소드형이기 때문에 D1, D2, D3, D4 핀은 LOW가 될때 a,b,c,d,e,f,g,dp 핀이 HIGH일 때 해당 LED에 불이 들어오게 됩니다. 지난시간의 애노드형 2-Digit 7-Segment Display 반대입니다.

2. 4-Digit 7-Segment Display 핀 번호


위 표를 꼭 기억해 주세요. 4-Digit 7-Segment Display 부품의 위의 부품이미지처럼 순서대로 1~12번까지 있는데 각 핀에 해당된 값을 기억해 주세요. 세개의 표가 있는데 양쪽 표는 여러분들이 보기 편한 것을 참조해 주시고요. 가운데 표는 아두이노와 연결했을 때의 표입니다. 아두이노 핀은 여러분들이 실제 4-Digit 7-Segment Display 부품의 핀을 아두이노에 어떤식으로 연결하느냐에 따라서 아두이노핀 번호는 달라집니다. 가운데 표는 여러분들이 실제 구현을 할 때 표로 직접 작성해주세요. 그리고 나서 코딩을 할 때 해당 4-Digit 7-Segment Display 핀의 값을 기준으로 변수를 선언하실 수 있습니다.

즉, 위 표와 같이 연결을 한다면,

byte segPin[8]={7,3,A3,A1,A0,6,A4,A2}; //사용핀{a,b,c,d,e,f,g,dp} 순서대로임
byte digitPin[4] = {8,5,4,A5}; //segment 위치 핀

이런식으로 pin번호를 순서대로 4-Digit 7-Segment Display 핀값에 매칭되는 아두이노 핀번호를 선언해주면 됩니다. 위 배열 변수에 저장된 값은 4-Digit 7-Segment Display부품과 아두이노에 어떻게 연결했느냐에 따라서 값이 달라집니다.

여러분들이 편한 방식으로 마음대로 연결하시고 코딩할 때만 핀변수값을 정확히 선언하시면 부품을 제어하는데 어려움은 없을 거라 생각됩니다.

참고로, 선 연결 할 때 a,b,d,c,e,f,g,dp핀을 한쪽으로 뭉쳐서 순서대로 아두이노에 연결하고 나머지 4개의 핀은 d1,d2,d3,d4에 순서대로 연결하셔도 됩니다. 하지만 이경우는 4-Digit 7-Segment Display 부품의 핀 위치값을 정확히 알고 있을 때 선을 연결하는 방법인데 좀 지져분하게 선이 연결 됩니다. 그리고, 선 연결 할 때 실수 할 가능성이 가장 큽니다. 별로 추천드리지 않습니다.

쉽게, 4-Digit 7-Segment Display 부품 핀번호 1~12번을 아두이노 2~12번으로 순서대로 매칭시켜서 선을 연결하거나 아니면 아두이노의 아날로그와 디지털핀을 이용하여 4-Digit 7-Segment Display 부품 핀 번호 1~6번은 아두이노 A0~A5에 연결하고 나머지 7~12번은 아두이노 2~7번으로 위아래 순서대로 선을 연결하셔도 됩니다. 그냥 순서대로 핀을 보기 좋게 연결하시고 코딩에서 해당핀에 대한 변수만 제대로 선언하시면 제어하는데 어려움이 없을 꺼에요

2. 4-Digit 7-Segment Display 회로도


준비물 : 4-Digit 7-Segment Display 1개, 아두이노우노
내용 : 4-Digit 7-Segment Display 부품의 핀 번호 순서에 맞게 아두이노우노에 연결 하시오.


위 회로도는 4-Digit 7-Segment Display 핀번호 1~6번은 아날로그 핀 A0~A5에 순서대로 연결하고 7~12번은 순서대로 2~7번으로 연결하려다가 따로 스위치버턴을 인터럽트 핀을 이용할 까 고민중이라 인터럽트핀이 2,3 번 핀 중에 우선 2번핀 하나정도는 남겨 두기 위해서 3~8번으로 순서대로 핀을 연결했네요.

핀 연결은 여러분들이 편하신 방법으로 연결하시면 됩니다. 규칙도 없고 그냥 여러분이 원하는 스타일로 연결만 해주세요. 연결하시고 나서 코딩을 할 때 해당핀에 대한 변수를 선언할 때 정확히 지정만 해주면 됩니다.

2. 코딩


1)LED 숫자 패턴


[애노드형]

//a,b,c,d,e,f,g
byte segValue[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  
};

캐소드형 회로도이기 때문에 아래와 같이 1은 0으로 0은 1로 변경만 시키면 됩니다.

//a,b,c,d,e,f,g 상태값
byte segValue[10][7] = {
   {1,1,1,1,1,1,0}, //0
   {0,1,1,0,0,0,0}, //1
   {1,1,0,1,1,0,1}, //2
   {1,1,1,1,0,0,1}, //3
   {0,1,1,0,0,1,1}, //4
   {1,0,1,1,0,1,1}, //5
   {1,0,1,1,1,1,1}, //6
   {1,1,1,0,0,0,0}, //7
   {1,1,1,1,1,1,1}, //8
   {1,1,1,1,0,1,1}  //9  
};

2) 숫자 카운트 (0~9999)


아래와 같이 millis()함수는 실시간으로 현재 타이머시간값을 읽어옵니다 그 값을 기준으로 각 자릿숫자를 d1,d2,d3,d4에 저장됩니다.

readTime = millis()/1000;
d1 = readTime%10; //1의 자리
d2 = (readTime/10)%10; //10의 자리
d3 = (readTime/100)%10; //100의 자리
d4 = (readTime/1000)%10; //1000의 자리

2-Digit 7-Segment Display 에서 100의 자리, 1000의 자리가 추가 되었을 뿐 따로 코딩에는 변동이 없습니다.

2) 숫자 카운트 출력(0~9999)

segOutput(3,d1,0); //1의 자리
if(readTime>=10) segOutput(2,d2,0); //10의 자리  
if(readTime>=100) segOutput(1,d3,0); //100의 자리  
if(readTime>=1000) segOutput(0,d4,0); //1000의 자리  

출력되 100의 자리, 1000의 자리로 segOutput()함수 인자만 맞게 넣어주시면 4자리 숫자가 카운트 되어 출력됩니다.

3) 종합소스


//a,b,c,d,e,f,g 상태값
byte segValue[10][7] = {
   {1,1,1,1,1,1,0}, //0
   {0,1,1,0,0,0,0}, //1
   {1,1,0,1,1,0,1}, //2
   {1,1,1,1,0,0,1}, //3
   {0,1,1,0,0,1,1}, //4
   {1,0,1,1,0,1,1}, //5
   {1,0,1,1,1,1,1}, //6
   {1,1,1,0,0,0,0}, //7
   {1,1,1,1,1,1,1}, //8
   {1,1,1,1,0,1,1}  //9  
};

byte segPin[8]={7,3,A3,A1,A0,6,A4,A2}; //사용핀{a,b,c,d,e,f,g,dp} 순서대로임
byte digitPin[4] = {8,5,4,A5}; //segment 위치 핀

unsigned long readTime=0; //현재시간
int d1 = 0; //1의 자리
int d2 = 0; //10의 자리
int d3 = 0; //100의 자리
int d4 = 0; //1000의 자리

void setup() {
  for(int i=0;i<10;i++){
    pinMode(segPin[i], OUTPUT);
  }
  for(int j=0;j<4;j++){
    pinMode(digitPin[j], OUTPUT);   
    digitalWrite(digitPin[j], HIGH); 
  }
}

void loop() {   
  readTime = millis()/1000;
  d1 = readTime%10; //1의 자리
  d2 = (readTime/10)%10; //10의 자리
  d3 = (readTime/100)%10; //100의 자리
  d4 = (readTime/1000)%10; //1000의 자리
  
  segOutput(3,d1,0); //1의 자리
  if(readTime>=10) segOutput(2,d2,0); //10의 자리  
  if(readTime>=100) segOutput(1,d3,0); //10의 자리  
  if(readTime>=1000) segOutput(0,d4,0); //10의 자리  
}
//LED 초기화
void segClear(){ 
  for(int i=0;i<8;i++){
    digitalWrite(segPin[i], LOW);        
  }
}
//LED 출력
void segOutput(int d, int Number, int dp){ 
  segClear();
  digitalWrite(digitPin[d], LOW); 
  for(int i=0;i<7;i++){
     digitalWrite(segPin[i], segValue[Number][i]);        
  }
  digitalWrite(segPin[7], dp);
  delayMicroseconds(1000);
  digitalWrite(digitPin[d], HIGH); 
}

3. 결과


동영상 결과는 사실 1초 단위로 카운트 할려고 했는데 사실 4개의 7-Segment의 숫자가 정확히 출력되는지 확인하기 위해서는 1000초가 걸립니다. 즉, 16분 40초를 기다려야 합니다. 그래서 0.01초로 카운트를 한 영상입니다.

readTime = millis()/10; //0.01초 단위

4. 입터럽트 스위치 버턴으로 타이머 리셋


스위치버턴을 입터럽트 이벤트를 발생시킬 예정입니다. 스톱워치처럼 스위치를 누르면 타이머가 누른 시점에서 리셋되어 돌아가고 다시 스위치를 누르면 정지되고 타이머가 돌다가 멈춘 시간값을 보여주게 됩니다. 그리고 다시 스위치를 누르면 처음부터 다시 타이머가 돌게하는 실험을 할 예정입니다.

1) 회로도


  • 준비물 : 4-Digit 7-Segment Display 1개, 스위치버턴 1개, 아두이노우노
  • 내용 : 4-Digit 7-Segment Display 부품의 핀 번호 순서에 맞게 아두이노우노에 연결하고, 스위치 버턴은 2번핀에 연결하시오.

2번핀은 인터럽트 핀으로 스위치 버턴을 2번핀에 연결했습니다.

2) 코딩



인터럽트스위치 버턴을 사용하니깐 아래와 같이 코딩합니다 사전학습에 있던 내용이깐 가셔서 읽고 오세요.

const byte interruptPin = 2;//인터럽트핀
void setup() {
  pinMode(interruptPin, INPUT_PULLUP); 
  attachInterrupt(digitalPinToInterrupt(interruptPin), switchFn, FALLING);
}
void loop() {   
  if(state==true){ //스위치 상태가 true일때 카운트
        스위치눌러질때 동작명령;
    }
}
void switchFn(){
  state=!state;
  if(state==true){
    timer0_millis=0; //타이머변수 리셋  
  }
}

여기서, switchFn() 함수를 약간 수정했는데 그것은 state의 값이 true일 때만 timer0_millis을 0으로 초기화 했습니다. 즉, 스위치눌러 타이버가 동작할 때 그 시점에 timer0_millis=0으로 초기화 한다는 의미입니다.

위에서 타이머 동작 기본 소스에서 인터럽트 스위치 버턴 코딩을 합치면 아래와 같은 전체 소스가 완성 됩니다.

//a,b,c,d,e,f,g 상태값
const byte segValue[10][7] = {
   {1,1,1,1,1,1,0}, //0
   {0,1,1,0,0,0,0}, //1
   {1,1,0,1,1,0,1}, //2
   {1,1,1,1,0,0,1}, //3
   {0,1,1,0,0,1,1}, //4
   {1,0,1,1,0,1,1}, //5
   {1,0,1,1,1,1,1}, //6
   {1,1,1,0,0,0,0}, //7
   {1,1,1,1,1,1,1}, //8
   {1,1,1,1,0,1,1}  //9  
};

const byte segPin[8]={7,3,A3,A1,A0,6,A4,A2}; //사용핀{a,b,c,d,e,f,g,dp} 순서대로임
const byte digitPin[4] = {8,5,4,A5}; //segment 위치 핀

const byte interruptPin = 2;//인터럽트핀
extern volatile unsigned long timer0_millis; //타이머변수

boolean state = false;//타이머 동작 제어

unsigned long readTime=0; //현재시간
int d1 = 0; //1의 자리
int d2 = 0; //10의 자리
int d3 = 0; //100의 자리
int d4 = 0; //1000의 자리

void setup() {
  pinMode(interruptPin, INPUT_PULLUP); 
  attachInterrupt(digitalPinToInterrupt(interruptPin), switchFn, FALLING);
  
  for(int i=0;i<10;i++){
    pinMode(segPin[i], OUTPUT);
  }
  for(int j=0;j<4;j++){
    pinMode(digitPin[j], OUTPUT);    
    digitalWrite(digitPin[j], HIGH); 
  }
}

void loop() {   
  if(state==true){ //스위치 상태가 true일때 카운트
    readTime = millis()/1000;
    d1 = readTime%10; //1의 자리
    d2 = (readTime/10)%10; //10의 자리
    d3 = (readTime/100)%10; //100의 자리
    d4 = (readTime/1000)%10; //1000의 자리 
  }
  if(readTime>=0)segOutput(3,d1,0); //1의 자리
  if(readTime>=10) segOutput(2,d2,0); //10의 자리  
  if(readTime>=100) segOutput(1,d3,0); //10의 자리  
  if(readTime>=1000) segOutput(0,d4,0); //10의 자리 
}
//스위치버턴 이벤트
void switchFn(){
  state=!state;
  if(state==true){
    timer0_millis=0; //타이머변수 리셋  
  }
}
//LED 초기화
void segClear(){ 
  for(int i=0;i<8;i++){
    digitalWrite(segPin[i], LOW);        
  }
}
//LED 출력
void segOutput(int d, int Number, int dp){ 
  segClear();
  digitalWrite(digitPin[d], LOW); 
  for(int i=0;i<7;i++){
     digitalWrite(segPin[i], segValue[Number][i]);        
  }
  digitalWrite(segPin[7], dp);
  delayMicroseconds(1000);
  digitalWrite(digitPin[d], HIGH); 
}

3) 결과


스위치가 눌러지면 state=true가 되고 1초 단위로 카운트 하게 됩니다. 참고로 다시 누르면 state=false로 정지됩니다. 다시 누르면 state=true가 되고 timer0_millis=0으로 초기화 되고 처음부터 다시 1초 단위로 카운트를 하게 됩니다.

마무리


오늘은 실제 4-Digit 7-Segment Display 부품에 카운트 결과를 출력해 보았습니다. 지난 시간에 시리얼모니터로 결과를 출력했던 것과 다르게 좀 복잡해 보였을 꺼에요. 하나하나 뜯어보면 어렵지 않는 내용이니깐 분리해서 하나씩 살펴보시기 바랍니다.

다음 시간에는 아두이노 시계로 4-Digit 7-Segment Display에 현재 시간을 만들고 그 시간을 기준으로 시간이 흘러가는 것을 실험해 보겠습니다.

Sort:  

(jjangjjangman 태그 사용시 댓글을 남깁니다.)
호출에 감사드립니다! 즐거운 스티밋하세요!

짱짱맨 방문에 감사합니다.

ღ•̀ᴗ•̀ღ

⊂( ̄(エ) ̄)⊃

시물레이션이 아니라 직접 만드셨네요. 일일히 손으로 배선한다는 게 무지 귀찮은 일인데 꼼꼼하신 모양입니다.

그래도 예전 3x3x3 큐브 회로도 배선 할때보다는 쉬운 것 같아요. 그때 가지고 있는 선을 다 연결했어도 모자랐는데 이번에는 좀 편하게 했네요.

취미신가요??대단하시네요.ㅎㅎ

네! 취미로 놀고 있어요.
몇년전에 잠깐 놀았는데 스티미언 활동하면서 새롭게 정리를 하면서 post하고 있네요

Coin Marketplace

STEEM 0.18
TRX 0.16
JST 0.030
BTC 65989.03
ETH 2622.29
USDT 1.00
SBD 2.65