반응형

ADUPAD application

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

 

ADUPAD - Google Play 앱

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

play.google.com

 

Basic code for remote control

- Set Bluetooth Serial library to communicate with Bluetooth component of ESP32

#include "BluetoothSerial.h"
BluetoothSerial SerialBT;

 

- Function for callback when attempt with Bluetooth pairing to ESP32

void BTConfirmRequestCallback(uint32_t numVal){
  SerialBT.confirmReply(true);
}

 

- setup() function

void setup() {
  Serial.begin(115200);// Set the baud rate for communication with the serial monitor of the Arduino IED to 115200
  SerialBT.enableSSP();// set paring mode for bluetooth classic of ESP32
  SerialBT.onConfirmRequest(BTConfirmRequestCallback); // set callback fuction when attempted pairing
  SerialBT.begin(btName); //start software Serial for Bluetooth of ESP32 and set Bluetooth device name
  Serial.println(F("Bluetooth 2.0"));
}

 

- loop() function

bool gotData = false;

void loop() {
  if (SerialBT.available()) { // when incomming data from HC06
    uint8_t temp = SerialBT.read();
    Serial.println(temp); // Output data of the HC06 to the serial monitor.
    gotData = true; // the flag for response
  } else {
    if (gotData) {   // if response
      String setVal = "";
      setVal += char(0xF4);      // protocol header of text for ADUPAD with bluetooth
      setVal += "Hello World ";
      setVal += random(100,200); // the message for sending
      setVal += char(0xF1);      // protocol footer of text for ADUPAD with bluetooth
      Serial.println(setVal);    // Output the message to the serial monitor.
      SerialBT.print(setVal);    // send data to HC06 as response 
      gotData = false;           // initialize the flag
    }
  }
}

 

ESP32_BT_BASIC.zip

ESP32_BT_BASIC.zip
0.00MB

 

- Output of Serial Monitor after upload scketch "ESP32_BT_BASIC.ino"

 

Pairing to ESP32 at mobile phone and connecting to ESP32 on the ADUPAD app

1. Bluetooth pairing

Select the ESP32 on the Bluetooth setting screen of your mobile phone.

Confirm the callback Message from ESP32 for pairing

 

2. Bluetooth 2.0 Search and Connection in the App

Click the Bluetooth icon in the app and select Bluetooth 2.0 in Select Ver.

Click the Bluetooth button and select the bluetooth of ESP32.

received data "248(0xF8) 99(c) 111(o) 110(n) 110(n) 101(e) 99(c) 116(t) 10(\n)"
response from ESP32

 

Code for remote control with Bluetooth of ADUPAD applications

- SerialBT_read() function

1. Protocol header definition

ADUPAD app's protocol header settings

Define the headers for Bluetooth in the Arduino sketch according to the protocol header settings in the ADUPAD app.

#define pinHD 0xF0
#define joyHD 0xF3
#define strHD 0xF4
#define footHD 0xF1
#define echoHD 0xE1
#define connectHD 0xF8
#define optionHD 0xF9
#define checkHD 0xF5

 

2. Code to check the connection attempt of ADUPAD app

bool appConnection = false;

if (appConnection) { // If app connection is confirmed
  // Execute code after app connection is confirmed
} else {
  if (SerialBT.peek() == connectHD) appConnection = true; // Check if the value is 0xF8.
  else SerialBT.disconnect(); // disconnect and advertise for new pairing
}

 

3. Handling of values according to connection header "connectHD(0xF8)"

0xF8 + connect: Transmit the necessary app settings through the iniSet() function.

0xF8 + disconnect: Disconnect and change value of appConnection to false.

0xF8 + NA: Change setting values for the bluetooth of ESP32.

if (temp == F("connect")) iniSet(); 
else if (temp == F("disconnect")) { appConnection = false; Serial.println(F("disconnect")); }
else if (temp.startsWith(F("NA"))) { sendMessage(F("This funtion is not available.")); }
else Serial.println(temp);

 

4. Handling of values according to option header "optionHD(0xF9)"

void CheckF9(String temp) {
  Serial.println(temp);
  if (temp.startsWith(F("RAD"))) { } // if it starts with "RAD"
  else if (temp.startsWith(F("CKB"))) { } // if it starts with "CKB"
  else if (temp.startsWith(F("CHD"))) { } // if it starts with "CHD"
  else if (temp.startsWith(F("LSD"))) { } // if it starts with "LSD"
  else if (temp.startsWith(F("STR"))) { } // if it starts with "STR"
}

 

5. Handling of values according to button header "pinHD(0xF0)"

// 0xF0 + 1byte Num + 0xF1
while (SerialBT.peek() == pinHD) { // need depend on left arrow pad mode 
  SerialBT.readBytes(data, 3); // Store 3 bytes of data in array "data" from Serial Buffer
  if (data[2] == footHD) { // if the third byte is 0xF1
    pin_control(data[1]);  // execute the code with the value of second byte
    data[2] = 0;
  }
}

 

6. Handling of values according to SeekBar(slide bar) header "joyHD(0xF3)"

// 0xF3 + 1byte Num(id) + 2byte Num(heading) + 1byte Num(strength) + 0xF1
while (SerialBT.peek() == joyHD) { 
  SerialBT.readBytes(data, 6); // Store 6 bytes of data in array "data" from Serial Buffer
  if (data[5] == footHD) {     // if the sixth byte is 0xF1
    uint16_t value = data[3];  // Swap third and fourth bytes
    value = value << 8 | data[2];
    joystick_control(data[1], value, data[4]); // execute the code with values
    data[5] = 0;
  }
}
if (joyEcho) { sendJoyEcho(); joyEcho = 0; } // Prevent data transmission while receiving data
// refer to "Precautions when using the HC-06 with Serial communication" posted in Basic code.

 

7. Sending a flag that causes the ADUPAD app to immediately terminate the timer for receiving data

if (dataSend) { SerialBT.write(checkHD); dataSend = false; } // send 0xF5 to terminate the timer.

 

Protocol function to send data from Arduino to app

1. Change the state of the button.

void sendPinState(uint8_t pin_val){
  uint8_t pin[3] = {pinHD, pin_val, footHD};
  SerialBT.write(pin, 3);
  dataSend = true;
}

 

2. Transmits an echo for the received value of the button.

void sendPinEcho(uint8_t pin_val){
  uint8_t pin[3] = {pinHD, pin_val, echoHD};
  SerialBT.write(pin, 3);
  dataSend = true;
}

 

3. Change the Joystick state of the app.

// id 0:Left Joystick, 1:Right Joystick 2:Gravity Sensor(change only text)
void sendJoyState(uint8_t id, uint16_t heading, uint8_t strength) { 
  uint8_t joy[6] = {joyHD, id, heading, heading >> 8, strength, footHD};
  SerialBT.write(joy, 6);
  dataSend = true;
}

 

4. Transmits the echo for the received value of the Joystick.

uint8_t joyEcho = 0;
uint8_t ecVal[12] = { 0, };

void send_joy_echo(uint8_t id, uint16_t heading, uint8_t strength) {
  if (joyEcho > 2) joyEcho = 0;
  ecVal[joyEcho*4] = id; 
  ecVal[(joyEcho*4)+1] = heading;
  ecVal[(joyEcho*4)+2] = heading >> 8;
  ecVal[(joyEcho*4)+3] = strength; 
  joyEcho++;
}

void sendJoyEcho() {
  uint8_t ch = 0;
  while (joyEcho) {
    joyEcho--;
    uint8_t joy[6] = {joyHD, ecVal[ch*4], ecVal[(ch*4)+1], ecVal[(ch*4)+2], ecVal[(ch*4)+3], echoHD};
    SerialBT.write(joy, 6); ch++;
  }
  dataSend = true;
}

 

5. Send text.

void sendText(String str) {
  String setVal = "";
  setVal += char(strHD);
  setVal += str;
  setVal += char(footHD);
  SerialBT.print(setVal);
  dataSend = true;
}

 

6. Instruct the app to click the Disconnect Button.

void sendDisconnect(){ // order disconnect to App 
  uint8_t setVal[3] = {connectHD, 0x01, 0x00};
  SerialBT.write(setVal, 3);
  dataSend = true;
}

Disconnect Button for Bluetooth

 

7. Use when you want to acquire control authority by using the set password for ESP32

It can be changed to any name through definition of the passName and passNameLen for processing the password in the sketch and the app send datas starting with passName as password value. This is to enhance security.

#define passName F("PAS:")
#define passNameLen 0x04

void requestPass(bool val){ 
  String setVal = "";
  setVal += char(connectHD);
  setVal += char(0x02);
  if (val) {
    setVal += char(passNameLen);
    setVal += passName;
  } else setVal += char(val);
  SerialBT.print(setVal);
  dataSend = true;
}

 

8. Response for correct or not through password confirmation

void responsePass(bool val){ 
  uint8_t setVal[3] = {connectHD, 0x03, val};
  SerialBT.write(setVal, 3);
  dataSend = true;
}

 

9. Outputs the message in the form of a pop-up.

void sendMessage(String str) {
  String setVal = "";
  setVal += char(connectHD);
  setVal += char(0x04);
  setVal += str;
  setVal += char(footHD);
  SerialBT.print(setVal);
  dataSend = true;
}

 

10. Set the function to continuously transmit the changed value of the Joystick according to the specified interval.

*** The Gravity Sensor always works in an active Mode.

true: Active Joystick Mode

false: Passive Joystick Mode (transmits only values when the slide bar is touched up)

void setActiveJoystick(bool val){ 
  uint8_t setVal[4] = {optionHD, 0x01, val, 0x00};
  SerialBT.write(setVal, 4);
  dataSend = true;
}

 

11. Set transmission interval of ACTIVE JOYSTIC MODE. (Unit: Millisecond)

void setJoystickInterval(uint16_t val){ 
  uint8_t setVal[4] = {optionHD, 0x02, val, val >> 8};
  SerialBT.write(setVal, 4);
  dataSend = true;
}

 

12. Set the range where the strength of the joystick becomes 0. (enter a value from 0 to 35)

void setJoyZeroRange(uint8_t val){ 
  if (val > 35) val = 35;
  uint8_t setVal[4] = {optionHD, 0x03, val, 0x00};
  SerialBT.write(setVal, 4);
  dataSend = true;
}

 

13. Set whether or not to use a function that converts the Strength value of Joystick or Gravity Sensor into a value between 0 and 10.

void setJoyStrengthAdjust(bool val){ 
  uint8_t setVal[4] = {optionHD, 0x04, val, 0x00};
  SerialBT.write(setVal, 4);
  dataSend = true;
}

 

14. Activate a timer that sends checkHD(0xF5) at regular time intervals.

Regardless of the app, it is used to reflect independently changed values in the Arduino to the app.

void setRequest(bool val){ 
  uint8_t setVal[4] = {optionHD, 0x05, val, 0x00};
  SerialBT.write(setVal, 4);
  dataSend = true;
}

 

15. Set the operation interval of the timer sending checkHD(%%F5). (Unit: Millisecond)

void setRequestInterval(uint16_t val){ 
  uint8_t setVal[4] = {optionHD, 0x06, val, val >> 8};
  SerialBT.write(setVal, 4);
  dataSend = true;
}

 

16. Set the group for the left arrow keypad.

// 1: independent 2: group1(up-down) / group2 (left-right) 4: group4(only 1)
void setLeftPadMode(uint8_t val){   
  if (val == 0 || val > 2) val = 4; 
  uint8_t setVal[4] = {optionHD, 0x07, val, 0x00};
  SerialBT.write(setVal, 4);
  dataSend = true;
}

 

17. Set the 4-way control of the joystick.

// 0: Left & Right False 1: Left 4 Way 2: Right 4Way 3: Both 4 Way
void setJoyWay4(uint8_t val){
  uint8_t setVal[4] = {optionHD, 0x08, val, 0x00};
  SerialBT.write(setVal, 4);
  dataSend = true;
}

 

18. Set whether or not to display the group button.

// 0: none 1: group1 2: group1&2
void setDisplayAddButton(uint8_t val){ 
  if (val > 2) val = 2;
  uint8_t setVal[4] = {optionHD, 0x09, val, 0x00};
  SerialBT.write(setVal, 4);
  dataSend = true;
}

 

19. Set the operation function when clicking the label displaying the current connection status.

0: No function.

1: Show only connection information when it clicked.

3: Show connection information and password when it clicked so that the connection and password can be set.

// 0: not use, 1: show only name, 2(OTHER)/3(HC06): show name & pass, defalult: 2
void setSSIDLabelMode(uint8_t val) { 
  uint8_t setVal[4] = {optionHD, 0x0A, val, 0x00};
  SerialBT.write(setVal, 4);
  dataSend = true;
}

 

20. Set the activation interval of the gravity sensor and transmission of the tilt value.

// defalt interval : 180 millis, 180, 180 * 6 = 1080
void useGravityAndInterval(uint16_t val){ 
  uint8_t setVal[4] = {optionHD, 0x0B, val, val >> 8};
  SerialBT.write(setVal, 4);
  dataSend = true;
}

 

21. Set labels for buttons.

//f("BT1,BT2,BT3,BT4,BT5,BT6")
void setAddButtonLabel(String str){ 
  String setVal = "";
  setVal += char(optionHD); 
  setVal += char(0x0C);
  setVal += str; 
  setVal += char(footHD); 
  SerialBT.print(setVal);
  dataSend = true;
}

 

 

22. Set the toggle/push properties of the left 4 buttons or 20 buttons of all.

//F("0000")          // left pad: up-left-right-down
//F("00000000001111110000") // 0000:left, 0000:right, 001111110000:center
void setLeftPadOrAllToggle(String str){ 
  String setVal = "";
  setVal += char(optionHD); 
  setVal += char(0x0D);
  setVal += str; 
  setVal += char(footHD); 
  SerialBT.print(setVal);
  dataSend = true;
}

 

23. Set the toggle/push properties of the right 4 buttons.

// F("0000")           // right pad: top-left-right-bottom
void setRightPadToggle(String str){ 
  String setVal = "";
  setVal += char(optionHD); 
  setVal += char(0x0E);
  setVal += str; 
  setVal += char(footHD); 
  SerialBT.print(setVal);
  dataSend = true;
}

 

24. Set the toggle/push properties of the middle 12 buttons.

// F("000000000000"); // center: view-menu-bt1-bt2-bt3-bt4-bt5-bt6-LB-LT-RB-RT
void setButtonToggle(String str){ // must after setLeftPadMode(uint8_t val)
  String setVal = "";
  setVal += char(optionHD); 
  setVal += char(0x0F);
  setVal += str; 
  setVal += char(footHD); 
  SerialBT.print(setVal);
  dataSend = true;
}

 

25. Dialog Message: radio button

// option = "A,B,C" -> index = 1(A) ~ 3(C)
void dialogRadio(uint8_t id, String title, String option, uint8_t selection){ 
  String setVal = "";
  setVal += char(optionHD); 
  setVal += char(0x10);
  setVal += F("RAD:"); 
  setVal += String(id); setVal += ':';
  setVal += title; setVal += ':';
  setVal += option; setVal += ':';
  setVal += String(selection);
  setVal += char(footHD); 
  SerialBT.print(setVal);
  dataSend = true;
} // Return -> RAD:0:1(index) , RAD:id:option index

 

26. Dialog Message: Checkbox

// option = "A,B,C"
void dialogCheckbox(uint8_t id, String title, String option){ 
  String setVal = "";
  setVal += char(optionHD); 
  setVal += char(0x10);
  setVal += F("CKB:"); 
  setVal += String(id); setVal += ':';
  setVal += title; setVal += ':';
  setVal += option; 
  setVal += char(footHD); 
  SerialBT.print(setVal);
  dataSend = true;
} // Return -> CKB:0:1,3(index) , CKB:id:option index

 

27. Dialog Message: Select button

// option = "A,B"
void dialogChoose(uint8_t id, String message, String option){ 
  String setVal = "";
  setVal += char(optionHD); 
  setVal += char(0x10);
  setVal += F("CHD:"); 
  setVal += String(id); setVal += ':';
  setVal += message; setVal += ':';
  setVal += option; 
  setVal += char(footHD); 
  SerialBT.print(setVal);
  dataSend = true;
} // Return -> CHD:0:B , CHD:id:option str

 

28. Dialog Message: List Window

// option = "A,B,C,D,E,F,G,H"
void dialogList(uint8_t id, String title, String option){ 
  String setVal = "";
  setVal += char(optionHD); 
  setVal += char(0x10);
  setVal += F("LSD:"); 
  setVal += String(id); setVal += ':';
  setVal += title; setVal += ':';
  setVal += option; 
  setVal += char(footHD); 
  SerialBT.print(setVal);
  dataSend = true;
} // Return -> LSD:0:F , LSD:id:option str

 

29. Dialog Message: Input text

void dialogInput(uint8_t id, String title){ 
  String setVal = "";
  setVal += char(optionHD); 
  setVal += char(0x10);
  setVal += F("STR:"); 
  setVal += String(id); setVal += ':';
  setVal += title; 
  setVal += char(footHD); 
  SerialBT.print(setVal);
  dataSend = true;
} // Return -> STR:0:str , STR:id:str

 

1.ESP32_BT_JOYSTIC.zip

 

1.ESP32_BT_JOYSTIC.zip
0.00MB

 

https://youtu.be/VP5Wy1T5n_0

 

Main sketch

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

#define btName F("ESP32blue")

void BTConfirmRequestCallback(uint32_t numVal){
  SerialBT.confirmReply(true);
}

#include "protocol.h"

void setup() {
  Serial.begin(115200);
  SerialBT.enableSSP();
  SerialBT.onConfirmRequest(BTConfirmRequestCallback);
  SerialBT.begin(btName); //Bluetooth device name
  Serial.println(F("Bluetooth 2.0"));
}

void pin_control(uint8_t value) {
  if (value != 0) {
    switch (value) {
      case 11: Serial.println("button 1 : on"); 
                  break;
      case 10: Serial.println("button 1 : off");
                  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");
                //uint8_t id, String title, String option
                dialogList(0, F("MENU"), F("select,tomato,banana,mango")); 
                  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;  
      case 131: Serial.println("button 13 : on");
                  break;  
      case 130: Serial.println("button 13 : off");
                  break;  
      case 141: Serial.println("button 14 : on");
                  break;  
      case 140: Serial.println("button 14 : off");
                  break;  
      case 151: Serial.println("button 15 : on");
                  break;  
      case 150: Serial.println("button 15 : off");
                  break;         
      case 161: Serial.println(F("button 16 : on"));
                  break;
      case 160: Serial.println(F("button 16 : off"));
                  break;  
      case 171: Serial.println(F("button 17 : on"));
                  break;
      case 170: Serial.println(F("button 17 : off"));
                  break;  
      case 181: Serial.println(F("button 18 : on"));
                  break;  
      case 180: Serial.println(F("button 18 : off"));
                  break;  
      case 191: Serial.println(F("button 19 : on"));
                  break;  
      case 190: Serial.println(F("button 19 : off"));
                  break;  
      case 201: Serial.println(F("button 20 : on"));
                  break;  
      case 200: Serial.println(F("button 20 : off"));
                  break; 
      case 210: Serial.println(F("button 21 : off"));
                  break;  
      case 220: Serial.println(F("button 22 : off"));
                  break;            
    }
  }
}

// headingVal = false;
//           Top
//         6  7  0
//          \ | /
//  Left 5 --   -- 1 Right
//          / | \
//         4  3  2
//          Bottom

bool headingVal = true; 

void joystick_control(uint8_t id, uint16_t heading, uint8_t strength) {
  //sendJoyEcho(id, heading, strength); 
  if (id == 0) Serial.print(F("L: "));
  else if (id == 1) Serial.print(F("R: "));
  else Serial.print(F("C: "));
  if (headingVal) {
    Serial.print(heading); Serial.print('/'); Serial.println(strength);
  } else {
    if (heading <= 23) heading = 359;
    int8_t stickDir = (heading-23)/45;  
    Serial.println(stickDir);
  }
}

bool appConnection = false;
uint8_t data[6] = {0, 0, 0, 0, 0, 0};

void SerialBT_read() {
  if (SerialBT.available()) {  
    if (appConnection) {
      if (SerialBT.peek() == joyHD) { // 0xF3
        while (SerialBT.peek() == joyHD) {
          SerialBT.readBytes(data, 6);
          if (data[5] == footHD) {
            uint16_t value = data[3];
            value = value << 8 | data[2];
            joystick_control(data[1], value, data[4]);
            data[5] = 0;
          }
        }
        if (joyEcho) { sendJoyEcho(); joyEcho = 0; }
      } else if (SerialBT.peek() == pinHD) {  // 0xf0
        while (SerialBT.peek() == pinHD) { // need depend on left arrow pad mode 
          SerialBT.readBytes(data, 3);
          if (data[2] == footHD) {
            pin_control(data[1]);
            data[2] = 0;
          }
        }
      } else {
        uint8_t dump;
        if (SerialBT.peek() == checkHD) { dump = SerialBT.read(); dataSend = true; }
        else if (SerialBT.peek() == optionHD || SerialBT.peek() == connectHD) { 
          dump = SerialBT.read();
          String temp = SerialBT.readStringUntil('\n');
          if (dump == connectHD) {
            if (temp == F("connect")) iniSet();
            else if (temp == F("disconnect")) appConnection = false;
            else if (temp.startsWith(F("NA"))) { sendMessage(F("This funtion is not available.")); } 
            else Serial.println(temp);
          } else CheckF9(temp); 
        } else {
          dump = SerialBT.read();
          Serial.write(dump);
        }
      }
      if (!dataSend) SerialBT.write(checkHD); // empty return
      else dataSend = false;
    } else {
      if (SerialBT.peek() == connectHD) appConnection = true;
      else SerialBT.disconnect();
    }
  }
}

void loop() {
  SerialBT_read(); 
  if(Serial.available()) { // if there is data in the serial buffer
    String temp = Serial.readStringUntil('\n'); // option of serial monitor: NEW LINE
    Serial.println(temp);
    if(temp == "1"){   
      setAddButtonLabel(F("BT1,BT23,BT3,BT4,BT5,BT6"));
    } else if(temp == "2"){ 
      sendJoyState(0, 45, 10);
    } else if(temp == "3"){ 
      send_joy_echo(1, 45, 10);
    } else if(temp == "4"){
      setActiveJoystick(true);
    } else if(temp == "5"){
      setActiveJoystick(false);
    } 
  }
}

 

Protocol sketch

더보기
//////////////////////////////////////////////////////////// COMMON
///////////////////////////////////////// ESSENTIAL 
#define pinHD 0xF0
#define joyHD 0xF3
#define strHD 0xF4
#define footHD 0xF1
#define echoHD 0xE1
#define connectHD 0xF8
#define optionHD 0xF9
#define checkHD 0xF5

bool dataSend = false;

void sendPinState(uint8_t pin_val){
  uint8_t pin[3] = {pinHD, pin_val, footHD};
  SerialBT.write(pin, 3);
  dataSend = true;
}

void sendPinEcho(uint8_t pin_val){
  uint8_t pin[3] = {pinHD, pin_val, echoHD};
  SerialBT.write(pin, 3);
  dataSend = true;
}

// id 0:Left Joystick, 1:Right Joystick 2:Gravity Sensor(change only text)
void sendJoyState(uint8_t id, uint16_t heading, uint8_t strength) { 
  uint8_t joy[6] = {joyHD, id, heading, heading >> 8, strength, footHD};
  SerialBT.write(joy, 6);
  dataSend = true;
}

uint8_t joyEcho = 0;
uint8_t ecVal[12] = { 0, };

void send_joy_echo(uint8_t id, uint16_t heading, uint8_t strength) {
  if (joyEcho > 2) joyEcho = 0;
  ecVal[joyEcho*4] = id; 
  ecVal[(joyEcho*4)+1] = heading;
  ecVal[(joyEcho*4)+2] = heading >> 8;
  ecVal[(joyEcho*4)+3] = strength; 
  joyEcho++;
}

void sendJoyEcho() {
  uint8_t ch = 0;
  while (joyEcho) {
    joyEcho--;
    uint8_t joy[6] = {joyHD, ecVal[ch*4], ecVal[(ch*4)+1], ecVal[(ch*4)+2], ecVal[(ch*4)+3], echoHD};
    SerialBT.write(joy, 6); ch++;
  }
  dataSend = true;
}

void sendText(String str) {
  String setVal = "";
  setVal += char(strHD);
  setVal += str;
  setVal += char(footHD);
  SerialBT.print(setVal);
  dataSend = true;
}

///////////////////////////////////////// CONNECTION 
void sendDisconnect(){ // order disconnect to App 
  uint8_t setVal[3] = {connectHD, 0x01, 0x00};
  SerialBT.write(setVal, 3);
  dataSend = true;
}

//#define passName F("PAS:")
//#define passNameLen 0x04
//
//void requestPass(bool val){ // order disconnect to App 
//  String setVal = "";
//  setVal += char(connectHD);
//  setVal += char(0x02);
//  if (val) {
//    setVal += char(passNameLen);
//    setVal += passName;
//  } else setVal += char(val);
//  SerialBT.print(setVal);
//  dataSend = true;
//}
//
//void responsePass(bool val){ // order disconnect to App 
//  uint8_t setVal[3] = {connectHD, 0x03, val};
//  SerialBT.write(setVal, 3);
//  dataSend = true; 
//}

void sendMessage(String str) {
  String setVal = "";
  setVal += char(connectHD);
  setVal += char(0x04);
  setVal += str;
  setVal += char(footHD);
  SerialBT.print(setVal);
  dataSend = true;
}

///////////////////////////////////////// OPTION
///////////////////////// SET FUNCION
void setActiveJoystick(bool val){ 
  uint8_t setVal[4] = {optionHD, 0x01, val, 0x00};
  SerialBT.write(setVal, 4);
  dataSend = true;
}

// SEND SLIDE GET VALUE INTERVAL
void setJoystickInterval(uint16_t val){ 
  uint8_t setVal[4] = {optionHD, 0x02, val, val >> 8};
  SerialBT.write(setVal, 4);
  dataSend = true;
}

void setJoyZeroRange(uint8_t val){ 
  if (val > 35) val = 35;
  uint8_t setVal[4] = {optionHD, 0x03, val, 0x00};
  SerialBT.write(setVal, 4);
  dataSend = true;
}

void setJoyStrengthAdjust(bool val){ 
  uint8_t setVal[4] = {optionHD, 0x04, val, 0x00};
  SerialBT.write(setVal, 4);
  dataSend = true;
}

void setRequest(bool val){ 
  uint8_t setVal[4] = {optionHD, 0x05, val, 0x00};
  SerialBT.write(setVal, 4);
  dataSend = true;
}

void setRequestInterval(uint16_t val){ 
  uint8_t setVal[4] = {optionHD, 0x06, val, val >> 8};
  SerialBT.write(setVal, 4);
  dataSend = true;
}

// 1: independent 2: group1(up-down) / group2 (left-right) 4: group4(only 1)
void setLeftPadMode(uint8_t val){   
  if (val == 0 || val > 2) val = 4; 
  uint8_t setVal[4] = {optionHD, 0x07, val, 0x00};
  SerialBT.write(setVal, 4);
  dataSend = true;
}

// 0: Left & Right False 1: Left 4 Way 2: Right 4Way 3: Both 4 Way
void setJoyWay4(uint8_t val){
  uint8_t setVal[4] = {optionHD, 0x08, val, 0x00};
  SerialBT.write(setVal, 4);
  dataSend = true;
}

// 0: none 1: group1 2: group1&2
void setDisplayAddButton(uint8_t val){ 
  if (val > 2) val = 2;
  uint8_t setVal[4] = {optionHD, 0x09, val, 0x00};
  SerialBT.write(setVal, 4);
  dataSend = true;
}

// 0: not use, 1: show only name, 2: show name & pass, defalult: 2
void setSSIDLabelMode(uint8_t val) { 
  uint8_t setVal[4] = {optionHD, 0x0A, val, 0x00};
  SerialBT.write(setVal, 4);
  dataSend = true;
}

// defalt interval : 180 millis, 180, 180 * 6 = 1080
void useGravityAndInterval(uint16_t val){ 
  uint8_t setVal[4] = {optionHD, 0x0B, val, val >> 8};
  SerialBT.write(setVal, 4);
  dataSend = true;
}

//f("BT1,BT2,BT3,BT4,BT5,BT6")
void setAddButtonLabel(String str){ 
  String setVal = "";
  setVal += char(optionHD); 
  setVal += char(0x0C);
  setVal += str; 
  setVal += char(footHD); 
  SerialBT.print(setVal);
  dataSend = true;
}

//F("0000")          // left pad: up-left-right-down
void setLeftPadOrAllToggle(String str){ 
  String setVal = "";
  setVal += char(optionHD); 
  setVal += char(0x0D);
  setVal += str; 
  setVal += char(footHD); 
  SerialBT.print(setVal);
  dataSend = true;
}
// F("0000")           // right pad: top-left-right-bottom
void setRightPadToggle(String str){ 
  String setVal = "";
  setVal += char(optionHD); 
  setVal += char(0x0E);
  setVal += str; 
  setVal += char(footHD); 
  SerialBT.print(setVal);
  dataSend = true;
}
// F("000000000000"); // center: view-menu-bt1-bt2-bt3-bt4-bt5-bt6-LB-LT-RB-RT
void setButtonToggle(String str){ // must after setLeftPadMode(uint8_t val)
  String setVal = "";
  setVal += char(optionHD); 
  setVal += char(0x0F);
  setVal += str; 
  setVal += char(footHD); 
  SerialBT.print(setVal);
  dataSend = true;
}

///////////////////////// PERFORM DIALOG
// option = "A,B,C" -> index = 1(A) ~ 3(C)
void dialogRadio(uint8_t id, String title, String option, uint8_t selection){ 
  String setVal = "";
  setVal += char(optionHD); 
  setVal += char(0x10);
  setVal += F("RAD:"); 
  setVal += String(id); setVal += ':';
  setVal += title; setVal += ':';
  setVal += option; setVal += ':';
  setVal += String(selection);
  setVal += char(footHD); 
  SerialBT.print(setVal);
  dataSend = true;
} // Return -> RAD:0:1(index) , RAD:id:option index

// option = "A,B,C"
void dialogCheckbox(uint8_t id, String title, String option){ 
  String setVal = "";
  setVal += char(optionHD); 
  setVal += char(0x10);
  setVal += F("CKB:"); 
  setVal += String(id); setVal += ':';
  setVal += title; setVal += ':';
  setVal += option; 
  setVal += char(footHD); 
  SerialBT.print(setVal);
  dataSend = true;
} // Return -> CKB:0:1,3(index) , CKB:id:option index

// option = "A,B"
void dialogChoose(uint8_t id, String message, String option){ 
  String setVal = "";
  setVal += char(optionHD); 
  setVal += char(0x10);
  setVal += F("CHD:"); 
  setVal += String(id); setVal += ':';
  setVal += message; setVal += ':';
  setVal += option; 
  setVal += char(footHD); 
  SerialBT.print(setVal);
  dataSend = true;
} // Return -> CHD:0:B , CHD:id:option str

// option = "A,B,C,D,E,F,G,H"
void dialogList(uint8_t id, String title, String option){ 
  String setVal = "";
  setVal += char(optionHD); 
  setVal += char(0x10);
  setVal += F("LSD:"); 
  setVal += String(id); setVal += ':';
  setVal += title; setVal += ':';
  setVal += option; 
  setVal += char(footHD); 
  SerialBT.print(setVal);
  dataSend = true;
} // Return -> LSD:0:F , LSD:id:option str 

void dialogInput(uint8_t id, String title){ 
  String setVal = "";
  setVal += char(optionHD); 
  setVal += char(0x10);
  setVal += F("STR:"); 
  setVal += String(id); setVal += ':';
  setVal += title; 
  setVal += char(footHD); 
  SerialBT.print(setVal);
  dataSend = true;
} // Return -> STR:0:str , STR:id:str

//////////////////////////////////////////////////////////// INDIVIDUAL
void iniSet() {
  setAddButtonLabel(F("BT1,BT22,BT3,BT4,BT5,BT6"));
  setDisplayAddButton(2); // 0: none 1: group1 2: group1&2
  setLeftPadMode(1);      // 1: independent 2: group1(up-down) / group2 (left-right) 4: group4(only 1)
  setLeftPadOrAllToggle(F("00000000001111110000"));
  setJoyWay4(false);
  setActiveJoystick(true); setJoystickInterval(100);
  setJoyStrengthAdjust(true);
  setRequest(false); //setRequestInterval(250);
  setSSIDLabelMode(0); // btName Label long click function disabled
  //useGravityAndInterval(180);
}

void CheckF9(String temp) {
  Serial.println(temp);
  if (temp.startsWith(F("RAD"))) {  }
  else if (temp.startsWith(F("CKB"))) {  }
  else if (temp.startsWith(F("CHD"))) {  }
  else if (temp.startsWith(F("LSD"))) {  }
  else if (temp.startsWith(F("STR"))) {  }
}

 

Example of using Protocol to set ADUPAD app

- ADUPAD app settings: label/toggle properties, use of the timer for checkHD(0xF5), Joystic Mode settings, etc.

void iniSet() {
  setAddButtonLabel(F("BT1,BT2,BT3,BT4,BT5,BT6"));
  setDisplayAddButton(2); // 0: none 1: group1 2: group1&2
  setLeftPadMode(1);      // 1: independent 2: group1(up-down) / group2 (left-right) 4: group4(only 1)
  setLeftPadOrAllToggle(F("00000000001111110000")); 
  setJoyWay4(false); 
  setActiveJoystick(true); setJoystickInterval(100); // Active Slide Mode
  setJoyStrengthAdjust(true);                        // value of Joystick adjusted into 0 ~ 10
  setSSIDLabelMode(0); // not use change the name for blutooth of ESP32
  setRequest(false); //setRequestInterval(250); // Disable timer for check(0xF5)
  //useGravityAndInterval(180 * 2); // use or not the Gravity sensor with the interval
}

 

- Example of code processing for each function of a button that changes according to the leftPadMode and menu-related button.

void pin_control(uint8_t value) {
  if (value != 0) {
    switch (value) {
      case 11: if (leftPadMode > 1) Serial.println(F("Up DIR"));
               else Serial.println(F("button 1 : on")); 
                  break;
      case 10: if (leftPadMode > 1) Serial.println(F("Up off"));
               else Serial.println(F("button 1 : off"));
                  break;
      case 21: if (leftPadMode > 1) Serial.println(F("Left DIR"));
               else Serial.println(F("button 2 : on"));
                  break;
      case 20: if (leftPadMode > 1) Serial.println(F("Left off"));
               else Serial.println(F("button 2 : off"));
                  break;
      case 31: if (leftPadMode > 1) Serial.println(F("Right DIR"));
               else Serial.println(F("button 3 : on"));
                  break;
      case 30: if (leftPadMode > 1) Serial.println(F("Right off"));
               else Serial.println(F("button 3 : off"));
                  break;
      case 41: if (leftPadMode > 1) Serial.println(F("Down DIR"));
               else Serial.println(F("button 4 : on"));
                  break;
      case 40: if (leftPadMode > 1) Serial.println(F("Down off"));
               else Serial.println(F("button 4 : off"));
                  break;
      case 91: Serial.println(F("button 9 : on"));
               //uint8_t id, String title, String option
               dialogList(0, F("LEFT PAD"), F("SELECT,TOGGLE,PUSH")); // dialog message
                  break;
      case 90: Serial.println(F("button 9 : off"));
                  break;  
      case 101: Serial.println("button 10 : on");
                //uint8_t id, String title, String option
                dialogList(2, F("RIGHT PAD"), F("SELECT,TOGGLE,PUSH")); // dialog message
                  break;
    }
  }
}

 

- Example of modifying the function "CheckF9()" that handles dialog messages.

void CheckF9(String temp) {
  Serial.println(temp);
  if (temp.startsWith(F("RAD"))) {  }         // radio button
  else if (temp.startsWith(F("CKB"))) {  }    // Checkbox
  else if (temp.startsWith(F("CHD"))) {  }    // Select button
  else if (temp.startsWith(F("LSD"))) {       // List Window
    int ed = temp.indexOf(':');
    temp.remove(0, ed+1);
    ed = temp.indexOf(':');
    String ID = temp.substring(0, ed);
    uint8_t id = ID.toInt();
    temp.remove(0, ed+1);
    if (id == 0) {
      if (temp.startsWith(F("PUS"))) { leftPadMode = 0; setLeftPadOrAllToggle(F("0000")); }
      else if (temp.startsWith(F("TOG"))) {
        setLeftPadOrAllToggle(F("1111")); // set toggle for left button
        dialogList(1, F("LEFT PAD MODE AT TOGGLE"), F("SELECT,INDIVIDUAL,TWO GROUP,ONLY ONE")); // dialog message
      }
    } else if (id == 1) {
      if (temp.startsWith(F("IND"))) leftPadMode = 1; // independant
      else if (temp.startsWith(F("TWO"))) leftPadMode = 2; // 2 group: up/down, left/right
      else if (temp.startsWith(F("ONL"))) leftPadMode = 4; // 4psc button is 1 group
      setLeftPadMode(leftPadMode);
    } else if (id == 2) {
      if (temp.startsWith(F("PUS"))) { rightPadMode = 0; setRightPadToggle(F("0000")); } // set push for right button
      else { rightPadMode = 1; setRightPadToggle(F("1111")); }
    }
  }
  else if (temp.startsWith(F("STR"))) {  }       // Input text
}

 

1-1.ESP32_BT_JOYSTIC_MENU.zip

1-1.ESP32_BT_JOYSTIC_MENU.zip
0.00MB

 

https://youtu.be/2dOWqdPc2fY

 

 

Change name for the bluetooth of ESP32 on ADUPAD App

 

- Define array variable to save the name for the bluetooth of ESP32.

char btName[11] = "ESP32blue";  // 10 char

 

- SPIFFS Setting

#include "SPIFFS.h"  // ESP32 SPIFSPIFFS LIBRARY

bool saveConfig() {   // Write NAME
  String value = btName;
  Serial.println(value);
  File configFile = SPIFFS.open(F("/config.txt"), "w");
  if (!configFile) {
    Serial.println(F("Failed to open config file for writing"));
    return false;
  } else {
    configFile.println(value); // save at config.txt including '\n'
    configFile.close();
    return true;
  }
}

bool loadConfig() { // Read NAME
  File configFile = SPIFFS.open(F("/config.txt"), "r");
  if (!configFile) {
    Serial.println(F("Failed to open config file"));
    return false;
  } else {
    String temp = configFile.readStringUntil('\r');
    for (int i = 0; i < temp.length(); i++) btName[i] = temp[i];
    btName[temp.length()] = '\0';
    configFile.close();
    Serial.println(btName);
    return true;
  }
}

void setup() {
    if (SPIFFS.exists(F("/config.txt"))) loadConfig(); // if there is "/config.txt", read
    else saveConfig();  // if there is not, save a new config.txt 
}

// SPIFFS initialization code at serial monitor
void loop() {
  if(Serial.available()) { // Serial monitor
    String temp = Serial.readStringUntil('\n');
    Serial.println(temp);
    if(temp == "1"){   
      Serial.println(F("format..."));
      SPIFFS.format();
      Serial.println(F("done. can start upload."));
      while(1); // stanby for uploading
    } 
  }
}

 

- Save parsing data for name and remove the data for password and send a message applyed in Arduino.

void changeBTname(String str) { 
  bool save = false; 
  String temp = str.substring(0, 1);
  bool delPass = temp.toInt(); // if true, there is data for password which is not used in this sketch 
  str.remove(0, 1);
  if (delPass) str.remove(0, 6); // remove pass
  if (str != btName) {
    if (temp != "") {
      for (int i = 0; i < str.length(); i++) btName[i] = str[i];
      btName[str.length()] = '\0';
      save = true; 
    }
  }
  if (save) {
    saveConfig();
    temp  = F("<p>NAME:  ");
    temp += btName;
    temp += F("</p>Value's Saved.");
    if (delPass) temp += F("<br/>Function of Set pass is not provided.<br/>");
    temp += F(" The module will reboot.<br/>try to reconnect.");
    sendMessage(temp);
    sendDisconnect(); delay(500); ESP.restart();
  } else {
    temp  = F("There's no change.");
    if (delPass) temp += F("<br/>Function of Set pass is not provided.");
    sendMessage(temp);
  }
}

 

2.ESP32_BT_JOYSTIC_NAME.zip

2.ESP32_BT_JOYSTIC_NAME.zip
0.00MB

SPIFFS_FORMAT_ESP32.zip

SPIFFS_FORMAT_ESP32.zip
0.00MB

 

https://youtu.be/wyp9JWiUu0s

 

 

App Login

Obtain control authority using the password for bluetooth of ESP32.

 

- Define array variable to save the name for the bluetooth of ESP32 and the set password for login.

char pass[7] = "123456";        // 6 char
char btName[11] = "ESP32blue";  // 10 char

 

- Password handling code: response message, input prohibition setting, etc.

#define passWaitTime 120000
#define banResetTime 600000
unsigned long int disconnectTime = 0;

void banReset() { // if wrong password is entered 5 times, banned inputting for banResetTime
  if (millis() - disconnectTime > banResetTime) passAllow = 5; 
}

void passTerminate() { // if there's no input a pass within passWaitTime, terminate the connection
  if (millis() - disconnectTime > passWaitTime) { // 2min
    waitPass = false; appConnection = false; 
    sendMessage(F("It's disconnected by time expires.<br/>Try to reconnect."));
    sendDisconnect(); 
  }
}

void CheckF8(String temp) {
  if (temp == "") {
    uint8_t dump = SerialBT.read();
    if (dump == connectHD && passAllow) {
      temp = SerialBT.readStringUntil('\n');
      Serial.println(temp);
      if (waitPass) { 
        if (temp.startsWith(passName)) {
          temp.remove(0, passNameLen); bool ok = true;
          if (temp.length() == 6) {
            for (int i = 0; i < 6; i++) { if (temp[i] != pass[i]) { ok = false; break; } }
          }
          if (ok) { passOK = true; waitPass = false; iniSet(); send_State(); }
          else { passAllow--; disconnectTime = millis(); } // wrong password & timer set
          if (!passAllow) { // if wrong password is entered 5 times
            waitPass = false; appConnection = false; 
            sendMessage(F("You've got wrong password 5 times.<br/>Try to reconnect 10 Min later."));
            sendDisconnect(); 
          } else responsePass(ok);
        } else if (temp == F("connect")) { requestPass(usePass); disconnectTime = millis(); } // request pass & timer set
        else if (temp == F("disconnect")) { waitPass = false; appConnection = false; SerialBT.flush();}  
      } else {
        if (temp == F("connect")) {
          appConnection = true; 
          if (usePass) { requestPass(true); waitPass = true; disconnectTime = millis(); } 
          else { iniSet(); send_State(); }
        } 
      }
    } else if (dump == checkHD) {  }
    else SerialBT.disconnect();
  } else {
    Serial.println(temp);
    if (temp == F("disconnect")) { appConnection = false; passOK = false; SerialBT.flush();}
    else if (temp.startsWith(F("NA"))) { temp.remove(0, 2); changeBTname(temp); }
  }
}

 

3.ESP32_BT_JOYSTIC_PASS.zip

3.ESP32_BT_JOYSTIC_PASS.zip
0.01MB

 

https://youtu.be/reOJK8MkddE

 

[Arduino/ADUPAD] - ADUPAD - Arduino wireless remote control PAD application

 

 

 

+ Recent posts