Motion Detect with Gyro sensor

#define SV_Motor_x_PIN 32
#define SV_Motor_y_PIN 26
#define SV_Motor_z_PIN 14

#include<math.h>
#define Deg2rad 3.1415 /180
#include <MadgwickAHRS.h>

//MPU9250
#include <Wire.h>
const int MPU_addr=0x68;  // I2C address of the MPU-6050
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ,MgX,MgY,MgZ;

//Actual unitization scale factor of acquired data
float SF_Acc = 16384; //acceleration scale factor   (digit/g) 
float SF_Gy  = 131; //Gyro scale factor (digit/dps)
float SF_Mg  = 500; //magnetic scale factor(500☛0.6かも。。)
float SF_Tmp = 333.87; //temperature scale factor
float g2mpss = 9.80665; //conversion from G to m/s2
float deg2rad = 3.14159265/180; //from degree to radian


Madgwick MadgwickFilter;

//servo motor define duty min and max
float duty_min = 25.6; // at 0 deg
float duty_max = 122.9; // at 180 deg
float duty_active = duty_max - duty_min;
float duty_mid = (duty_min + duty_max)/2; // at 90 deg

///タイマー割込み 参考https://55life555.blog.fc2.com/blog-entry-3194.html
volatile int timeCounter1;
hw_timer_t *timer1 = NULL; 
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
void IRAM_ATTR onTimer1(){

  portENTER_CRITICAL_ISR(&timerMux);
  timeCounter1++;
  portEXIT_CRITICAL_ISR(&timerMux);
}

void setup() {

  //SVmotor
  pinMode(SV_Motor_x_PIN, OUTPUT); //Brushless_Motor_PIN as OUTPUT
  pinMode(SV_Motor_y_PIN, OUTPUT); //Brushless_Motor_PIN as OUTPUT
  pinMode(SV_Motor_z_PIN, OUTPUT); //Brushless_Motor_PIN as OUTPUT
  ledcSetup(0, 50, 10);
  ledcSetup(1, 50, 10);
  ledcSetup(2, 50, 10);
  ledcAttachPin(SV_Motor_x_PIN,0); 
  ledcAttachPin(SV_Motor_y_PIN,1); 
  ledcAttachPin(SV_Motor_z_PIN,2); 

////////////////////////////Highly needed module
  Serial.begin(115200);
////////////////////////////

//MPU9250 set up
  Wire.begin();
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);
  setupMPU9255();

  //MadgwickFilter
  MadgwickFilter.begin(10);//filtering frequency 100Hz

//タイマー割込み
  timer1 = timerBegin(0, 80, true);
  timerAttachInterrupt(timer1, &onTimer1, true);
  timerAlarmWrite(timer1, 100000, true);
  timerAlarmEnable(timer1);

}

//value after sensor value scaling
float AcX_SF;
float AcY_SF;
float AcZ_SF;
float GyX_SF;
float GyY_SF;
float GyZ_SF;

//変数
struct strc{
  float AXIS_X;
  float AXIS_Y;
  float AXIS_Z;
};

float ROLL, PITCH, YAW;

void setupMPU9255() {
  Wire.beginTransmission(0x68);
  Wire.write(0x6B);
  Wire.write(0x00);
  Wire.endTransmission();

  Wire.beginTransmission(0x68);
  Wire.write(0x1A);
  Wire.write(0x05);
  Wire.endTransmission();

  Wire.beginTransmission(0x68);
  Wire.write(0x37);
  Wire.write(0x02);
  Wire.endTransmission();

  Wire.beginTransmission(0x0C);
  Wire.write(0x0A);
  Wire.write(0x16);
  Wire.endTransmission();
  delay(500);
}

//MPU9250 setup
void readCompass() {
  Wire.beginTransmission(0x0C);
  Wire.write(0x02);
  Wire.endTransmission();
  Wire.requestFrom(0x0C, 1);

  uint8_t ST1 = Wire.read();
  if (ST1 & 0x01) {
    Wire.beginTransmission(0x0C);
    Wire.write(0x03);
    Wire.endTransmission();
    Wire.requestFrom(0x0C, 7);
    uint8_t i = 0;
    uint8_t buf[7];
    while (Wire.available()) {
      buf[i++] = Wire.read();
    }
    if (!(buf[6] & 0x08)) {
      MgX = ((int16_t)buf[1] << 8) | buf[0];
      MgY = ((int16_t)buf[3] << 8) | buf[2];
      MgZ = ((int16_t)buf[5] << 8) | buf[4];
    }
  }
}

void loop() 
{ 
  unsigned long time;//「time」をunsigned longで変数宣言, declared "time"as variable
  time = millis();//プログラム実行からの経過時間(ms)をtimeに返す,Returns from program execution lapsed time (ms) to "time" 

    if (timeCounter1 > 0) 
      {
      portENTER_CRITICAL(&timerMux);
      timeCounter1--;
      portEXIT_CRITICAL(&timerMux);
    
      ////MPU9250関連////
      //読み出し, read
      Wire.beginTransmission(MPU_addr);
      Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
      Wire.endTransmission(false);
      Wire.requestFrom(MPU_addr,16,true);  // request a total of 14 registers
      AcX=Wire.read()<<8|Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)    
      AcY=Wire.read()<<8|Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
      AcZ=Wire.read()<<8|Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
      Tmp=Wire.read()<<8|Wire.read();  // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
      GyX=Wire.read()<<8|Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
      GyY=Wire.read()<<8|Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
      GyZ=Wire.read()<<8|Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
      readCompass();
    
      //Acc/g->m/s^2,Gy/dps->rad/s
      MadgwickFilter.update(GyX/SF_Gy, GyY/SF_Gy, GyZ/SF_Gy, AcX/SF_Acc, AcY/SF_Acc, AcZ/SF_Acc, MgX/SF_Mg, MgY/SF_Mg, MgZ/SF_Mg);
      ROLL = MadgwickFilter.getRoll();
      PITCH = MadgwickFilter.getPitch();
      YAW  = MadgwickFilter.getYaw();
    
      //for serial plot
      Serial.print(ROLL); Serial.print(",");
      Serial.print(PITCH); Serial.print(",");
      Serial.print(YAW);
      Serial.print("\n");

      //convert from angle of sensor for servo control
      ROLL = duty_mid + ROLL/180 * duty_active;
      ROLL = min(max(ROLL, duty_min), duty_max);
      
      PITCH = duty_mid + PITCH/180 * duty_active;
      PITCH = min(max(PITCH, duty_min), duty_max);
      
      YAW = duty_mid + YAW/180 * duty_active;
      YAW = min(max(YAW, duty_min), duty_max);
                   
      ledcWrite(0, ROLL);
      ledcWrite(1, PITCH);
      ledcWrite(2, YAW);
      
      delay(10);
    }

DIY RC : Simple Structure Air Plane

#include "BluetoothSerial.h"

#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif

#define Brushless_Motor_PIN 25
#define SV_Motor_PIN 32
int i = 0;

BluetoothSerial SerialBT;

void setup() {
  //Bluetooth
  Serial.begin(115200);
  SerialBT.begin("ESP32test"); //Bluetooth device name
  Serial.println("The device started, now you can pair it with bluetooth!");

  //Brushlessmotor
  pinMode(Brushless_Motor_PIN, OUTPUT); //Brushless_Motor_PIN as OUTPUT
  ledcSetup(0, 1000, 8); //PWM channel is 0, Frequency 1000Hz, 8 bit(Duty with 256 levels of resolution, the value is 0-255)
  ledcAttachPin(Brushless_Motor_PIN,0); //Assign channel 0 to Brushless_Motor_PIN

  //SVmotor
  pinMode(SV_Motor_PIN, OUTPUT); //Brushless_Motor_PIN as OUTPUT
  ledcSetup(10, 50, 10);
  ledcAttachPin(SV_Motor_PIN,10); 
}

uint8_t calculate_checksum(uint8_t *data) {
  uint8_t checksum = 0;
  checksum |= 0b11000000 & data[1];
  checksum |= 0b00110000 & data[2];
  checksum |= 0b00001100 & data[3];
  checksum |= 0b00000011 & data[4];
  return checksum;
}

void loop() {
  uint8_t recv_data[6];
  if (SerialBT.available()) {
    SerialBT.readBytes(recv_data, 6);
    
    if (recv_data[0] != 'T') {
      Serial.print("Receive error!");
      return;
    }

    if (recv_data[5] != calculate_checksum(recv_data)) {
      Serial.print("Decode error!");
      return;
    }
    Serial.printf("left_x: %d, left_y: %d, right_x: %d, right_y: %d\n", recv_data[1], recv_data[2], recv_data[3], recv_data[4]);
   if((recv_data[2] < 50)&&(i < 200)){//Duty MAX About 0.5(≒124/255)
      ledcWrite(0, i++);
          if(recv_data[3] > 200){//turn left
            ledcWrite(10, 110);
            }
          if(recv_data[3] < 50){//turn left
            ledcWrite(10, 50);
          }
          if((recv_data[3] >= 50)&&(recv_data[3] <= 200)){//turn standard position
            ledcWrite(10, 80);
          }
    }  
    if((recv_data[2] > 200)&&(i >= 1)){
      ledcWrite(0, i--);
          if(recv_data[3] > 200){//turn left
            ledcWrite(10, 110);
            }
          if(recv_data[3] < 50){//turn left
            ledcWrite(10, 50);
          }
          if((recv_data[3] >= 50)&&(recv_data[3] <= 200)){//turn standard position
            ledcWrite(10, 80);
          }
    }
    else{
          if(recv_data[3] > 200){//turn left
            ledcWrite(10, 110);
            }
          if(recv_data[3] < 50){//turn left
            ledcWrite(10, 50);
          }
          if((recv_data[3] >= 50)&&(recv_data[3] <= 200)){//turn standard position
            ledcWrite(10, 80);
          }
      }
  
    Serial.printf("i:%d\n", i);
  }
  delay(20);
}

controller side source code is same with below.

desktopmake.hateblo.jp

DIY Drone - ESP32 [Version 2] #4 (How to detect Drone angle) Source code

#include "BluetoothSerial.h"
#include<math.h>
#define Deg2rad 3.1415 /180
#include <MadgwickAHRS.h>

//MPU9250関連
#include <Wire.h>
const int MPU_addr=0x68;  // I2C address of the MPU-6050
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ,MgX,MgY,MgZ;

//取得データの実単位化スケールファクター
float SF_Acc = 16384; //加速度のスケールファクタ   (digit/g) 
float SF_Gy  = 131; //#ジャイロのスケールファクタ  (digit/dps)
float SF_Mg  = 500; //磁気のスケールファクタ(500☛0.6かも。。)
float SF_Tmp = 333.87; //温度のスケールファクタ
float g2mpss = 9.80665; //Gをm/s2に変換
float deg2rad = 3.14159265/180; //ディグリーをラジアンに

int i;

#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif

BluetoothSerial SerialBT;
Madgwick MadgwickFilter;

///タイマー割込み 参考https://55life555.blog.fc2.com/blog-entry-3194.html
volatile int timeCounter1;
hw_timer_t *timer1 = NULL; 
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
void IRAM_ATTR onTimer1(){

  portENTER_CRITICAL_ISR(&timerMux);
  timeCounter1++;
  portEXIT_CRITICAL_ISR(&timerMux);
}

void setup() {
  //Bluetooth
  Serial.begin(115200);
  SerialBT.begin("ESP32test"); //Bluetooth device name
  Serial.println("The device started, now you can pair it with bluetooth!");

  //Brushlessmotor
//  pinMode(Brushless_Motor_PIN, OUTPUT);//Brushless_Motor_PIN as OUTPUT
//  ledcSetup(0, 1000, 8);//PWM channel is 0, Frequency 1000Hz, 8 bit(Duty with 256 levels of resolution, the value is 0-255)
//  ledcAttachPin(Brushless_Motor_PIN,0);//Assign channel 0 to Brushless_Motor_PIN

//MPU9250 set up
  Wire.begin();
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);
  setupMPU9255();

  //MadgwickFilter
  MadgwickFilter.begin(10);//filtering frequency 100Hz

//タイマー割込み
  timer1 = timerBegin(0, 80, true);
  timerAttachInterrupt(timer1, &onTimer1, true);
  timerAlarmWrite(timer1, 100000, true);
  timerAlarmEnable(timer1);
}

///通信データの正しさの確認
uint8_t calculate_checksum(uint8_t *data) {
  uint8_t checksum = 0;
  checksum |= 0b11000000 & data[1];
  checksum |= 0b00110000 & data[2];
  checksum |= 0b00001100 & data[3];
  checksum |= 0b00000011 & data[4];
  return checksum;
}

//センサー値スケール化後数値
float AcX_SF;
float AcY_SF;
float AcZ_SF;
float GyX_SF;
float GyY_SF;
float GyZ_SF;

//変数
struct strc{
  float AXIS_X;
  float AXIS_Y;
  float AXIS_Z;
};

float ROLL, PITCH, YAW;

void setupMPU9255() {
  Wire.beginTransmission(0x68);
  Wire.write(0x6B);
  Wire.write(0x00);
  Wire.endTransmission();

  Wire.beginTransmission(0x68);
  Wire.write(0x1A);
  Wire.write(0x05);
  Wire.endTransmission();

  Wire.beginTransmission(0x68);
  Wire.write(0x37);
  Wire.write(0x02);
  Wire.endTransmission();

  Wire.beginTransmission(0x0C);
  Wire.write(0x0A);
  Wire.write(0x16);
  Wire.endTransmission();
  delay(500);
}

//MPU9250セットアップ関連
void readCompass() {
  Wire.beginTransmission(0x0C);
  Wire.write(0x02);
  Wire.endTransmission();
  Wire.requestFrom(0x0C, 1);

  uint8_t ST1 = Wire.read();
  if (ST1 & 0x01) {
    Wire.beginTransmission(0x0C);
    Wire.write(0x03);
    Wire.endTransmission();
    Wire.requestFrom(0x0C, 7);
    uint8_t i = 0;
    uint8_t buf[7];
    while (Wire.available()) {
      buf[i++] = Wire.read();
    }
    if (!(buf[6] & 0x08)) {
      MgX = ((int16_t)buf[1] << 8) | buf[0];
      MgY = ((int16_t)buf[3] << 8) | buf[2];
      MgZ = ((int16_t)buf[5] << 8) | buf[4];
    }
  }
}

void loop() {
unsigned long time;//「time」をunsigned longで変数宣言, declared "time"as variable
time = millis();//プログラム実行からの経過時間(ms)をtimeに返す,Returns from program execution lapsed time (ms) to "time" 

if (timeCounter1 > 0) {
  portENTER_CRITICAL(&timerMux);
  timeCounter1--;
  portEXIT_CRITICAL(&timerMux);

  ////MPU9250関連////
  //読み出し, read
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_addr,16,true);  // request a total of 14 registers
  AcX=Wire.read()<<8|Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)    
  AcY=Wire.read()<<8|Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
  AcZ=Wire.read()<<8|Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
  Tmp=Wire.read()<<8|Wire.read();  // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
  GyX=Wire.read()<<8|Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
  GyY=Wire.read()<<8|Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
  GyZ=Wire.read()<<8|Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
  readCompass();

  //実単位化(Acc/g->m/s^2,Gy/dps->rad/s)
  MadgwickFilter.update(GyX/SF_Gy, GyY/SF_Gy, GyZ/SF_Gy, AcX/SF_Acc, AcY/SF_Acc, AcZ/SF_Acc, MgX/SF_Mg, MgY/SF_Mg, MgZ/SF_Mg);
  ROLL = MadgwickFilter.getRoll();
  PITCH = MadgwickFilter.getPitch();
  YAW  = MadgwickFilter.getYaw();

  //書き出し
  Serial.print(ROLL); Serial.print(",");
  Serial.print(PITCH); Serial.print(",");
  Serial.print(YAW);
  Serial.print("\n");
  //Serial.print(AcZ/SF_Acc*g2mpss);
  delay(10);
  
///////////////////////////////////////////  
  uint8_t recv_data[6];
  if (SerialBT.available()) {
    SerialBT.readBytes(recv_data, 6);
    
    if (recv_data[0] != 'T') {
      Serial.print("Receive error!");
      return;
    }

    if (recv_data[5] != calculate_checksum(recv_data)) {
      Serial.print("Decode error!");
      return;
    }
    Serial.printf("left_x: %d, left_y: %d, right_x: %d, right_y: %d\n", recv_data[1], recv_data[2], recv_data[3], recv_data[4]);
    if((recv_data[2] < 50)&&(i < 200)){//Duty MAX About 0.5(≒124/255)
      ledcWrite(0, i++);
    }
    if((recv_data[2] > 200)&&(i >= 1)){
      ledcWrite(0, i--);
    }
    Serial.printf("i:%d\n", i);
  }
  delay(20);
}
}

DIY Drone - ESP32 [Version 2] #3 (How to control Brushless Motor) Source code

Receiver side

#include "BluetoothSerial.h"

#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif

#define Brushless_Motor_PIN 25
int i = 0;

BluetoothSerial SerialBT;

void setup() {
  //Bluetooth
  Serial.begin(115200);
  SerialBT.begin("ESP32test"); //Bluetooth device name
  Serial.println("The device started, now you can pair it with bluetooth!");

  //Brushlessmotor
  pinMode(Brushless_Motor_PIN, OUTPUT);//Brushless_Motor_PIN as OUTPUT
  ledcSetup(0, 1000, 8);//PWM channel is 0, Frequency 1000Hz, 8 bit(Duty with 256 levels of resolution, the value is 0-255)
  ledcAttachPin(Brushless_Motor_PIN,0);//Assign channel 0 to Brushless_Motor_PIN
}

uint8_t calculate_checksum(uint8_t *data) {
  uint8_t checksum = 0;
  checksum |= 0b11000000 & data[1];
  checksum |= 0b00110000 & data[2];
  checksum |= 0b00001100 & data[3];
  checksum |= 0b00000011 & data[4];
  return checksum;
}

void loop() {
  uint8_t recv_data[6];
  if (SerialBT.available()) {
    SerialBT.readBytes(recv_data, 6);
    
    if (recv_data[0] != 'T') {
      Serial.print("Receive error!");
      return;
    }

    if (recv_data[5] != calculate_checksum(recv_data)) {
      Serial.print("Decode error!");
      return;
    }
    Serial.printf("left_x: %d, left_y: %d, right_x: %d, right_y: %d\n", recv_data[1], recv_data[2], recv_data[3], recv_data[4]);
    if((recv_data[2] < 50)&&(i < 125)){//Duty MAX About 0.5(≒124/255)
      ledcWrite(0, i++);
    }
    if((recv_data[2] > 200)&&(i >= 1)){
      ledcWrite(0, i--);
    }
    Serial.printf("i:%d\n", i);
  }
  delay(20);
}

Controller side is ↓↓↓↓↓↓↓↓
desktopmake.hateblo.jp

DIY Drone - ESP32 [Version 2] #2 (How to connect ESP32 to ESP32 by Bluetooth) Source Code

Check MACadd

void setup(void) {
  Serial.begin(115200);
  Serial.println("-----------------");
  uint8_t macBT[6];
  esp_read_mac(macBT, ESP_MAC_BT);
}

void loop() {
  uint8_t macBT[6];
  esp_read_mac(macBT, ESP_MAC_BT);
  Serial.printf("%02X:%02X:%02X:%02X:%02X:%02X\r\n", macBT[0], macBT[1], macBT[2], macBT[3], macBT[4], macBT[5]);
  delay(10000);  
}

Controller Side

#include "BluetoothSerial.h"
#define Right_VRX_PIN 12
#define Right_VRY_PIN 13
#define Left_VRX_PIN 25
#define Left_VRY_PIN 26

int left_x_val;
int left_y_val;
int right_x_val;
int right_y_val;  

BluetoothSerial SerialBT;

String MACadd = "9C:9C:1F:D0:05:4E";//Write Drone side MAC address
uint8_t address[6]  = {0x9C, 0x9C, 0x1F, 0xD0, 0x05, 0x4E};//Write Drone side MAC address in HEX
bool connected;

void setup() {
  Serial.begin(115200);
  SerialBT.begin("ESP32test", true); 
  Serial.println("The device started in master mode, make sure remote BT device is on!");
  
  // connect(address) is fast (upto 10 secs max), connect(name) is slow (upto 30 secs max) as it needs
  // to resolve name to address first, but it allows to connect to different devices with the same name.
  // Set CoreDebugLevel to Info to view devices bluetooth address and device names
  connected = SerialBT.connect(address);
  
  if(connected) {
    Serial.println("Connected Succesfully!");
  } else {
    while(!SerialBT.connected(10000)) {
      Serial.println("Failed to connect. Make sure remote device is available and in range, then restart app."); 
    }
  }
  // disconnect() may take upto 10 secs max
  if (SerialBT.disconnect()) {
    Serial.println("Disconnected Succesfully!");
  }
  // this would reconnect to the name(will use address, if resolved) or address used with connect(name/address).
  SerialBT.connect();

  pinMode(Left_VRX_PIN, INPUT);
  pinMode(Left_VRY_PIN, INPUT);
  pinMode(Right_VRX_PIN, INPUT);
  pinMode(Right_VRX_PIN, INPUT);
  
}

uint8_t calculate_checksum(uint8_t *data) {
  uint8_t checksum = 0;
  checksum |= 0b11000000 & data[1];
  checksum |= 0b00110000 & data[2];
  checksum |= 0b00001100 & data[3];
  checksum |= 0b00000011 & data[4];
  return checksum;
}

void loop() {

  uint8_t send_data[6];
  
  left_x_val = analogRead(Left_VRX_PIN) >> 4;//value 0-255 (">> 4" convert maximum value from 4095 to 255 )
  left_y_val = analogRead(Left_VRY_PIN) >> 4;//value 0-255  
  right_x_val = analogRead(Right_VRX_PIN) >> 4;//value 0-255
  right_y_val = analogRead(Right_VRY_PIN) >> 4;//value 0-255

  send_data[0] = 'T';
  send_data[1] = left_x_val;
  send_data[2] = left_y_val;
  send_data[3] = right_x_val;
  send_data[4] = right_y_val;
  send_data[5] = calculate_checksum(send_data);
  SerialBT.write(send_data, 6);

  delay(20);
}

Receiver Side

#include "BluetoothSerial.h"

#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif

BluetoothSerial SerialBT;

void setup() {
  Serial.begin(115200);
  SerialBT.begin("ESP32test"); //Bluetooth device name
  Serial.println("The device started, now you can pair it with bluetooth!");
}

uint8_t calculate_checksum(uint8_t *data) {
  uint8_t checksum = 0;
  checksum |= 0b11000000 & data[1];
  checksum |= 0b00110000 & data[2];
  checksum |= 0b00001100 & data[3];
  checksum |= 0b00000011 & data[4];
  return checksum;
}

void loop() {
  uint8_t recv_data[6];
  if (SerialBT.available()) {
    SerialBT.readBytes(recv_data, 6);
    
    if (recv_data[0] != 'T') {
      Serial.print("Receive error!");
      return;
    }

    if (recv_data[5] != calculate_checksum(recv_data)) {
      Serial.print("Decode error!");
      return;
    }
    Serial.printf("left_x: %d, left_y: %d, right_x: %d, right_y: %d\n", recv_data[1], recv_data[2], recv_data[3], recv_data[4]);
  }
  delay(20);
}

DIY Drone - ESP32 [Version 2] #1 (How to make Joystick Controller) Source Code

//ref. https://101010.fun/iot/esp32-joystick.html
//ref. https://wak-tech.com/archives/742

#define Right_VRX_PIN 12
#define Right_VRY_PIN 13
#define Left_VRX_PIN 25
#define Left_VRY_PIN 26

int left_x_val;
int left_y_val;
int right_x_val;
int right_y_val;  

void setup() {
  Serial.begin(115200);
  pinMode(Left_VRX_PIN, INPUT);
  pinMode(Left_VRY_PIN, INPUT);
  pinMode(Right_VRX_PIN, INPUT);
  pinMode(Right_VRX_PIN, INPUT);
  }

void loop() {
  
  left_x_val = analogRead(Left_VRX_PIN) >> 4;//value 0-255 (">> 4" convert maximum value from 4095 to 255 )
  left_y_val = analogRead(Left_VRY_PIN) >> 4;//value 0-255  
  right_x_val = analogRead(Right_VRX_PIN) >> 4;//value 0-255
  right_y_val = analogRead(Right_VRY_PIN) >> 4;//value 0-255
  
  Serial.printf("left_x: %d, left_y: %d, right_x: %d, right_y: %d\n", left_x_val, left_y_val, right_x_val, right_y_val);

  delay(100);
}

DIY RC Bowling [ESP32 ] Source code

Bowl side source code

//参考https://rikoubou.hatenablog.com/entry/2017/10/06/181805

#include <WiFi.h>
#include <WiFiUdp.h>
#include "esp_system.h"

const char ssid[] = "ESP32_wifi"; // SSID
const char pass[] = "esp32pass";  // password
const int localPort = 10000;      // ポート番号(pythonのポート番号に合わせる)

const IPAddress ip(192, 168, 4, 1);       // IPアドレス(pythonのIPアドレスに合わせる)
const IPAddress subnet(255, 255, 255, 0); // サブネットマスク

WiFiUDP udp;

//https://wak-tech.com/archives/742
const int dcmotor = 32;
const int svmotor = 2;

void setup() {

  //UDP通信関係
  Serial.begin(115200);

  WiFi.softAP(ssid, pass);           // SSIDとパスの設定
  delay(100);                        // 追記:このdelayを入れないと失敗する場合がある
  WiFi.softAPConfig(ip, ip, subnet); // IPアドレス、ゲートウェイ、サブネットマスクの設定

  Serial.print("AP IP address: ");
  IPAddress myIP = WiFi.softAPIP();
  Serial.println(myIP);

  Serial.println("Starting UDP");
  udp.begin(localPort);  // UDP通信の開始(引数はポート番号)

  Serial.print("Local port: ");
  Serial.println(localPort);

  //LEDC関係
  // 使用するタイマーのチャネルと周波数を設定
  ledcSetup(0, 12800, 8);
  ledcSetup(10, 50, 10);
  // ledPinをチャネル0へ接続
  ledcAttachPin(dcmotor, 0);
  ledcAttachPin(svmotor, 10);
}

void loop() {
  // 初期の状態を指定
  static uint8_t dc = 0;
  static uint8_t sv = 73;
  
  if (udp.parsePacket()) {
    
    char val = udp.read();
    val = int(val);

    if (val == 48){//停止
      dc = 0;
      sv = 73;
    }

    else if (val == 49){//前
      dc = 50;
      sv = 73;
    }


    else if (val == 50){//右
      dc = 0;
      sv = 26;
    }

    else if (val == 51){//後
      dc = 0;
      sv = 73;
    }

    else if (val == 52){//左
      dc = 0;
      sv = 123;
    }

    else if (val == 53){//右前
      dc = 30;
      sv = 26;
    }

    else if (val == 56){//左前
      dc = 30;
      sv = 123;
    }
 
    ledcWrite(0, dc);
    ledcWrite(10,sv);    

  }  

}

Controller(PC and Plyastation3) side source code

#参考https://rikoubou.hatenablog.com/entry/2017/10/06/181805
#参考https://greenhornprofessional.hatenablog.com/entry/2020/09/13/223155

from __future__ import print_function
import socket
import time
from time import sleep
from contextlib import closing
import pygame
from pygame.locals import *

###ジョイスティック側
# ジョイスティックの初期化
pygame.joystick.init()
try:
   # ジョイスティックインスタンスの生成
   joystick = pygame.joystick.Joystick(0)
   joystick.init()
   print('ジョイスティックの名前:', joystick.get_name())
   print('ボタン数 :', joystick.get_numbuttons())
except pygame.error:
   print('ジョイスティックが接続されていません')

# pygameの初期化
pygame.init()

# 画面の生成
SCREEN_SIZE = (640, 480)  # 画面サイズ (横/縦)
STEP = 10       #キーボード/ハットスイッチの反応の良さ
X_CENTER = int(SCREEN_SIZE[0]/2)
Y_CENTER = int(SCREEN_SIZE[1]/2)

screen = pygame.display.set_mode(SCREEN_SIZE) 
screen2 = pygame.display.set_mode(SCREEN_SIZE) 

screen.fill((0,0,0))
screen2.fill((0,0,0))

#通信部分
def main():
  host = '192.168.4.1' # IPアドレス
  port = 10000 # ポート番号
  sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #AFINETは、V4を使うという意味、DGRAMはUDP指定の意味
  with closing(sock):
    while True:
        
   # イベントの取得
       for e in pygame.event.get():
       # 終了ボタン
           if e.type == QUIT:
               active = False
    
           # ジョイスティックのボタンの入力
           if e.type == pygame.locals.JOYAXISMOTION:
               print(joystick.get_axis(0), -1*joystick.get_axis(1), joystick.get_axis(2), -1*joystick.get_axis(3))


               command1 = -joystick.get_axis(1)+1
               command1 = str(round(command1))
               print(command1)
               print(type(command1))
               
               command2 = joystick.get_axis(2)+1
               command2 = str(round(command2))
               print(command2)
               print(type(command2))
               
               command = command1 + command2
               
               if command == "21": #前
                       command = "1"
                
               elif command == "12": #右
                       command = "2"
                        
               elif command == "01": #後
                       command = "3"

               elif command == "10": #左
                       command = "4"
                
               elif command == "22": #右前
                       command = "5"
                        
               elif command == "02": #右後
                       command = "6"

               elif command == "00": #左後
                       command = "7"

               elif command == "20": #右前
                       command = "8"
                    
               elif command == "11": #継続
                       command = "0"

               print(command)
               command = str(command).encode("UTF-8")
               print(command)
                
               
                  
               sock.sendto(command,(host, port))
               
               time.sleep(0.05)
        
               #sock.sendto(bytes(command, encoding='ascii'), (host, port))



    return

"""
      message = 'A'.encode('utf-8') # 送る文字列(ここでは「A」という文字列を送っている)
      print(message)
      sock.sendto(message, (host, port))
      time.sleep(1)
"""
    #return

if __name__ == '__main__':
  main()