nkolban / esp32-snippets

Sample ESP32 snippets and code fragments
https://leanpub.com/kolban-ESP32
Apache License 2.0
2.37k stars 710 forks source link

BLE Indication blocking #600

Open JonathanConstant opened 6 years ago

JonathanConstant commented 6 years ago

Hello Neil, First thank you for your great work. I am using esp32 for accurate frequency counter and sending the result with ble. My problem is that I need a high speed counter, I calculate the frequency every 2 ms and I send the result every 40ms. If I use indicate, it blocks 24ms for sending the data and it blocks my counter. However my counter is running on the core 1 and ble on the core 0. How the indicate can block two cores waiting the client confirmation ? If I use notify, it is not blocking but my counter is not anymore accurate and I got exceptions and the program crashs after 30 seconds.. Thanks for your help,

chegewara commented 6 years ago

This is how indications works. Its not blocking in this library, its blocking in lower level (bluedroid), because indication requires confirmation (acknowledge). Since ble has latency it takes some time. You can decrease it by changing connection parameters: https://github.com/nkolban/esp32-snippets/issues/555#issuecomment-401625606 but still there will be some latency.

Now is the question why it is blocking both cores? To be honest i didnt do any tests with indicate, since you have such strange behavior i have to find some time and do some tests. If you can provide some code this would save me some time and speed up tests.

JonathanConstant commented 6 years ago

Thank you chegewara for your answer. I try to provide you some code.

Here is my code for creating the ble Service.

  void ble::init_ble()  {   

   BLEDevice::init("Esp32");
   // Set max mtu 
    BLEDevice::setMTU(500);

    // Create the BLE server 
    m_server = BLEDevice::createServer();
    // Link ble callbacks with this class
    m_server->setCallbacks(this); 

    // Create the BLE Service
    BLEService *Service = m_server->createService(BLEUUID(SERVICE_UUID));

    // Create a BLE Characteristic
    m_characteristic = Service->createCharacteristic(
        BLEUUID(CHARACTERISTIC_UUID),
        BLECharacteristic::PROPERTY_READ   |
        BLECharacteristic::PROPERTY_WRITE  |
        BLECharacteristic::PROPERTY_NOTIFY |
        BLECharacteristic::PROPERTY_INDICATE
    );

    BLEDescriptor* descriptor = new BLE2902();
    m_characteristic->addDescriptor(descriptor);

    // Set max power
    BLEDevice::setPower(ESP_PWR_LVL_P7);

    // Start the service
    Service->start();

    m_server->getAdvertising()->setScanFilter(false, false);
    advertise();
}
void ble::advertise() {  
    m_server->startAdvertising();
}

Create Task in core 1

void app_main()
{     
    xTaskCreatePinnedToCore(counter, "Counter", 20000, NULL, 15, NULL, 1);    
}

My task is sending data every 40ms by a ble indication. I turn on/off the led every 2ms to see the esp32 entering in blocking mode when I send the indication.

void counter() {          
   int index;
   bool bLed = false;
    while( 1 ) {                                               
            timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0);                                         
            index++;

            // send data every 40ms   
            if (index == 20) {
                  m_Ble->m_characteristic->setValue(0x01, 1);  
                  m_Ble->m_characteristic->indicate();  
                  index = 0;
            }

            while (1) {                                      
                uint64_t counterValue = 0;
                timer_get_counter_value(TIMER_GROUP_0, TIMER_0, &counterValue);                  
                // I turn on/off the led every 2ms
                if (counterValue >= 80000) { 
                    bLed = !bLed;
                    gpio_set_level(GPIO_NUM_22, bLed);  
                    break;
                }            
            } 
        }       
    }            
}