arduino

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

SmartPop 2019. 8. 30. 04:54

arduino bluetooth controller PWM v3.5

안드로이드 버전업에 따라 안드로이드 특정버전에서만 와이이파이 및 블루투스 연결이 가능합니다. 

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

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

 

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

플레이 스토어에서 "아두이노 pwm"이나 "arduino pwm"을 검색하시면 빠르게 찾을 수 있습니다.

 

특징

- Bluetooth 2.0 / Bluetooth 4.0 BLE 연결 : HC-05, HC-06, HM-10, AT-09, BT05 

- ESP8266 NodeMcu 와이파이 / ESP32 Bluetooth 2.0, BLE, 와이파이 연결 가능 

- 디지털 버튼 12개 : 토글 및 푸쉬 버튼 속성 설정 기능

- 아날로그 콘트롤러 3개(PWM) : Min 및 Max 값 설정 기능

  RGB LED 제어용 Color Picker 모드

  PWM 제어용 디지털 노브 모드

- 텍스트 입력 기능 및 전송 옵션 설정 기능(NO-없음, NL-새 줄, CR-캐리지 리턴, BOTH-캐리지 리턴+새 줄)

- 표시 설정 화면: 

  메인화면의 버튼 및 PWM 슬라이드 표시 설정

  버튼 라벨 사용자 지정 기능

  라벨 외부 파일 저장 기능:  /arduino_BT_button_label.txt 

- 통신 연결 시 안드로이드 시스템 날짜 및 시간 자동 전송 기능

- 플로팅 버튼

  푸시버튼 4개(13, 14, 15, 16) 

  안드로이드 시스템 날짜 및 시간 수동 전송 버튼

  시간 설정값 전송 버튼

 

메인화면

 

표시 설정 화면

 

버튼 속성 설정 화면

 

연결 옵션 설정

 

Send Date/Time : 통신 연결 시 안드로이드 시스템의 현재 날짜 및 시간을 1회만 전송합니다.

SERVICE UUID : Bluetooth 4.0 BLE의 Custom UUID를 설정할 수 있습니다. 

Wifi PWM / Bluetooth PWM : PWM 제어를 위한 데이터 전송 간격, 단위-밀리초

                                                         값이 클수록 배터리 소모를 줄일 수 있지만 아두이노의 응답은 느려집니다. 

                                                         값이 너무 작으면 아두이노 및 모듈의 성능에 따라 리셋될 수 있습니다. 

Read data from arduino : 체크 해제 시 아두이노로부터 오는 데이터를 받지 않습니다.

                                                   (Bluetooth 2.0 Classic, Wifi 연결 시)

                                                   배터리 소모를 줄일 수 있습니다.

Reading Interval : Read data from arduino가 체크된 상태에서 데이터를 읽어오는 간격을 설정합니다. 

                                    값이 클수록 배터리 소모를 줄일 수 있지만 데이터 수신에 대한 표시는 느려집니다. 

 

- Bluetooth 접속 :

블루투스 아이콘 클릭 -> Bluetooth 2.0 / Bluetooth 4.0 BLE 선택 -> Bluetooth 버튼 클릭 -> 모듈 선택

   

- 와이파이 연결 : 와이파이 아이콘 클릭 -> Soft AP 접속 및 확인 -> Soft IP 주소 입력 -> Confirm 클릭

 

- 제어용 PROTOCOL

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

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

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

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

    Alarm: 0xF9 + 21:20(String) + \n(새 줄)

더보기
uint8_t pin_a[3] = {0, };
uint8_t pwm_a[5] = {0, };

void btSerial_read() {
  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');
        Serial.println(temp);
      }
      else if (btSerial.peek() == 0xF9) {
        String temp = btSerial.readStringUntil('\n');
        Serial.println(temp);
      } 
      else {
        general_use();  // 텍스트 출력함수
      }
    }
  }
}

 

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

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

    PWM echo(pwm 값 확인) : 0xF3+1byte number+2byte number+0xF1

    PWM slide(슬라이드 위치 변경):  0xF4 + 1byte number + 2byte 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++) {
    SerialBT.write(pin_echo[i]);
  }
}

uint8_t pwm_echo[] = {0xF3, 0, 0, 0, 0xF1};

void send_pwm_echo(uint8_t slide, uint16_t pwm_val) {
  pwm_echo[1] = slide;
  if (pwm1 < 256) {
    pwm_echo[2] = pwm_val;
    pwm_echo[3] = 0;
  }
  else {
    pwm_echo[2] = pwm_val;
    pwm_echo[3] = pwm_val >> 8;
  }
  for (int i = 0; i < 5; i++) {
    SerialBT.write(pwm_echo[i]);
  }
}

uint8_t pwm_slide[] = {0xF4, 0, 0, 0, 0xF1};

void send_pwm_slide(uint8_t slide, uint16_t pwm_val) {
  pwm_slide[1] = slide;
  if (pwm1 < 256) {
    pwm_slide[2] = pwm_val;
    pwm_slide[3] = 0;
  }
  else {
    pwm_slide[2] = pwm_val;
    pwm_slide[3] = pwm_val >> 8;
  }
  for (int i = 0; i < 5; i++) {
    SerialBT.write(pwm_slide[i]);
  }
}

 

2. 와이파이 : 앱 송신 -> 아두이노 수신

    디지털 버튼: %%F0 + 1byte number + %%F1

    PWM1 : %%F31 + String + %%F1

    PWM2 : %%F32 + String + %%F1

    PWM3 : %%F33 + String + %%F1

    Date / Time: %%F8 + 07/24/2019 + %7C + 15:55:32 + \n(새 줄)

    Alarm: %%F9 + 21:20 + \n(새 줄)

    아두이노 응답 요청: %%F5

더보기
void wifi_read() { // wifi 데이터 수신
  client = server.available(); // 서버가 작동하고 있으면 client 생성
  if(client.available()) {     // 클라이언트에 데이터가 있으면
    income_wifi = client.readStringUntil('\r');
    if (income_wifi.indexOf("%%F1") != -1) {          // 종료문자가 있으면
      if (income_wifi.indexOf("%%F0") != -1) {        // 디지털 핀 값 수신
        String wifi_temp = income_wifi.substring(income_wifi.indexOf("%%F0")+4, income_wifi.indexOf("%%F1"));
        pin_val = wifi_temp.toInt();
        pin_control();
      }
      else if (income_wifi.indexOf("%%F31") != -1) {  // 슬라이드1, PWM 값 수신
        String wifi_temp = income_wifi.substring(income_wifi.indexOf("%%F31")+5, income_wifi.indexOf("%%F1"));
        pwm1 = wifi_temp.toInt();
        Serial.print("pwm1: "); Serial.println(pwm1);
      }
      else if (income_wifi.indexOf("%%F32") != -1) {  // 슬라이드2, PWM 값 수신 
        String wifi_temp = income_wifi.substring(income_wifi.indexOf("%%F32")+5, income_wifi.indexOf("%%F1"));
        pwm2 = wifi_temp.toInt();
        Serial.print("pwm2: "); Serial.println(pwm2);
      }
      else if (income_wifi.indexOf("%%F33") != -1) {  // 슬라이드3, PWM 값 수신
        String wifi_temp = income_wifi.substring(income_wifi.indexOf("%%F33")+5, income_wifi.indexOf("%%F1"));
        pwm3 = wifi_temp.toInt();
        Serial.print("pwm3: "); Serial.println(pwm3); 
      }
    }
    else if (income_wifi.indexOf("%%F5") != -1) { // 스케쥴 접속확인 응답, 텍스트 및 로컬값 전송
      client.println("HTTP/1.1 200 OK\r\n");      // 스케쥴 웹요청시 응답 헤더 "%%F5"
      if (send_pin != "") {                       // 전송할 핀 상태 값이 있으면 "/ HTTP/1.1"
        client.print(send_pin); 
        send_pin = "";
      }
      if (send_Pwm_echo != "") {                  // 전송할 PWM 상태(echo) 값이 있으면
        client.print(send_Pwm_echo);
        send_Pwm_echo = "";
      }
      if (send_Pwm_slide != "") {                 // 전송할 PWM 슬라이브 바 상태 값이 있으면
        client.print(send_Pwm_slide);
        send_Pwm_slide = "";
      }
      if (send_text != "") {                      // 전송할 텍스트가 있으면
        client.print(send_text);
        send_text = "";
      }
    }
    else{
      if (income_wifi.indexOf("%%F8") != -1) {  // 날짜 및 시간 정보 수신
        String wifi_temp = income_wifi.substring(income_wifi.indexOf("%%F8")+4, income_wifi.indexOf("\n"));
        Serial.print("Date/Time: "); Serial.println(wifi_temp); 
      }
      else if (income_wifi.indexOf("%%F9") != -1) {  // 알람 설정값 수신
        String wifi_temp = income_wifi.substring(income_wifi.indexOf("%%F9")+4, income_wifi.indexOf("\n"));
        Serial.print("Alarm set: "); Serial.println(wifi_temp); 
      }
      else {  // 텍스트 시리얼 출력
        String wifi_temp = income_wifi.substring(income_wifi.indexOf("GET /")+5, income_wifi.indexOf("HTTP/1.1")-1);
        if (wifi_temp.indexOf("%20") != -1) { // 웹브라우저 공백문자 %20을 공백문자로 변경
          String space = "%20";
          String space_convert = " ";
          wifi_temp.replace(space, space_convert);
        }
        Serial.println(wifi_temp);
      }
    }
    income_wifi = "";
  }
}

 

3. 와이파이: 아두이노 송신 -> 앱 수신

    디지털 버튼: %%F0 + 스트링 값 + %%P1

    PWM1 echo(pwm 값 확인): %%F31 + String + %%E1

    PWM2 echo(pwm 값 확인): %%F32 + String + %%E1

    PWM3 echo(pwm 값 확인): %%F33 + String + %%E1

    PWM1 slide(슬라이드 위치 변경): %%F41 + String + %%S1

    PWM2 slide(슬라이드 위치 변경): %%F42 + String + %%S1

    PWM3 slide(슬라이드 위치 변경): %%F43 + String + %%S1

더보기
String send_pin = "";
String send_Pwm_echo = "";
String send_Pwm_slide = "";

void send_pin_echo(uint8_t pin_val){  // 디지털 버튼 상태값 전송
  String s_temp ="";
  s_temp += "%%F0";
  s_temp += pin_val;
  s_temp += "%%P1";
  if (client.connected())  client.print(s_temp); // 사용자 웹요청 응답
  else  send_pin = s_temp;                       // 스케쥴 웹요청 응답
}

void send_pwm_echo(uint8_t slide, uint16_t pwm_val) { // PWM값 echo 전송
  String s_temp ="";                                  
  s_temp += "%%F3";
  s_temp += slide;
  s_temp += pwm_val;
  s_temp += "%%E1";
  if (client.connected())  client.print(s_temp); // 사용자 웹요청 응답
  else  send_Pwm_echo = s_temp;                  // 스케쥴 웹요청 응답
}

void send_pwm_slide(uint8_t slide, uint16_t pwm_val) { // 슬라이더 상태값 전송
  String s_temp ="";
  s_temp += "%%F4";
  s_temp += slide;
  s_temp += pwm_val;
  s_temp += "%%S1";
  if (client.connected())  client.print(s_temp); // 사용자 웹요청 응답
  else  send_Pwm_slide = s_temp;                 // 스케쥴 웹요청 응답
}

 

4. 디지털 버튼 1byte number 값 (토글 버튼 on/off, 푸시버튼 down/up)

    Button1 on: 11, off: 10 또는 down: 11, up: 10

    Button2 on: 21, off: 20 또는 down: 21, up: 20 

    .

    .

    .

    Button12 on: 121, off: 120 또는 down: 121, up: 120

    Button13 down: 131, up: 130

    Button14 down: 141, up: 140

    Button15 down: 151, up: 150

    Button16 down: 161, up: 160

 

5. PWM 1byte number 값: slide 번호

    PWM 2byte number 값: PWM 값

 

- RGB LED 제어용 Color Picker 모드

  색상 휠 상의 점을 드래그하거나 색상 휠의 특정 지점을 터치하면 그때의 색상 RGB 값을 송신하여 LED 제어

  PWM 최대 최솟값 강제 고정: 0 ~ 255

  PWM 라벨 강제 고정: Red / Green / Blue

- PWM 디지털 노브 모드 

  디지털 노브를 이용하여 PWM의 제어를 더 편하게 할 수 있습니다. 

  우측 1/2/3 버튼: 슬라이드 선택 버튼

  좌측 + - 버튼: 미세조정 및 길게 누를 경우 빠르게 이동

 

- 아두이노 + 통신 모듈(HC-06 블루투스 2.0 CLASSIC / AT-09 블루투스 4.0 BLE)

arduino_uart_full.ino
0.01MB

 

더보기
#include <SoftwareSerial.h> 
#define BT_rxPin 3 // Bluetooth RX -> 3(arduino TX)
#define BT_txPin 2 // Bluetooth TX -> 2(arduino RX)
SoftwareSerial btSerial(BT_txPin, BT_rxPin); // (arduino RX, arduino TX)

String s =""; // 시리얼 모니터 텍스트 제어용 변수

// 블루투스 앱 디지털 핀 제어용 변수
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};
uint8_t pwm_echo[] = {0xF3, 0, 0, 0, 0xF1};
uint8_t pwm_slide[] = {0xF4, 0, 0, 0, 0xF1};

void setup() {
  Serial.begin(9600);
  btSerial.begin(9600); //Bluetooth 
}

void loop() {
  btSerial_read(); // 블루투스 시리얼 읽기 함수
  if(Serial.available()) { // 시리얼 버퍼에 데이터 있으면
    char c = Serial.read();  
    if(c != '\n') {
      s += c;
    } else {
      if(s == "on"){ // 시리얼 모니터 제어 led on
        Serial.println("LED ON");
        send_pin_echo(11); // 블루투스 앱 버튼 상태: on
        btSerial.print("LED ON");
        s = "";  
      }
      else if(s == "off"){ // 시리얼 모니터 제어 led off 
        Serial.println("LED OFF"); 
        send_pin_echo(10); // 블루투스 앱 버튼 상태: off
        btSerial.print("LED OFF");  
        s = "";
      }
      else {
        btSerial.println(s); 
        s = "";
      }
    }
  }
}

void general_use() { 
  char text = btSerial.read();  // text value for some purpose.
  Serial.write(text);      // print text to Serial Monitor
}

void pin_control() {
  pin_val = pin_a[1];
  if (pin_val != 0) {
    switch (pin_val) {
      case 11: Serial.println("button 1 : on"); 
                  break;
      case 10: Serial.println("button 1 : off");
                  break;
      case 21: Serial.println("button 2 : on");
               send_pin_echo(pin_val); // 버튼 상태 echo 
                  break;
      case 20: Serial.println("button 2 : off");
               send_pin_echo(pin_val); // 버튼 상태 echo 
                  break;
      case 31: Serial.println("button 3 : on");
                  break;
      case 30: Serial.println("button 3 : off");
                  break;
      case 41: Serial.println("button 4 : on");
                  break;
      case 40: Serial.println("button 4 : off");
                  break;
      case 51: Serial.println("button 5 : on");
                  break;
      case 50: Serial.println("button 5 : off");
                  break;
      case 61: Serial.println("button 6 : on");
                  break;
      case 60: Serial.println("button 6 : off");
                  break;
      case 71: Serial.println("button 7 : on");
                  break;
      case 70: Serial.println("button 7 : off");
                  break;
      case 81: Serial.println("button 8 : on");
                  break;
      case 80: Serial.println("button 8 : off");
                  break;
      case 91: Serial.println("button 9 : on");
                  break;
      case 90: Serial.println("button 9 : off");
                  break;  
      case 101: Serial.println("button 10 : on");
                  break;
      case 100: Serial.println("button 10 : off");
                  break;  
      case 111: Serial.println("button 11 : on");
                  break;
      case 110: Serial.println("button 11 : off");
                  break;  
      case 121: Serial.println("button 12 : on");
                  break;
      case 120: Serial.println("button 12 : off");
                  break;  
    }
  pin_val = 0;
  }
}

void pwm_control() {
  uint16_t temp = pwm_a[3];
  temp = temp << 8 | pwm_a[2];
  if (pwm_a[1] == 1) {  // 슬라이드 1번
    pwm1 = temp;
//    send_pwm_echo(1, pwm1); // PWM 값 echo
    Serial.print("pwm1: "); Serial.println(pwm1);
  }
  else if (pwm_a[1] == 2) { // 슬라이드 2번
    pwm2 = temp;
    Serial.print("pwm2: "); Serial.println(pwm2);
  }
  else if (pwm_a[1] == 3) {  // 슬라이드 3번
    pwm3 = temp;
    Serial.print("pwm3: "); Serial.println(pwm3);
  }
}

void btSerial_read() {
  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');
        Serial.println(temp);
      }
      else if (btSerial.peek() == 0xF9) {
        String temp = btSerial.readStringUntil('\n');
        Serial.println(temp);
      } 
      else {
        general_use();  // 텍스트 출력함수
      }
    }
  }
}

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 send_pwm_echo(uint8_t slide, uint16_t pwm_val) {
  pwm_echo[1] = slide;
  if (pwm_val < 256) {
    pwm_echo[2] = pwm_val;
    pwm_echo[3] = 0;
  }
  else {
    pwm_echo[2] = pwm_val;
    pwm_echo[3] = pwm_val >> 8;
  }
  for (int i = 0; i < 5; i++) {
    btSerial.write(pwm_echo[i]);
  }
}

void send_pwm_slide(uint8_t slide, uint16_t pwm_val) {
  pwm_slide[1] = slide;
  if (pwm_val < 256) {
    pwm_slide[2] = pwm_val;
    pwm_slide[3] = 0;
  }
  else {
    pwm_slide[2] = pwm_val;
    pwm_slide[3] = pwm_val >> 8;
  }
  for (int i = 0; i < 5; i++) {
    btSerial.write(pwm_slide[i]);
  }
}

 

- ESP8266, NodeMcu wifi_Soft_AP

arduino_remote_control_esp8266.ino
0.01MB

더보기
#include <ESP8266WiFi.h>
#define AP_SSID  "Esp12"
#define AP_PASS  "1234test"

String s =""; // 시리얼 모니터 텍스트 제어용 변수

// 디지털 핀 제어용 변수
uint8_t pin_val = 0;

// PWM 제어용 변수
uint16_t pwm1 = 0;  
uint16_t pwm2 = 0;  
uint16_t pwm3 = 0;  

String income_wifi = ""; // 와이파이 수신 스트링 저장 변수

// 웹요청 응답용 변수
String send_pin = "";
String send_Pwm_echo = "";
String send_Pwm_slide = "";
String send_text = "";

WiFiServer server(80);
WiFiClient client;

void setup() {
  Serial.begin(115200);
  WiFi.softAP(AP_SSID, AP_PASS);  // WiFi.softAP(ssid, password);
  IPAddress myIP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(myIP);
  server.begin();
}

void loop() {
  wifi_delay(); // 와이파이 데이터 읽기
  if (Serial.available()) {   
    char c = Serial.read();  
    if(c != '\n') {
      s += c;
    } else {
      if(s == "on"){ // 시리얼 모니터 제어 led on
        Serial.println("LED_ON");
        send_pin_echo(11);        // 스케쥴 웹요청 응답, 블루투스 앱 버튼 상태: on
        send_text = "LED ON";     // 스케쥴 웹요청 응답
        s = "";  
      }
      else if(s == "off"){ // 시리얼 모니터 제어 led off 
        Serial.println("LED_OFF");
        send_pin_echo(10);        // 스케쥴 웹요청 응답, 블루투스 앱 버튼 상태: off
        send_text = "LED OFF";    // 스케쥴 웹요청 응답
        s = "";
      }
      else {
        send_text = s;  // 스케쥴 웹요청시 응답변수에 저장
        s = "";
      }
    }      
  }
}

void pin_control() {
  if (pin_val != 0) {
    switch (pin_val) {
      case 11: Serial.println("button 1 : on"); // button 1 : on
               client.println("HTTP/1.1 200 OK\r\n"); // 사용자 웹요청시 응답 헤더
               send_pin_echo(pin_val);
               client.print("LED_ON_11"); 
                  break;
      case 10: Serial.println("button 1 : off"); // button 1 : off
               client.println("HTTP/1.1 200 OK\r\n"); // 사용자 웹요청시 응답 헤더
               send_pin_echo(pin_val);
               client.print("LED_ON_10");
                  break;
      case 21: Serial.println("button 2 : on");
                  break;
      case 20: Serial.println("button 2 : off");
                  break;
      case 31: Serial.println("button 3 : on");
                  break;
      case 30: Serial.println("button 3 : off");
                  break;
      case 41: Serial.println("button 4 : on");
                  break;
      case 40: Serial.println("button 4 : off");
                  break;
      case 51: Serial.println("button 5 : on");
                  break;
      case 50: Serial.println("button 5 : off");
                  break;
      case 61: Serial.println("button 6 : on");
                  break;
      case 60: Serial.println("button 6 : off");
                  break;
      case 71: Serial.println("button 7 : on");
                  break;
      case 70: Serial.println("button 7 : off");
                  break;
      case 81: Serial.println("button 8 : on");
                  break;
      case 80: Serial.println("button 8 : off");
                  break;
      case 91: Serial.println("button 9 : on");
                  break;
      case 90: Serial.println("button 9 : off");
                  break;  
      case 101: Serial.println("button 10 : on");
                  break;
      case 100: Serial.println("button 10 : off");
                  break;  
      case 111: Serial.println("button 11 : on");
                  break;
      case 110: Serial.println("button 11 : off");
                  break;  
      case 121: Serial.println("button 12 : on");
                  break;
      case 120: Serial.println("button 12 : off");
                  break;  
    }
  pin_val = 0;
  }
}

unsigned long int one_millis = 0;

void wifi_delay() { // 30 밀리초 마다 client 연결 확인 및 데이터 수신
  if (millis() - one_millis > 30) {
    one_millis = millis();
    wifi_read();
  }
}

void wifi_read() { // wifi 데이터 수신
  client = server.available(); // 서버가 작동하고 있으면 client 생성
  if(client.available()) {     // 클라이언트에 데이터가 있으면
    income_wifi = client.readStringUntil('\r');
    if (income_wifi.indexOf("%%F1") != -1) {          // 종료문자가 있으면
      if (income_wifi.indexOf("%%F0") != -1) {        // 디지털 핀 값 수신
        String wifi_temp = income_wifi.substring(income_wifi.indexOf("%%F0")+4, income_wifi.indexOf("%%F1"));
        pin_val = wifi_temp.toInt();
        pin_control();
      }
      else if (income_wifi.indexOf("%%F31") != -1) {  // 슬라이드1, PWM 값 수신
        String wifi_temp = income_wifi.substring(income_wifi.indexOf("%%F31")+5, income_wifi.indexOf("%%F1"));
        pwm1 = wifi_temp.toInt();
        Serial.print("pwm1: "); Serial.println(pwm1);
      }
      else if (income_wifi.indexOf("%%F32") != -1) {  // 슬라이드2, PWM 값 수신 
        String wifi_temp = income_wifi.substring(income_wifi.indexOf("%%F32")+5, income_wifi.indexOf("%%F1"));
        pwm2 = wifi_temp.toInt();
        Serial.print("pwm2: "); Serial.println(pwm2);
      }
      else if (income_wifi.indexOf("%%F33") != -1) {  // 슬라이드3, PWM 값 수신
        String wifi_temp = income_wifi.substring(income_wifi.indexOf("%%F33")+5, income_wifi.indexOf("%%F1"));
        pwm3 = wifi_temp.toInt();
        Serial.print("pwm3: "); Serial.println(pwm3); 
      }
    }
    else if (income_wifi.indexOf("%%F5") != -1) { // 스케쥴 접속확인 응답, 텍스트 및 로컬값 전송
      client.println("HTTP/1.1 200 OK\r\n");      // 스케쥴 웹요청시 응답 헤더 "%%F5"
      if (send_pin != "") {                       // 전송할 핀 상태 값이 있으면 "/ HTTP/1.1"
        client.print(send_pin); 
        send_pin = "";
      }
      if (send_Pwm_echo != "") {                  // 전송할 PWM 상태(echo) 값이 있으면
        client.print(send_Pwm_echo);
        send_Pwm_echo = "";
      }
      if (send_Pwm_slide != "") {                 // 전송할 PWM 슬라이브 바 상태 값이 있으면
        client.print(send_Pwm_slide);
        send_Pwm_slide = "";
      }
      if (send_text != "") {                      // 전송할 텍스트가 있으면
        client.print(send_text);
        send_text = "";
      }
    }
    else{
      if (income_wifi.indexOf("%%F8") != -1) {  // 슬라이드3, PWM 값 수신
        String wifi_temp = income_wifi.substring(income_wifi.indexOf("%%F8")+4, income_wifi.indexOf("\n"));
        Serial.print("Date/Time: "); Serial.println(wifi_temp); 
      }
      else if (income_wifi.indexOf("%%F9") != -1) {  // 슬라이드3, PWM 값 수신
        String wifi_temp = income_wifi.substring(income_wifi.indexOf("%%F9")+4, income_wifi.indexOf("\n"));
        Serial.print("Alarm set: "); Serial.println(wifi_temp); 
      }
      else {  // 텍스트 시리얼 출력
        String wifi_temp = income_wifi.substring(income_wifi.indexOf("GET /")+5, income_wifi.indexOf("HTTP/1.1")-1);
        if (wifi_temp.indexOf("%20") != -1) { // 웹브라우저 공백문자 %20을 공백문자로 변경
          String space = "%20";
          String space_convert = " ";
          wifi_temp.replace(space, space_convert);
        }
        Serial.println(wifi_temp);
      }
    }
    income_wifi = "";
  }
}

void send_pin_echo(uint8_t pin_val){  // 디지털 버튼 상태값 전송
  String s_temp ="";
  s_temp += "%%F0";
  s_temp += pin_val;
  s_temp += "%%P1";
  if (client.connected())  client.print(s_temp); // 사용자 웹요청 응답
  else  send_pin = s_temp;                       // 스케쥴 웹요청 응답
}

void send_pwm_echo(uint8_t slide, uint16_t pwm_val) { // PWM값 echo 전송
  String s_temp ="";                                  
  s_temp += "%%F3";
  s_temp += slide;
  s_temp += pwm_val;
  s_temp += "%%E1";
  if (client.connected())  client.print(s_temp); // 사용자 웹요청 응답
  else  send_Pwm_echo = s_temp;                  // 스케쥴 웹요청 응답
}

void send_pwm_slide(uint8_t slide, uint16_t pwm_val) { // 슬라이더 상태값 전송
  String s_temp ="";
  s_temp += "%%F4";
  s_temp += slide;
  s_temp += pwm_val;
  s_temp += "%%S1";
  if (client.connected())  client.print(s_temp); // 사용자 웹요청 응답
  else  send_Pwm_slide = s_temp;                 // 스케쥴 웹요청 응답
}

 

- ESP32 DevKit Blutooth 2.0

esp32_BT_uart_full.ino
0.01MB

더보기
#include "BluetoothSerial.h"
BluetoothSerial SerialBT;

String s =""; // 시리얼 모니터 텍스트 제어용 변수

// 블루투스 앱 디지털 핀 제어용 변수
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};
uint8_t pwm_echo[] = {0xF3, 0, 0, 0, 0xF1};
uint8_t pwm_slide[] = {0xF4, 0, 0, 0, 0xF1};

void setup() {
  Serial.begin(115200);
  SerialBT.begin("ESP32test"); //Bluetooth device name
}

void loop() {
  SerialBT_read(); // 블루투스 시리얼 읽기 함수
  if(Serial.available()) { // 시리얼 버퍼에 데이터 있으면
    char c = Serial.read();  
    if(c != '\n') {
      s += c;
    } else {
      if(s == "on"){ // 시리얼 모니터 제어 led on
        Serial.println("LED ON");
        send_pin_echo(11); // 블루투스 앱 버튼 상태: on
        SerialBT.print("LED ON");
        s = "";  
      }
      else if(s == "off"){ // 시리얼 모니터 제어 led off 
        Serial.println("LED OFF"); 
        send_pin_echo(10); // 블루투스 앱 버튼 상태: off
        SerialBT.print("LED OFF");  
        s = "";
      }
      else {
        SerialBT.println(s); 
        s = "";
      }
    }
  }
}

void general_use() { 
  char text = SerialBT.read();  // text value for some purpose.
  Serial.write(text);      // print text to Serial Monitor
}

void pin_control() {
  pin_val = pin_a[1];
  if (pin_val != 0) {
    switch (pin_val) {
      case 11: Serial.println("button 1 : on"); 
                  break;
      case 10: Serial.println("button 1 : off");
                  break;
      case 21: Serial.println("button 2 : on");
               send_pin_echo(pin_val); // 버튼 상태 echo 
                  break;
      case 20: Serial.println("button 2 : off");
               send_pin_echo(pin_val); // 버튼 상태 echo 
                  break;
      case 31: Serial.println("button 3 : on");
                  break;
      case 30: Serial.println("button 3 : off");
                  break;
      case 41: Serial.println("button 4 : on");
                  break;
      case 40: Serial.println("button 4 : off");
                  break;
      case 51: Serial.println("button 5 : on");
                  break;
      case 50: Serial.println("button 5 : off");
                  break;
      case 61: Serial.println("button 6 : on");
                  break;
      case 60: Serial.println("button 6 : off");
                  break;
      case 71: Serial.println("button 7 : on");
                  break;
      case 70: Serial.println("button 7 : off");
                  break;
      case 81: Serial.println("button 8 : on");
                  break;
      case 80: Serial.println("button 8 : off");
                  break;
      case 91: Serial.println("button 9 : on");
                  break;
      case 90: Serial.println("button 9 : off");
                  break;  
      case 101: Serial.println("button 10 : on");
                  break;
      case 100: Serial.println("button 10 : off");
                  break;  
      case 111: Serial.println("button 11 : on");
                  break;
      case 110: Serial.println("button 11 : off");
                  break;  
      case 121: Serial.println("button 12 : on");
                  break;
      case 120: Serial.println("button 12 : off");
                  break;  
    }
  pin_val = 0;
  }
}

void pwm_control() {
  uint16_t temp = pwm_a[3];
  temp = temp << 8 | pwm_a[2];
  if (pwm_a[1] == 1) {  // 슬라이드 1번
    pwm1 = temp;
//    send_pwm_echo(1, pwm1); // PWM 값 echo
    Serial.print("pwm1: "); Serial.println(pwm1);
  }
  else if (pwm_a[1] == 2) { // 슬라이드 2번
    pwm2 = temp;
    Serial.print("pwm2: "); Serial.println(pwm2);
  }
  else if (pwm_a[1] == 3) {  // 슬라이드 3번
    pwm3 = temp;
    Serial.print("pwm3: "); Serial.println(pwm3);
  }
}

void SerialBT_read() {
  if (SerialBT.available()) {  
    if (SerialBT.peek() == 0xF3) get_pwm_val = true; 
    else if (SerialBT.peek() == 0xF0) get_pin_val = true; 
    if (get_pwm_val == true ) { // pwm 제어값 수신
      uint8_t temp = SerialBT.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 = SerialBT.read();
      pin_a[pin_count] = temp;
      pin_count++;
      if (temp == 0xF1) {
        get_pin_val = false;
        pin_count = 0;
        pin_control();
      }
    }
    else {
      if (SerialBT.peek() == 0xF8) {
        String temp = SerialBT.readStringUntil('\n');
        Serial.println(temp);
      }
      else if (SerialBT.peek() == 0xF9) {
        String temp = SerialBT.readStringUntil('\n');
        Serial.println(temp);
      } 
      else {
        general_use();  // 텍스트 출력함수
      }
    }
  }
}

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

void send_pwm_echo(uint8_t slide, uint16_t pwm_val) {
  pwm_echo[1] = slide;
  if (pwm_val < 256) {
    pwm_echo[2] = pwm_val;
    pwm_echo[3] = 0;
  }
  else {
    pwm_echo[2] = pwm_val;
    pwm_echo[3] = pwm_val >> 8;
  }
  for (int i = 0; i < 5; i++) {
    SerialBT.write(pwm_echo[i]);
  }
}

void send_pwm_slide(uint8_t slide, uint16_t pwm_val) {
  pwm_slide[1] = slide;
  if (pwm_val < 256) {
    pwm_slide[2] = pwm_val;
    pwm_slide[3] = 0;
  }
  else {
    pwm_slide[2] = pwm_val;
    pwm_slide[3] = pwm_val >> 8;
  }
  for (int i = 0; i < 5; i++) {
    SerialBT.write(pwm_slide[i]);
  }
}

 

- ESP32 DevKit Blutooth 4.0 BLE

esp32_ble_uart_full.ino
0.01MB

더보기
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>

BLEServer *pServer = NULL;
BLECharacteristic * pTxCharacteristic;
bool deviceConnected = false;
bool rx_received = false;      // BLE 수신시 함수 실행 플래그
std::string rxValue; // BLE 클래스 수신 데이터 값 전역변수 설정

#define SERVICE_UUID           "0000FFE0-0000-1000-8000-00805F9B34FB" // UART service UUID
#define CHARACTERISTIC_UUID_RX "0000FFE1-0000-1000-8000-00805F9B34FB"
#define CHARACTERISTIC_UUID_TX "0000FFE2-0000-1000-8000-00805F9B34FB"

String s =""; // 시리얼 모니터 텍스트 제어용 변수

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

// 블루투스 앱 PWM 제어용 변수
bool get_pwm_val = false;
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};
uint8_t pwm_echo[] = {0xF3, 0, 0, 0, 0xF1};
uint8_t pwm_slide[] = {0xF4, 0, 0, 0, 0xF1};

bool date_time = false;
bool alarm_set = false;

class MyServerCallbacks: public BLEServerCallbacks {
  void onConnect(BLEServer* pServer) {
    deviceConnected = true;
  };
  void onDisconnect(BLEServer* pServer) {
    deviceConnected = false;
    pServer->getAdvertising()->start();
  }
};

class MyCallbacks: public BLECharacteristicCallbacks {
  void onWrite(BLECharacteristic *pCharacteristic) {
    rxValue = pCharacteristic->getValue();
//    if (rxValue.length() > 0) {
//      for (int i = 0; i < rxValue.length(); i++) {
//        Serial.print(i); Serial.print(": "); Serial.println(rxValue[i], HEX);
//      }
//    }
    rx_received = true;
  }
};

void setup() {
  Serial.begin(115200);
  BLEDevice::init("ESP32 BLE");  // Create the BLE Device
  pServer = BLEDevice::createServer();  // Create the BLE Server
  pServer->setCallbacks(new MyServerCallbacks());
  BLEService *pService = pServer->createService(SERVICE_UUID);  // Create the BLE Service
  pTxCharacteristic = pService->createCharacteristic (  // Create a BLE Characteristic
                      CHARACTERISTIC_UUID_TX,
                      BLECharacteristic::PROPERTY_NOTIFY
                    );
  pTxCharacteristic->addDescriptor(new BLE2902());
  BLECharacteristic * pRxCharacteristic = pService->createCharacteristic (
                                          CHARACTERISTIC_UUID_RX,
                                          BLECharacteristic::PROPERTY_WRITE
                                        );
  pRxCharacteristic->setCallbacks(new MyCallbacks());
  pService->start();  // Start the service
  pServer->getAdvertising()->start();  // Start advertising
  Serial.println("Waiting a client connection to notify...");
}

void loop() {
  BLE_read();
  if(Serial.available()) { // 시리얼 버퍼에 데이터 있으면
    char c = Serial.read();  
    if(c != '\n') {
      s += c;
    } else {
      if(s == "on"){ // 시리얼 모니터 제어 led on
        Serial.println("LED ON");
        send_pin_echo(11); // 블루투스 앱 버튼 상태: on
        pTxCharacteristic->setValue("LED ON");
        pTxCharacteristic->notify();
        s = "";  
      }
      else if(s == "off"){ // 시리얼 모니터 제어 led off 
        Serial.println("LED OFF");
        send_pin_echo(10); // 블루투스 앱 버튼 상태: off
        pTxCharacteristic->setValue("LED OFF");
        pTxCharacteristic->notify();
        s = "";
      }
      else {
        char temp [21]; 
        s.toCharArray(temp, s.length()+1); 
        pTxCharacteristic->setValue(temp); 
        pTxCharacteristic->notify();
        s = "";
      }
    }
  }
}

void general_use() { 
  for (int i = 0; i < rxValue.length(); i++) Serial.write(rxValue[i]);
}

void pin_control() {
  pin_val = pin_a[1];
  if (pin_val != 0) {
    switch (pin_val) {
      case 11: Serial.println("button 1 : on"); 
                  break;
      case 10: Serial.println("button 1 : off"); 
                  break;
      case 21: Serial.println("button 2 : on");
               send_pin_echo(pin_val); // 버튼 상태 echo 
                  break;
      case 20: Serial.println("button 2 : off");
               send_pin_echo(pin_val); // 버튼 상태 echo 
                  break;
      case 31: Serial.println("button 3 : on");
                  break;
      case 30: Serial.println("button 3 : off");
                  break;
      case 41: Serial.println("button 4 : on");
                  break;
      case 40: Serial.println("button 4 : off");
                  break;
      case 51: Serial.println("button 5 : on");
                  break;
      case 50: Serial.println("button 5 : off");
                  break;
      case 61: Serial.println("button 6 : on");
                  break;
      case 60: Serial.println("button 6 : off");
                  break;
      case 71: Serial.println("button 7 : on");
                  break;
      case 70: Serial.println("button 7 : off");
                  break;
      case 81: Serial.println("button 8 : on");
                  break;
      case 80: Serial.println("button 8 : off");
                  break;
      case 91: Serial.println("button 9 : on");
                  break;
      case 90: Serial.println("button 9 : off");
                  break;  
      case 101: Serial.println("button 10 : on");
                  break;
      case 100: Serial.println("button 10 : off");
                  break;  
      case 111: Serial.println("button 11 : on");
                  break;
      case 110: Serial.println("button 11 : off");
                  break;  
      case 121: Serial.println("button 12 : on");
                  break;
      case 120: Serial.println("button 12 : off");
                  break;  
    }
  pin_val = 0;
  }
}

void pwm_control() {
  uint16_t temp = pwm_a[3];
  temp = temp << 8 | pwm_a[2];
  if (pwm_a[1] == 1) {  // 슬라이드 1번
    pwm1 = temp;
//    send_pwm_echo(1, pwm1); // PWM 값 echo
    Serial.print("pwm1: "); Serial.println(pwm1);
  }
  else if (pwm_a[1] == 2) { // 슬라이드 2번
    pwm2 = temp;
    Serial.print("pwm2: "); Serial.println(pwm2);
  }
  else if (pwm_a[1] == 3) {  // 슬라이드 3번
    pwm3 = temp;
    Serial.print("pwm3: "); Serial.println(pwm3);
  }
}

void BLE_read() {
  if (rx_received == true) {         
    if (rxValue[0] == 0xF0) get_pin_val = true;
    else if (rxValue[0] == 0xF3) get_pwm_val = true;
    if (get_pin_val == true) {  // 디지털 핀 제어값 수신
      pin_a[0] = rxValue[0];
      pin_a[1] = rxValue[1];
      pin_a[2] = rxValue[2];
      if (pin_a[0] == 0xF0 && pin_a[2] == 0xF1) { // 수신값 검증 완료시
        pin_control();    // 디지털 핀 출력함수 실행}
      }
      get_pin_val = false;
    }
    else if (get_pwm_val == true) { // pwm 제어값 수신
      pwm_a[0] = rxValue[0];
      pwm_a[1] = rxValue[1];
      pwm_a[2] = rxValue[2];
      pwm_a[3] = rxValue[3];
      pwm_a[4] = rxValue[4];
      if (pwm_a[0] == 0xF3 && pwm_a[4] == 0xF1) { // 수신값 검증 완료시
        pwm_control(); // PWM 출력함수 실행
      }
      get_pwm_val = false;
    }
    else {
      if (rxValue[0] == 0xF8) date_time = true;
      else if (rxValue[0] == 0xF9) alarm_set = true;
      if (date_time == true) {
        String temp = "";
        for (int i = 0; i < rxValue.length(); i++) {
          if (rxValue[i] != '\n') temp += rxValue[i];
          else break;
        }
        Serial.println(temp);
      }
      else if (alarm_set == true) {
        String temp = "";
        for (int i = 0; i < rxValue.length(); i++) {
          if (rxValue[i] != '\n') temp += rxValue[i];
          else break;
        }
        Serial.println(temp);
      } 
      else {
        general_use();  // 텍스트 출력함수
      }
    }
    rx_received = false;
  }
}

void send_pin_echo(uint8_t pin_val){
  pin_echo[1] = pin_val;
  pTxCharacteristic->setValue((uint8_t*)&pin_echo, 3);
  pTxCharacteristic->notify();
}

void send_pwm_echo(uint8_t slide, uint16_t pwm_val) {
  pwm_echo[1] = slide;
  if (pwm_val < 256) {
    pwm_echo[2] = pwm_val;
    pwm_echo[3] = 0;
  }
  else {
    pwm_echo[2] = pwm_val;
    pwm_echo[3] = pwm_val >> 8;
  }
    pTxCharacteristic->setValue((uint8_t*)&pwm_echo, 5);
    pTxCharacteristic->notify();
}

void send_pwm_slide(uint8_t slide, uint16_t pwm_val) {
  pwm_slide[1] = slide;
  if (pwm_val < 256) {
    pwm_slide[2] = pwm_val;
    pwm_slide[3] = 0;
  }
  else {
    pwm_slide[2] = pwm_val;
    pwm_slide[3] = pwm_val >> 8;
  }
    pTxCharacteristic->setValue((uint8_t*)&pwm_slide, 5);
    pTxCharacteristic->notify();
}

 

- ESP32 DevKit wifi_Soft_AP

arduino_remote_control_esp32_full.ino
0.01MB

더보기
#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiAP.h>
#define AP_SSID  "Esp32"
#define AP_PASS  "1234test"

String s =""; // 시리얼 모니터 텍스트 제어용 변수

// 디지털 핀 제어용 변수
uint8_t pin_val = 0;

// PWM 제어용 변수
uint16_t pwm1 = 0;  
uint16_t pwm2 = 0;  
uint16_t pwm3 = 0;  

String income_wifi = ""; // 와이파이 수신 스트링 저장 변수

// 웹요청 응답용 변수
String send_pin = "";
String send_Pwm_echo = "";
String send_Pwm_slide = "";
String send_text = "";

WiFiServer server(80);
WiFiClient client;

void setup() {
  Serial.begin(115200);
  WiFi.softAP(AP_SSID, AP_PASS);
  IPAddress myIP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(myIP);
  server.begin();
}

void loop() {
  wifi_delay(); // 와이파이 데이터 읽기
  if (Serial.available()) {   
    char c = Serial.read();  
    if(c != '\n') {
      s += c;
    } else {
      if(s == "on"){ // 시리얼 모니터 제어 led on
        Serial.println("LED ON");
        send_pin_echo(11);        // 스케쥴 웹요청 응답, 블루투스 앱 버튼 상태: on
        send_text = "LED ON";     // 스케쥴 웹요청 응답
        s = "";  
      }
      else if(s == "off"){ // 시리얼 모니터 제어 led off 
        Serial.println("LED OFF");
        send_pin_echo(10);        // 스케쥴 웹요청 응답, 블루투스 앱 버튼 상태: off
        send_text = "LED OFF";    // 스케쥴 웹요청 응답
        s = "";
      }
      else {
        send_text = s;  // 스케쥴 웹요청시 응답변수에 저장
        s = "";
      }
    }      
  }
}

void pin_control() {
  if (pin_val != 0) {
    switch (pin_val) {
      case 11: Serial.println("button 1 : on"); 
               client.println("HTTP/1.1 200 OK\r\n"); // 사용자 웹요청시 응답 헤더
               send_pin_echo(pin_val);
               client.print("LED_ON_11"); 
                  break;
      case 10: Serial.println("button 1 : off");
               client.println("HTTP/1.1 200 OK\r\n"); // 사용자 웹요청시 응답 헤더
               send_pin_echo(pin_val);
               client.print("LED_ON_10");
                  break;
      case 21: Serial.println("button 2 : on");
                  break;
      case 20: Serial.println("button 2 : off");
                  break;
      case 31: Serial.println("button 3 : on");
                  break;
      case 30: Serial.println("button 3 : off");
                  break;
      case 41: Serial.println("button 4 : on");
                  break;
      case 40: Serial.println("button 4 : off");
                  break;
      case 51: Serial.println("button 5 : on");
                  break;
      case 50: Serial.println("button 5 : off");
                  break;
      case 61: Serial.println("button 6 : on");
                  break;
      case 60: Serial.println("button 6 : off");
                  break;
      case 71: Serial.println("button 7 : on");
                  break;
      case 70: Serial.println("button 7 : off");
                  break;
      case 81: Serial.println("button 8 : on");
                  break;
      case 80: Serial.println("button 8 : off");
                  break;
      case 91: Serial.println("button 9 : on");
                  break;
      case 90: Serial.println("button 9 : off");
                  break;  
      case 101: Serial.println("button 10 : on");
                  break;
      case 100: Serial.println("button 10 : off");
                  break;  
      case 111: Serial.println("button 11 : on");
                  break;
      case 110: Serial.println("button 11 : off");
                  break;  
      case 121: Serial.println("button 12 : on");
                  break;
      case 120: Serial.println("button 12 : off");
                  break;  
    }
  pin_val = 0;
  }
}

unsigned long int one_millis = 0;

void wifi_delay() { // 30 밀리초 마다 client 연결 확인 및 데이터 수신
  if (millis() - one_millis > 30) {
    one_millis = millis();
    wifi_read();
  }
}

void wifi_read() { // wifi 데이터 수신
  client = server.available(); // 서버가 작동하고 있으면 client 생성
  if(client.available()) {     // 클라이언트에 데이터가 있으면
    income_wifi = client.readStringUntil('\r');
    if (income_wifi.indexOf("%%F1") != -1) {          // 종료문자가 있으면
      if (income_wifi.indexOf("%%F0") != -1) {        // 디지털 핀 값 수신
        String wifi_temp = income_wifi.substring(income_wifi.indexOf("%%F0")+4, income_wifi.indexOf("%%F1"));
        pin_val = wifi_temp.toInt();
        pin_control();
      }
      else if (income_wifi.indexOf("%%F31") != -1) {  // 슬라이드1, PWM 값 수신
        String wifi_temp = income_wifi.substring(income_wifi.indexOf("%%F31")+5, income_wifi.indexOf("%%F1"));
        pwm1 = wifi_temp.toInt();
        Serial.print("pwm1: "); Serial.println(pwm1);
      }
      else if (income_wifi.indexOf("%%F32") != -1) {  // 슬라이드2, PWM 값 수신 
        String wifi_temp = income_wifi.substring(income_wifi.indexOf("%%F32")+5, income_wifi.indexOf("%%F1"));
        pwm2 = wifi_temp.toInt();
        Serial.print("pwm2: "); Serial.println(pwm2);
      }
      else if (income_wifi.indexOf("%%F33") != -1) {  // 슬라이드3, PWM 값 수신
        String wifi_temp = income_wifi.substring(income_wifi.indexOf("%%F33")+5, income_wifi.indexOf("%%F1"));
        pwm3 = wifi_temp.toInt();
        Serial.print("pwm3: "); Serial.println(pwm3);
      }
    }
    else if (income_wifi.indexOf("%%F5") != -1) { // 스케쥴 접속확인 응답, 텍스트 및 로컬값 전송
      client.println("HTTP/1.1 200 OK\r\n");      // 스케쥴 웹요청시 응답 헤더 "%%F5"
      if (send_pin != "") {                       // 전송할 핀 상태 값이 있으면 "/ HTTP/1.1"
        client.print(send_pin); 
        send_pin = "";
      }
      if (send_Pwm_echo != "") {                  // 전송할 PWM 상태(echo) 값이 있으면
        client.print(send_Pwm_echo);
        send_Pwm_echo = "";
      }
      if (send_Pwm_slide != "") {                 // 전송할 PWM 슬라이브 바 상태 값이 있으면
        client.print(send_Pwm_slide);
        send_Pwm_slide = "";
      }
      if (send_text != "") {                      // 전송할 텍스트가 있으면
        client.print(send_text);
        send_text = "";
      }
    }
    else{
      if (income_wifi.indexOf("%%F8") != -1) {  // 슬라이드3, PWM 값 수신
        String wifi_temp = income_wifi.substring(income_wifi.indexOf("%%F8")+4, income_wifi.indexOf("\n"));
        Serial.print("Date/Time: "); Serial.println(wifi_temp); 
      }
      else if (income_wifi.indexOf("%%F9") != -1) {  // 슬라이드3, PWM 값 수신
        String wifi_temp = income_wifi.substring(income_wifi.indexOf("%%F9")+4, income_wifi.indexOf("\n"));
        Serial.print("Alarm set: "); Serial.println(wifi_temp); 
      }
      else {  // 텍스트 시리얼 출력
        String wifi_temp = income_wifi.substring(income_wifi.indexOf("GET /")+5, income_wifi.indexOf("HTTP/1.1")-1);
        if (wifi_temp.indexOf("%20") != -1) { // 웹브라우저 공백문자 %20을 공백문자로 변경
          String space = "%20";
          String space_convert = " ";
          wifi_temp.replace(space, space_convert);
        }
        Serial.println(wifi_temp);
      }
    }
    income_wifi = "";
    client.stop();
  }
}

void send_pin_echo(uint8_t pin_val){  // 디지털 버튼 상태값 전송
  String s_temp ="";
  s_temp += "%%F0";
  s_temp += pin_val;
  s_temp += "%%P1";
  if (client.connected())  client.print(s_temp); // 사용자 웹요청 응답
  else  send_pin = s_temp;                       // 스케쥴 웹요청 응답
}

void send_pwm_echo(uint8_t slide, uint16_t pwm_val) { // PWM값 echo 전송
  String s_temp ="";                                  
  s_temp += "%%F3";
  s_temp += slide;
  s_temp += pwm_val;
  s_temp += "%%E1";
  if (client.connected())  client.print(s_temp); // 사용자 웹요청 응답
  else  send_Pwm_echo = s_temp;                  // 스케쥴 웹요청 응답
}

void send_pwm_slide(uint8_t slide, uint16_t pwm_val) { // 슬라이더 상태값 전송
  String s_temp ="";
  s_temp += "%%F4";
  s_temp += slide;
  s_temp += pwm_val;
  s_temp += "%%S1";
  if (client.connected())  client.print(s_temp); // 사용자 웹요청 응답
  else  send_Pwm_slide = s_temp;                 // 스케쥴 웹요청 응답
}

 

arduino bluetooth controller PWM v3.5 사용 예제 글

[arduino] - 아두이노 - 안드로이드를 이용한 무선 원격제어 그리고 시리얼 통신 - 1편

[arduino] - 아두이노 - 안드로이드를 이용한 무선 원격제어 그리고 시리얼 통신 - 2편

[arduino] - 아두이노 - 안드로이드를 이용한 무선 원격제어 그리고 시리얼 통신 - 3편

[arduino] - 아두이노 - 안드로이드를 이용한 무선 원격제어 그리고 시리얼 통신 - 4편

[arduino] - 아두이노 - 안드로이드를 이용한 무선 원격제어 그리고 시리얼 통신 - 5편

[arduino] - 블루투스 4.0 BLE 이용 아두이노 및 ESP32 원격제어

[arduino] - 아두이노 - 시리얼통신 주요함수와 예제, String class

[arduino] - 아두이노 - ESP01 wifi 모듈 무선 원격제어 그리고 시리얼 통신 - 6편

[arduino] - ESP8266 - NodeMcu 1.0 와이파이 이용 원격제어(soft AP, wifi)

[arduino] - ESP32 - Dev Module 와이파이 이용 원격제어(soft AP, wifi)

 

 

최신 버전 유료앱(광고 제거)

 

https://play.google.com/store/apps/details?id=com.tistory.postpop.hmi 

 

ADUCON - Google Play 앱

무선(WiFi/Bluetooth/BLE)을 통한 Arduino 원격 제어 앱

play.google.com

※ 특징
- 블루투스 2.0 / 블루투스 4.0 BLE 연결 : HC-05, HC-06, HM-10, AT-09, BT05
- WiFi를 통해 모듈의 Access Point 또는 공용 네트워크의 IP에 연결
- 15개의 디지털 버튼: 토글 및 푸시 버튼 속성 설정
- 6개의 아날로그 컨트롤러(SeekBar): 최소 및 최대 값 설정
- 메인 화면 표시 설정
- 버튼 레이블 사용자 정의
- 설정값 저장 기능
- RGB LED 제어를 위한 색상 선택기
- PWM 제어를 위한 다이얼 노브
- Arduino Sketch의 HTML 페이지용 웹 뷰어
- 비밀번호를 이용하여 제어권한을 설정할 수 있는 대화창 제공
- 사용자 정의 대화창 제공(라디오박스, 체크박스, 텍스트 입력 등)
- 앱이 실행되는 동안 화면이 계속 켜져 있음(화면이 꺼지는 것을 방지)

 

[Arduino] - Setting up Wi-Fi module ESP01 and basic code for Arduino remote control

[Arduino/ADUCON] - Arduino WiFi remote control with ADUCON and ESP-01

[Arduino] - Arduino Basic code for bluetooth remote contol with HC-06

[Arduino/ADUCON] - Arduino Bluetooth remote control with ADUCON and HC-06

[Arduino] - Arduino Basic code for BLE remote contol with BT05

[Arduino/ADUCON] - Arduino BLE remote control with ADUCON and BT05

[Arduino] - ESP32/NodeMcu Basic code for WiFi remote contol

[Arduino/ADUCON] - ESP32/NodeMcu WiFi remote control with ADUCON

[Arduino/ADUCON] - ESP32 Bluetooth remote control with ADUCON

[Arduino/ADUCON] - ESP32 BLE remote control with ADUCON

 

 

 

https://play.google.com/store/apps/details?id=io.kodular.skyship72.pad01 

 

ADUPAD - Google Play 앱

무선(WiFi/Bluetooth/BLE)을 통한 Arduino 원격 제어 PAD

play.google.com

- 조이스틱 2개.
- 1개의 중력 센서 컨트롤러.
- 제어용 20개 버튼: 토글 및 푸시 버튼 속성 설정 기능.
일부 버튼 레이블은 사용자 정의할 수 있습니다.
- 비밀번호를 이용하여 제어권한을 설정할 수 있는 대화창 제공
- 사용자 정의 대화창 제공(라디오박스, 체크박스, 텍스트 입력 등)
- 앱이 실행되는 동안 화면이 계속 켜져 있음(화면이 꺼지는 것을 방지)

 

[Arduino] - Setting up Wi-Fi module ESP01 and basic code for Arduino remote control

[Arduino/ADUPAD] - Arduino WiFi remote control with ADUPAD and ESP-01

[Arduino] - Arduino Basic code for bluetooth remote contol with HC-06

[Arduino/ADUPAD] - Arduino Bluetooth remote control with ADUPAD and HC-06

[Arduino] - Arduino Basic code for BLE remote contol with BT05

[Arduino/ADUPAD] - Arduino BLE remote control with ADUPAD and BT05

[Arduino] - ESP32/NodeMcu Basic code for WiFi remote contol

[Arduino/ADUPAD] - ESP32/NodeMcu WiFi remote control with ADUPAD

[Arduino/ADUPAD] - ESP32 Bluetooth remote control with ADUPAD

[Arduino/ADUPAD] - ESP32 BLE remote control with ADUPAD