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..
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
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
Hi mahmed106,
Thanks for your response. Let me check it and I’ll get back to you/
Thanks, PM_Dialog
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:
Thanks, PM_Dialog
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
So it means of i reduce my connection interval to 7ms ,, my throughput will increase?
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