차완기 - @10/20/2024, 5:04:00 PM
지난 과정에서 아두이노를 통해 블루투스 통신을 해봤습니다.
당시에는 아두이노의 온보드(내장) LED를 활용했습니다. 그런데, 이렇게 작은 LED는 방을 밝히기는 커녕 눈에 보이지도 않겠죠. 뭔가 눈에 보이는게 있어야 재미있지 않을까 싶어, 조금 이르지만 나름 쓸모가 있는 조명을 만들어보기로 했습니다.
준비물
결선도
전체 결선도입니다.
어댑터에서 조명으로 향하는 케이블을 잘라, 중간에 모스펫 모듈을 연결합니다. 이때 어댑터 전원을 아두이노의 Vin에 연결하면 어댑터의 전원으로 아두이노까지 켤 수 있습니다.
한편 아두이노에는 모스펫 모듈과 블루투스 모듈이 연결됩니다. 모스펫 모듈은 PWM 출력을 지원하는 5번 핀에 연결했습니다.
어댑터, 모스펫 모듈 연결
자, 그럼 눈을 감고 어댑터를 잘라봅시다. 조명 근처에 아두이노를 두기는 싫으니 가급적이면 어댑터의 머리 근처를 자르는게 좋을겁니다.
잘린 두 부위 중, 어댑터 머리 부분에서 나온 케이블은 모스펫 모듈의 IN에, 배럴잭을 향하는 부위는 OUT에 연결합니다.
다음으로 아두이노 결선을 진행합니다.
모스펫 모듈의 신호 핀(SIG)은 디지털 핀 5번에, VCC, GND는 각각 5V, GND에 연결합니다. 위 사진에서는 모스펫 모듈이 2번 핀에 연결되어 있으니 주의해주세요.
조명 테스트
연결이 잘 되었으면, 조명을 켜볼까요?
여기서 사용한 IRF520 모스펫 모듈은 HIGH일 때 입력과 출력이 연결되고, LOW일 때 입력과 연결이 분리됩니다. 이는 HIGH에서는 어댑터가 조명과 연결되고, LOW에서는 어댑터가 조명이 연결되지 않는 것과 같습니다. 즉, HIGH에서 조명이 켜지겠죠. Blink 예제를 통해 13번 LED가 켜지는 것과 동일합니다.
조명을 켜기 위해 Blink 예제에서 핀 번호인 13번을 5번으로 수정해보겠습니다.
void setup() {
pinMode(5, OUTPUT);
}
void loop() {
digitalWrite(5, HIGH);
delay(1000);
digitalWrite(5, LOW);
delay(1000);
}
C++
복사
잘 작동하죠?
외부 전원 연결
한편, 아두이노 우노는 대략 3가지 방법으로 전원을 공급받을 수 있습니다.
•
USB 포트로 5V 전원 공급
•
배럴잭 포트로 9~20V 전원 공급
•
Vin 핀으로 9~20V 전원 공급
조명 어댑터를 통해 12V 전원이 공급되고 있고, 이 12V 전원을 아두이노에 연결하면 USB를 연결하지 않더라도 전원을 공급할 수 있습니다. 여기서는 가장 마지막 방법인 “Vin 핀으로 9~20V 전원 공급”을 활용해 12V 어댑터를 연결하면 아두이노 역시 전원이 켜지도록 했습니다.
아두이노는 조명에 비하면 아주 적은 전기를 사용하기 때문에 이걸 조금 훔쳐쓰더라도 조명은 모를겁니다
모스펫 모듈에서 어댑터쪽과 연결된 VIN, GND를 각각 아두이노의 Vin, GND에 연결합니다.
밝기 조절 (PWM)
앞에서 모스펫 모듈을 설명하며 밝기 조절이 가능하기 때문에 모스펫을 선택했다고 했는데요, 이참에 밝기를 한번 조절해보죠.
아두이노는 0과 1, 전압으로는 0V와 5V밖에 모르기 때문에 밝기를 조절할 수 없습니다. 켜지면 켜진거고 꺼지면 꺼진 것. 이렇게 2가지 상태만 가지고 있습니다. 그런데, 사람의 눈은 잔상이라는게 있기 때문에 불빛을 아주 빠르게 켜고 끄면 마치 밝기가 조절되는 것처럼 느낄 수 있습니다.
꺼진 시간이 켜진 시간보다 길다면 상대적으로 어둡게, 반대로 켜진 시간이 꺼진 시간보다 길다면 상대적으로 밝게 느껴집니다. 이런 트릭을 바로 “PWM 방식 밝기조절”이라 이야기합니다. 아두이노에서 PWM 신호를 출력해, 그 신호를 이용해 조명을 켜고 끄는 것이죠.
그런데 이런 밝기 조절 방식은 조명을 아주 빠르게 켜고 꺼야하기 때문에 아두이노의 아무 디지털 핀을 사용할 수는 없습니다.
위 사진에서 표시한 물결 표시(~)가 있는 핀만이 PWM 신호를 출력할 수 있습니다. 앞서 결선도에서 조명을 5번 핀에 연결한 이유가 바로 5번 핀이 PWM을 지원하기 때문입니다.
모스펫 모듈을 PWM을 지원하는 핀에 연결했다면, 다음은 소스코드에서 밝기 조절이 가능하도록 만들어줘야 합니다. PWM 방식이 비록 눈속임이기는 하지만, 아두이노에서는 아날로그로 취급하나 봅니다. 앞에서 조명을 켜고 껐던 digitalWrite() 함수 대신 analogWrite() 함수를 사용합니다.
analogWrite() 함수는 아두이노의 CPU가 직접 디지털 핀을 제어하는 것이 아닌, “타이머”라고 부르는 특수한 장치가 디지털 핀을 제어합니다. 이름부터 뭔가 시간을 잘 맞출것 같죠? 타이머에서 핀을 아주 빠르게 켜고 끄고를 반복해야 사람을 속일 수 있으니 CPU따위를 거칠 시간이 없습니다. 그렇기 때문에 CPU에게 “나는 이 핀을 출력으로 사용할거야” 라고 이야기하는 pinMode() 함수는 더 이상 필요하지 않습니다.
analogWrite() 함수는 핀 번호, 밝기를 각각 입력받고, 여기서 밝기는 0~255 범위를 입력할 수 있습니다. 255에서 가장 밝고, 126 정도에서 중간 밝기를, 0에서 꺼집니다.
void setup() {
}
void loop() {
analogWrite(5, 255); // 최대 밝기로 조명을 켬
delay(1000);
analogWrite(5, 126); // 중간 밝기로 조명을 켬
delay(1000);
}
C++
복사
위 사진에서는 모스펫 모듈을 3번 핀에 연결했으니 주의해주세요.
void setup() {
}
void loop() {
for (int i = 0; i <= 255; i++) {
analogWrite(5, i);
delay(10);
}
for (int i = 255; i >= 0; i--) {
analogWrite(5, i);
delay(10);
}
}
C++
복사
이렇게 for문을 활용하면 숨쉬기 효과라 이야기하는것도 연출할 수 있습니다.
블루투스 연결
이제 블루투스를 사용해봅시다. 앞의 결선도를 참고해 블루투스 모듈을 연결합니다.
#include <SoftwareSerial.h>
SoftwareSerial BTSerial(2, 3); // HC-06을 위한 Serial
void setup() {
Serial.begin(9600); // 시리얼 통신 초기화 (시작)
BTSerial.begin(9600);
pinMode(13, OUTPUT);
}
void loop() {
// BTSerial 통신 버퍼에 새문자 존재 여부 확인
bool is_serial_available = BTSerial.available();
if (is_serial_available) {
char c = BTSerial.read(); // 버퍼에서 수신한 문자 하나를 꺼내 변수 c에 저장
if (c == '0') { // 만약 문자 0이 입력된 경우
digitalWrite(13, LOW); // LED를 끔
} else if (c == '1') { // 만약 문자 1이 입력된 경우
digitalWrite(13, HIGH); // LED를 켬
}
}
}
C++
복사
슬라이더 사용
어플리케이션에서 블루투스 모듈과 연결할 때 “Switch” 대신 “Dimmer”을 선택한 후 오른쪽 상단의 … 버튼을 클릭해 9로 설정합니다.
소스코드는 아래와 같습니다.
#include <SoftwareSerial.h>
SoftwareSerial BTSerial(2, 3); // HC-06을 위한 Serial
void setup() {
Serial.begin(9600); // 시리얼 통신 초기화 (시작)
BTSerial.begin(9600); // 블루투스 모듈과의 통신 초기화 (시작)
}
void loop() {
// BTSerial 통신 버퍼에 새문자 존재 여부 확인
bool is_serial_available = BTSerial.available();
if (is_serial_available) {
int c = BTSerial.read(); // 버퍼에서 수신한 문자 하나를 꺼내 변수 c에 저장
int brightness = map(c - 48, 0, 9, 0, 255); // 문자('0'~'9')를 정수로 변환('0'-48)하며,
// 동시에 0~9 범위를 0~255 범위로 변환
analogWrite(5, brightness); // 밝기 반영
}
}
C++
복사
기타: 밝기 부드럽게 전환
0~9까지 10단계로 조절이 되기 때문에, 밝기 단계가 변할 때 마다 지진이 난 것처럼 조명이 덜컹거릴겁니다. 이걸 해결하기 위해 조명의 밝기가 천천히 조절되도록 코드를 수정했습니다.
#include <SoftwareSerial.h>
SoftwareSerial BTSerial(2, 3); // HC-06을 위한 Serial
void setup() {
Serial.begin(9600); // 시리얼 통신 초기화 (시작)
BTSerial.begin(9600);
pinMode(13, OUTPUT);
}
void go_to_target(int target) {
static int current = 0;
if (target > current) {
current++;
} else if (target < current) {
current--;
} else {
return;
}
analogWrite(5, current);
delay(5);
}
void loop() {
// BTSerial 통신 버퍼에 새문자 존재 여부 확인
bool is_serial_available = BTSerial.available();
static int target = 0;
if (is_serial_available) {
int c = BTSerial.read(); // 버퍼에서 수신한 문자 하나를 꺼내 변수 c에 저장
target = map(c - 48, 0, 9, 0, 255);
}
go_to_target(target);
}
C++
복사