256KB data transfer over BLE , DA14681

⚠️
Hi there.. thanks for coming to the forums. Exciting news! we’re now in the process of moving to our new forum platform that will offer better functionality and is contained within the main Dialog website. All posts and accounts have been migrated. We’re now accepting traffic on the new forum only - please POST any new threads at https://www.dialog-semiconductor.com/support . We’ll be fixing bugs / optimising the searching and tagging over the coming days.
8 posts / 0 new
Last post
mahmed106
Offline
Last seen: 1 month 2 weeks ago
Joined: 2019-05-03 17:28
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: 2 months 2 weeks ago
Staff
Joined: 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 2 weeks ago
Joined: 2019-05-03 17:28
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<R_PTR_PacketNumber)) // Payload
                        {
#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 = LoggingStopped;
#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: 2 months 2 weeks ago
Staff
Joined: 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: 2 months 2 weeks ago
Staff
Joined: 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:

  • The Connection interval. The lowest allowed interval 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 2 weeks ago
Joined: 2019-05-03 17:28
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 2 weeks ago
Joined: 2019-05-03 17:28
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: 2 months 2 weeks ago
Staff
Joined: 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