74HC595+CD4511+7SegmentLED 제어(아두이노)

in #kr-newbie6 years ago (edited)

74HC595+CD4511+7SegmentLED 제어(아두이노)



최종적으로 쉬프트레지스터(74HC595)와 7 segment Decoder(CD4511)를 결합하여 7 Segment LED를 제어하는 실험을 하고자 합니다. 아두이노에서 7 Segment LED를 제어하는 실험에서 출발하여 74HC595, CD4511 칩들을 개별적으로 이용하여 7 Segment LED를 제어 했었습니다. 이 두 칩을 연결하여 제어를 통해 7 Segment LED 실험을 마루리 하고자 합니다.

1. 7 74HC595 + CD4511 연결


위 그림에서 보면 아두이노에서 74HC595 칩으로 3개의 핀으로 입력을 하면 74HC595 칩에서는 8개의 출력 신호를 만들어 냅니다. 8개의 출력 신호에서 4개의 출력로 나눠서 각 CD4511 칩에 입력으로 들어가고 CD4511 칩에서 7개의 출력 신호를 최종적으로 만들어 냅니다.

여기서 출력핀을 제외한 나머지 핀들은 Vcc, Gnd에 연결되는 핀인데 그림에서는 생략 했습니다. 혹시 이해가 안되시는 분들은 위의 참고자료를 보시고 각 칩에 대한 연결을 다시 공부하셔야 합니다.

2. 회로도 구성


  • 준비물 : 74HC595 칩 1개, CD4511 칩 1개, 7 Segment LED 2개, 저항 330옴 2개, 저항 10k옴 8개, 아두이노우노, 뻥판
  • 내용 : 74HC595+CD4511 칩을 연결하여 7 Segment LED에 숫자를 출력하게 하자. 참고로 7 Segment LED(캐소드형)

전체 회로도 구성을 보시면 머리가 복잡해질 꺼에요. 이것은 개별적으로 이해 하시면 쉬울 꺼에요.

첫번째, 74HC595 칩을 제어하기 위해서 9,11,12핀을 이용한다. 회로도 74HC595 칩에 입력선과 Vcc, Gnd 선 연결만 생각하시고 출력선은 잠시 잊어주세요.

두번쨰, CD4511 칩을 제어하기 위해서는 4개의 입력이 필요합니다 하지만 회로도에서 입력선을 제외한 나머지 Vcc, Gnd 선 연결만 생각하시고 입력선, 출력선은 잠시 잊어 주세요.

세번째, CD4511 칩 입력 4개의 핀이고 8421(BCD) 코드표의 기준으로 배치하니깐 '0000'은 74HC595 출력핀 기준으로 '4321' 핀 순서로 입력을 넣어야 합니다. 그래서 1=A, 2=B, 3=C, 4=D 핀끼리 연결합니다. 나머지 CD4511 칩에다도 '0000'은 '8765' 핀 순서로 입력을 넣어야 겠죠. 5=A, 6=B, 7=C, 8=D 핀끼리 연결합니다.

네번째, 7 Segment LED은 CD4511칩의 출력 A,B,C,D,E,F,G핀에서 7 Segment LED의 입력 a,b,c,d,e,f,g핀으로 순서대로 A=a, B=b, C=c, D=d, E=e, F=f, G=g로 연결하면 됩니다.

다섯번째, 7 Segment LED은 캐소드형으로 변경 해주세요. 보고 똑같이 선 연결했는데 왜! 안돼! 이럴 수 있습니다. 애노드형인지 캐소드 형인지 꼭 확인이 필요합니다. 7 Segment LED은 캐소드형이여서 COM2의 핀에 Gnd로 연결을 하게 됩니다. 딱 볼때 COM1 or COM2가 Vcc로 연결되면 애노드형, Gnd로 연결되면 캐소드형으로 생각하시면 됩니다.

보시면 선연결이 많다 보니깐 복잡해 보이는데 개별적으로 하나씩 선 연결하시면 그리 어렵지 않을거라 생각 되네요.

3. 코딩


  • 사용함수 : pinMode(출력핀, 모드), digitalWrite(결쇠핀, 열림/잠금), shiftOut(데이터입력핀, 클럭핀, 순서, 데이터전송값)
  • 내용 : 쉬프트레지스터(74HC595)에 맞춰서 2개의 7 Segment LED에 숫자를 출력해 보자.
  • 참고 : 쉬프트레지스터(74HC595) 제어(아두이노)

설계

(1) 숫자패턴 배열변수 만든다.

byte data[]={
0B00000000,
0B00000001,  
0B00000010,
0B00000011,
0B00000100,  
0B00000101,  
0B00000110,  
0B00000111,
0B00001000,  
0B00001001,  
};

지난 시간의 쉬프트레지스터(74HC595) 코딩을 기준으로 약간만 수정하여 의미만 전달하도록 코딩했습니다. 8개의 비트값이 있습니다. 왼쪽 4개는 왼쪽 CD4511 칩에 입력값이고 오른쪽 4개는 오른쪽 CD4511 칩에 입력값이 됩니다.

즉,

0000 0001 => '0' 과 '1' 이 7 Segment LED에 출력됩니다.

만약에 '1'과 '2'을 출력하고 싶다면 바이트 값이 어떻게 바꿔야 할까요.

0001 0010 => 0B00010010

이해가 되셨죠.

(2) 숫자 출력

digitalWrite(latchPin, LOW); //열림
shiftOut(dataPin, clockPin, MSBFIRST, data[i]); //패턴입력
digitalWrite(latchPin, HIGH); //닫힘

코딩을 하면

byte data[]={
0B00000000,
0B00000001,  
0B00000010,
0B00000011,
0B00000100,  
0B00000101,  
0B00000110,  
0B00000111,
0B00001000,  
0B00001001,  
};

int latchPin = 11; //ST_CP Pin
int clockPin = 12; //SH_CP Pin
int dataPin = 9; //DS Pin

void setup(){
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
}
void loop(){
 for(int i=0;i<10;i++){
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, data[i]);
    digitalWrite(latchPin, HIGH);       
    delay(1000);
  }  
}

4. 추가 코딩(프로그램영역이라 생략하셔도 됨)


본 코딩은 제 블로그에 올렸던 코딩으로 설명 드리겠습니다.

0B00000000을 16진수로 표현할 수 있다고 했죠. 16진수로 '0x00'로 표현이 됩니다.
그러면 위 값들을 다시 표현을 하면은 다음과 같습니다.

0x00
0x01
0x02
0x03
0x04
0x05
0x06
0x07
0x08
0x09

자세히 보시면 한자리씩 증가되는걸 보실 수 있을꺼에요. 그러면 11이면 '0x11'로 표현이 되면 '0x' 이것만 빼면은 그냥 숫자로 생각해도 되겠다는 생각이 아마 들꺼에요. 이걸 이용해서 숫자를 쉽게 만들어보자는 생각을 하셔야 합니다.

7 Segment LED가 2개를 사용하니깐 16진수를 사용하면 2자리 숫자를 쉽게 표현이 되겠죠.

byte total=0x00; //출력
byte A=0x00; //1의 자리
byte B=0x00; //10의 자리

이렇게 3개의 변수를 선언합니다. loop()함수 내에서

A=A+0x01;  or A+=0x01;

이렇게 하면 A은 0x01씩 증가합니다. delay(1000) 함수로 1초 단위로 저 명령문을 수행하면 1초 단위로 '0x01'씩 숫자를 증가 시키고 그 값은7 Segment LED로 숫자 1씩 증가한 숫자가 출력되겠죠.

1분짜리 시간을 카운터 한다고 해봅시다.

void loop(){
  
  total = A+B;  
  현재 total값 74HC595에 출력;

  delay(1000);
    
  A=A+0x01; 
  if(A==0x0A){
    A=0x00;
    B=B+0x10;
  }
    
  if(total==0X59) B=0x00;
}

A을 '0x01'증가 시킵니다. if 조건문으로 '0x0A' 이면 '0x00' 초기화 합니다. 여기서 '0x0A'은 10을 나타냅니다. 16진수는 9까지는 숫자로 나타내고 10부터 A,B,C,D,E,F로 0~15까지 숫자를 한자리에 표현을 할 수 있습니다. 그래서 16진수인거죠. 우리가 일상에서 쓰는 0~9까지 10진수 입니다. 그렇다고 10진수라고 부르며 쓰지는 않죠. 생략해서 그냥 숫자를 쓰는 것 뿐이죠. 16진수는 0~15까지 한자리에 표현할 수 있는 숫자라는 것만 머리속에 담아 놓으시면 됩니다.

다시 돌아와서 A은 일의 자리이기 때문에 0~9까지 숫자가 표현되고 10(0x0A)가 되면 안되겠죠. 딱 9(0x09)까지만 출력되여야 하기 때문에 조건문으로 10인지 체크하는 것이죠. 10이면 B가 10의 자리이기 때문에 그때 두번째 자리에 '0x10'을 더하게 됩니다. 조건문에서 10이 되니깐 1의 자리는 '0x00'으로 초기화 하고 10의 자리는 '0x10'으로 1이 증가 시키는 로직으로 표현된 것이죠.

마지막으로 if문은 total이 0x59이면 이전에 delay()함수로 1초가 지났기 때문에 실제는 60초가 됩니다. 하지만 loop()함수가 다음 호출되어 반복하기 전이기 때문에 total값은 59초값을 가지고 있기 때문에 if 조건문에서 '0x59' 인가라고 조건을 단것이지요. 실제로는 60초인가라는 조건문으로 생각하시면 됩니다. 60초면 B를 초기화 시키기 위해서 B=0x00로 표현하게 됩니다.

결론은 첫번째 if문은 A을 증가시킨값이 10초 되면 A를 초기화 후 B를 1씩 증가시키고 두번재 if문 B가 60초가 되면 B를 초기화 시키라는 로직입니다. 60초 되면 A은 10초가 되고 A는 초기화 되고 B은 60초 되면 당연이 B도 초기화 됩니다. 다음 루프함수는 total = 0x00 + 0x00; 이 됩니다. 결론은 00이 7 Segment LED에 출력이 됩니다.

이걸 이용하시면 시계를 만들 수 있겠죠. 초기값을 현재 시간값으로 저장시키면 자동으로 그 시간을 기준으로 시간을 계속 출력시킬 수 있겠죠.

코딩을 수정을 하면

byte total=0x00;//출력
byte A=0x00; //1의 자리
byte B=0x00; //10의 자리

int latchPin = 11; //ST_CP Pin
int clockPin = 12; //SH_CP Pin
int dataPin = 9; //DS Pin

void setup(){
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
}

void loop(){

  total = A+B;  
   
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, total);
  digitalWrite(latchPin, HIGH);       
  
  delay(1000);
    
  A=A+0x01; 
  if(A==0x0A){
    A=0x00;
    B=B+0x10;
  }
    
  if(total==0X59) B=0x00;
}

5. 결과


회로도를 만드는 과정을 영상으로 만들려고 하니깐 너무 심한 노가다여서 그냥 마지막 출력된 영상만 보여줄까도 고민하다고 그래도 전과정을 보여주는게 나을 것 같아서 이미 회로도를 만들어 놓은게 있었지만 한번 더 작업을 했네요.

마무리


드디어 7 Segment LED를 아두이노 제어에서 여기까지 왔습니다. 다른 칩까지 가면 너무 힘들 것 같아서 여기서 최종적으로 마무리 할까 합니다. 원래는 74HC595, CD4511 칩들은 대량의 LED를 제어할 목적으로 많이 쓰는 것 같더군요. 이 칩만 잘 활용해도 아두이노우노의 적은 핀을 가지고도 많은 부품들을 제어할 수 있어 확장성이 엄청 좋습니다. 한번 힘들더라도 부품의 데이터시트나 여러 블로그의 예제들을 보고 연구해 보셨으면 합니다.
이것만 알아도 표현할 수 있는 것들이 무궁무진 하니깐 상상의 나래를 펼쳐 보세요.

Sort:  

스스로 홍보하는 프로젝트에서 나왔습니다.
오늘도 좋은글 잘 읽었습니다.
오늘도 여러분들의 꾸준한 포스팅을 응원합니다.

방문해주셔서 감사합니다.

Congratulations @codingman! You have completed some achievement on Steemit and have been rewarded with new badge(s) :

Award for the number of comments

Click on any badge to view your own Board of Honor on SteemitBoard.

To support your work, I also upvoted your post!
For more information about SteemitBoard, click here

If you no longer want to receive notifications, reply to this comment with the word STOP

Upvote this notification to help all Steemit users. Learn why here!

코딩맨님 안녕하세요~!!

가끔식 코딩맨님 글 읽으려 오는데

저는 코딩에 문외한이라... 너무 어려워서 댓글 조차 달기가 가끔 어렵네요 ㅜ

저번 3D 렌더링 글 이후로는 댓글을 못 달고 있네요ㅜ

최근 칩 부분 실험이 들어가다 보니깐 거기에 동작 로직을 코딩하다 보니깐 좀 어렵게 진행 됐네요.

코딩은 엑셀를 혹시 사용하실 수 있으시면 엑셀함수로 생각하시면 아마 될 듯요.
하나의 동작을 아두이노 IDE에서 대부분 함수로 제공되고 그 함수를 원하는 동작을 수행하기 위해서 순서대로 배치하는 것 뿐이라서요.

코딩이 쉽게 표현하자면 어린시절에 생활계획표를 짜보신적 있을거에요. 아침기상, 아침식사, 학교등교......
이걸 하루일과 로직 코딩으로
void loop(){
아침기상() ;
아침식사();
학교등교();
오전수업();
점심식사();
오후수업();
하교();
학원();
저녁식사();
취침();
}

이렇게 제공되는 함수들을 순서대로 배치하는게 코딩이라고 생각하시면 아마 이해가 되실꺼에요.

오 조금이나마 이해가 되었습니다. ㅋㅋ

차츰차츰 알아가봐야겠어요

2018년에는 두루 평안하시길!

감사합니다. 오치님도 2017년 두루 평안하시길 기원합니다.

Coin Marketplace

STEEM 0.26
TRX 0.11
JST 0.032
BTC 63585.64
ETH 3035.86
USDT 1.00
SBD 3.84