아두이노에 블루투스 2.0 모듈(HC-06) 또는 4.0 BLE 모듈(AT-09 등)을 연결하고 안드로이드 앱 arduino bluetooth controller PWM v3.5를 이용하여 이전 글 아두이노 - 무드등 예제, RGB LED 제어에서 구현했던 무드등을 스마트폰에서 원격 제어해보도록 하겠다.

 

원격제어 기능 

1. 스마트폰 앱을 이용하여 아두이노 무드등의 블루투스 모듈에 연결

2. 블루투스가 연결되면 아두이노 무드등의 현재 버튼 또는 작동 모드의 상태에 관한 데이터를 전송받아 앱에 표시

   2-1. 블루투스 연결 시 RGB LED가 켜진 상태인지 꺼진 상태인지를 "LED ON" 버튼에 반영 

   2-2. 블루투스 연결 시 색상 패턴" 버튼에 상태 반영

   2-3. 블루투스 연결 시 무지개 패턴 모드 일 경우 "무지개" 버튼에 상태 반영

   2-4. 블루투스 연결 시 랜덤 색상 패턴 모드 일 경우 "랜덤 색상"  버튼에 상태 반영

3. RGB LED의 ON/OFF 제어

4. 밝기 제어

5. 사용자 색상 선택  

6. PWM 슬라이드 또는 Color Picker로 변경한 색상을 새로운 사용자 색상으로 저장

7. 패턴 모드의 커스텀 색상 패턴, 무지개 패턴, 랜덤 색상 패턴 선택

8. 패턴 모드의 시간 간격 제어

9. 색상 초기화 

10. EEPROM을 이용하여 색상 배열 및 중요 변수 값을 저장하여 아두이노 리셋 후에도 리셋 전의 설정 상태를 유지한다.

 

상기 기능들을 구현하기 위해 이전 아두이노 무드등 코드에 소프트 웨어 시리얼 관련 코드와 EEPROM 설정 코드를 추가하고 안드로이드 앱으로 제어할 수 있도록 명령어 코드도 추가해 주겠다.

* 블루투스 RX핀 -> 아두이노 3번 핀

* 블루투스 TX핀 -> 아두이노 2번 핀

 

10번 항목을 위해 EEPROM 라이브러리를 등록하고 EEPROM 인덱스 별 저장 항목은 아래와 같다. 

EEPROM 인덱스 0 : 초기 EEPROM 저장 플래그

EEPROM 인덱스 1 ~ 8 : RED 색상 배열

EEPROM 인덱스 9 ~ 16 : GREEN 색상 배열

EEPROM 인덱스 17 ~ 24 : BLUE 색상 배열

EEPROM 인덱스 25 : 밝기 제어 변수 값 저장

EEPROM 인덱스 26 : 색상 선택용 인덱스 값 저장

EEPROM 인덱스 27 : 사용자 색상 패턴 변경 시간 저장, 자료형이 uint16_t으로 2바이트 - put 함수 이용 저장

EEPROM 인덱스 29 : 무지개 색상 패턴 변경 시간 저장, 자료형이 uint16_t으로 2바이트 - put 함수 이용 저장 

EEPROM 인덱스 31 : 랜덤 색상 패턴 변경 시간 저장, 자료형이 uint16_t으로 2바이트 - put 함수 이용 저장

* EEPROM.put(index, value) 함수 : 저장하고자 하는 value의 자료형 크기에 의해 지정 index부터 자료형 크기만큼 저장

예) uint16_t value -> EEPROM.put(0, value); // EEPROM 인덱스 0과 1에 1바이트씩 총 2바이트 저장

    uint32_t value -> EEPROM.put(0, value); // EEPROM 인덱스 0, 1, 2, 3에 1바이트씩 총 4바이트 저장

* EEPROM.get(index, value) 함수 : 읽은 값을 저장하고자 하는 변수의 자료형의 크기에 의해 지정 index부터 자료형 크기만큼 읽고 저항하고자 하는 변수에 값을 저장

 

 

상기 항목에 맞게 아래와 같이 코드를 추가해 주었다. 이를 기준으로 전체 코드에서 EEPROM과 관련된 변수들의 변동사항이 있을 때마다 EEPROM에 변경된 변숫값을 저장하는 코드를 추가해 주어야 한다.  

#include <EEPROM.h>

// setup() 함수 추가
if(EEPROM.read(0) != 1) {
  EEPROM.write(0, 1); // eeprom 저장 플래그
  for (uint8_t i = 0; i < 8 ; i++) {   // 인덱스 1 ~ 25, 24바이트 저장
    EEPROM.write(i + 1, red_t[i]);     // 1 ~ 8 red
    EEPROM.write(i + 9, green_t[i]);   // 9 ~ 16 green
    EEPROM.write(i + 17, blue_t[i]);   // 17 ~ 24 green
  }
  EEPROM.write(25, brightness);        // eeprom 밝기 저장
  EEPROM.write(26, color_index);       // eeprom 색상 인덱스 저장
  EEPROM.put(27, auto_duration);     // uint16_t 자료형, 2바이트, 사용자 색상 패턴 변경 시간 저장
  EEPROM.put(29, rainbow_duration);    // uint16_t 자료형, 2바이트, 무지개 색상 변경 시간 저장
  EEPROM.put(31, pause_duration);      // uint16_t 자료형, 2바이트, 랜덤 색상 유지 시간 저장
} else {
  for (uint8_t i = 0; i < 8 ; i++) {   // 인덱스 1 ~ 24, 24바이트 읽기
    red_t[i] = EEPROM.read(i + 1);     // 1 ~ 8 red
    green_t[i] = EEPROM.read(i + 9);   // 9 ~ 16 green
    blue_t[i] = EEPROM.read(i + 17);   // 17 ~ 24 green
  }
  brightness = EEPROM.read(25);
  color_index = EEPROM.read(26);
  EEPROM.get(27, auto_duration);
  EEPROM.get(29, rainbow_duration);
  EEPROM.get(31, pause_duration);
}

1번 항목을 위해 SoftwareSerial 라이브러리를 등록하고 수신 및 송신 핀 설정을 해준다.

#include <SoftwareSerial.h> 
#define TX 3 // bluetooth RX -> arduino 3
#define RX 2 // bluetooth TX -> arduino 2 
SoftwareSerial btSerial(RX, TX); // (RX, TX)

스마트폰으로 블루투스 시리얼 통신을 통해 원격 제어하기 위해서는 블루투스 앱에서 사용하는 프로토콜을 알아야 한다. 필요한 디지털 버튼과 PWM 제어용 명령어만 다루겠다. 더 자세한 사항은 아래 글을 참조하기 바란다.

arduino bluetooth controller PWM - 아두이노 원격제어 안드로이드 앱 버전 3.5

arduino bluetooth controller PWM 매뉴얼

(*** 상기앱의 와이파이 연결은 안드로이드8 [갤럭시S7]이하 버전에서만 작동합니다 ***)

(*** 상기앱의 블루투스 연결은 안드로이드10 이하 버전에서만 작동합니다 ***)

 

1. 블루투스 앱 송신 -> 아두이노 수신

    1-1. 디지털 버튼 전송 값 : 0xF0 + 1byte number + 0xF1 // 총 3바이트

    1-2. PWM : 0xF3 + 1byte number + 2byte number + 0xF1

    1-3. Date / Time: 0xF8 + 07/24/2019(String) + 0x7C + 15:55:32(String) + \n(새 줄)

 

 

상기 항목 1-1은 스마트폰 앱에서 디지털 버튼을 클릭했을 때 블루투스 모듈로 전송하는 값이다. 버튼 번호에 따라 들어오는 1byte 값이 다르게 되는데 그 의미는 아래와 같다. 

1번 버튼이 눌린 상태로 변경(토글/푸시 버튼) : 1byte number = 11 // ON

1번 버튼이 안 눌린 상태(토글 버튼) : 1byte number = 10              // OFF

2번 버튼이 눌린 상태로 변경(토글/푸시 버튼) : 1byte number = 21 // ON

2번 버튼이 안 눌린 상태(토글 버튼) : 1byte number = 20              // OFF

31/30, 41/40, ............

 

상기 항목 1-2는 스마트폰에서 PWM 슬라이드를 변경했을 때 블루투스 모듈로 전송하는 값이다. PWM 번호에 따라 들어오는 3byte 값이 다르게 되는데 그 의미는 아래와 같다. 

1번 PWM 슬라이드 변경 : 1byte number = 1, 2byte number = 슬라이드 값

2번 PWM 슬라이드 변경 : 1byte number = 2, 2byte number = 슬라이드 값

3번 PWM 슬라이드 변경 : 1byte number = 3, 2byte number = 슬라이드 값

 

시리얼 모니터 버퍼의 값을 확인하여 헥사 값 0xF0가 있으면 디지털 핀 제어에 관한 값이므로 디지털 핀 제어 수신용 플래그를 get_pin_val = true;으로 변경하고 그 수신용 플래그에 따라 원하는 값을 수신하고 헥사 값 0xF3이 있으면 PWM 제어에 관한 값이므로 PWM 제어 수신용 플래그를 get_pwm_val = true;으로 변경하고 그 수신용 플래그에 따라 원하는 값을 수신하도록 아래처럼 수신 코드를 작성해 준다. 

// 블루투스 앱 디지털 핀 제어용 변수
bool get_pin_val = false;
uint8_t pin_count = 0;
uint8_t pin_a[3] = {0, };
uint8_t pin_val;

// 블루투스 앱 PWM 제어용 변수
bool get_pwm_val = false;
uint8_t pwm_count = 0;
uint8_t pwm_a[5] = {0, };
uint16_t pwm1 = 0;  
uint16_t pwm2 = 0;  
uint16_t pwm3 = 0; 

if (btSerial.peek() == 0xF3) get_pwm_val = true; 
else if (btSerial.peek() == 0xF0) get_pin_val = true; 
if (get_pwm_val == true ) { // pwm 제어값 수신
  uint8_t temp = btSerial.read();
  pwm_a[pwm_count] = temp;
  pwm_count++; 
  if (temp == 0xF1) {
    get_pwm_val = false;
    pwm_count = 0;
    pwm_control();
  }
}
else if (get_pin_val == true) {  // 디지털 핀 제어값 수신
  uint8_t temp = btSerial.read();
  pin_a[pin_count] = temp;
  pin_count++;
  if (temp == 0xF1) {
    get_pin_val = false;
    pin_count = 0;
    pin_control();
  }
}

상기 항목 1-3은 블루투스 앱과 블루투스 모듈이 연결될 경우 최초 1회만 Data/Time 값을 전송하는 옵션 설정에 의해 보내는 값에 대한 프로토콜이다. 하지만 상기 코드의 날짜 및 시간 값은 사용할 필요 없고 단지 블루투스가 연결되었을 때 현재 무드등의 상태 및 옵션 값 등으로 전송하는 데에만 사용하기로 한다. 즉, 시리얼 모니터 버퍼의 값을 확인하여 헥사 값 0xF8이 있으면 블루투스가 연결된 것으로 간주하고 필요한 값들을 스마트폰에 전송하며 블루투스 앱에서는 그 값에 따라 현재 버튼 상태의 표시를 반영하게 된다. 들어온 날짜 및 시간에 관한 데이터는 사용하지 않으므로 아래 함수를 통해 시리얼 버퍼에서 비워주어야만 한다. 

String temp = btSerial.readStringUntil('\n'); // dump

블루투스 연결 시 무드등의 현재 상태 값 전송 코드는 아래와 같다.

// 블루투스 수신 함수
else if (btSerial.peek() == 0xF8) {  // 날짜 및 시간 값 수신
  String temp = btSerial.readStringUntil('\n'); // dump
  if (rgb_change_start) send_pin_echo(71);
  else if (rainbow_delay_start) send_pin_echo(81);
  else if (random_delay_start) send_pin_echo(91);
  if (button_mode == 0) send_pin_echo(10);
  else send_pin_echo(11);
  if (button_mode == 1) {
    btSerial.print("Brightness Mode: "); btSerial.print(brightness);
    btSerial.print(" ");
    btSerial.print("Color: "); btSerial.print(color_index);
  }
  else if (button_mode == 2) {
    btSerial.print("Color Change Mode: "); btSerial.print(color_index);
  }
  else if (button_mode == 3) {
    if (pattern_mode == 0) btSerial.print("Custom Color Loop");  
    else if (pattern_mode == 1) btSerial.print("Rainbow");
    else if (pattern_mode == 2) btSerial.print("Random Color");
  }
}


2. 블루투스 아두이노 송신 -> 앱 수신

    디지털 버튼 전송 값 : 0xF0 + 1byte number + 0xF1

 

상기 프로토콜은 현재 디지털 핀 상태를 스마트폰 블루투스 앱에 전송하기 위한 프로토콜로서 아래와 같이 전송 코드를 적용하면 된다.

// 블루투스 앱 상태표시 변수 및 함수
uint8_t pin_echo[] = {0xF0, 0, 0xF1};

void send_pin_echo(uint8_t pin_val){
  pin_echo[1] = pin_val;
  for (int i = 0; i < 3; i++) {
    btSerial.write(pin_echo[i]);
  }
}

1번 버튼 상태 ON : send_pin_echo(11);

1번 버튼 상태 OFF : send_pin_echo(10);

2번 버튼 상태 ON : send_pin_echo(21);

 

이번 예제에서는 블루투스 앱의 12개의 버튼을 모두 사용하게 된다 각 버튼의 기능은 아래와 같다.

1번 버튼 : 토글 버튼 - RGB LED ON/OFF - "LED ON"

2번 버튼 : 푸시 버튼 - birghtness 값 감소 - "밝기 증가"

3번 버튼 : 푸시 버튼 - birghtness 값 증가 - "밝기 감소"

4번 버튼 : 푸시 버튼 - color index 증가 - "다음 색상"

5번 버튼 : 푸시 버튼 - color index 감소 - "이전 색상"

6번 버튼 : 푸시 버튼 - pwm1, pwm2, pwm3값을 현재 color index의 RGB 배열에 저장 - "색상 저장"

7번 버튼 : 토글 버튼 - "parttern mode = 0;"으로 설정 - "색상 패턴"

8번 버튼 : 토글 버튼 - "parttern mode = 1;"으로 설정 - "무지개"

9번 버튼 : 토글 버튼 - "parttern mode = 2;"으로 설정 - "랜덤 색상"

10번 버튼 : 푸시 버튼 - pattern mode에 따라 패턴 해당 시간 변숫값 증가 - "시간 증가"

11번 버튼 : 푸시 버튼 - pattern mode에 따라 패턴 해당 시간 변숫값 감소 - "시간 감소"

* parttern mode = 0 : auto_duration, parttern mode = 1 : rainbow_duration, parttern mode = 2 : pause_duration 

12번 버튼 : 푸시 버튼 - 사용자 색상 배열 값을 상수 색상 배열 값으로 변경 - "색상 초기화"

 

수신된 디지털 버튼 값에 따라 상기 기능을 구현하기 위해 아래와 같이 코드를 작성해 주었다. 

void pin_control() {
  pin_val = pin_a[1];
  if (pin_val != 0) {
    switch (pin_val) {  // 수신된 핀 값이 pin_val인 경우
      case 11: button_mode = 1;        // 버튼 모드 1
               rgb_display();          // RGB LED ON
               btSerial.print("Color: "); btSerial.print(color_index);
               btSerial.print(" ");    // 색상 인덱스 번호와 현재 밝기 표시
               btSerial.print("Brightness: "); btSerial.print(brightness);
                  break;
      case 10: button_mode = 0;        // 버튼 모드 0
               analogWrite(Red, 0);    // RGB LED OFF
               analogWrite(Green, 0);  // RGB LED OFF
               analogWrite(Blue, 0);   // RGB LED OFF
               rgb_change_start = false;    // 사용자 색상 패턴 모드 중지
               rainbow_delay_start = false; // 무지개 패턴 모드 중지
               random_delay_start = false;  // 랜덤 색상 패턴 모드 중지
               send_pin_echo(70);           // 블루투스 앱 "색상 패턴" 버튼 표시 끄기
               send_pin_echo(80);           // 블루투스 앱 "무지개" 버튼 표시 끄기
               send_pin_echo(90);           // 블루투스 앱 "랜덤 색상" 버튼 표시 끄기
                  break;
      case 21: brightness--;                        // 밝기 증가 - 변수를 나누는 값 감소
               if (brightness < 0) brightness = 4;  // 음수 표시 위해 변수 자료형을 uint8_t -> int8_로 변경
               btSerial.print("Brightness: "); btSerial.print(brightness);
               EEPROM.write(25, brightness);        // eeprom 밝기 변수 나누는 값 저장
               rgb_display();                       // 변경된 밝기 적용
                  break;
      case 31: brightness++;                        // 밝기 감소 - 변수를 나누는 값 증가
               if (brightness == 5) brightness = 0; // 밝기 범위 벗어나면 0으로 초기화
               btSerial.print("Brightness: "); btSerial.print(brightness);
               EEPROM.write(25, brightness);        // eeprom 밝기 변수 나누는 값 저장
               rgb_display();                       // 변경된 밝기 적용
                  break;
      case 41: if (rgb_change_start != true && rainbow_delay_start != true && random_delay_start != true) {
                 button_mode = 2; // 버튼 모드 2 - 색상 변경은 사용자 색상, 무지개, 랜덤 색상 패턴이 아닌 경우에만 실행 
                 color_index++;   // 색상 변경위해 색상 인덱스 증가
                 if (color_index == 8) color_index = 0; // 인덱스 범위 벗어나면 0으로 초기화
                 btSerial.print("Color: "); btSerial.print(color_index);
                 EEPROM.write(26, color_index); // eeprom 색상 인덱스 값 저장
                 rgb_display();                 // 변경된 색상 적용
               }
                  break;
      case 51: if (rgb_change_start != true && rainbow_delay_start != true && random_delay_start != true) {
                 button_mode = 2; // 버튼 모드 2
                 color_index--;   // 색상 변경위해 색상 인덱스 감소
                 if (color_index < 0) color_index = 7; // 음수 표시 위해 변수 자료형을 uint8_t -> int8_로 변경
                 btSerial.print("Color: "); btSerial.print(color_index);
                 EEPROM.write(26, color_index); // eeprom 색상 인덱스 값 저장
                 rgb_display();                 // 변경된 색상 적용
               }
                  break;
      case 61: if (rgb_change_start != true && rainbow_delay_start != true && random_delay_start != true) {
                 red_t[color_index] = pwm1; // 새로운 색상 저장은 사용자 색상, 무지개, 랜덤 색상 패턴이 아닌 경우에만 실행 
                 EEPROM.write(color_index + 1, pwm1);  // pwm1값 현재 색상 인덱스의 빨간색 red_t 배열에 저장하고 eeprom에도 저장
                 green_t[color_index] = pwm2;          // pwm2값 현재 색상 인덱스의 녹색 green_t 배열에 저장
                 EEPROM.write(color_index + 9, pwm2);  // eeprom 저장위치에 녹색 값 저장
                 blue_t[color_index] = pwm3;           // pwm2값 현재 색상 인덱스의 녹색 green_t 배열에 저장
                 EEPROM.write(color_index + 17, pwm3); // eeprom 저장위치에 녹색 값 저장
                 btSerial.print("New Color: "); btSerial.print(color_index);
                 btSerial.print(", R: "); btSerial.print(pwm1);
                 btSerial.print(" G: "); btSerial.print(pwm2);
                 btSerial.print(" B: "); btSerial.print(pwm3);
               }
                  break;
      case 71: rgb_change_start = true;      // 사용자 색상 패턴 시작 -> 무지개 / 랜덤 색상 패턴 종료
               rainbow_delay_start = false;  // 무지개 패턴 종료
               random_delay_start = false;   // 랜덤 색상 패턴 종료
               send_pin_echo(11);            // 블루투스 앱 "LED ON" 버튼 표시 켜기
               send_pin_echo(80);            // 블루투스 앱 "무지개" 버튼 표시 끄기
               send_pin_echo(90);            // 블루투스 앱 "랜덤 색상" 버튼 표시 끄기
               button_mode = 3;              // 버튼 모드 3 - 패턴 선택 모드 -> 물리 버튼 작동 시 사용위해
               pattern_mode = 0;             // 패턴 모드 0 - 사용자 색상 패턴 -> 물리 버튼 작동 시 사용위해
                  break;
      case 70: rgb_change_start = false;     // 사용자 색상 패턴 종료
               button_mode = 1;              // 버튼 모드 1 - 색상 선택 모드
               pattern_mode = 0;             // 패턴 모드는 0으로 초기화
               rgb_display();                // 현재 색상 인덱스 색상 출력
                  break;
      case 81: rgb_change_start = false;     // 사용자 색상 패턴 종료
               rainbow_delay_start = true;   // 무지개 패턴 시작 -> 사용자 색상 / 랜덤 색상 패턴 종료
               random_delay_start = false;   // 랜덤 색상 패턴 종료
               send_pin_echo(11);            // 블루투스 앱 "LED ON" 버튼 표시 켜기
               send_pin_echo(70);            // 블루투스 앱 "색상 패턴" 버튼 표시 끄기
               send_pin_echo(90);            // 블루투스 앱 "랜덤 색상" 버튼 표시 끄기
               button_mode = 3;              // 버튼 모드 3 - 패턴 선택 모드 -> 물리 버튼 작동 시 사용위해
               pattern_mode = 1;             // 패턴 모드 1 - 무지개 패턴 -> 물리 버튼 작동 시 사용위해
                  break;
      case 80: rainbow_delay_start = false;  // 무지개 패턴 종료
               button_mode = 1;              // 버튼 모드 1 - 색상 선택 모드
               pattern_mode = 0;             // 패턴 모드는 0으로 초기화
               rgb_display();                // 현재 색상 인덱스 색상 출력
                  break;
      case 91: rgb_change_start = false;     // 사용자 색상 패턴 종료
               rainbow_delay_start = false;  // 무지개 패턴 종료
               random_delay_start = true;    // 랜덤 색상 패턴 시작 -> 사용자 색상 / 무지개 패턴 종료
               send_pin_echo(11);            // 블루투스 앱 "LED ON" 버튼 표시 켜기
               send_pin_echo(70);            // 블루투스 앱 "색상 패턴" 버튼 표시 끄기
               send_pin_echo(80);            // 블루투스 앱 "무지개" 버튼 표시 끄기
               button_mode = 3;              // 버튼 모드 3 - 패턴 선택 모드 -> 물리 버튼 작동 시 사용위해
               pattern_mode = 2;             // 패턴 모드 2 - 랜덤 색상 패턴 -> 물리 버튼 작동 시 사용위해
                  break;
      case 90: random_delay_start = false;   // 랜덤 색상 패턴 종료
               button_mode = 1;              // 버튼 모드 1 - 색상 선택 모드
               pattern_mode = 0;             // 패턴 모드는 0으로 초기화
               rgb_display();                // 현재 색상 인덱스 색상 출력
                  break;  
      case 101: if (rgb_change_start) {           // 사용자 색상 패턴이 실행중인 경우
                  auto_duration += 100;           // 색상 변경 시간값 증가
                  EEPROM.put(27, auto_duration);  // 변경된 값 EEPROM 저장
                  btSerial.print(auto_duration);
                }
                else if (rainbow_delay_start) {      // 무지개 패턴이 실행중인 경우
                  rainbow_duration++;                // HUE 각도값 증가 시간값 증가 
                  EEPROM.put(29, rainbow_duration);  // 변경된 값 EEPROM 저장
                  btSerial.print(rainbow_duration);
                }
                else if (random_delay_start) {     // 랜덤 색상 패턴이 실행중인 경우
                  pause_duration += 100;           // 색상 변경 완료후 유지 시간값 증가
                  EEPROM.put(31, pause_duration);  // 변경된 값 EEPROM 저장
                  btSerial.print(pause_duration);
                }
                  break;
      case 111: if (rgb_change_start) {
                  if (auto_duration >= 200) {      // 최솟값 100
                    auto_duration -= 100;          // 색상 변경 시간값 감소
                    EEPROM.put(27, auto_duration); 
                    btSerial.print(auto_duration);
                  }
                }
                else if (rainbow_delay_start) {
                  if (rainbow_duration >= 2) {         // 최솟값 1
                    rainbow_duration--;                // HUE 각도값 증가 시간값 감소
                    EEPROM.put(29, rainbow_duration);
                    btSerial.print(rainbow_duration);
                  }
                }
                else if (random_delay_start) {
                  if (pause_duration >= 200) {         // 최솟값 100
                    pause_duration -= 100;             // 색상 변경 완료후 유지 시간값 감소
                    EEPROM.put(31, pause_duration);
                    btSerial.print(pause_duration);
                  }
                }
                  break;  
      case 121: for (uint8_t i = 0; i < 8 ; i++) {   // 인덱스 1 ~ 25, 24바이트 색상 배열에 저장
                  red_t[i] = red_t_reset[i];         
                  green_t[i] = green_t_reset[i];
                  blue_t[i] = blue_t_reset[i];
                  EEPROM.write(i + 1, red_t_reset[i]);     // 1 ~ 8 red
                  EEPROM.write(i + 9, green_t_reset[i]);   // 9 ~ 16 green
                  EEPROM.write(i + 17, blue_t_reset[i]);   // 17 ~ 24 green
                  if (rgb_change_start != true && rainbow_delay_start != true && random_delay_start != true) {
                    rgb_display(); // 사용자 색상, 무지개, 랜덤 색상 패턴이 아닌 경우에는 변경된 색상 값 반영
                  }
                }
                  break; 
    }
    pin_val = 0;
  }
}

새로운 사용자 색상 값을 만들기 위해 PWM 슬라이드를 이용하여 RGB LED를 제어할 수 있도록 아래 코드를 추가해 주었으며, 이 기능은 사용자 색상, 무지개, 랜덤 색상 패턴이 아닌 경우에만 작동해야 한다. 

void pwm_control() {
  uint16_t temp = pwm_a[3];
  temp = temp << 8 | pwm_a[2];
  if (rgb_change_start != true && rainbow_delay_start != true && random_delay_start != true) {
    if (pwm_a[1] == 1) {  // 슬라이드 1번
      pwm1 = temp;
      analogWrite(Red, pwm1);
    }
    else if (pwm_a[1] == 2) { // 슬라이드 2번
      pwm2 = temp;
      analogWrite(Green, pwm2);
    }
    else if (pwm_a[1] == 3) {  // 슬라이드 3번
      pwm3 = temp;
      analogWrite(Blue, pwm3);
    }
  }
}

 

1019.10.7 수정사항

12V 어댑터를 이용한 외부 전원을 사용할 경우 터치 값 범위의 변동이 발생하여 터치버튼 코드가 작동되는 현상이 발견되었다. 터치 값 조건을 아래와 같이 조정해 주었다.

if(val > 720 || val > 500 && val < 669 ) // 700 -> 720 수정

 

블루투스 연결시 RGB LED가 꺼진 상태, 즉 button_mode == 0일 때에도 패턴모드 상태값이 버튼 표시에 반영되던 것을 RGB LED가 켜지고 button_mode == 3일 때에만 패턴모드 상태값이 버튼 표시에 반영되도록 아래와 같이 수정해 주었다. 

 

    else if (btSerial.peek() == 0xF8) {  // 날짜 및 시간 값 수신
      String temp = btSerial.readStringUntil('\n'); // dump
      if (button_mode == 0) {
        send_pin_echo(10);
      }
      else send_pin_echo(11);
      if (button_mode == 1) {
        btSerial.print("Brightness Mode: "); btSerial.print(brightness);
        btSerial.print(" ");
        btSerial.print("Color: "); btSerial.print(color_index);
      }
      else if (button_mode == 2) {
        btSerial.print("Color Change Mode: "); btSerial.print(color_index);
      }
      else if (button_mode == 3) {
        if (pattern_mode == 0) {
          send_pin_echo(71);
          btSerial.print("Custom Color Loop");  
        }
        else if (pattern_mode == 1) {
          send_pin_echo(81);
          btSerial.print("Rainbow");
        }
        else if (pattern_mode == 2) {
          send_pin_echo(91);
          btSerial.print("Random Color");
        }
      }

 

Color Picker를 사용하여 RGB LED를 제어하게 되면 디지털 버튼이 보이지 않게되어 현재 색상을 저장할 수 없게 된다. 플로팅 버튼을 사용하여 저장 할 수 있도록 pin_control() 함수에 아래와 같이 코드를 추가해 주었다.

      case 131: if (rgb_change_start != true && rainbow_delay_start != true && random_delay_start != true) {
                 red_t[color_index] = pwm1;
                 EEPROM.write(color_index + 1, pwm1);
                 green_t[color_index] = pwm2;
                 EEPROM.write(color_index + 9, pwm2);
                 blue_t[color_index] = pwm3;
                 EEPROM.write(color_index + 17, pwm3);
                 btSerial.print("New Color: "); btSerial.print(color_index);
                 btSerial.print(", R: "); btSerial.print(pwm1);
                 btSerial.print(" G: "); btSerial.print(pwm2);
                 btSerial.print(" B: "); btSerial.print(pwm3);
               }
                  break;

기존 무드등 코드에 상기 추가 코드를 반영해준 아래 스케치를 아두이노에 업로드 해주자.

mood_rgbled_rainbow_bluetooth.ino
0.02MB

더보기
const uint8_t lights[360]={  // sine wave 방식
  0,   0,   0,   0,   0,   1,   1,   2,   2,   3,   4,   5,   6,   7,   8,   9, 
 11,  12,  13,  15,  17,  18,  20,  22,  24,  26,  28,  30,  32,  35,  37,  39, 
 42,  44,  47,  49,  52,  55,  58,  60,  63,  66,  69,  72,  75,  78,  81,  85, 
 88,  91,  94,  97, 101, 104, 107, 111, 114, 117, 121, 124, 127, 131, 134, 137, 
141, 144, 147, 150, 154, 157, 160, 163, 167, 170, 173, 176, 179, 182, 185, 188, 
191, 194, 197, 200, 202, 205, 208, 210, 213, 215, 217, 220, 222, 224, 226, 229, 
231, 232, 234, 236, 238, 239, 241, 242, 244, 245, 246, 248, 249, 250, 251, 251, 
252, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 253, 
252, 251, 251, 250, 249, 248, 246, 245, 244, 242, 241, 239, 238, 236, 234, 232, 
231, 229, 226, 224, 222, 220, 217, 215, 213, 210, 208, 205, 202, 200, 197, 194, 
191, 188, 185, 182, 179, 176, 173, 170, 167, 163, 160, 157, 154, 150, 147, 144, 
141, 137, 134, 131, 127, 124, 121, 117, 114, 111, 107, 104, 101,  97,  94,  91, 
 88,  85,  81,  78,  75,  72,  69,  66,  63,  60,  58,  55,  52,  49,  47,  44, 
 42,  39,  37,  35,  32,  30,  28,  26,  24,  22,  20,  18,  17,  15,  13,  12, 
 11,   9,   8,   7,   6,   5,   4,   3,   2,   2,   1,   1,   0,   0,   0,   0, 
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
  0,   0,   0,   0,   0,   0,   0,   0};

// EEPROM
#include <EEPROM.h>

#include <SoftwareSerial.h> 
#define TX 3 // bluetooth RX -> arduino 3
#define RX 2 // bluetooth TX -> arduino 2 
SoftwareSerial btSerial(RX, TX); // (RX, TX)

// 색상 초기화 배열
const uint8_t red_t_reset[8] = {255, 255, 0, 0, 255, 0, 255, 210};
const uint8_t green_t_reset[8] = {255, 0, 255, 0, 255, 255, 0, 105};
const uint8_t blue_t_reset[8] = {255, 0, 0, 255, 0, 255, 255, 30};

#define ledPin 13
#define Red 9
#define Green 10
#define Blue 11
#define capSensePin A0 // ADC pin (paperclip, conductive paint/fabric/thread, wire)
#define buttonPin 7

// 색상 배열
int8_t color_index = 0;
uint8_t red_t[8] = {255, 255, 0, 0, 255, 0, 255, 210};
uint8_t green_t[8] = {255, 0, 255, 0, 255, 255, 0, 105};
uint8_t blue_t[8] = {255, 0, 0, 255, 0, 255, 255, 30};

// touch button 변수
unsigned int long cap_button_delay = 0;
bool cap_button_check = false;
uint8_t delay_count = 0;
bool start_count = false;
int val;
uint8_t pattern_mode = 0;

// tact button 변수
unsigned int long button_delay = 0;
bool button_hold = false;
bool pre_button_state = 1; // PULL_UP button 접점 붙은 상태: 0, 떨어진 상태: 1 -> 초기값 1
bool button_state = 1;  
uint8_t button_mode = 0;   // 버튼 모드용 변수 

// brightness 설정 변수
int8_t brightness = 0;
uint8_t red_tb = 0;
uint8_t green_tb = 0;
uint8_t blue_tb = 0;

// 사용자 색상 패턴 변수
unsigned long int rgb_delay = 0;
bool rgb_change = false;
bool rgb_change_start = false;
uint16_t auto_duration = 1000;  // 색상 패턴 변경 시간

// 무지개 색상 변경
unsigned long int rainbow_delay = 0;
uint16_t rainbow_duration = 40;  // 무지개 색상 변경 시간
bool rainbow_start = false;
bool rainbow_delay_start = false;
int rainbow_k = 0;

// 랜덤 색상 변경
uint16_t color[3], nextColor[3];
long colorStep[3];
byte count, a0, a1, a2;

unsigned long int random_delay = 0;
uint16_t random_duration = 20;
bool random_color_start = false;
bool random_delay_start = false;
int random_k = 0;

unsigned long int pause_delay = 0;
uint16_t pause_duration = 2000;    // 랜덤 색상 유지 시간
bool random_pause = false;
bool random_resume = false;

// 블루투스 앱 디지털 핀 제어용 변수
bool get_pin_val = false;
uint8_t pin_count = 0;
uint8_t pin_a[3] = {0, };
uint8_t pin_val;

// 블루투스 앱 PWM 제어용 변수
bool get_pwm_val = false;
uint8_t pwm_count = 0;
uint8_t pwm_a[5] = {0, };
uint16_t pwm1 = 0;  
uint16_t pwm2 = 0;  
uint16_t pwm3 = 0; 

// 블루투스 앱 상태표시 변수 및 함수
uint8_t pin_echo[] = {0xF0, 0, 0xF1};

void send_pin_echo(uint8_t pin_val){
  pin_echo[1] = pin_val;
  for (int i = 0; i < 3; i++) {
    btSerial.write(pin_echo[i]);
  }
}

void setup() {
  if(EEPROM.read(0) != 1) {
    EEPROM.write(0, 1); // eeprom 저장 플래그
    for (uint8_t i = 0; i < 8 ; i++) {   
      EEPROM.write(i + 1, red_t[i]);     
      EEPROM.write(i + 9, green_t[i]);   
      EEPROM.write(i + 17, blue_t[i]);   
    }
    EEPROM.write(25, brightness);        
    EEPROM.write(26, color_index);       
    EEPROM.put(27, auto_duration);     
    EEPROM.put(29, rainbow_duration);  
    EEPROM.put(31, pause_duration);    
  } else {
    for (uint8_t i = 0; i < 8 ; i++) {   
      red_t[i] = EEPROM.read(i + 1);     
      green_t[i] = EEPROM.read(i + 9);  
      blue_t[i] = EEPROM.read(i + 17);   
    }
    brightness = EEPROM.read(25);
    color_index = EEPROM.read(26);
    EEPROM.get(27, auto_duration);
    EEPROM.get(29, rainbow_duration);
    EEPROM.get(31, pause_duration);
  }
  Serial.begin(9600);       // 시리얼 모니터
  btSerial.begin(9600);     // bluetooth Serial
  pinMode(ledPin, OUTPUT);
  pinMode(Red, OUTPUT);
  pinMode(Green, OUTPUT);
  pinMode(Blue, OUTPUT);
  pinMode(capSensePin, INPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  randomSeed(analogRead(5) + random(50));
}

void loop() {
  if (btSerial.available()) {  
    if (btSerial.peek() == 0xF3) get_pwm_val = true; 
    else if (btSerial.peek() == 0xF0) get_pin_val = true; 
    if (get_pwm_val == true ) { // pwm 제어값 수신
      uint8_t temp = btSerial.read();
      pwm_a[pwm_count] = temp;
      pwm_count++; 
      if (temp == 0xF1) {
        get_pwm_val = false;
        pwm_count = 0;
        pwm_control();
      }
    }
    else if (get_pin_val == true) {  // 디지털 핀 제어값 수신
      uint8_t temp = btSerial.read();
      pin_a[pin_count] = temp;
      pin_count++;
      if (temp == 0xF1) {
        get_pin_val = false;
        pin_count = 0;
        pin_control();
      }
    }
    else if (btSerial.peek() == 0xF8) {  // 날짜 및 시간 값 수신
      String temp = btSerial.readStringUntil('\n'); // dump
      if (button_mode == 0) {
        send_pin_echo(10);
      }
      else send_pin_echo(11);
      if (button_mode == 1) {
        btSerial.print("Brightness Mode: "); btSerial.print(brightness);
        btSerial.print(" ");
        btSerial.print("Color: "); btSerial.print(color_index);
      }
      else if (button_mode == 2) {
        btSerial.print("Color Change Mode: "); btSerial.print(color_index);
      }
      else if (button_mode == 3) {
        if (pattern_mode == 0) {
          send_pin_echo(71);
          btSerial.print("Custom Color Loop");  
        }
        else if (pattern_mode == 1) {
          send_pin_echo(81);
          btSerial.print("Rainbow");
        }
        else if (pattern_mode == 2) {
          send_pin_echo(91);
          btSerial.print("Random Color");
        }
      }
    }
    else {
      char text = btSerial.read();  // text value for some purpose.
      btSerial.write(text); // print text to app
    }
  }
  cap_button();
  cap_button_act();
  button();
  button_act();
  rgb_display_auto();
  rgb_display_delay();
  rainbow_display_delay();
  rainbow();
  random_display_delay();
  random_color();
  random_pause_delay();
}

void pin_control() {
  pin_val = pin_a[1];
  if (pin_val != 0) {
    switch (pin_val) {
      case 11: button_mode = 1;
               rgb_display();
               btSerial.print("Color: "); btSerial.print(color_index);
               btSerial.print(" ");
               btSerial.print("Brightness: "); btSerial.print(brightness);
                  break;
      case 10: button_mode = 0;
               analogWrite(Red, 0);
               analogWrite(Green, 0);
               analogWrite(Blue, 0);
               rgb_change_start = false;
               rainbow_delay_start = false;
               random_delay_start = false;
               send_pin_echo(70);
               send_pin_echo(80);
               send_pin_echo(90);
                  break;
      case 21: brightness--;
               if (brightness < 0) brightness = 4;
               btSerial.print("Brightness: "); btSerial.print(brightness);
               EEPROM.write(25, brightness); // eeprom 밝기 저장
               rgb_display(); 
                  break;
      case 31: brightness++;
               if (brightness == 5) brightness = 0; // 음수 표시 위해 변수 자료형을 uint8_t -> int8_로 변경
               btSerial.print("Brightness: "); btSerial.print(brightness);
               EEPROM.write(25, brightness); // eeprom 밝기 저장
               rgb_display();
                  break;
      case 41: if (rgb_change_start != true && rainbow_delay_start != true && random_delay_start != true) {
                 button_mode = 2;
                 color_index++;
                 if (color_index == 8) color_index = 0;
                 btSerial.print("Color: "); btSerial.print(color_index);
                 EEPROM.write(26, color_index); // eeprom 색상 인덱스 저장
                 rgb_display();
               }
                  break;
      case 51: if (rgb_change_start != true && rainbow_delay_start != true && random_delay_start != true) {
                 button_mode = 2;
                 color_index--;
                 if (color_index < 0) color_index = 7; // 음수 표시 위해 변수 자료형을 uint8_t -> int8_로 변경
                 btSerial.print("Color: "); btSerial.print(color_index);
                 EEPROM.write(26, color_index); // eeprom 색상 인덱스 저장
                 rgb_display();
               }
                  break;
      case 61: if (rgb_change_start != true && rainbow_delay_start != true && random_delay_start != true) {
                 red_t[color_index] = pwm1;
                 EEPROM.write(color_index + 1, pwm1);
                 green_t[color_index] = pwm2;
                 EEPROM.write(color_index + 9, pwm2);
                 blue_t[color_index] = pwm3;
                 EEPROM.write(color_index + 17, pwm3);
                 btSerial.print("New Color: "); btSerial.print(color_index);
                 btSerial.print(", R: "); btSerial.print(pwm1);
                 btSerial.print(" G: "); btSerial.print(pwm2);
                 btSerial.print(" B: "); btSerial.print(pwm3);
               }
                  break;
      case 71: rgb_change_start = true;
               rainbow_delay_start = false;
               random_delay_start = false;
               send_pin_echo(11);
               send_pin_echo(80);
               send_pin_echo(90);
               button_mode = 3;
               pattern_mode = 0;
                  break;
      case 70: rgb_change_start = false;
               button_mode = 1;
               pattern_mode = 0;
               rgb_display();
                  break;
      case 81: rgb_change_start = false;
               rainbow_delay_start = true;
               random_delay_start = false;
               send_pin_echo(11);
               send_pin_echo(70);
               send_pin_echo(90);
               button_mode = 3;
               pattern_mode = 1;
                  break;
      case 80: rainbow_delay_start = false;
               button_mode = 1;
               pattern_mode = 0;
               rgb_display();
                  break;
      case 91: rgb_change_start = false;
               rainbow_delay_start = false;
               random_delay_start = true;
               send_pin_echo(11);
               send_pin_echo(70);
               send_pin_echo(80);
               button_mode = 3;
               pattern_mode = 2;
                  break;
      case 90: random_delay_start = false;
               button_mode = 1;
               pattern_mode = 0;
               rgb_display();
                  break;  
      case 101: if (rgb_change_start) {
                  auto_duration += 100;
                  EEPROM.put(27, auto_duration); 
                  btSerial.print(auto_duration);
                }
                else if (rainbow_delay_start) {
                  rainbow_duration++;
                  EEPROM.put(29, rainbow_duration);
                  btSerial.print(rainbow_duration);
                }
                else if (random_delay_start) {
                  pause_duration += 100;
                  EEPROM.put(31, pause_duration);
                  btSerial.print(pause_duration);
                }
                  break;
      case 111: if (rgb_change_start) {
                  if (auto_duration >= 200) {    // 최솟값 100
                    auto_duration -= 100;
                    EEPROM.put(27, auto_duration); 
                    btSerial.print(auto_duration);
                  }
                }
                else if (rainbow_delay_start) {
                  if (rainbow_duration >= 2) {   // 최솟값 1
                    rainbow_duration--;  
                    EEPROM.put(29, rainbow_duration);
                    btSerial.print(rainbow_duration);
                  }
                }
                else if (random_delay_start) {
                  if (pause_duration >= 200) {   // 최솟값 100
                    pause_duration -= 100; 
                    EEPROM.put(31, pause_duration);
                    btSerial.print(pause_duration);
                  }
                }
                  break;  
      case 121: for (uint8_t i = 0; i < 8 ; i++) {   // 인덱스 1 ~ 25, 24바이트 저장
                  red_t[i] = red_t_reset[i];
                  green_t[i] = green_t_reset[i];
                  blue_t[i] = blue_t_reset[i];
                  EEPROM.write(i + 1, red_t_reset[i]);     // 1 ~ 8 red
                  EEPROM.write(i + 9, green_t_reset[i]);   // 9 ~ 16 green
                  EEPROM.write(i + 17, blue_t_reset[i]);   // 17 ~ 24 green
                  if (rgb_change_start != true && rainbow_delay_start != true && random_delay_start != true) {
                    rgb_display();
                  }
                }
                  break; 
      case 131: if (rgb_change_start != true && rainbow_delay_start != true && random_delay_start != true) {
                 red_t[color_index] = pwm1;
                 EEPROM.write(color_index + 1, pwm1);
                 green_t[color_index] = pwm2;
                 EEPROM.write(color_index + 9, pwm2);
                 blue_t[color_index] = pwm3;
                 EEPROM.write(color_index + 17, pwm3);
                 btSerial.print("New Color: "); btSerial.print(color_index);
                 btSerial.print(", R: "); btSerial.print(pwm1);
                 btSerial.print(" G: "); btSerial.print(pwm2);
                 btSerial.print(" B: "); btSerial.print(pwm3);
               }
                  break;
    }
    pin_val = 0;
  }
}

void pwm_control() {
  uint16_t temp = pwm_a[3];
  temp = temp << 8 | pwm_a[2];
  if (rgb_change_start != true && rainbow_delay_start != true && random_delay_start != true) {
    if (pwm_a[1] == 1) {  // 슬라이드 1번
      pwm1 = temp;
      analogWrite(Red, pwm1);
    }
    else if (pwm_a[1] == 2) { // 슬라이드 2번
      pwm2 = temp;
      analogWrite(Green, pwm2);
    }
    else if (pwm_a[1] == 3) {  // 슬라이드 3번
      pwm3 = temp;
      analogWrite(Blue, pwm3);
    }
  }
}

// 랜덤 색상 변경
void random_color() {
  if (random_color_start == true) {
    if (random_pause == false) {
      if (random_k == 0) {
        setNextColorSine();
        for (byte k=0; k<3; k++) colorStep[k] = ((long)nextColor[k] - color[k])/255;
      }
      setRGBpoint((color[0] + colorStep[0] * lights[random_k]) >> 8,
                  (color[1] + colorStep[1] * lights[random_k]) >> 8,
                  (color[2] + colorStep[2] * lights[random_k]) >> 8);
      random_k++;
      random_color_start = false;
      if (random_k == 120) {
        random_k = 0;
        for (byte k=0; k<3; k++) color[k] = nextColor[k];
        setRGBpoint(color[0] >> 8, color[1] >> 8, color[2] >> 8);
        pause_delay = millis();
        random_pause = true;
      }
    }
    if (random_resume == true) {
      count++;
      count %= 3;
      random_resume = false;
    }
  }
}

void random_pause_delay() {
  if (random_pause == true) {
    if (millis() - pause_delay >= pause_duration) {
      random_resume = true;
      random_pause = false;
    }
  }
}

void random_display_delay() {
  if (random_delay_start == true) {
    if (millis() - random_delay >= random_duration) {
      random_delay = millis();
      random_color_start = true;
    }
  }
}

void setNextColorSine() {
  a0 = random(240);
  nextColor[count] = lights[a0] << 8;
  a1 = random(1);
  a2 = ((!a1)+count+1) % 3;
  a1 = (count+a1+1) % 3;
  nextColor[a1] = lights[(a0+100)%240] << 8;
  nextColor[a2] = 0;
}


void rainbow() {
  if (rainbow_start == true) {
    sineLED(rainbow_k);
    rainbow_k++;
    if (rainbow_k == 360) rainbow_k = 0;
    rainbow_start = false;
  }
}

void rainbow_display_delay() {
  if (rainbow_delay_start == true) {
    if (millis() - rainbow_delay >= rainbow_duration) {
      rainbow_delay = millis();
      rainbow_start = true;
    }
  }
}

void sineLED(int angle)  {  // sine wave rainbow
  setRGBpoint(lights[(angle+120)%360], lights[angle],  lights[(angle+240)%360]);
}

void setRGBpoint(uint8_t red, uint8_t green, uint8_t blue) {  
  red_tb = red >> brightness;
  green_tb = green >> brightness;
  blue_tb = blue >> brightness;
  analogWrite(Red, red_tb);
  analogWrite(Green, green_tb);
  analogWrite(Blue, blue_tb);
}

// 사용자 색상 패턴 변경
void rgb_display_auto() {
  if (rgb_change == true) {
    rgb_display();
    color_index++;
    if (color_index == 8) color_index = 0;
    rgb_change = false;
  }
}

void rgb_display_delay() {
  if (rgb_change_start == true) {
    if (millis() - rgb_delay >= auto_duration) {
      rgb_delay = millis();
      rgb_change = true;
    }
  }
}

void rgb_display() {
  red_tb = red_t[color_index] >> brightness;
  green_tb = green_t[color_index] >> brightness;
  blue_tb = blue_t[color_index] >> brightness;
  analogWrite(Red, red_tb);
  analogWrite(Green, green_tb);
  analogWrite(Blue, blue_tb);
}

// 터치 버튼
void cap_button_act() {
  if (cap_button_check == true) {
    if (start_count == false) val = analogRead(capSensePin); // 기준값: 673 ~ 692(3.3V, 10K ohm)
    else  delay_count++; 
    if (delay_count == 0) {
      if(val > 720 || val > 500 && val < 669 ){  // 기준값보다 떨어지는 경우: 500 ~ 670 
        if (button_mode == 1) {
          brightness++;
          if (brightness == 5) brightness = 0;
          btSerial.print("Brightness: "); btSerial.print(brightness);
          EEPROM.write(25, brightness); // eeprom 밝기 저장
          rgb_display();
        }
        else if (button_mode == 2) {
          color_index++;
          if (color_index == 8) color_index = 0;
          EEPROM.write(26, color_index); // eeprom 색상 인덱스 저장
          btSerial.print("Color: "); btSerial.print(color_index);
          rgb_display();
        }
        else if (button_mode == 3) {
          pattern_mode++;
          if (pattern_mode == 1) {
            rgb_change_start = false;
            rainbow_delay_start = true;
            send_pin_echo(70);
            send_pin_echo(81);
            btSerial.print("Rainbow");
          }
          else if (pattern_mode == 2) {
            rainbow_delay_start = false;
            random_delay_start = true;
            send_pin_echo(80);
            send_pin_echo(91);
            btSerial.print("Random Color");
          }
          else if (pattern_mode == 3) {
            pattern_mode = 0;
            rgb_change_start = true;
            random_delay_start = false;
            send_pin_echo(71);
            send_pin_echo(90);
            btSerial.print("Custom Color Loop");
          }
        }
        start_count = true;
      }
    }
    else if (delay_count == 3) {
      start_count = false;
      delay_count = 0;
    }
    cap_button_check = false;
  }
}

void cap_button() {
  if (millis() - cap_button_delay >= 100) {
    cap_button_delay = millis();
    cap_button_check = true;
  }
}

// 일반 버튼
void button_act() {
  button_state = digitalRead(buttonPin);
  if (button_hold == false) {
    if (button_state != pre_button_state) {
      button_hold = true;
      button_delay = millis();
      if (button_state == 0) {
        button_mode ++;
        if (button_mode == 1) {
          rgb_display();
          send_pin_echo(11);
          btSerial.print("Color: "); btSerial.print(color_index);
          btSerial.print(" ");
          btSerial.print("Brightness: "); btSerial.print(brightness);
        }
        else if (button_mode == 2) {
          digitalWrite(ledPin, HIGH);
          btSerial.print("Color Change Mode: "); btSerial.print(color_index);
        }
        else if (button_mode == 3) {
          digitalWrite(ledPin, LOW);
          rgb_change_start = true;
          send_pin_echo(71);
          btSerial.print("Custom Color Loop");
        }
        else if (button_mode == 4) {
          button_mode = 0;
          analogWrite(Red, 0);
          analogWrite(Green, 0);
          analogWrite(Blue, 0);
          rgb_change_start = false;
          color_index = 0;
          rainbow_delay_start = false;
          random_delay_start = false;
          send_pin_echo(10);
          send_pin_echo(70);
          send_pin_echo(80);
          send_pin_echo(90);
          btSerial.print("LED OFF");
        }
      }
      pre_button_state = button_state;
    }
  }
}

void button() {
  if (button_hold == true) {
    if (millis() - button_delay >= 100) {
      button_hold = false;
    }
  }
}

 

 

 

블루투스 앱 설정

https://play.google.com/store/apps/details?id=com.appybuilder.arduino_appy.arduino_BT_controller_PWM

 

상기 앱을 설치하고 버튼을 클릭하면 아래와 같은 메시지가 출력된다.

블루투스가 연결이 되지 않은 상태에서 블루투스로 데이터를 전송하려고 시도하면 표시되는 메시지이다. 블루투스 연결 전에 앱을 설정할 것이므로 "Stop"을 클릭하여 더 이상 메시지가 표시되지 않도록 해준다. 

 

아래 그림처럼 화면 표시 설정 아이콘을 클릭한 다음 버튼 라벨을 변경해준다.

버튼 속성 설정 아이콘을 클릭하고 아래 그림처럼 버튼 속성을 설정해준다.

아두이노 아이콘을 클릭하면 아래 그림처럼 버튼의 라벨이 변경된 것을 확인할 수 있다. 

우측의 블루투스 아이콘을 클릭하여 블루투스 연결화면으로 이동한다.

블루투스가 연결되면 최초 1회 날짜 및 시간 정보를 전송하는 기능을 사용하기 위해 Send Date/Time 체크박스에 체크를 해준다. 아두이노의 블루투스 모듈이 HC-06이라면 Bluetooth 2.0을 선택한 상태에서 Bluetooth 버튼을 클릭하여 연결해주고 AT-09와 같은 블루투스 4.0 BLE 모듈이라면 Bluetooth 4.0으로 변경해준 상태에서 Bluetooth 버튼을 클릭하고 연결을 해준다. 연결이 되면 블루투스를 이용하여 무드등을 원격 제어할 수 있다.

PWM으로 새로운 사용자 색상을 저장할 때 Color Picker를 이용할 수 있다. 

아래 그림처럼 화면 표시 설정에 들어가서 Color Picker 체크박스에 체크 박스를 해주고 메인 화면으로 이동하면 칼라 서클에서 원하는 색상을 터치하여 RGB 슬라이드 값을 변경 시 킬 수 있다.

Color Picker를 이용할 때 우측 아래 화살표 아이콘을 클릭하고 플로팅 버튼 13번을 터치하면 색상값을 저장할 수 있다.

아래 영상 5분 34초 에서 Color Picker를 이용하여 RGB LED를 제어하는 것을 볼수 있다. 

 

 

 

최신 업데이트 유료앱(모든 안드로이드 버전 블루투스 연결 지원)

https://postpop.tistory.com/175

 

ADUCON - Arduino wireless remote control application

Arduino remote control app using a wireless module available in Arduino. Bluetooth 2.0 Classic / 4.0 BLE : HC-05, HC-06, HM-10, AT-09, BT05, ESP32, etc. Wi-Fi : ESP01, ESP8266 NodeMcu, ESP32, etc. https://play.google.com/store/apps/details?id=com.tistory.p

postpop.tistory.com

 

 

관련 글

[arduino] - 아두이노 - 입력 버튼 설정 방법, debouncing

[arduino] - 아두이노 - ADC 핀을 이용한 터치 센서의 구현

[arduino] - 아두이노 - 무드등 예제, RGB LED 제어

[arduino] - 아두이노 - 무드등, 블루투스 연결 스마트폰 원격제어

 

arduino bluetooth controller PWM - 아두이노 원격제어 안드로이드 앱 버전 3.5 다운로드

arduino bluetooth controller PWM 매뉴얼

 

 

 

반응형

+ Recent posts