[아두이노] 74HC595+8x8 도트매트릭스 제어

IOT/아두이노|2019. 3. 31. 09:00

[아두이노] 74HC595+8x8 도트매트릭스 제어



이전 시간에는 8x8 LED 핀을 일일히 아두이노에 연결을 하다 보니깐 16개의 핀이 필요했습니다. 너무 많은 핀을 사용하다 보니깐 줄여보고 싶은 마음이 생기지 않나요. 우리가 7 Segment LED를 제어할 때 사용한 부품이 떠오르는 분이 있을 지 모르겠군요. 그 부품은 74HC595칩 핀으로 쉬프트레지스트를 이용하면 16개 핀에서 3개의 핀으로 줄어들게 됩니다. 74HC595 칩은 8개의 출력 핀을 제공하는데 이 칩을 직렬로 연결하면 무제한 핀을 사용할 수 있습니다. 물론 Max7219칩 하나로 16개핀을 한번에 제어가 가능합니다. 하지만 가상시뮬레이터에서는 해당 칩이 없고 74HC595 칩뿐이 없으니 그걸로 실험을 할 수 밖에 없겠죠.
그러면 74HC595 칩 2개를 이용해서 8x8 LED를 제어해보록 하겠습니다.

1. 74HC595 직렬 연결



복습의 시간으로 latchPin(12), clockPin(11), dataPin(9)을 통해서 제어합니다. 9번, 11번, 12번 핀을 연결한 선 색을 잘 보시기 바랍니다. 11, 12번핀은 서로 연결되어 있지만 9번 데이터 입력되는 핀은 Orange 선이 수평선으로 이여진게 직렬 데이터가 전송되는 연결인데 오른쪽 74HC595핀의 Q7s핀에서 왼쪽 74HC595의 dataPin에 입력으로 이여집니다.

예) 아래와 같은 입력이 이뤄질 경우74HC595 직렬 연결시 데이터는 어떻게 배치되는지 살펴 봅시다.

0B11111110 00000001


어떤 느낌으로 들어가시는지 아시겠지요.

실제로 코딩할대는 byte 배열 변수를 층과 호실로 나눠서 2개를 만들었는데요. 가능하다면 int형으로 하나로 16bit로 표현하셔도 됩니다. 이해를 돕기위해서 실험은 2개의 byte(8bit)로 실험 했습니다.

2. 회로도 구성


  • 준비물 : Yellow LED 64개, 저항 220옴 8개, 74HC595 칩 2개, 아두이노우노, 뻥판
  • 내용 : 8x8 도트매트릭스 형태를 표현하고 74HC595 칩 두개로 출력하니깐 거기에 맞게 배치해보자.


3. 코딩



복습

  • 74HC595칩 제어 :
    - latchPin, clockPin, dataPin을 pinMode(출력핀, 모드)로 선언
    - digitalWrite(결쇠핀, 열림/잠금)으로 74HC595 칩에 입력할때 열림/잠금을 제어
    - shiftOut(데이터입력핀, 클럭핀, MSBFIRST, 전송값)으로 이걸 통해서 역순으로 데이터가 배치

설계

1층만 개방은 1층에 Gnd 상태이고 나머지 층은 HIGH상태여야 하잖아요.

OB11111110

이렇게 됩니다. 오른쪽 끝이 1층이고 역순으로 순서대로 '87654321'층으로 위치가 결정됩니다.

그럼 1층1호실에 불이 들어올려면은 어떻게 해야 할까요. '0B11111110' 로 1층만 개방해야 겠죠.
1~8호실중에 1호실만 불이 들어올려면 1호실만 HIGH 상태이고 나머지는 Gnd(LOW)상태여야 겠죠.

0B00000001

1층(0B11111110)과 1호실(0B00000001)로 합쳐져서 1호실만 불이 들어오게 됩니다.
층별 개방할려면,

0B11111110,  
0B11111101,
0B11111011,
0B11110111,
0B11101111,
0B11011111,
0B10111111,  
0B01111111,

이렇게 '0'인 위치만 개방 해야겠죠

호실별 개방할려면,

0B00000001,  
0B00000010,  
0B00000100,  
0B00001000,  
0B00010000,  
0B00100000,  
0B01000000,  
0B10000000

이렇게 '1'인 위치로 호실만 전류를 보내겠다는 표현이겠죠. 각층의 8개의 호실에 불이 순서대로 깜박일려면 2중 for문을 사용해서 표현하면 됩니다.

for(int i=0;i<8;i++){
 for(int j=0;j<8;j++){
     층[i] 패턴에 호실[j=0~7]까지 순서대로 호실패턴이 대입을 수행;
 }
}

즉, 층[0] 패턴일때 호실[0]~[7]패턴이 대입된다면
'0B11111110 ' + '0B00000001 = 1층1호실 불이 들어옴
'0B11111110 ' + '0B00000010 = 1층2호실 불이 들어옴
'0B11111110 ' + '0B00000100 = 1층3호실 불이 들어옴
.......

대충 이런식으로 층[0]~[7]까지의 패턴이 있는데 각 층에 대한 호실[0]~[7]까지의 패턴이 순차적으로 대입되는 로직을 머리속에서 그리셔야 합니다. 어떤식인지 이해하셨는지 모르겠네요.

전체적으로 코딩을 하면,

byte layer[]={ //층
0B11111110,  
0B11111101,
0B11111011,
0B11110111,
0B11101111,
0B11011111,
0B10111111,  
0B01111111,
};
byte room[]={ //호실
0B00000001,  
0B00000010,  
0B00000100,  
0B00001000,  
0B00010000,  
0B00100000,  
0B01000000,  
0B10000000
};
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<8;i++){  //순차적으로 릴레이 깜박이기    
    for(int j=0;j<8;j++){
      digitalWrite(latchPin, LOW);
      shiftOut(dataPin, clockPin, MSBFIRST, layer[i]);
      shiftOut(dataPin, clockPin, MSBFIRST, room[j]);
      digitalWrite(latchPin, HIGH);       
      delay(100);
    }
  }  
}

4. 결과


간단히 실험 결과 영상만 올렸습니다. 회로도 제작 과정은 생략합니다. 이전 74HC595 칩을 제어할때 다뤘던 내용이니 결과로 어떻게 출력되니지만 확인하시고 회로도 만드는 과정은 74HC595편을 참고하세요


마무리


오늘은 어제 실험한 내용에 오래전에 배운 74HC595칩을 결합을 해보았습니다.

내일은 LED의 꽃인 네오픽셀을 다루는 것을 해보겠습니다. LED에 관해서는 얼추 기초적인 부분은 다 끝난 것 같네요. 나머지 부분은 대부분 여러가지 부품과 결합해서 표현하는 응용편이니깐요. 암튼 네오픽셀이 가장 화려하고 재미 있을 듯 싶네요.


댓글()

[아두이노] 74HC595+CD4511+7SegmentLED 제어

IOT/아두이노|2019. 2. 18. 08:19

[아두이노] 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를 제어할 목적으로 많이 쓰는 것 같더군요. 이 칩만 잘 활용해도 아두이노우노의 적은 핀을 가지고도 많은 부품들을 제어할 수 있어 확장성이 엄청 좋습니다. 한번 힘들더라도 부품의 데이터시트나 여러 블로그의 예제들을 보고 연구해 보셨으면 합니다.
이것만 알아도 표현할 수 있는 것들이 무궁무진 하니깐 상상의 나래를 펼쳐 보세요.


댓글()

[아두이노] 74HC595+ 7 Segment LED 실제 실험

IOT/아두이노|2019. 2. 15. 09:26

[아두이노] 74HC595+ 7 Segment LED 실제 실험



가상시뮬레이터에서 아두이노우노를 다루면서 실제 현실에서도 동일하게 작동을 하는지 궁금하신 분들이 있을꺼에요. 그래서 귀찮니즘을 안고 실제로 실험을 하였습니다. 예전에 74HC595 칩을 뻥판에 꼽을 개고생 했는데 뻥판이 싼거라 핀이 잘 안들어가서 핀 부분이 약간 오그라졌는데 이번에도 역시나 꼽을 때 오그라지고 뽑을 때 오그라져서 나오더군요. 몇번 실험하고 나면 74HC595 칩이 망가질것 같네요.

1. 회로도 구성



[아두이노] 쉬프트레지스터(74HC595) 제어 편에서 실제로 7 Segment LED도 뻥판에 배치를 해야하기 때문에 약간 배치하는 위치를 수정했네요.


좀 더 깔끔해진 회로도 모습이지요.

지난시간에 가상시뮬레이터로 설계한 모습에서 다시 가상시뮬레이터의 뻥판에 재배치한 모습입니다. 그런데 실제로 같은 위치에 배치하면 이런 모습이 아니라 지져분한 모습입니다. 가상시뮬레이터에서 회로도를 배치한대로 실제로 동일하게 배치했습니다. 참고로 저항은 220옴뿐이 없어서 이걸로 했습니다. 저항은 LED에 필요한 허용치 저항을 연결하면 되니깐 제 경우는 저항 220옴으로 실험했네요.


위 사진은 뻥판 연결된 모습인데 실험 중의 한 컷인데요. 선만 봐도 엄청 지져분하죠. 74HC595 칩을 뻥판에 꼽을 때 개고생 했네요. 핀 위치는 대충 가상시뮬레이터에서 연습 몇번해서 그런지 선 연결은 지져분할 뿐 간단했네요. 가상시뮬레이터에 연습없이 바로 실제로 실험한다면 선 연결할 때 실수하는 경우가 많겠죠.

2. 코딩


코딩은 지난시간에 숫자를 순차적으로 출력하는 로직을 그대로 집어 넣었습니다.

byte data[]={
0B10000001,  
0B11110010,
0B01001001,
0B01100000,
0B00110011,
0B00100100,
0B00000101,
0B11110000,
0B00000001,
0B00100000
};
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);
  }  
}

3. RaspberryPi3 에서 아두이노우노로 프로그램 이식


PC에서 RaspberryPi3를 원격 제어를 통해 아두이노 IDE를 띄워고 위 코딩을 복사한 뒤에 실제 아두이노우노에 프로그램 이식을 수행했습니다.
PC에 아두이노 IDE를 설치했다면 바로 PC에서 아두이노우노에 프로그램을 이식하면 됩니다.


4. 결과


아래 13초짜리 동영상은 실제 프로그램이 이식된 아두이노우노가 74HC595 칩에 숫자 패턴 데이터값을 전송하여 7 Segment LED에 숫자가 가상시뮬레이터에서 나왔던 결과와 동일하게 출력되는지 테스트한 결과입니다.


마무리


실제 아두이노우노로 실험을 해 보았습니다. 가상시뮬레터의 결과와 동일하게 나오는 것을 보실 수 있었을 겁니다. 이처럼 실제로 키트를 사서 실험을 하실 수 있지만 실제로 실험하면 가상으로 한것보다 시간도 많이 걸리고 손으로 일일히 노가다 작업을 많이 해야 합니다. 편하게 마우스로 선을 연결할 수 있는 것을 실제로 뻥판에 억지로 꼽고 하는게 쉽지가 않죠. 그리고 부품이 작어서 아무 지식도 없는 상태에서 보고 따라서 꼽을려고 하면 그것도 만만치 않습니다.

특히, 74HC595 칩의 경우는 작고 핀들의 네임들을 외우지 않는 이상 햇갈릴 수 있습니다. 하지만 가상에서는 마우스을 대면 핀 네임들을 쉽게 확인이 가능합니다. 가상시뮬레이터로 여러번 반복 실험을 하다보면은 실제 실험에서도 어렵지 않게 핀 연결을 할 수 있게 됩니다.

제가 아두이노우노를 실험할 때 실제 아두이노우노 키트가 있지만 가상시뮬레이터에서 하는 이유는 실제 아두이노키트를 사용해서 실험하는 것보다 가상시뮬레이터에서 더 쉽게 실험할 수 있기 때문입니다.

막연히 아두이노우노 키트를 사서 하는것보다 가상시뮬레이터로 충분히 즐긴 후 좀 더 다양한 실험을 하고 싶을때
아두이노 시리즈 중 원하는 싱글보드를 구매하셔서 실험하시면 됩니다.


댓글()

[아두이노] 직렬 연결한 쉬프트레지스터(74HC595) 제어

IOT/아두이노|2019. 2. 14. 09:32

[아두이노] 직렬 연결한 쉬프트레지스터(74HC595) 제어



이번에는 2개의 74HC595칩을 직렬로 연결하여 3개의 핀을 이용해서 2개 7 Segment LED를 제어하는 실험을 하였습니다. 이번에도 제 블로그에 포스팅 했던 내용인데 코딩은 최대한 원리를 설명하기 위한 로직이라서 기존 블러그에 있던 로직을 수정없이 그대로 소개하도록 하겠습니다. 여기다 살을 더 붙여서 60초 카운터 하는 로직을 설계할 수 있지만 그러면 군더더기 붙은 코딩으로 60초 변수를 만들고 if 조건문을 써서 십의자리와 일의자리를 쪼갤지 아니면 따로 카운터 변수로 정해서 조건문으로 표현할지 정하다 보면 본래 설명하고자하는 직렬 연결 설명이 복잡해 보일 수 있어 이번 포스팅은 간단히 어떻게 출력이 되는지만 실험하는 거라서 60초 카운터 출력은 독자의 몫으로 남겨 두겠습니다.

1. 직렬 쉬프트레지스터(75HC595) 연결



이전 시간에 75HC595 칩 하나를 아두이노에 연결하는 회도로를 이해했다는 전재하에서 기본 STCP, SHCP, DP 핀으로 해서 75HC595 칩을 제어를 하게 됩니다. 이 3핀을 제어하는데 직렬로 연결하면 위 그림처럼 연결을 하게 됩니다. STCP(결쇠)와 SHCP(클럭)핀은 공유합니다. DP핀은 오른쪽 75HC595 칩에 입력되고 그 입력된값이 Q7S 핀을 통해서 왼쪽 75HC595 칩의 DS 핀의 입력으로 들어 갑니다.

처음 아두이노에서 입력된 값이 16개의 값이 입력되면 앞에 8개 값이 왼쪽 75HC595 칩에 쌓이고 나머지 8개가 오른쪽 칩에 쌓여서 출력됩니다.

여기서 선색으로 대충 의미를 이해하시면 되겠습니다.

2. 회로도 구성


  • 준비물 : 75HC595칩 2개, 7 Segment LED 2개, 저항 330옴 2개, 아두이노우노, 뻥판
  • 내용 : 두개의 7 Segment LED에 숫자를 출력하게 하자.


74HC595 칩을 하나 사용할때도 복잡했는데 그림으로 2개를 사용하니깐 더 복잡해 보일꺼에요. 이전 시간에 한개로 했을때 선 연결과 동일하고 그걸 참고해서 두개를 동일하게 선 연결을 하시면 됩니다. 그리고 추가된것은 위의 직렬 쉬프트레지스터 연결을 보시면서 선이 왜 이렇게 연결되었는지 이해하시면 됩니다.

복잡해 보일뿐 단순합니다. 핀에 마우스를 대면 핀 이름이 나오고 해당된 부품과 연결하시면 됩니다.

3. 코딩


  • 사용함수 : pinMode(출력핀, 모드), digitalWrite(결쇠핀, 열림/잠금), shiftOut(데이터입력핀, 클럭핀, 순서, 데이터전송값)
  • 내용 : 아두이노에서 제공되는 shiftOut( )함수로 74HC595칩을 제어를 통해 2개 7 Segment LED에 숫자를 0과1, 1과2 ... 순차적으로 출력해보자.

  • 74HC595칩 제어 :
  • latchPin, clockPin, dataPin을 pinMode(출력핀, 모드)로 선언
  • digitalWrite(결쇠핀, 열림/잠금)으로 74HC595 칩에 입력할때 열림/잠금을 제어
  • shiftOut(데이터입력핀, 클럭핀, MSBFIRST, 전송값)으로 이걸 통해서 역순으로 데이터가 배치

설계

오른쪽 0부터 왼쪽 1부터 순차적으로 숫자를 출력

이전시간에

열림
쉬프트레지스트에 데이터 전송
닫침

코딩으로

digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, data[i]);
digitalWrite(latchPin, HIGH);       

숫자 1개는 8개 값이 필요합니다. 그러면 쉽게 생각해보세요. 숫자가 2개면 16개의 값이 필요합니다. 그러면 쉬프트레지스트로 shiftOut()을 통해 두번 데이터를 전송하면 되겠다는것이 떠올라야 겠죠.
0과 1, 1과2 이렇게 순차적으로 출력하도록 설계할꺼니깐 아래과 같이 표현하면 되겠죠.

    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, data[i]);
    shiftOut(dataPin, clockPin, MSBFIRST, data[i+1]);
    digitalWrite(latchPin, HIGH);       

코딩을 하면

byte data[]={
0B10000001,  
0B11110010,
0B01001001,
0B01100000,
0B00110011,
0B00100100,
0B00000101,
0B11110000,
0B00000001,
0B00100000
};
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<9;i++){    
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, data[i]);
    shiftOut(dataPin, clockPin, MSBFIRST, data[i+1]);
    digitalWrite(latchPin, HIGH);       
    delay(1000);
  }  
}

4. 결과



마무리


3핀을 이용하여 2개의 74HC595 칩을 제어하여 2개의 7 Segment LED에 출력하였습니다.
회로도 보면 지져분하고 선연결이 복잡해 보일 수 있어요. 지난 시간에 배운 쉬프트레지스트 회로도를 디자인을 어느정도 이해하시면 2개든 3개든 보기에만 복잡해 보일뿐 참 쉬운 회로도입니다. 코딩도 지난시간에 했던 것에서 딱 한줄 늘어났을뿐 변화가 없습니다.

이 세줄만 이해하시면 몇개의 74HC595 칩을 사용해도 쉽게 해결됩니다.

열림
쉬프트레지스트에 데이터 전송
닫힘

오늘은 직렬 두개였으니깐

열림
쉬프트레지스트에 데이터 전송1
쉬프트레지스트에 데이터 전송2
닫힘

참쉽죠.

60초 카운터를 만들려 했는데 그러면 약간 직렬 제어 코딩에 혼동을 줄 수 있기 때문에 간단하게 두개를 어떻게 제어하는지만 배우는 것이 목적임으로 생략이 되었네요.

한번 여러분들이 60초 카운터 로직을 설계 해 보세요.
그리고 74HC595 칩의 원리로 어떤걸 표현하면 좋을지 상상의 나래를 펼쳐보세요.


댓글()

[아두이노] 쉬프트레지스터(74HC595) 제어

IOT/아두이노|2019. 2. 13. 14:32

[아두이노] 쉬프트레지스터(74HC595)



제 블로그에 포스팅 했던 내용인데 좀 어려운 내용이라서 이걸 소개해야하나 남감했지만 7 Segment LED의 연결되기 때문에 최대한 간단하게만 설명하겠습니다.

이전 시간에 7 Segment LED 제어를 배웠습니다. 이걸 사용하기 위해서 총 8핀을 아두이노에 연결해야 합니다. 문제는 2개 이상의 7 Segment LED를 제어할 경우 아두이노핀이 부족하게 됩니다. 그래서 아두이노 사용되는 핀을 줄일 수 있는 방법을 찾다보니깐 여러 칩중에 쉬프트레지스터라는 칩을 알게 되었으며 온라인 가상시뮬레이터에서도 모델명 75HC595칩(쉬프트레지스터)이 제공하기 때문에 이 칩을 이용해서 제어해보도록 하겠습니다.

1. 쉬프트레지스터(75HC595)


칩만보면은 햇갈립니다. 실제로 칩을 구매하실때 데이터시트를 꼭 인터넷에서 찾으셔서 살펴봐야 합니다. 물론 전 데이터시트를 보기가 참 힘들더군요. 간단히 칩구성과 핀 연결로 대충 이 칩의 작동원리만 이해하고 사용해 보았습니다. 참고로 칩을 사용하실때 칩에 사용되는 전압을 꼭 확인하시고 써야 합니다. 그렇지 않으면 칩이 망가질 수 있어서 조심해서 다루셔야 합니다.


  • 그림에서 보듯이 Vcc, Gnd은 그대로 해당 핀에 연결해주면 됩니다.
  • 데이터입력핀 DS핀 : 아두이노에서 데이터를 이칩에 보내게 됩니다.(총8개 출력값)
  • STCP 핀 : HIGH, LOW값으로 결쇠 역할을 하는 핀입니다. 칩에 입력할때 LOW 칩을 개방하고 입력을 끝내면 HIGH 칩닫음
  • SHCP 핀 : 클럭핀
  • MR 핀 : 5V 연결하더군요. 사용목적은 데이터시트 참고(저도 기억이 가물)
  • Q7S 핀 : 직렬 연결할때 사용합니다.이 칩 역시 8개값을 출력하기 때문에 더 많은 값을 출력하기 위해서 칩을 직렬 연결용으로 사용
  • Q0~Q7 : 각 핀으로 입력된 8개의 값을 출력합니다.

결론적으로 3개의 핀을 사용하여 결쇠핀, 클럭핀, 데이터핀으로 해서 이 칩을 제어할 수 있습니다. 가령 2개 이상의 75HC595를 사용해도 3핀만으로 직렬연결을 통해 제어가 가능합니다. 이건 다음에 소개하고 현재 이 칩을 아두이노에서 제어하는게 가장 중요합니다.

2. 회로도 구성


  • 준비물 : 75HC595 칩 1개, 7 Segment LED 1개, 저항 330옴 1개, 아두이노우노, 뻥판
  • 내용 : 숫자를 순차적으로 출력해보자.


칩이 정면으로 되어 있기 때문에 칩을 회전시켜야합니다. 그림을 잘 보시면 뒤집어져있는걸 보실꺼에요. 마우스로 해당칩에 끝점을 대면 핀이름이 나타납니다. 5V와 Gnd은 그림에서 보는것처럼 동일하게 배치하시면 됩니다.

참고로 Q0이 기름에서 보는것처럼 하단에 있어서 지난시간에 배운데로 A~G핀과 DP핀을 순차적으로 Q0~Q7까지 연결하면 선이 안이뻐서 Q0을 그냥 DP핀(점 LED)으로 했네요. 나머지 Q1~Q7을 A~G핀으로 연결했습니다. 그래서 배열변수값들이 지난시간에 제대로 이해 못하셨다면 약간 혼동되실꺼에요.

  • 7 Segment LED 제어 :
    74HC595칩의 Q0~Q7핀을 통해서 A~G핀과 DP핀 연결

3. 코딩


  • 사용함수 : pinMode(출력핀, 모드), digitalWrite(결쇠핀, 열림/잠금), shiftOut(데이터입력핀, 클럭핀, 순서, 데이터전송값)
  • 내용 : 아두이노에서 제공되는 shiftOut( )함수로 74HC595칩을 제어를 통해 7 Segment LED에 숫자를 순차적으로 출력해보자.

  • 74HC595칩 제어 :
    • latchPin, clockPin, dataPin을 pinMode( )로 선언
    • digitalWrite(결쇠핀, 열림/잠금)으로 74HC595칩에 입력할때 열림/잠금을 제어
    • shiftOut(데이터입력핀, 클럭핀, MSBFIRST, 전송값)으로 이걸 통해서 역순으로 데이터가 배치

설계

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



7 Segment LED 연결된 것이 DP핀, A~G핀이 Q0~Q7순으로 순차적으로 연결됩니다. 홀짝에서 홀수일때 DP핀에 불이 들어오게 싶다면 숫자 0이면 G핀과 DP핀만 꺼지면 되니 10000001 이 됩니다. 그런데 1일때 0100111이겠지라고 생각하시면 안됩니다. MSBFIRST은 현재 연결핀 순서라면 역순이 됩니다. 11110010이 되어야 합니다.

이걸배열변수로 하면

byte data[]={
0B10000001,  
0B11110010,
0B01001001,
0B01100000,
0B00110011,
0B00100100,
0B00000101,
0B11110000,
0B00000001,
0B00100000
};

아마 지난시간을 생각하면 2차 배열변수로 생각하셨던 분도 있을꺼에요. 이건 하나의 값으로 표현이 가능합니다.
이걸 16진수로 하면 0x81 이 됩니다. 데이터숫자값으로 표현이 가능합니다. 이 같은 2진수 비트로 해서 다시 표현하면 위 배열처럼 나타나게 됩니다. 위 표현은 기계가 이해하기 쉬운 숫자형태입니다.

진법을 알아야하는 간단히 설명하자면
10000001 은 패턴이고 2진수입니다.
1000 0001로 4개씩 쪼개서 16진수로 나타냅니다.
8과 1로 표현됩니다.

0001=>1
0010=>2
0011=>3
.....
원래 8421 표를 숙지해야 하는데 현재 이것이 중요한것이 아니기 때문에 대충 네개로 묶으면 16진수 3개씩 묶으면 8진수라는 정도로 의미만 이해하세요.
16진수로 배열변수 값을 한다면 0x81로 표현해서 저장해도 동일한 결과가 나옵니다. 그냥 이해하기 쉽게 위 배열변수의 형식으로 이해하셔서 코딩하세요.
10진수가 아닌 기계가 이해하기 쉬운 숫자형태로 표현한다고 생각하세요.

(2) 74HC595칩에 원하는 숫자패턴을 전송한다.

  • 출력핀모드 선언 :
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);

(3) 74HC595칩에 숫자패턴을 입력한다.

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

(4) 7 Segment LED에 출력한다.

74HC595칩(Q0~Q7) => 7 Segment LED(DP,A~G) 출력

코딩을 하면

byte data[]={
0B10000001,  
0B11110010,
0B01001001,
0B01100000,
0B00110011,
0B00100100,
0B00000101,
0B11110000,
0B00000001,
0B00100000
};
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. 결과



마무리


3핀을 이용하여 74HC595 칩을 제어하여 7 Segment LED에 출력하였습니다. 쉬프트 로직은 사실 좀 복잡합니다. 코딩 독해능력이 있어야 하는 부분임으로 그냥 함수명만 이해해 주세요. 위의 참고출처 가시면 튜토리얼로 쉬프트 함수의 로직을 살펴볼 수 있습니다. 독해능력이 되시면 어떤식으로 74HC595 칩에 데이터를 보내는지 확인하실 수 있을 꺼에요.

코딩에 자신있는분들은 본인이 직접 로직을 짜는분들도 있지만 초보분들은 그냥 있는 함수만 잘 사용하여 원하는 동작을 수행하는게 중요합니다.

digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, data[i]);
digitalWrite(latchPin, HIGH);       

이것이 코딩의 전부입니다. 이걸 통해서 74HC595 칩을 제어할 수 있어서 쉽게 원하는 글자나 숫자를 7 Segment LED에 출력을 할 수 있는 것이죠.

이 세줄만 이해하시면 됩니다.

열림
쉬프트레지스트에 데이터 전송
닫힘

이 문장만 숙지하시고 한번 이 세줄을 가지고 뭘 만들지 상상의 나래를 펼쳐보세요.


댓글()