Advertisement
firtel

xbox_controller_ble_motor

Mar 19th, 2022
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Arduino 12.71 KB | None | 0 0
  1. //ESP32 Arduino Core 1.0.4
  2. //NimBLE library 1.20
  3.  
  4. #define FASTLED_ESP32_I2S true
  5. #include <FastLED.h>
  6. #include <Arduino.h>
  7. #include <NimBLEDevice.h>
  8. #include <Wire.h>
  9.  
  10. #define NUM_LEDS 12
  11. #define LED_PIN 27
  12. #define BTN_PIN 39
  13. CRGB leds[NUM_LEDS];
  14.  
  15. //コントローラーの値代入用
  16. int lx = 0;
  17. int ly = 0;
  18. int rx = 0;
  19. int ry = 0;
  20. int lt = 0;
  21. int rt = 0;
  22.  
  23. //モーター出力設定
  24. int8_t speed_sendbuff[4] = { 0 };
  25. //進行方向用各要素定義
  26. int8_t MoveY[4] = { 50, 50, 50, 50 };
  27. int8_t MoveX[4] = { 50, -50, -50, 50 };
  28. int8_t ROTATE[4] = { 30, -30, 30, -30 };
  29.  
  30. //ポーリング用
  31. unsigned long lastMotor = 0;
  32. unsigned long lastupdate = 0;
  33.  
  34. void scanEndedCB(NimBLEScanResults results);
  35.  
  36. static NimBLEAdvertisedDevice* advDevice;
  37.  
  38. bool scanning = false;
  39. bool connected = false;
  40. static uint32_t scanTime = 0; /** 0 = scan forever */
  41.  
  42. static NimBLEAddress targetDeviceAddress("c8:3f:26:8b:5f:69");
  43.  
  44. static NimBLEUUID uuidServiceUnknown("00000001-5f60-4c4f-9c83-a7953298d40d");
  45. static NimBLEUUID uuidServiceGeneral("1801");
  46. static NimBLEUUID uuidServiceBattery("180f");
  47. static NimBLEUUID uuidServiceHid("1812");
  48. static NimBLEUUID uuidCharaReport("2a4d");
  49. static NimBLEUUID uuidCharaPnp("2a50");
  50. static NimBLEUUID uuidCharaHidInformation("2a4a");
  51. static NimBLEUUID uuidCharaPeripheralAppearance("2a01");
  52. static NimBLEUUID uuidCharaPeripheralControlParameters("2a04");
  53.  
  54. class ClientCallbacks : public NimBLEClientCallbacks {
  55.   void onConnect(NimBLEClient* pClient) {
  56.     Serial.println("Connected");
  57.     connected = true;
  58.     leds[0].setRGB(0,0,10);
  59.     FastLED.show();
  60.     // pClient->updateConnParams(120,120,0,60);
  61.   };
  62.  
  63.   void onDisconnect(NimBLEClient* pClient) {
  64.     Serial.print(pClient->getPeerAddress().toString().c_str());
  65.     Serial.println(" Disconnected");
  66.     connected = false;
  67.     leds[0].setRGB(10,0,0);
  68.     FastLED.show();
  69.   };
  70.  
  71.   /** Called when the peripheral requests a change to the connection parameters.
  72.    *  Return true to accept and apply them or false to reject and keep
  73.    *  the currently used parameters. Default will return true.
  74.    */
  75.   bool onConnParamsUpdateRequest(NimBLEClient* pClient,
  76.                                  const ble_gap_upd_params* params) {
  77.     Serial.print("onConnParamsUpdateRequest");
  78.     if (params->itvl_min < 24) { /** 1.25ms units */
  79.       return false;
  80.     } else if (params->itvl_max > 40) { /** 1.25ms units */
  81.       return false;
  82.     } else if (params->latency > 2) { /** Number of intervals allowed to skip */
  83.       return false;
  84.     } else if (params->supervision_timeout > 100) { /** 10ms units */
  85.       return false;
  86.     }
  87.  
  88.     return true;
  89.   };
  90.  
  91.   /********************* Security handled here **********************
  92.   ****** Note: these are the same return values as defaults ********/
  93.   uint32_t onPassKeyRequest() {
  94.     Serial.println("Client Passkey Request");
  95.     /** return the passkey to send to the server */
  96.     return 0;
  97.   };
  98.  
  99.   bool onConfirmPIN(uint32_t pass_key) {
  100.     Serial.print("The passkey YES/NO number: ");
  101.     Serial.println(pass_key);
  102.     /** Return false if passkeys don't match. */
  103.     return true;
  104.   };
  105.  
  106.   /** Pairing process complete, we can check the results in ble_gap_conn_desc */
  107.   void onAuthenticationComplete(ble_gap_conn_desc* desc) {
  108.     Serial.println("onAuthenticationComplete");
  109.     if (!desc->sec_state.encrypted) {
  110.       Serial.println("Encrypt connection failed - disconnecting");
  111.       /** Find the client with the connection handle provided in desc */
  112.       NimBLEDevice::getClientByID(desc->conn_handle)->disconnect();
  113.       return;
  114.     }
  115.   };
  116. };
  117.  
  118. /** Define a class to handle the callbacks when advertisments are received */
  119. class AdvertisedDeviceCallbacks : public NimBLEAdvertisedDeviceCallbacks {
  120.   void onResult(NimBLEAdvertisedDevice* advertisedDevice) {
  121.     Serial.print("Advertised Device found: ");
  122.     Serial.println(advertisedDevice->toString().c_str());
  123.     Serial.printf("name:%s, address:%s\n", advertisedDevice->getName().c_str(),
  124.                   advertisedDevice->getAddress().toString().c_str());
  125.     Serial.printf("uuidService:%s\n",
  126.                   advertisedDevice->haveServiceUUID()
  127.                       ? advertisedDevice->getServiceUUID().toString().c_str()
  128.                       : "none");
  129.  
  130.     if (advertisedDevice->getAddress().equals(targetDeviceAddress))
  131.     // if (advertisedDevice->isAdvertisingService(uuidServiceHid))
  132.     {
  133.       Serial.println("Found Our Service");
  134.       /** stop scan before connecting */
  135.       NimBLEDevice::getScan()->stop();
  136.       /** Save the device reference in a global for the client to use*/
  137.       advDevice = advertisedDevice;
  138.     }
  139.   };
  140. };
  141.  
  142. unsigned long printInterval = 100UL;
  143.  
  144. /** Notification / Indication receiving handler callback */
  145. void notifyCB(NimBLERemoteCharacteristic* pRemoteCharacteristic, uint8_t* pData,
  146.               size_t length, bool isNotify) {
  147.   static bool isPrinting = false;
  148.   static unsigned long printedAt = 0;
  149.   if (isPrinting || millis() - printedAt < printInterval) return;
  150.   isPrinting = true;
  151.   std::string str = (isNotify == true) ? "Notification" : "Indication";
  152.   str += " from ";
  153.   /** NimBLEAddress and NimBLEUUID have std::string operators */
  154.   str += std::string(
  155.       pRemoteCharacteristic->getRemoteService()->getClient()->getPeerAddress());
  156.   str += ": Service = " +
  157.          std::string(pRemoteCharacteristic->getRemoteService()->getUUID());
  158.   str += ", Characteristic = " + std::string(pRemoteCharacteristic->getUUID());
  159.   // str += ", Value = " + std::string((char*)pData, length);
  160.   Serial.println(str.c_str());
  161.   //lx = pData[1] << 8 | pData[0];
  162.   //ly = pData[3] << 8 | pData[2];
  163.   //ry = pData[5] << 8 | pData[4];
  164.   //rx = pData[7] << 8 | pData[6];
  165.   //lt = pData[9] << 8 | pData[8];
  166.   //rt = pData[11] << 8 | pData[10];
  167.   //Serial.print("info: ");
  168.   //Serial.print(lx);
  169.   //Serial.println("");
  170.   //Serial.print(pData[1]);
  171.   //Serial.println("");
  172.   //モータコントローラが8bitなので下位だけ使用
  173.   lx = pData[1] - 127;
  174.   ly = pData[3] - 127;
  175.   ry = pData[5] - 127;
  176.   rx = pData[7] - 127;
  177.   lt = pData[9];
  178.   rt = pData[11];
  179.  
  180.  
  181.   /*Serial.print("value: ");
  182.   for (int i = 0; i < length; ++i) {
  183.     Serial.printf(" %02x", pData[i]);
  184.   }
  185.   Serial.println("");*/
  186.   printedAt = millis();
  187.   isPrinting = false;
  188. }
  189.  
  190. void scanEndedCB(NimBLEScanResults results) {
  191.   Serial.println("Scan Ended");
  192.   scanning = false;
  193. }
  194.  
  195. static ClientCallbacks clientCB;
  196.  
  197. void charaPrintId(NimBLERemoteCharacteristic* pChara) {
  198.   Serial.printf("s:%s c:%s h:%d",
  199.                 pChara->getRemoteService()->getUUID().toString().c_str(),
  200.                 pChara->getUUID().toString().c_str(), pChara->getHandle());
  201. }
  202.  
  203. void printValue(std::__cxx11::string str) {
  204.   Serial.printf("str: %s\n", str.c_str());
  205.   Serial.printf("hex:");
  206.   for (auto v : str) {
  207.     Serial.printf(" %02x", v);
  208.   }
  209.   Serial.println("");
  210. }
  211.  
  212. void charaRead(NimBLERemoteCharacteristic* pChara) {
  213.   if (pChara->canRead()) {
  214.     charaPrintId(pChara);
  215.     Serial.println(" canRead");
  216.     auto str = pChara->readValue();
  217.     if (str.size() == 0) {
  218.       str = pChara->readValue();
  219.     }
  220.     printValue(str);
  221.   }
  222. }
  223.  
  224. void charaSubscribeNotification(NimBLERemoteCharacteristic* pChara) {
  225.   if (pChara->canNotify()) {
  226.     charaPrintId(pChara);
  227.     Serial.println(" canNotify ");
  228.     if (pChara->subscribe(true, notifyCB, true)) {
  229.       Serial.println("set notifyCb");
  230.       // return true;
  231.     } else {
  232.       Serial.println("failed to subscribe");
  233.     }
  234.   }
  235. }
  236.  
  237. bool afterConnect(NimBLEClient* pClient) {
  238.   for (auto pService : *pClient->getServices(true)) {
  239.     auto sUuid = pService->getUUID();
  240.     if (!sUuid.equals(uuidServiceHid)) {
  241.       continue;  // skip
  242.     }
  243.     Serial.println(pService->toString().c_str());
  244.     for (auto pChara : *pService->getCharacteristics(true)) {
  245.       charaRead(pChara);
  246.       charaSubscribeNotification(pChara);
  247.     }
  248.   }
  249.  
  250.   return true;
  251. }
  252.  
  253. /** Handles the provisioning of clients and connects / interfaces with the
  254.  * server */
  255. bool connectToServer(NimBLEAdvertisedDevice* advDevice) {
  256.   NimBLEClient* pClient = nullptr;
  257.  
  258.   /** Check if we have a client we should reuse first **/
  259.   if (NimBLEDevice::getClientListSize()) {
  260.     pClient = NimBLEDevice::getClientByPeerAddress(advDevice->getAddress());
  261.     if (pClient) {
  262.       pClient->connect();
  263.     }
  264.   }
  265.  
  266.   /** No client to reuse? Create a new one. */
  267.   if (!pClient) {
  268.     if (NimBLEDevice::getClientListSize() >= NIMBLE_MAX_CONNECTIONS) {
  269.       Serial.println("Max clients reached - no more connections available");
  270.       return false;
  271.     }
  272.  
  273.     pClient = NimBLEDevice::createClient();
  274.  
  275.     Serial.println("New client created");
  276.  
  277.     pClient->setClientCallbacks(&clientCB, false);
  278.     pClient->setConnectionParams(12, 12, 0, 51);
  279.     pClient->setConnectTimeout(5);
  280.     pClient->connect(advDevice, false);
  281.   }
  282.  
  283.   int retryCount = 5;
  284.   while (!pClient->isConnected()) {
  285.     if (retryCount <= 0) {
  286.       return false;
  287.     } else {
  288.       Serial.println("try connection again " + String(millis()));
  289.       delay(1000);
  290.     }
  291.  
  292.     NimBLEDevice::getScan()->stop();
  293.     pClient->disconnect();
  294.     delay(500);
  295.     // Serial.println(pClient->toString().c_str());
  296.     pClient->connect(true);
  297.     --retryCount;
  298.   }
  299.  
  300.   Serial.print("Connected to: ");
  301.   Serial.println(pClient->getPeerAddress().toString().c_str());
  302.   Serial.print("RSSI: ");
  303.   Serial.println(pClient->getRssi());
  304.  
  305.   pClient->discoverAttributes();
  306.  
  307.   bool result = afterConnect(pClient);
  308.   if (!result) {
  309.     return result;
  310.   }
  311.  
  312.   Serial.println("Done with this device!");
  313.   return true;
  314. }
  315.  
  316. void setup() {
  317.   FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
  318.   leds[0].setRGB(20,0,0);
  319.   FastLED.show();
  320.   Serial.begin(115200);
  321.   Serial.println("Starting NimBLE Client");
  322.   /** Initialize NimBLE, no device name spcified as we are not advertising */
  323.   NimBLEDevice::init("");
  324.   NimBLEDevice::setOwnAddrType(BLE_OWN_ADDR_RANDOM);
  325.   NimBLEDevice::setSecurityAuth(true, true, true);
  326.   NimBLEDevice::setPower(ESP_PWR_LVL_P9); /** +9db */
  327.  
  328.   Wire.begin(26,32);//SDA SCL
  329.  
  330. }
  331.  
  332. void startScan() {
  333.   scanning = true;
  334.   auto pScan = NimBLEDevice::getScan();
  335.   pScan->setAdvertisedDeviceCallbacks(new AdvertisedDeviceCallbacks());
  336.   pScan->setInterval(45);
  337.   pScan->setWindow(15);
  338.   Serial.println("Start scan");
  339.   pScan->start(scanTime, scanEndedCB);
  340. }
  341.  
  342. void loop() {
  343.   if (lastupdate + 2000 <= millis()) {
  344.     lastupdate = millis();//次の実行のために時間更新
  345.   if (!connected) {
  346.     if (!scanning && advDevice == nullptr) {
  347.       startScan();
  348.     }
  349.     if (advDevice != nullptr) {
  350.       if (connectToServer(advDevice)) {
  351.         Serial.println("Success! we should now be getting notifications");
  352.       } else {
  353.         Serial.println("Failed to connect");
  354.       }
  355.       advDevice = nullptr;
  356.     }
  357.   }
  358.   }
  359.   if (lastMotor + 50 <= millis()) {
  360.     lastMotor = millis();//次の実行のために時間更新
  361.     setspeed(lx/127.00,ly/-127.00,ry/127.00);
  362.   }
  363.   // Serial.println("scanning:" + String(scanning) + " connected:" + String(connected) + " advDevice is nullptr:" + String(advDevice == nullptr));
  364.   //delay(2000);
  365. }
  366.  
  367. uint8_t setspeed(float x, float y, float r) {  // 前後左右回転それぞれを係数と掛けて足す
  368.     for (int i = 0; i < 4; i++) {
  369.         //speed_sendbuff[i] = FORWARD[i] * f;
  370.         //speed_sendbuff[i] += BACKWARD[i] * b;
  371.         //speed_sendbuff[i] += RIGHT[i] * r;
  372.         //speed_sendbuff[i] += LEFT[i] * l;
  373.         //speed_sendbuff[i] += ROTATE_L[i] * rl;
  374.         //speed_sendbuff[i] += ROTATE_R[i] * rr;
  375.         speed_sendbuff[i] = MoveY[i] * y;
  376.         speed_sendbuff[i] += MoveX[i] * x;
  377.         speed_sendbuff[i] += ROTATE[i] * r;
  378.     }
  379.     float limit = 0.0;
  380.     for (int i = 0; i < 4; i++) {
  381.         // speedが100を超えないようにリミッターをかける
  382.         limit = 100.0 / max(abs(speed_sendbuff[3]), max(abs(speed_sendbuff[2]), max(abs(speed_sendbuff[1]), abs(speed_sendbuff[0]))));
  383.     }
  384.     //    printf("limit = %f\n", limit);
  385.     if (limit < 1.0) {
  386.         for (int i = 0; i < 4; i++) {
  387.             speed_sendbuff[i] = speed_sendbuff[i] * limit;
  388.         }
  389.     }
  390.    
  391.     //Serial.print(speed_sendbuff[0]);
  392.     //Serial.print(",");
  393.     //Serial.print(speed_sendbuff[1]);
  394.     //Serial.print(",");
  395.     //Serial.print(speed_sendbuff[2]);
  396.     //Serial.print(",");
  397.     //Serial.println(speed_sendbuff[3]);
  398.  
  399.     return I2CWritebuff(0x00, (uint8_t*) speed_sendbuff, 4);
  400. }
  401.  
  402. uint8_t I2CWritebuff(uint8_t Addr, uint8_t *Data, uint16_t Length)
  403. {
  404.     Wire.beginTransmission(0x38);
  405.     Wire.write(Addr);
  406.     for (int i = 0; i < Length; i++)
  407.     {
  408.         Wire.write(Data[i]);
  409.     }
  410.     return Wire.endTransmission();
  411. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement