256KB data transfer over BLE , DA14681

Learn MoreFAQsTutorials

8 posts / 0 new
Last post
mahmed106
Offline
Last seen:1 month 4 days ago
加入:2019-05-03所
256KB data transfer over BLE , DA14681

Hi Dialog

We are working on a custom board based on DA14681. In our application the normal scnerio is that device records temperature and stores it in eeprom. After several days when user connects the device with BLE app. All offline data gets transferred to the mobile.

Our eeprom size is 256KB and packet size is 10 Bytes, so we need to send 25600 packets, and right now we are transferring data via a BLE service.

Here is the flow :

1 - Mobile app makes the connection with the device.

2 - Mobile app request a read characteristics of the particular service.

3 - DA14681 returns the data bytes that were requested.

So mobile app constantly make a read request and firmware sends the value.

In this method the speed of data transfer is very slow. Aproximately 2 packets per seconds which means it will take 3.5 Hours to send all packets to the mobile app.

My question is ,, is there a fast method to do it? Because 256 KB data is not too big to send in hours.. I m missing something here..

Device:
PM_Dialog
Offline
Last seen:11 hours 34 min ago
工作人员
加入:2018-02-08 11:03
Hi mahmed106,

Hi mahmed106,

Could you please share the code snippet you are using in order to transmit data over BLE? I assume that you are using BLE notifications or indications for this.

Thanks, PM_Dialog

mahmed106
Offline
Last seen:1 month 4 days ago
加入:2019-05-03所
I was using a read request

I was using a read request from the app side to read the data.

Here is the code of that

static void handle_read_req(ble_service_t *svc, const ble_evt_gatts_read_req_t *evt){
sftemps_service_t *sftemps = (sftemps_service_t *) svc;

if (evt->handle == sftemps->temperature_count_h)
{
uint16_t ccc_val = rand()%100;//get_sf_temp_num_records_device();

//ble_storage_get_u16(evt->conn_idx, bcs->bcs_ccc_h, &ccc_val);

// we're little-endian, ok to write directly from uint16_t
ble_gatts_read_cfm(evt->conn_idx, evt->handle, ATT_ERROR_OK,
sizeof(ccc_val), &ccc_val);
}
else if (evt->handle == sftemps->temperature_data_h)
{
// uint32_t ccc_val = rand()%100;//get_sf_temp_records_device();

//ble_storage_get_u16(evt->conn_idx, bcs->bcs_ccc_h, &ccc_val);

// we're little-endian, ok to write directly from uint16_t

if(ReadPacketNumber==0) // 1st packet Header // Add exception of restart but data in flash
{
// ReadPacketNumFromFlash=read_packetNumbers_from_Flash();
// printf("PN %d",ReadPacketNumFromFlash);
#if NoFlashDummyCode
R_PTR_PacketNumber = 50;//rand()%100;
M24ElapsedTime = R_PTR_PacketNumber*3;
memset(LoggingPacket,0x00,sizeof(LoggingPacket));
LoggingPacket[0]=0xCD;
LoggingPacket[1]=0x11;
LoggingPacket[2]=0x12;
LoggingPacket[3]=M24ElapsedTime >> 24;
LoggingPacket[4]=M24ElapsedTime >> 16;
LoggingPacket[5]=M24ElapsedTime >> 8;
LoggingPacket[6]=M24ElapsedTime & 0xFF;
LoggingPacket[7]=R_PTR_PacketNumber>>8;
LoggingPacket[8]=R_PTR_PacketNumber&0xFF;
LoggingPacket[9]=LoggingPacket[0];
for(int by=1;by<9;by++)
{
LoggingPacket[9]^=LoggingPacket[by];
}
ReadPacketNumber++;// Read next packet in next iteration
R_PTR_ChipNo = 1; // Select Chip one as it is the start
R_PTR_ReadAddress = 0;//0xF9C9; // Start from chip 0 and address 0
#else
R_PTR_PacketNumber = read_packetNumbers_from_M24Flash();
M24ElapsedTime = ReadElapsedTimeFromM24Flash();
memset(LoggingPacket,0x00,sizeof(LoggingPacket));
LoggingPacket[0]=0xCD;
LoggingPacket[1]=0x11;
LoggingPacket[2]=0x12;
LoggingPacket[3]=M24ElapsedTime >> 24;
LoggingPacket[4]=M24ElapsedTime >> 16;
LoggingPacket[5]=M24ElapsedTime >> 8;
LoggingPacket[6]=M24ElapsedTime & 0xFF;
LoggingPacket[7]=R_PTR_PacketNumber>>8;
LoggingPacket[8]=R_PTR_PacketNumber&0xFF;
LoggingPacket[9]=LoggingPacket[0];
for(int by=1;by<9;by++)
{
LoggingPacket[9]^=LoggingPacket[by];
}
ReadPacketNumber++;// Read next packet in next iteration
R_PTR_ChipNo = 1; // Select Chip one as it is the start
R_PTR_ReadAddress = 0;//0xF9C9; // Start from chip 0 and address 0
#endif
}
#if 1
else if(ReadPacketNumber>0 && (ReadPacketNumber{
#if NoFlashDummyCode
Dummy_R_PTR_PacketNumber=ReadPacketNumber;
Dummy_M24ElapsedTime=Dummy_R_PTR_PacketNumber*3;
memset(LoggingPacket,0x00,sizeof(LoggingPacket));
LoggingPacket[0]=0xCD;
LoggingPacket[1]=0x12;
LoggingPacket[2]=0x13;
memset(M24CurrentPacket,0x00,sizeof(M24CurrentPacket));
LoggingPacket[3]=0;
LoggingPacket[4]=Dummy_R_PTR_PacketNumber++;
LoggingPacket[5]=Dummy_M24ElapsedTime >> 24;
LoggingPacket[6]=Dummy_M24ElapsedTime >> 16;
LoggingPacket[7]=Dummy_M24ElapsedTime >> 8;
LoggingPacket[8]=Dummy_M24ElapsedTime;
LoggingPacket[9]=rand()%60;
LoggingPacket[10]=rand()%9;
LoggingPacket[11]=LoggingPacket[0];
for(int by=1;by<11;by++)
{
LoggingPacket[11]^=LoggingPacket[by];
}
ReadPacketNumber++;// Read next packet in next iteration
#else
memset(LoggingPacket,0x00,sizeof(LoggingPacket));
LoggingPacket[0]=0xCD;
LoggingPacket[1]=0x12;
LoggingPacket[2]=0x13;
memset(M24CurrentPacket,0x00,sizeof(M24CurrentPacket));
// printf("CN %d - Add %d",R_PTR_ChipNo,R_PTR_ReadAddress);
// fflush(stdout);
SequentialReadM24Flash(((R_PTR_ReadAddress & 0xFF00)>>8),(R_PTR_ReadAddress),8,R_PTR_ChipNo);
R_PTR_ReadAddress+=8;
for(uint8_t TempBuffFill=3;TempBuffFill<11;TempBuffFill++)
{
LoggingPacket[TempBuffFill] = M24CurrentPacket[TempBuffFill-3];
// LoggingPacket[TempBuffFill] = M24_I2C_AD_read((R_PTR_ReadAddress & 0xFF),(R_PTR_ReadAddress & 0xFF00),R_PTR_ChipNo);
// printf("\n%d ",R_PTR_ReadAddress);
// R_PTR_ReadAddress++;
}
// ReadPacketNumber=(LoggingPacket[3]*10)+LoggingPacket[4]; // If there is a mismatch between packet number write and its read index
LoggingPacket[11]=LoggingPacket[0];
for(int by=1;by<11;by++)
{
LoggingPacket[11]^=LoggingPacket[by];
}
ReadPacketNumber++;// Read next packet in next iteration
if(R_PTR_ReadAddress>=0xF9F6 && R_PTR_ChipNo<4) // 0xF9F6 is the address which will be the last 64k/15 = 4266
{
R_PTR_ChipNo++;
R_PTR_ReadAddress=0;
}
#endif
}
else if(ReadPacketNumber>R_PTR_PacketNumber)// Footer
{
#if NoFlashDummyCode
memset(LoggingPacket,0x00,sizeof(LoggingPacket));
LoggingPacket[0]=0xCD;
LoggingPacket[1]=0x13;
LoggingPacket[2]=0x14;
LoggingPacket[3]=0xDA;
ReadPacketNumber=0;
LoggingStatus =日志gingStopped;
#else
memset(LoggingPacket,0x00,sizeof(LoggingPacket));
LoggingPacket[0]=0xCD;
LoggingPacket[1]=0x13;
LoggingPacket[2]=0x14;
LoggingPacket[3]=0xDA;
if(PassCodeVerification==1)
{
M24FlashPacketNumber=0;
ResetPacketNumberInM24Flash();// take care as high speed read from app may pre-empt it
LoggingStatus=LoggingStopped;
FLASH_FULL=0;
ResetElaspedTimeInM24Flash();// take care as high speed read from app may pre-empt it
M24ElapsedTime=0;
PauseElapsedTimeCounting=ET_PAUSE;
ResetChipNoInM24Flash();// take care as high speed read from app may pre-empt it
}
ReadPacketNumber=0;

// FlashPacketNumber=1;
// Elapsed_Time=0;
#endif
}
#endif
ble_gatts_read_cfm(evt->conn_idx, evt->handle, ATT_ERROR_OK,
sizeof(LoggingPacket), &LoggingPacket);
#if ENABLE_UART_PRINTF
printf("FLSH-RD %d-%d\n",ReadPacketNumber,R_PTR_PacketNumber);
#endif
}
else
{

ble_gatts_read_cfm(evt->conn_idx, evt->handle, ATT_ERROR_READ_NOT_PERMITTED, 0,
NULL);
}

The app continuously makes a read request and DA14681 send data in response.

I also have tried notification method it is better than the above method but that also takes alot of time. I want to know the recommeneded method to send large chunks of data over the ble using DA14681

PM_Dialog
Offline
Last seen:11 hours 34 min ago
工作人员
加入:2018-02-08 11:03
Hi mahmed106,

Hi mahmed106,

Thanks for your response. Let me check it and I’ll get back to you/

Thanks, PM_Dialog

PM_Dialog
Offline
Last seen:11 hours 34 min ago
工作人员
加入:2018-02-08 11:03
Hi mahmed106,

Hi mahmed106,

The amount of data that the device can send during a connection interval is closely dependent on the number of packets that the Central allows a peripheral to send. To do so, could you please check how many packets are exchanged when there is a data transaction? Would it be possible to use a BLE sniffer tool, so that we can understand what is happing over the air during the transaction? Do you have the notifications enable after the first read request?

Keep in mind that according to the BLE specifications, up to 251 bytes in one packet can be sent in one packet. What is the max data length for the packets received/transmitted? So check dg_configBLE_DATA_LENGTH_RX_MAX and dg_configBLE_DATA_LENGTH_TX_MAX macros. The ble_gap_mtu_size_set() could be used to set the appropriate mtu_size. Please note that the specific API should be called before the attribute database creation because the device configuration is going to be modified, which will result in clearing the current attribute database (if it exists).

A couple of things reggaridng the pure performance might the following:

  • 连接时间间隔。最低允许间歇雨刷al that can be used is 7.5ms. What is the connection interval is used in the application code? Either the Central can set the connection interval or the Peripheral can request to have a specific connection interval and it’s up to the Central to accept or not (connection update parameters).
  • Slave latency. What you please indicate this? The lowest latency value could be used which is equal to zero (0).
  • The number of packets per connection interval. This might be limited by the Central and affect the performance. What is the Central that is used? Is it another DA14681, or a smartphone?

Thanks, PM_Dialog

mahmed106
Offline
Last seen:1 month 4 days ago
加入:2019-05-03所
Thanks for the detailed reply

Thanks for the detailed reply. Now i understand better. As per your questions, below is the answers:

1 - 750ms is the connection interval

2 - Slave latency is 0

3 - Central is a smartphone

mahmed106
Offline
Last seen:1 month 4 days ago
加入:2019-05-03所
So it means of i reduce my

So it means of i reduce my connection interval to 7ms ,, my throughput will increase?

PM_Dialog
Offline
Last seen:11 hours 34 min ago
工作人员
加入:2018-02-08 11:03
Hi mahmed106,

Hi mahmed106,

Yes please try to use a smaller connection interval than 750ms and send data via notifications. According to BLE specifications, the connection interval should be from 7.5ms (Conn_Interval_Min) to 5sec (Conn_Interval_Max).

Thanks, PM_Dialog