Hello
I have a problem with the scanning of ble phy coded in Android, I need it to be continuous (or almost) but it seems that for coded it is not possible unlike with legacy.
First of all, I would like to explain briefly what the project is about.There are some nodes located in different areas called sensors nodes that read in real time the value of an oxygen sensor by saadc and the temperature and humidity. These values with the area and battery charge are coded in 6 bytes along with 32 bytes of a sha-256 hash, all of these is in the advertising (so I also use extended advertising) In addition, as this is a very noisy industrial environment I have used the lowest coding rate with fast advertising to ensure better reception with poor RSSI.
On the other hand a bridge node that reads the data encoded in the advertising (working on scan mode) processes it and generates a command to forward it through LoRaWAN (via uart). With a smartphone that supports long range it is possible to read the advertising data too, whit some fancy graphics and dashboards to display data
The point is that our client wants fast update times and since they will also be able to receive from different nodes depending on your location, I decided that the best thing to do is to advertise from the sensors by updating the advertising data every second. The optimal when dealing with a data flow that changes so fast is to establish a connection but as there are different nodes it would have to connect separately to each one of them which I don't think is efficient so I opted to advertise the sensor nodes.
So on one hand there are the sensor nodes doing advertisement of the sensor values changing every second and on the other hand a scanner is receiving this data on the bridge node or on the smartphone. The boards I used as sensor and bridge nodes are nrf52840. The scanner mode in the bridge node works perfectly for each second shows me about 4 or 5 advertising and is a constant flow, then I have a timer to take one per second and process it.
The problem comes with android, I tried to make a continuous scan with the following parameters that are the most aggressive.
scanSettings = new ScanSettings.Builder().setScanMode(this.scanMode) .setLegacy(false) .setPhy(ScanSettings.PHY_LE_ALL_SUPPORTED) .setNumOfMatches(ScanSettings.MATCH_NUM_MAX_ADVERTISEMENT) .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES) .setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE).build();
This is more or less continuous with legacy but not with phy coded, I have tried changing the fast advertising and raising the times but it seems that what it does is stops of about 15 or 20 seconds, putting CALLBACK_TYPE_ALL_MATCHES I receive all the advertisements, if I increase the advertisement time a little I can see for 2 or 3 seconds, with fast advertisiment only one second, 2 at most, I could attach some logs of a test application that I did only for the scanning part, but I think it is more informative this nRF connect capture where you can see this same behavior. In options I put continuous scanning with low latency and also it's possible to see that big whit some fancy graphics and dashboard to display datagap for coded that is tiny in legacy.
The part of the code related to the advertising on the sensor node is the following.
void advertising_init(void) { uint32_t err_code; ble_advdata_t advdata; uint8_t flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE; ble_advdata_manuf_data_t manuf_specific_data; sd_ble_gap_adv_stop(m_adv_handle); manuf_specific_data.company_identifier = APP_COMPANY_IDENTIFIER; manuf_specific_data.data.p_data = (uint8_t *) data_and_hash; manuf_specific_data.data.size = 35; // Build and set advertising data. memset(&advdata, 0, sizeof(advdata)); advdata.name_type = BLE_ADVDATA_NO_NAME; // beacons has no flags advdata.p_manuf_specific_data = &manuf_specific_data; // all data here advdata.include_appearance = false; // Initialize advertising parameters (used when starting advertising). memset(&m_adv_params, 0, sizeof(m_adv_params)); m_adv_params.properties.type = BLE_GAP_ADV_TYPE_EXTENDED_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED; // lowest bitrate 125kbps m_adv_params.p_peer_addr = NULL; // Undirected advertisement. m_adv_params.filter_policy = BLE_GAP_ADV_FP_ANY; m_adv_params.interval = APP_ADV_INTERVAL; m_adv_params.duration = 0; // Never time out. m_adv_params.primary_phy = BLE_GAP_PHY_CODED; // for coded advertisement m_adv_params.secondary_phy = BLE_GAP_PHY_CODED; // for coded advertisement m_adv_params.filter_policy = BLE_GAP_ADV_FP_ANY; err_code = ble_advdata_encode(&advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len); APP_ERROR_CHECK(err_code); err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &m_adv_params); APP_ERROR_CHECK(err_code); // set 8 dbm of tx_power (max) err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV, m_adv_handle, 8); APP_ERROR_CHECK(err_code); }
It is a behavior similar to the one of a beacon but changing the data every second
In a nutshell, I think that the option to make advertisement with new values every second is the most viable for this use case but the problem is that it doesn't seem to work well for android scanning, at least not like in the dongle. The phone I am using is a oneplus 6T and according to the nordic app it supports all bluetooth 5 features. I'm aware that Android doesnt like scanning intensive modes (plus these drain your battery) but is there any chance to get the scanning of ble coded as fast as the one of legacy on Android? If this is not possible I guess I'll choose to establish a connection with the phone to the bridge node and send the data stream directly to the phone, as a bridge node is in range with several sensors it's possible to see the data from them on the phone, so if you are moving from zone to zone just connect to the bridge node of the zone, it's not as fast as moving and directly read the sensor that is in range but it's better than connecting to each one separately.
Thanks in advance