Hardware | LED bar graph 를 컨트롤 해보자 - 2

|

1. 12 segments


LED bargraph 를 컨트롤시에 shift register 를 사용하면, arduino의 3가지 선으로 LED 들을 조정할 수 있습니다.

다만, shift register 의 사용 가능한 pin 갯수가 8개라서 shift register 로 컨트롤 할 수 있는 LED 갯수가 8개로 한정됩니다.


지금 가지고 있는 LED bargraph 가 12 segments, 즉 12개짜리인 관계로 4개를 사용하지 못하고 있었습니다.


* Hardware | LED bar graph 를 컨트롤 해보자 - 1

     - http://chocoball.tistory.com/entry/Hardware-LED-bar-graph-controlling-1



* Hardware | 74HC595 shift register 를 사용해 보자

http://chocoball.tistory.com/entry/Hardware-74HC595-shift-register


그럼 shift register 2개를 사용하여 12 segments 전부를 사용해 보고자 합니다.





2. Pinout


12개의 LED 를 조작하기 위한 선과 shift register 끼리 연결하는 Pin, GND, Power 선 등 연결은 간단하지만,

jumper 갯수 자체는 1개의 shift register 를 사용했을 때 보다 2배 이상 많아집니다.


  LED       | Shift Register | Shift Register | Arduino
  Bargraph  | SN74HC595N (1) | SN74HC595N (2) |  Nano
--------------------------------------------------------
  anode 7   | Q1 (pin 1)     |                |
  anode 8   | Q2 (pin 2)     |                |
  anode 9   | Q3 (pin 3)     |                |
  anode 10  | Q4 (pin 4)     |                |
  anode 11  | Q5 (pin 5)     |                |
            | Q6 (pin 6)     |                |
            | Q7 (pin 7)     |                |
            | GND (pin 8)    |                |  GND
            | Vcc (pin 16)   |                |  3.3V
  anode 6   | Q0 (pin 15)    |                |
            | DS (pin 14)    |                |  D11     --> dataPin
            | OE (pin 13)    |                |  GND
            | ST_CP (pin 12) | ST_CP (pin 12) |  D8      --> latchPin
            | SH_CP (pin 11) | SH_CP (pin 11) |  D12     --> clockPin
            | MR (pin 10)    |                |  3.3V
            | Q7' (pin 9)    | DS (pin 14)    |
  anode 1   |                | Q1 (pin 1)     |
  anode 2   |                | Q2 (pin 2)     |
  anode 3   |                | Q3 (pin 3)     |
  anode 4   |                | Q4 (pin 4)     |
  anode 5   |                | Q5 (pin 5)     |
            |                | Q6 (pin 6)     |
            |                | Q7 (pin 7)     |
            |                | GND (pin 8)    |  GND
            |                | Vcc (pin 16)   |  3.3V
  anode 0   |                | Q0 (pin 15)    |
            |                | DS (pin 14)    |
            |                | OE (pin 13)    |  GND
            |                | MR (pin 10)    |  3.3V
            |                | Q7' (pin 9)    |
--------------------------------------------------------


포인트는 serial data output 을 다음 shift register 의 serial data input 으로 해주고,

latch 와 clock 은 동기를 위해 동일한 pin ( 12 / 11 ) 에 연결하는 것입니다.


그 외 LED 와 연결하는 parallel data output 은 LED 에 각각 연결하면 됩니다.





3. Layout


선을 연결해 보면 아래와 같이 됩니다.


선이 복잡하므로 10개짜리 LED bargraph 를 사용해서 그려봤습니다.
2배로 선이 많아지죠?

그나마 resistor network 을 이용해서 실제 배선이 많이 간결해 졌습니다.
Resistor Network 에 대해서는 아래 link 글을 참조해 주세요.

* Hardware | Resistor Network 을 사용해보자


제대로 연결하면 잘 움직입니다.

아래 소스를 토대로 참조한 사이트의 핀 배열을 조금 바꾸었습니다.

(원래 사이트에서는 8 + 8 = 16 개 기준으로 만들어 졌슴)





4. Source code


아래는 참조한 사이트 입니다.


http://www.instructables.com/id/Arduino-16-LEDs-using-two-74HC595-shift-registers-/


실제 코드는 아래 github 링크에 있습니다.


- https://github.com/janisrove/Arduino-74HC595-shift-registers/blob/master/ArduinoLEDsWithShiftRegisters/ArduinoLEDsWithShiftRegisters.ino


int latchPin = 8;
int clockPin = 12;
int dataPin = 11;

int numOfRegisters = 2;
byte* registerState;

long effectId = 0;
long prevEffect = 0;
long effectRepeat = 0;
long effectSpeed = 30;

void setup() {
	//Initialize array
	registerState = new byte[numOfRegisters];
	for (size_t i = 0; i < numOfRegisters; i++) {
		registerState[i] = 0;
	}
	
	//set pins to output so you can control the shift register
	pinMode(latchPin, OUTPUT);
	pinMode(clockPin, OUTPUT);
	pinMode(dataPin, OUTPUT);
}

void loop() {
	do {
		effectId = random(6);
	} while (effectId == prevEffect);
	prevEffect = effectId;
	
	switch (effectId) {
		case 0:
			effectRepeat = random(1, 2);
			break;
		case 1:
			effectRepeat = random(1, 2);
			break;
		case 3:
			effectRepeat = random(1, 5);
			break;
		case 4:
			effectRepeat = random(1, 2);
			break;
		case 5:
			effectRepeat = random(1, 2);
			break;
	}
	
	for (int i = 0; i < effectRepeat; i++) {
		effectSpeed = random(10, 90);
		
		switch (effectId) {
			case 0:
				effectA(effectSpeed);
				break;
			case 1:
				effectB(effectSpeed);
				break;
			case 3:
				effectC(effectSpeed);
				break;
			case 4:
				effectD(effectSpeed);
				break;
			case 6:
				effectE(effectSpeed);
				break;
		}
	}
}

void effectA(int speed) {
	for (int i = 0; i < 12; i++) {
		for (int k = i; k < 12; k++) {
			regWrite(k, HIGH);
			delay(speed);
			regWrite(k, LOW);
		}
		
		regWrite(i, HIGH);
	}
}

void effectB(int speed) {
	for (int i = 11; i >= 0; i--) {
		for (int k = 0; k < i; k++) {
			regWrite(k, HIGH);
			delay(speed);
			regWrite(k, LOW);
		}
		
		regWrite(i, HIGH);
	}
}

void effectC(int speed) {
	int prevI = 0;
	for (int i = 0; i < 12; i++) {
		regWrite(prevI, LOW);
		regWrite(i, HIGH);
		prevI = i;
		
		delay(speed);
	}
	
	for (int i = 11; i >= 0; i--) {
		regWrite(prevI, LOW);
		regWrite(i, HIGH);
		prevI = i;
		
		delay(speed);
	}
}

void effectD(int speed) {
	for (int i = 0; i < 6; i++) {
		for (int k = i; k < 6; k++) {
			regWrite(k, HIGH);
			regWrite(11 - k, HIGH);
			delay(speed);
			regWrite(k, LOW);
			regWrite(11 - k, LOW);
		}
		
		regWrite(i, HIGH);
		regWrite(11 - i, HIGH);
	}
}

void effectE(int speed) {
	for (int i = 5; i >= 0; i--) {
		for (int k = 0; k <= i; k++) {
			regWrite(k, HIGH);
			regWrite(11 - k, HIGH);
			delay(speed);
			regWrite(k, LOW);
			regWrite(11 - k, LOW);
		}
		
		regWrite(i, HIGH);
		regWrite(11 - i, HIGH);
	}
}

void regWrite(int pin, bool state) {
	//Determines register
	int reg = pin / 6;
	//Determines pin for actual register
	int actualPin = pin - (6 * reg);
	
	//Begin session
	digitalWrite(latchPin, LOW);
	
	for (int i = 0; i < numOfRegisters; i++) {
		//Get actual states for register
		byte* states = ®isterState[i];
		
		//Update state
		if (i == reg) {
			bitWrite(*states, actualPin, state);
		}
	
	//Write
	shiftOut(dataPin, clockPin, MSBFIRST, *states);
	}
	
	//End session
	digitalWrite(latchPin, HIGH);
}


소스를 잘 보면 16, 15, 8, 7 등의 숫자가 나옵니다.

이를 토대로 12, 11, 6, 5 등으로 12개에 맞춰서 숫자만 바꾸어 주면 됩니다.


따로 변수를 빼놓고, 자동으로 계산해서 사용될 수 있도록 하면, LED 갯수가 바뀌더라도 편할것 같습니다.

참조 사이트 말대로 "Unlimited Pins" 구조가 되겠네요.





5. 구동


아래는 멋지게 구동되는 모습입니다.



Fully! 12개의 LED 들을 모두 사용하는 모습입니다.



거참 source code 잘 짰네요.

수학적인 컨트롤 이므로, 다양한 모양으로 컨트롤이 가능할 듯 합니다.





FIN


이제 몇개의 LED 가 되었든, shift register 를 daisy chain 으로 엮으면 못할게 없겠습니다.


And