//ArduinoIDEにコピーして使います。 by Paradise
  1. #include <Wire.h>
  2. #include <BLEDevice.h>
  3. #include <BLEServer.h>
  4. #include <BLEUtils.h>
  5. #include <BLE2902.h>
  6. #define JOY_OFFSET_X 127 // 原点(極0を求めるオフセット値
  7. #define JOY_OFFSET_Y 127 // 原点(極0を求めるオフセット値
  8. #define I2C_SDA 8 // Nuncuck SDA input ESP32=21 C3=8
  9. #define I2C_CLK 9 // Nuncuck CLK input ESP32=22 C3=9
  10. BLECharacteristic *pCharacteristic;
  11. bool deviceConnected = false;
  12. uint8_t nunbuff[12]; // array to store ESP output
  13. int cnt = 0;
  14. int x_val = 0; // 1byte Data
  15. int y_val = 0; // 1byte Data
  16. int z_val = 0; // 1byte Data
  17. char number, speed;
  18. float r, t;
  19. int r_val;
  20. //Online UUID Generator https://www.uuidgenerator.net/     *ここでUUIDを取得します。
  21. #define SERVICE_UUID "********-4458-11e9-b210-************"
  22. #define CHARACTERISTIC_UUID "********-4458-11e9-b210-************"
  23. #define DEVICE_NAME "ESP32_BLE"
  24. class MyServerCallbacks : public BLEServerCallbacks {
  25.   void onConnect(BLEServer *pServer) {
  26.     deviceConnected = true;
  27.   };
  28.   void onDisconnect(BLEServer *pServer) {
  29.     deviceConnected = false;
  30.   }
  31. };
  32. void setup() {
  33.   Serial.begin(115200);
  34.   Wire.begin(); // join i2c bus with address 0x52
  35.   nunchuck_init(); // send the initilization handshake
  36.   BLEDevice::init(DEVICE_NAME);
  37.   BLEServer *pServer = BLEDevice::createServer();
  38.   pServer->setCallbacks(new MyServerCallbacks());
  39.   BLEService *pService = pServer->createService(SERVICE_UUID);
  40.   pCharacteristic = pService->createCharacteristic(
  41.     CHARACTERISTIC_UUID,
  42.     BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_NOTIFY | BLECharacteristic::PROPERTY_INDICATE);
  43.   pCharacteristic->addDescriptor(new BLE2902());
  44.   pService->start();
  45.   pServer->getAdvertising()->start();
  46.   Serial.println("Waiting a client connection to notify...");
  47. }
  48. void nunchuck_init() {
  49.   Wire.beginTransmission(0x52); // transmit to device 0x52
  50.   Wire.write(0x40); // sends memory address *(blackNunchuck:0xF0)
  51.   Wire.write(0x00); // sends sent a zero. *(blackNunchuck:0x55)
  52.   Wire.endTransmission(); // stop transmitting
  53. }
  54. void send_zero() {
  55.   Wire.beginTransmission(0x52); // transmit to device 0x52
  56.   Wire.write(0x00); // sends one byte
  57.   Wire.endTransmission(); // stop transmitting
  58. }
  59. void loop() {
  60.   Wire.requestFrom(0x52, 6); // request data from nunchuck
  61.   while (Wire.available()) {
  62.     nunbuff[cnt] = nunchuk_decode_byte(Wire.read());
  63.     cnt++;
  64.   }
  65.   int z = 0;
  66.   int c = 0;
  67.   if (cnt >= 5) {
  68.     x_val = nunbuff[0];
  69.     y_val = nunbuff[1];
  70.     x_val = x_val + 5; // 最初に誤差補正をします。
  71.     y_val = y_val - 7; // 最初に誤差補正をします。
  72.     //Serial.print(" x_val = ");
  73.     //Serial.print(x_val);
  74.     //Serial.print(" y_val = ");
  75.     //Serial.print(y_val);
  76.     //Serial.print(" z_val = ");
  77.     //Serial.println(z_val);
  78.     if ((nunbuff[5] >> 0) & 1) z = 1; // The first bit of data of the 5byte (Nuncuck Z-button)
  79.     if ((nunbuff[5] >> 1) & 1) c = 1; // The second bit of data of the 5byte (Nuncuck C-button)
  80.     if ((z == 1) & (c == 1)) z_val = 0;
  81.     if ((z == 0) & (c == 1)) z_val = 1;
  82.     if ((z == 1) & (c == 0)) z_val = 2;
  83.     if ((z == 0) & (c == 0)) z_val = 3;
  84.     delay(1);
  85.   }
  86.   cnt = 0;
  87.   send_zero(); // send the request for next bytes
  88.   delay(10);
  89.   x_val = x_val - JOY_OFFSET_X; // 中心点を0にオフセット
  90.   y_val = JOY_OFFSET_Y - y_val; // 中心点を0にオフセット
  91.   r = sqrt((float)x_val * x_val + (float)y_val * y_val);
  92.   int r_val = r;
  93.   if (r_val <= 50) { // MotorSpeed変更用 PWM値呼び出しキャラクターの選択
  94.     speed = 'A';
  95.   } else if ((r_val >= 51) & (r_val <= 60)) {
  96.     speed = 'B';
  97.   } else if ((r_val >= 61) & (r_val <= 70)) {
  98.     speed = 'C';
  99.   } else if ((r_val >= 71) & (r_val <= 80)) {
  100.     speed = 'D';
  101.   } else if ((r_val >= 81) & (r_val <= 90)) {
  102.     speed = 'E';
  103.   } else if (r_val >= 91) {
  104.     speed = 'F';
  105.   }
  106.   if (x_val == 0) { // 極座標Pの位置により、角度Tを求めます。
  107.     if (y_val > 0) {
  108.       t = 90;
  109.     } else if (y_val < 0) {
  110.       t = 270;
  111.     } else {
  112.       t = 0;
  113.     }
  114.   } else {
  115.     t = atan((float)y_val / x_val) / 3.141592 * 180.0;
  116.     if (x_val < 0) {
  117.       t += 180;
  118.     } else if (y_val < 0) {
  119.       t += 360;
  120.     }
  121.   }
  122.   if (r > 50) { // ジョイスチックの位置が半径(r)が50を超えると計算開始
  123.     if (t < 22) {
  124.       if (z_val == 1) { //Zボタンが押された場合
  125.         number = '#';
  126.         //MoveRight(); 右横移動
  127.         //Serial.println("#");
  128.       } else {
  129.         number = '6';
  130.         //TurnRight(); 右旋回
  131.         //Serial.println("6");
  132.       }
  133.     } else if (t < 67) {
  134.       number = '9';
  135.       //MoveRearRight(); 右斜め後方移動
  136.       //Serial.println("9");
  137.     } else if (t < 112) {
  138.       number = '8';
  139.       //MoveBackward(); 後進
  140.       //Serial.println("8");
  141.     } else if (t < 157) {
  142.       number = '7';
  143.       //MoveRearLeft(); 左斜め後方移動
  144.       //Serial.println("7");
  145.     } else if (t < 202) {
  146.       if (z_val == 1) { //Zボタンが押された場合
  147.         number = '*';
  148.         //MoveLeft(); 左横移動
  149.         //Serial.println("*");
  150.       } else {
  151.         number = '4';
  152.         //TurnLeft(); 左旋回
  153.         //Serial.println("4");
  154.       }
  155.     } else if (t < 247) {
  156.       number = '1';
  157.       //MoveFrontLeft(); 左斜め前方移動
  158.       //Serial.println("1");
  159.     } else if (t < 292) {
  160.       number = '2';
  161.       //MoveForward(); 前進
  162.       //Serial.println("2");
  163.     } else if (t < 337) {
  164.       number = '3';
  165.       //MoveFrontRight(); 右斜め前方移動
  166.       //Serial.println("3");
  167.     } else {
  168.       if (z_val == 1) { //Zボタンが押された場合
  169.         number = '#';
  170.         //MoveRight(); 右横移動
  171.         //Serial.println("#");
  172.       } else {
  173.         number = '6';
  174.         //TurnRight(); 右旋回
  175.         //Serial.println("6");
  176.       }
  177.     }
  178.   } else {
  179.     number = 'S';
  180.     //Stop(); 停止
  181.     //Serial.println("S");
  182.   }
  183.   if (deviceConnected) { // コネクトした場合、numberとspeedの状態を通知する
  184.     char str1 = number;
  185.     char str2 = speed;
  186.     char str3[10];
  187.     sprintf(str3, "%d,%d\n", str1, str2);
  188.     printf("%s", str3);
  189.     //Serial.println(str3);
  190.     pCharacteristic->setValue(str3);
  191.     pCharacteristic->notify();
  192.   }
  193. }
  194. char nunchuk_decode_byte(char x) {
  195.   x = (x ^ 0x17) + 0x17;
  196.   return x;
  197. }