국비과정을 진행하며 스마트시티라는 주제로 프로젝트를 진행하게 되었다.
프로젝트의 일환으로 시프트 레지스터에 연결된 LED 4개를 GUI로 제어할 수 있도록 구현해야 했으며, 동시에 여러 개의 LED가 켜져 있을 수 있어야 했다.
초기 구현에서는 GUI를 통해 LED 하나를 켜고 다른 LED를 켜려고 하면, 이전에 켜져 있던 LED가 꺼지고 새 LED만 켜지는 상황이 발생했다.
이는 각 LED의 상태가 개별적으로 관리되지 않아서 생긴 문제였다.
우선 초기 LED 상태는 OFF로 설정한다.
byte currentLedStatus = B11110000;
각 LED를 ON/OFF하기 위한 상태를 미리 정의한다.
byte LED_ON[] = {
B11111000,
B11110100,
B11110010,
B11110001
};
byte LED_OFF[] = {
B11110111,
B11111011,
B11111101,
B11111110
};
현재 LED ON/OFF 상태변수를 선언한다.
bool light[] = {
false,
false,
false,
false
};
setup
함수에서는 LED초기 상태를 업데이트해주고,
void setup()
{
Serial.begin(9600);
updateShiftRegister(currentLedStatus);
}
loop
함수에서는 GUI의 입력에 따라 각 LED의 상태를 업데이트하는 로직을 구현한다.
void loop()
{
if (Serial.available() > 0) {
char receivedChar = Serial.read(); // Read from GUI data
if (receivedChar == '1') {
if (light[0] == false)
{
updateShiftRegister(currentLedStatus | LED_ON[0]); // LED1 On
currentLedStatus = currentLedStatus | LED_ON[0];
light[0] = true;
}
else
{
updateShiftRegister(currentLedStatus & LED_OFF[0]); // LED1 Off
currentLedStatus = currentLedStatus & LED_OFF[0];
light[0] = false;
}
}
else if (receivedChar == '2') {
if (light[1] == false)
{
updateShiftRegister(currentLedStatus | LED_ON[1]); // LED2 On
currentLedStatus = currentLedStatus | LED_ON[1];
light[1] = true;
}
else
{
updateShiftRegister(currentLedStatus & LED_OFF[1]); // LED2 Off
currentLedStatus = currentLedStatus & LED_OFF[1];
light[1] = false;
}
}
else if (receivedChar == '3') {
if (light[2] == false)
{
updateShiftRegister(currentLedStatus | LED_ON[2]); // LED3 On
currentLedStatus = currentLedStatus | LED_ON[2];
light[2] = true;
}
else
{
updateShiftRegister(currentLedStatus & LED_OFF[2]); // LED3 Off
currentLedStatus = currentLedStatus & LED_OFF[2];
light[2] = false;
}
}
else if (receivedChar == '4') {
if (light[3] == false)
{
updateShiftRegister(currentLedStatus | LED_ON[3]); // LED4 On
currentLedStatus = currentLedStatus | LED_ON[3];
light[3] = true;
}
else
{
updateShiftRegister(currentLedStatus & LED_OFF[3]); // LED4 Off
currentLedStatus = currentLedStatus & LED_OFF[3];
light[3] = false;
}
}
}
}
LED를 ON하려면 currentLedStatus
와 LED_ON[index]
을 OR 연산을 해준다.
이 때, OR 연산은 한쪽만 1이어도 결괏값이 1이 되는 특징을 활용해 LED가 켜지도록 한다.
currentLedStatus = b11110001 // 4번 LED ON
LED_ON[0] = b11111000
currnetLEDStatus = currnetLEDStatus | LED_ON[0]
---
currentLedStatus = b11111001 // OR 연산 후 1, 4번 LED ON
마찬가지로, LED를 OFF하려면 currentLedStatus
와 LED_OFF[index]
를 AND 연산한다.
AND 연산은 한쪽이 0이면 결괏값이 0이 되는 특징을 활용해 LED가 꺼지도록 한다.
currentLedStatus = b11111001 // 1, 4번 LED ON
LED_OFF[0] = b11110111
currnetLEDStatus = currnetLEDStatus & LED_OFF[0]
---
currentLedStatus = b11110001 // AND 연산 후 4번 LED ON
필자는 이러한 방법으로 LED가 여러 개가 켜져 있거나 꺼져있게끔 만들었다.