Передача данных по bluetooth (BLE)
- Войдите на сайт для отправки комментариев
Здравствуйте. Нашёл проект умной перчатки для велосипедистов. Мне нужно, чтобы вместо жеста торможения было нажатие кнопки на стороне Nano 33 BLE Sense и вызывалась бы функция ScrollText_Stop() на ESP32. Насколько я понял передаётся значение объекта "ledCharacteristic", данное значение присваивается в условии if (oldNbGesture != nbGesture)в коде для Nano 33 BLE Sense. Поэтому я попробовал передавать значение для вызова функции ScrollText_Stop() на ESP32 в цикле while (peripheral.connected()).
В коде для Nano 33 BLE Sense я добавил только эти строки:
int BUTTON_PIN = 7; pinMode(BUTTON_PIN, INPUT); if (digitalRead(BUTTON_PIN) == HIGH) { ledCharacteristic.writeValue((byte)0x03); Serial.println("Stop"); }
Таким образом, код для Nano 33 BLE Sense стал таким:
/* Smartglove for cyclists: https://www.instructables.com/member/Matlek/ This code is made for an Arduino Nano 33 BLE Sense board: it detects left hand gestures, and sends the gestures information through BLE (to another microcontroller with an LED matrix); It is a mix of the following codes, after a few modifications: -"LED" example from the "ArduinoBLE" library (Peripheral>LED). -"IMU_Classifier" found here: https://github.com/arduino/ArduinoTensorFlowLiteTutorials/blob/master/Ge.... */ #include <ArduinoBLE.h> #include <Arduino_LSM9DS1.h> #include <TensorFlowLite.h> #include <tensorflow/lite/experimental/micro/kernels/all_ops_resolver.h> #include <tensorflow/lite/experimental/micro/micro_error_reporter.h> #include <tensorflow/lite/experimental/micro/micro_interpreter.h> #include <tensorflow/lite/schema/schema_generated.h> #include <tensorflow/lite/version.h> #include "model.h" const float gyroscopeThreshold = 300; const int numSamples = 64; int samplesRead = numSamples; // global variables used for TensorFlow Lite (Micro) tflite::MicroErrorReporter tflErrorReporter; // pull in all the TFLM ops, you can remove this line and // only pull in the TFLM ops you need, if would like to reduce // the compiled size of the sketch. tflite::ops::micro::AllOpsResolver tflOpsResolver; const tflite::Model* tflModel = nullptr; tflite::MicroInterpreter* tflInterpreter = nullptr; TfLiteTensor* tflInputTensor = nullptr; TfLiteTensor* tflOutputTensor = nullptr; // Create a static memory buffer for TFLM, the size may need to // be adjusted based on the model you are using constexpr int tensorArenaSize = 8 * 1024; byte tensorArena[tensorArenaSize]; // array to map gesture index to a name const char* GESTURES[] = { "Left arm", "Brake", "Hand front rotation", "Hand back rotation", "Hand left", "Hand right" }; #define NUM_GESTURES (sizeof(GESTURES) / sizeof(GESTURES[0])) int nbGesture = 0; int oldNbGesture = 0; int gestureTriggered; int BUTTON_PIN = 7; void setup() { Serial.begin(115200); if (!IMU.begin()) { Serial.println("Failed to initialize IMU!"); while (1); } // print out the samples rates of the IMUs Serial.print("Accelerometer sample rate = "); Serial.print(IMU.accelerationSampleRate()); Serial.println(" Hz"); Serial.print("Gyroscope sample rate = "); Serial.print(IMU.gyroscopeSampleRate()); Serial.println(" Hz"); Serial.println(); // get the TFL representation of the model byte array tflModel = tflite::GetModel(model); if (tflModel->version() != TFLITE_SCHEMA_VERSION) { Serial.println("Model schema mismatch!"); while (1); } // Create an interpreter to run the model tflInterpreter = new tflite::MicroInterpreter(tflModel, tflOpsResolver, tensorArena, tensorArenaSize, &tflErrorReporter); // Allocate memory for the model's input and output tensors tflInterpreter->AllocateTensors(); // Get pointers for the model's input and output tensors tflInputTensor = tflInterpreter->input(0); tflOutputTensor = tflInterpreter->output(0); pinMode(22, OUTPUT); pinMode(23, OUTPUT); pinMode(24, OUTPUT); pinMode(BUTTON_PIN, INPUT); digitalWrite(22, HIGH); digitalWrite(23, HIGH); digitalWrite(24, HIGH); // initialize the BLE hardware BLE.begin(); Serial.println("BLE Central - LED control"); // start scanning for peripherals //BLE.scanForUuid("e4297ee0-8c88-11ea-bc55-0242ac130003"); BLE.scan(); } void loop() { BLEDevice peripheral = BLE.available(); if (peripheral) { // discovered a peripheral, print out address, local name, and advertised service Serial.print("Found "); Serial.print(peripheral.address()); Serial.print(" '"); Serial.print(peripheral.localName()); Serial.print("' "); Serial.print(peripheral.advertisedServiceUuid()); Serial.println(); if (peripheral.localName() != "MySmartglove") { return; } BLE.stopScan(); // connect to the peripheral Serial.println("Connecting ..."); if (peripheral.connect()) { Serial.println("Connected"); } else { Serial.println("Failed to connect!"); return; } // discover peripheral attributes Serial.println("Discovering attributes ..."); if (peripheral.discoverAttributes()) { Serial.println("Attributes discovered"); } else { Serial.println("Attribute discovery failed!"); peripheral.disconnect(); return; } // retrieve the LED characteristic BLECharacteristic ledCharacteristic = peripheral.characteristic("e4297ee1-8c88-11ea-bc55-0242ac130003"); if (!ledCharacteristic) { Serial.println("Peripheral does not have LED characteristic!"); peripheral.disconnect(); return; } else if (!ledCharacteristic.canWrite()) { Serial.println("Peripheral does not have a writable LED characteristic!"); peripheral.disconnect(); return; } while (peripheral.connected()) { if (digitalRead(BUTTON_PIN) == HIGH) { ledCharacteristic.writeValue((byte)0x03); Serial.println("Stop"); } float aX, aY, aZ, gX, gY, gZ; // wait for significant motion while (samplesRead == numSamples) { if (IMU.gyroscopeAvailable()) { IMU.readGyroscope(gX, gY, gZ); // sum up the absolutes float gSum = fabs(gX) + fabs(gY) + fabs(gZ); // check if it's above the threshold if (gSum >= gyroscopeThreshold) { // reset the sample read count samplesRead = 0; break; } } } // check if the all the required samples have been read since // the last time the significant motion was detected oldNbGesture = nbGesture; while (samplesRead < numSamples) { // check if new acceleration AND gyroscope data is available if (IMU.accelerationAvailable() && IMU.gyroscopeAvailable()) { // read the acceleration and gyroscope data IMU.readAcceleration(aX, aY, aZ); IMU.readGyroscope(gX, gY, gZ); // normalize the IMU data between 0 to 1 and store in the model's // input tensor tflInputTensor->data.f[samplesRead * 6 + 0] = (aX + 4.0) / 8.0; tflInputTensor->data.f[samplesRead * 6 + 1] = (aY + 4.0) / 8.0; tflInputTensor->data.f[samplesRead * 6 + 2] = (aZ + 4.0) / 8.0; tflInputTensor->data.f[samplesRead * 6 + 3] = (gX + 2000.0) / 4000.0; tflInputTensor->data.f[samplesRead * 6 + 4] = (gY + 2000.0) / 4000.0; tflInputTensor->data.f[samplesRead * 6 + 5] = (gZ + 2000.0) / 4000.0; samplesRead++; if (samplesRead == numSamples) { // Run inferencing TfLiteStatus invokeStatus = tflInterpreter->Invoke(); if (invokeStatus != kTfLiteOk) { while (1); return; } // Loop through the output tensor values from the model for (int i = 0; i < NUM_GESTURES; i++) { Serial.print(GESTURES[i]); Serial.print(": "); Serial.println(tflOutputTensor->data.f[i], 6); if ((tflOutputTensor->data.f[i]) > 0.6) { gestureTriggered = i; nbGesture++; } } } } } Serial.print("The gesture is :"); Serial.println(GESTURES[gestureTriggered]); if (oldNbGesture != nbGesture) { if (gestureTriggered == 0) { ledCharacteristic.writeValue((byte)0x00); colors(0); } // if (gestureTriggered == 1) { // ledCharacteristic.writeValue((byte)0x01); // colors(1); // } if (gestureTriggered == 2) { ledCharacteristic.writeValue((byte)0x02); colors(2); } if (gestureTriggered == 3) { ledCharacteristic.writeValue((byte)0x03); colors(3); } if (gestureTriggered == 4) { ledCharacteristic.writeValue((byte)0x04); colors(4); } if (gestureTriggered == 5) { ledCharacteristic.writeValue((byte)0x05); colors(5); } } } // peripheral disconnected, start scanning again //BLE.scanForUuid("e4297ee0-8c88-11ea-bc55-0242ac130003"); BLE.scan(); } } int colors (int i) { if (i == 0) { for (int it1 = 0; it1 <= 1; it1++) { digitalWrite(22, LOW); digitalWrite(23, LOW); delay(500); digitalWrite(22, HIGH); digitalWrite(23, HIGH); delay(500); } } if (i == 1) { for (int it1 = 0; it1 <= 1; it1++) { digitalWrite(22, LOW); delay(500); digitalWrite(22, HIGH); delay(500); } } if (i == 2) { digitalWrite(23, LOW); delay(500); digitalWrite(23, HIGH); delay(500); } if (i == 3) { digitalWrite(22, LOW); delay(500); digitalWrite(22, HIGH); } if (i == 4) { digitalWrite(22, LOW); delay(500); digitalWrite(23, LOW); delay(500); digitalWrite(22, HIGH); digitalWrite(23, HIGH); } if (i == 5) { digitalWrite(23, LOW); delay(500); digitalWrite(22, LOW); delay(500); digitalWrite(22, HIGH); digitalWrite(23, HIGH); } }
Но в итоге я ничего не вижу в мониторе com порта при нажатии кнопки. На 7 пин у меня приходит 3,3В, как рекомендуется в спецификации для данной платы (5 страница)
Код для ESP32 не изменял. Но меня здесь также смущает условие if (gestureNb != old_gestureNb):
/* Smartglove for cyclists: https://www.instructables.com/member/Matlek/ This code is made for an ESP32 microcontroller, to control an LED matrix through BLE. It is a mix of the following codes, after a few modifications: -"BLE_Write" example from the "BLE ESP32 ARDUINO" library. -"MatrixGFXDemo64" example from the "FastLED NeoMatrix" library. */ #include <BLEDevice.h> #include <BLEUtils.h> #include <BLEServer.h> String gestureValue = "0"; int gestureNb = 0; int old_gestureNb = 0; BLEServer *pServer = NULL; bool deviceConnected = false; unsigned long previousMillis = 0; const long interval = 1000; // See the following for generating UUIDs: // https://www.uuidgenerator.net/ #define SERVICE_UUID "e4297ee0-8c88-11ea-bc55-0242ac130003" #define CHARACTERISTIC_UUID "e4297ee1-8c88-11ea-bc55-0242ac130003" #define DISABLE_WHITE #include <Adafruit_GFX.h> #include <FastLED_NeoMatrix.h> #include <FastLED.h> // Allow temporaly dithering, does not work with ESP32 right now #ifndef ESP32 #define delay FastLED.delay #endif #define PIN 33 #define BRIGHTNESS 64 #define mw 20 #define mh 8 #define NUMMATRIX (mw*mh) CRGB leds[NUMMATRIX]; // Define matrix width and height. FastLED_NeoMatrix *matrix = new FastLED_NeoMatrix(leds, mw, mh, NEO_MATRIX_BOTTOM + NEO_MATRIX_RIGHT + NEO_MATRIX_ROWS + NEO_MATRIX_ZIGZAG); void matrix_show() { matrix->show(); } // This could also be defined as matrix->color(255,0,0) but those defines // are meant to work for adafruit_gfx backends that are lacking color() #define LED_BLACK 0 #define LED_RED_VERYLOW (3 << 11) #define LED_RED_LOW (7 << 11) #define LED_RED_MEDIUM (15 << 11) #define LED_RED_HIGH (31 << 11) #define LED_GREEN_VERYLOW (1 << 5) #define LED_GREEN_LOW (15 << 5) #define LED_GREEN_MEDIUM (31 << 5) #define LED_GREEN_HIGH (63 << 5) #define LED_BLUE_VERYLOW 3 #define LED_BLUE_LOW 7 #define LED_BLUE_MEDIUM 15 #define LED_BLUE_HIGH 31 #define LED_ORANGE_VERYLOW (LED_RED_VERYLOW + LED_GREEN_VERYLOW) #define LED_ORANGE_LOW (LED_RED_LOW + LED_GREEN_LOW) #define LED_ORANGE_MEDIUM (LED_RED_MEDIUM + LED_GREEN_MEDIUM) #define LED_ORANGE_HIGH (LED_RED_HIGH + LED_GREEN_HIGH) #define LED_PURPLE_VERYLOW (LED_RED_VERYLOW + LED_BLUE_VERYLOW) #define LED_PURPLE_LOW (LED_RED_LOW + LED_BLUE_LOW) #define LED_PURPLE_MEDIUM (LED_RED_MEDIUM + LED_BLUE_MEDIUM) #define LED_PURPLE_HIGH (LED_RED_HIGH + LED_BLUE_HIGH) #define LED_CYAN_VERYLOW (LED_GREEN_VERYLOW + LED_BLUE_VERYLOW) #define LED_CYAN_LOW (LED_GREEN_LOW + LED_BLUE_LOW) #define LED_CYAN_MEDIUM (LED_GREEN_MEDIUM + LED_BLUE_MEDIUM) #define LED_CYAN_HIGH (LED_GREEN_HIGH + LED_BLUE_HIGH) #define LED_WHITE_VERYLOW (LED_RED_VERYLOW + LED_GREEN_VERYLOW + LED_BLUE_VERYLOW) #define LED_WHITE_LOW (LED_RED_LOW + LED_GREEN_LOW + LED_BLUE_LOW) #define LED_WHITE_MEDIUM (LED_RED_MEDIUM + LED_GREEN_MEDIUM + LED_BLUE_MEDIUM) #define LED_WHITE_HIGH (LED_RED_HIGH + LED_GREEN_HIGH + LED_BLUE_HIGH) void matrix_clear() { // clear does not work properly with multiple matrices connected via parallel inputs memset(leds, 0, sizeof(leds)); } void ScrollText_Left() { matrix_clear(); matrix->setTextWrap(false); // we don't wrap text so it scrolls nicely matrix->setTextSize(1); matrix->setRotation(0); for (int8_t x = 0; x >= -60; x--) { yield(); matrix_clear(); matrix->setCursor(x, 0); matrix->setTextColor(LED_ORANGE_HIGH); matrix->print("<<<<<<<<<<<<<<"); matrix_show(); delay(50); } matrix->setCursor(0, 0); } void ScrollText_Merci() { matrix_clear(); matrix->setTextWrap(false); // we don't wrap text so it scrolls nicely matrix->setTextSize(1); matrix->setRotation(0); for (int8_t x = 20; x >= -30; x--) { yield(); matrix_clear(); matrix->setCursor(x, 0); matrix->setTextColor(LED_PURPLE_HIGH); matrix->print("Merci"); matrix_show(); delay(70); } matrix->setCursor(0, 0); } void ScrollText_Hello() { matrix_clear(); matrix->setTextWrap(false); // we don't wrap text so it scrolls nicely matrix->setTextSize(1); matrix->setRotation(0); for (int8_t x = 20; x >= -30; x--) { yield(); matrix_clear(); matrix->setCursor(x, 0); matrix->setTextColor(LED_CYAN_HIGH); matrix->print("Hello!"); matrix_show(); delay(70); } matrix->setCursor(0, 0); } void ScrollText_Right() { matrix_clear(); matrix->setTextWrap(false); // we don't wrap text so it scrolls nicely matrix->setTextSize(1); matrix->setRotation(0); for (int8_t x = -60; x <= 0 ; x++) { yield(); matrix_clear(); matrix->setCursor(x, 0); matrix->setTextColor(LED_ORANGE_HIGH); matrix->print(">>>>>>>>>>>>>>"); matrix_show(); delay(50); } matrix->setCursor(0, 0); } void ScrollText_Wait() { matrix_clear(); matrix->setTextWrap(false); // we don't wrap text so it scrolls nicely matrix->setTextSize(1); matrix->setRotation(0); yield(); matrix_clear(); matrix->setCursor(2, 0); matrix->setTextColor(LED_ORANGE_HIGH); matrix->print("o"); matrix_show(); delay(500); yield(); matrix_clear(); matrix->setCursor(2, 0); matrix->setTextColor(LED_ORANGE_HIGH); matrix->print("oo"); matrix_show(); delay(500); yield(); matrix_clear(); matrix->setCursor(2, 0); matrix->setTextColor(LED_ORANGE_HIGH); matrix->print("ooo"); matrix_show(); delay(500); yield(); matrix_clear(); matrix->setCursor(0, 0); matrix->setTextColor(LED_BLACK); matrix_show(); delay(500); } void ScrollText_Stop() { matrix_clear(); matrix->setTextWrap(false); // we don't wrap text so it scrolls nicely matrix->setTextSize(1); matrix->setRotation(0); yield(); matrix_clear(); matrix->setCursor(2, 0); matrix->setTextColor(LED_RED_HIGH); matrix->print("!!!"); matrix_show(); delay(1000); yield(); matrix_clear(); matrix->setCursor(0, 0); matrix->setTextColor(LED_BLACK); matrix->print("STOP"); matrix_show(); delay(500); } void ScrollText_Straight() { uint8_t size = max(int(mw / 8), 1); matrix->setRotation(3); matrix->setTextSize(size); matrix->setTextColor(LED_GREEN_HIGH); for (int16_t x = -10; x <= 6; x++) { yield(); matrix_clear(); matrix->setCursor(x, ((mw / 2 - size * 4) + 1)); matrix->print(">"); matrix_show(); delay(100 / size); } matrix->setRotation(0); matrix->setCursor(0, 0); matrix_show(); } class MyServerCallbacks: public BLEServerCallbacks { void onConnect(BLEServer* pServer) { deviceConnected = true; Serial.println(" deviceConnected = true;"); }; void onDisconnect(BLEServer* pServer) { deviceConnected = false; Serial.println(" deviceConnected = false;"); } }; class MyCallbacks: public BLECharacteristicCallbacks { //public: void onWrite(BLECharacteristic *pCharacteristic) { std::string value = pCharacteristic->getValue(); if (value.length() > 0) { gestureValue = int(value[0]); gestureNb++; } } }; void setup() { Serial.begin(115200); FastLED.addLeds<NEOPIXEL, PIN>( leds, NUMMATRIX ).setCorrection(TypicalLEDStrip); delay(1000); matrix->begin(); matrix->setTextWrap(false); matrix->setBrightness(BRIGHTNESS); #ifndef DISABLE_WHITE matrix->fillScreen(LED_WHITE_HIGH); matrix_show(); delay(5000); matrix_clear(); #endif BLEDevice::init("MySmartglove"); BLEServer *pServer = BLEDevice::createServer(); pServer->setCallbacks(new MyServerCallbacks()); BLEService *pService = pServer->createService(SERVICE_UUID); BLECharacteristic *pCharacteristic = pService->createCharacteristic( CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE ); pCharacteristic->setCallbacks(new MyCallbacks()); //pCharacteristic->setValue("Hello World"); pService->start(); BLEAdvertising *pAdvertising = pServer->getAdvertising(); pAdvertising->start(); } void loop() { if (deviceConnected) { unsigned long currentMillis = millis(); if (currentMillis - previousMillis >= interval) { previousMillis = currentMillis; ScrollText_Straight(); } Serial.print("gestureValue : "); Serial.println(gestureValue); if (gestureNb != old_gestureNb) { if (gestureValue == "0" || gestureValue == "4") { ScrollText_Left(); } if (gestureValue == "5") { ScrollText_Right(); } if (gestureValue == "3") { ScrollText_Stop(); } if (gestureValue == "2") { ScrollText_Merci(); } old_gestureNb = gestureNb; } } if (!deviceConnected) { ScrollText_Wait(); pServer->startAdvertising(); // restart advertising } }
Класс :) А вопрос в чем ?
1. Если хотите, что бы сделали за вас, то есть тема "ищу исполнителя", там вам возможно помогут за деньги.
2. Можете попробовать обратится напрямую к автору кода, вдруг он поможет бесплатно.
3. Если решили САМИ доработать код, то описывая, то что вы сделали, рассказывайте, что не так.
Нашёл проект умной перчатки для велосипедистов. Мне нужно, чтобы вместо жеста торможения было нажатие кнопки ...
Ни надо его прогонять! Процесс отладки обещает быть кровавым
Ну так, бег с барьерами был бы более зрелищным видом спорта, если бы барьеры были намертво прикручены к полу.