Real Time EMG Signal Acquisition Using BLE NANO 1.5


#1

Hello everyone,

I am using Red Bear BLE Nano 1.5 to acquire EMG signals from a circuit which I created. I am using the nRF51822’s ADC to acquire the ADC samples, and I am using the Arduino IDE to acquire the 3 packets at a time using the following command:

ble.gattClient().write(GattClient::GATT_OP_WRITE_CMD,chars_hrm.getConnectionHandle(),0x0E,3,(uint8_t *)&valueArray);

As you can see the array size is 3 since nRF51822 IC supports a 10 bit ADC. I established connections between two BLE Nano devices. I am then using modified BLE Serial and BLE Central codes to acquire serial samples at 9600 baud rate and using Simulink to visualize the signals in real time.

I am receiving the data successfully, but the only problem is that the data rate is very slow. I have calculated it to be only 127 ms. I was hoping for a received data sampling rate to be more than 1 ms as the EMG signal is very fast.

Is there any way to make the data rate faster? I have only been studying the BLE for only one weeks and have no deep knowledge on the subject. The only thing I require is a fast data rate to reduce loss of data. I would be very grateful for any help.

Zahak


#2

There are a couple of bottle necks in your system. The 9600 baud rate being one of them
See https://www.forward.com.au/pfod/pfodDataLogging/highSpeedDataLogging.html
for some real life tests using Serial/Wifi. Actually I suggest you use WiFi connection instead.

As for the BLE transfer you can increase it by reducing the connection interval.

For the basics of BLE see

He also sells as hand book, which I have not purchased.


#3

Hey Zahak,

as already mentioned in the link in the post above, BLE is not the fastest communication channel.
BLE is used for applications that do not need to exchange large amounts of data. You use it if you have to transmit a small data packet every now and then. For example when transmitting data from a temperature sensor which state does not very often change.

In your specific application you could try Bluetooth classic instead (if you don’t want or can’t use WiFi). Bluetooth classic was originally designed for continuous, streaming data applications. Therefore it provides a higher throughput.

Markus


#4

@ drumpf. Thank you very much for your reply. It was very helpful. I have checked the ADC acquisition rate and the serial transfer, and I have found that these rates are very slow in itself. I see that the total ADC conversion and serial transfer at 9600 baud rate incurs a sampling rate of around 200 samples per second (time period 5 ms). I wanted to use faster transfer rates in serial, but I found out that Arduino IDE only allows 9600 baud rate.
Just for the purposes of knowledge, I was curious if the rest of the delay which causes my observed sampling time period of 127 ms is because of the BLE throughput. I have another question please. How would I increase the BLE transfer rate by reducing the connection interval. Can you please help me out with the coding matters?

I would be very grateful, and thank you for suggesting Bluetooth classic or WiFi.

Zahak


#5

@ ms-ich. I am very grateful for your very quick reply. Thank you very much for suggesting Bluetooth classic. I see now what you mean now that BLE is useful for only very low frequency signals which require less sampling rates.

Zahak


#6

see the Redbear NanoV1.5, BLE_SimplePeripheral.ino example and reduce the
minConnectionInterval and maxConnectionInterval to get faster through put.

I have not tried this as in my case I was aiming for slower, lower power, connections


#7

@drmpf thank you for your response. Can you please more specific with your response? I am not sure which commands or functions to invoke to alter the connection intervals.

I would be grateful for your reply.

Zahak


#8

call ble_error_t getPreferredConnectionParams(Gap::ConnectionParams_t *params)
and then change the connection params you want to change and then call
ble_error_t setPreferredConnectionParams(const Gap::ConnectionParams_t *params)

see the gap.h file for the list of ConnectionParams_t
see BLE_SimplePeripheral.ino for an example of printing them out


#9

Thank you for your reply. I see what you are saying but it still is not working. The code for BLE setup is shown below.

include <BLE_API.h>

BLE ble;

define BUF_LEN 20

define DEVICE_NAME “RCSSTeam”

// The Nordic UART Service static const uint8_t service1_uuid[] = {0x71, 0x3D, 0, 0, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E}; static const uint8_t service1_rx_uuid[] = {0x71, 0x3D, 0, 2, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E}; static const uint8_t uart_base_uuid_rev[] = {0x1E, 0x94, 0x8D, 0xF1, 0x48, 0x31, 0x94, 0xBA, 0x75, 0x4C, 0x3E, 0x50, 0, 0, 0x3D, 0x71};

GattCharacteristic NCKdata(service1_rx_uuid, rx_value, 1, BUF_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);

GattCharacteristic *uartChars[] = {&NCKdata};

GattService uartService(service1_uuid, uartChars, sizeof(uartChars) / sizeof(GattCharacteristic *));

void disconnectionCallBack(Gap::Handle_t handle, Gap::DisconnectionReason_t reason) { ble.startAdvertising(); }

void setup() { // BLE ble.init(); ble.onDisconnection(disconnectionCallBack);
// setup adv_data and srp_data
ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, (const uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME) - 1);
ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, (const uint8_t *)uart_base_uuid_rev, sizeof(uart_base_uuid_rev));

ble.accumulateScanResponse(GapAdvertisingData::SHORTENED_LOCAL_NAME, (const uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME) - 1);
ble.accumulateScanResponse(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, (const uint8_t *)uart_base_uuid_rev, sizeof(uart_base_uuid_rev));

// set adv_type
ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
// add service
ble.addService(uartService);
// set device name
ble.setDeviceName((const uint8_t *)DEVICE_NAME);
// set tx power,valid values are -40, -20, -16, -12, -8, -4, 0, 4
ble.setTxPower(4);
// set adv_interval, 100ms in multiples of 0.625ms.
ble.setAdvertisingInterval(160);
// set adv_timeout, in seconds
ble.setAdvertisingTimeout(0);
// start advertising
ble.startAdvertising();}}

I have little knowledge of data structures. I only know simple C commands for microcontroller programming. I would be grateful if you assist me in telling where and how to place the code for change connection parameters.

Thank you very much in advance.
Zahak


#10

suggest you start with BLEPeripheral library and Arduino. I avoids most of the C stuff


#11

Thank you very much for your response, but my problem remains the same. I need some help in changing connection speeds or connection intervals. I am studying the codes in the library which you have sent and it is apparently easy; however, I am not able to find any option or command which tells me to change the connection interval. I hope you would help me in this regard.

Thank you very much.
Zahak


#12

In that case perhaps start with some C struct tutorials


#13

I think I have solved the proble,. One can simply use the Central_Test code and write the following before connecting with the Peripheral device.

  Gap::ConnectionParams_t connectionParams;
  Gap::ConnectionParams_t *params1;
  connectionParams.minConnectionInterval = 6;
  connectionParams.maxConnectionInterval = 6;
  connectionParams.slaveLatency = 0;
  connectionParams.connectionSupervisionTimeout = 500;
  ble.gap().setPreferredConnectionParams(&connectionParams);
  ble.connect(params->peerAddr, BLEProtocol::AddressType::RANDOM_STATIC, &connectionParams, NULL);

by doing this we can adjust the connection parameters.

Zahak