11 posts / 0 new
Last post
young_dialog
Offline
Last seen:3 years 10 months ago
Joined:2016-05-10 07:14
变化的连接间隔

Hi support,

我的程序大概的逻辑是外挂ADC每4ms采一次数据,采集完毕后通过中断告诉MCU 14580,MCU开辟一个环形缓冲区来存储ADC result,当有5个result时启动数据发送(notify),数据大小20bytes,即每20ms有一包packet要发送,发送前先检查GATTC_CMP_EVT的到来,connection interval设置为10-20ms,实际测试发现,当连接后不发数据的时候,connection interval为规律的18ms(大概),当启动notify时,connection interval有时为18ms,有时为36ms,有时为54ms,每个connection interval发送的packet也不同,有时1包,有时2包,有时3、4包,这很不科学,connection interval应该是不受任何因素影响的,为什么示波器抓出来的波型显示是这个结果?

下面是部分代码:

1.
enum arch_main_loop_callback_ret user_app_on_ble_powered(void)
{
if(ptr_in != ptr_out) //if there is data left in the ring data buffer and then wake up the BLE to notify
{
return KEEP_POWERED;
}

return GOTO_SLEEP;
}
2.
enum arch_main_loop_callback_ret user_app_on_sytem_powered(void)
{
uint8_t tempdata[2];
int qrsdata_in;

if(adc_int_is_set) //adc sample is complete
{
ads1115_get_adc_result(tempdata);

DATA_FIFO[ptr_in][ADC_VALUE_SIZE * (1+cycle_num)] = tempdata[0]; //store adc sample result in the ring data buffer
DATA_FIFO[ptr_in][ADC_VALUE_SIZE * (1+cycle_num)+ 1 ] = tempdata[1]; //store adc sample result in the ring data buffer

cycle_num++;
if(cycle_num == CYCLE_NUM) //CYCLE_NUM = 5
{
DATA_FIFO[ptr_in][0] = (uint8_t)(counter/256); //high byte
DATA_FIFO[ptr_in][1] = (uint8_t)(counter%256); //low byte
if(counter == 0xFFFF)
{
counter = 0;
flag = true;
}
计数器+ +;
if(flag) {counter = 0; flag = false;}

cycle_num=0;

ptr_in++;
if(ptr_in >= PACKET_NUMBER) ptr_in = 0;

adc_int_is_set = false;
return KEEP_POWERED; //need to notify data
}
adc_int_is_set = false;
}
return GOTO_SLEEP; //no need to notify data
}
3.
static const struct arch_main_loop_callbacks user_app_main_loop_callbacks = {
.app_on_init = user_app_init,
.app_on_ble_powered = user_app_on_ble_powered,
.app_on_sytem_powered = user_app_on_sytem_powered,
.app_before_sleep = NULL,
.app_validate_sleep = NULL,
.app_going_to_sleep = NULL,
.app_resume_from_sleep = NULL,
};
4.数据发送函数,先检查TX_IS_COMPLETED标志
uint8_t data_send_process(void)
{
if(!TX_IS_COMPLETED) return 0; //the former notification is complete

data_to_notify(DATA_FIFO[ptr_out],PACKET_SIZE); //data transmitting

ptr_out++;

if(ptr_out >= PACKET_NUMBER) ptr_out = 0;

TX_IS_COMPLETED = false; //clear the TX_COMPLETE flag

return 0;
}
5.data_send_process()在BLE on的时候调用
static inline void schedule_while_ble_on(void)
{
// BLE clock is enabled
while (ble_is_powered()) {

// BLE event end is set. conditional RF calibration can run.
uint8_t ble_evt_end_set = ke_event_get(KE_EVENT_BLE_EVT_END);

//execute messages and events
rwip_schedule();

//
if (ble_evt_end_set)
{
uint32_t sleep_duration = 0;
rcx20_read_freq ();

/ /如果你有足够的时间跑calibr温度ation of the radio
if (lld_sleep_check(&sleep_duration, 4)) //6 slots -> 3.750 ms
// check time and temperature to run radio calibrations.
conditionally_run_radio_cals();
}

//grant control to the application, try to go to sleep
//if the applciation returns GOTO_SLEEP
if (!app_asynch_trm())
break;

//SDKIMPROVEMENTS Needs testing!! We can add the following condition and move
// it out of the loop
// we may consider putting it in before the app_asynch_trm
//if (GetBits16(CLK_CTRL_REG, RUNNING_AT_XTAL16M))

// execute the printf process
arch_printf_process();
data_send_process();
}
}
6.TX_IS_COMPLETED 置位,当上一包数据发送完毕的时候
void user_catch_rest_hndl(ke_msg_id_t const msgid,
void const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
switch(msgid)
{

case CUSTS1_VAL_NTF_CFM:
{
struct custs1_val_ntf_cfm const *msg_param = (struct custs1_val_ntf_cfm const *)(param);

switch (msg_param->handle)
{
case ECG_IDX_DATA_VAL:

TX_IS_COMPLETED = true; //set if the former packet is transmitted completely

break;

default:
break;
}
} break;

default:
break;
}
}
环境:
SDK5.0.3
测试手机:iphone6及samsung s6

BR,

Young

Device:
Gongyu_Dialog
Offline
Last seen:1 week 3 days ago
Joined:2016-04-27 07:07
1.你可以参考一下,SDK3.0

1.你可以参考一下,SDK3.0.10里的throughput工程。
2.我的建议是在enum arch_main_loop_callback_ret user_app_on_sytem_powered(void)里面只在收到中断的时候,发送消息出去,别的不用做。
在消息处理函数里面,拿ADC的值之前,调用一下arch_force_active_mode函数,然后存储数据到队列。收满5个,直接notification出去。

另外,你可以参考throughtput工程里的streamdatad_send_data_packets_req_handler函数写法,直接去检查l2CAP的队列,这样会比你通过notification返回值再决定是否继续发要快。

young_dialog
Offline
Last seen:3 years 10 months ago
Joined:2016-05-10 07:14
Hi Gongyu_Dialog,

Hi Gongyu_Dialog,

补充:在连接上之后我就调用了arch_disable_sleep()使系统进入idle状态,因为如果不醒着的话,恐怕处理不过来这么大的数据量吧,另外你说的消息处理函数是指"data_send_process()"还是“”arch_main_loop_callback_ret user_app_on_ble_powered()”,这两个函数是BLE醒了之后才会去执行,但是我的数据每4ms就要存储一次,放在这里处理不妥吧,会严重地丢数据!

BR,

Young

Gongyu_Dialog
Offline
Last seen:1 week 3 days ago
Joined:2016-04-27 07:07
1. adc_int_is

1. adc_int_is_set是通过wake的中断函数设置的,还是GPIO的中断函数?
2. ads1115_get_adc_result这个函数会有多大的耗时?
3. “在连接上之后我就调用了arch_disable_sleep()使系统进入idle状态”,// 现在你设置的不进extended sleep的?
4. 你可以评估一下你平均发出去一组包的耗时,可以用rwble_get_clock函数,一头一尾来计算差值,得到耗时。单位625us。

消息处理函数是另加的,做的事情和你的user_app_on_sytem_powered差不多。只不过再加判断,条件满足直接发notification。读取ADC值,放数,收满5个包直接发notification出去)。只要有TASK消息没被处理,BLE芯片就不会睡。

young_dialog
Offline
Last seen:3 years 10 months ago
Joined:2016-05-10 07:14
Hi Gongyu_Dialog,

Hi Gongyu_Dialog,

3.连接上之后设置为不进extended sleep的模式;
1.由于ADC采样是在连接上之后才执行的,所以其中断标志adc_int_is_set是由普通GPIO的中断产生而置位的;

其它的我需要做个测试才能得知,谢谢!

BR,

Young

Gongyu_Dialog
Offline
Last seen:1 week 3 days ago
Joined:2016-04-27 07:07
简单说来,就是

简单说来,就是

.app_on_ble_powered = user_app_on_ble_powered,// 收到异步中断后,直接发出消息
.app_on_sytem_powered = user_app_on_sytem_powered,//处理消息,写buffer,决定是否要发notificatiion消息

young_dialog
Offline
Last seen:3 years 10 months ago
Joined:2016-05-10 07:14
那真正notification数据的函数要放在哪里

那真正notification数据的函数要放在哪里,要在哪里发数据呢?

young_dialog
Offline
Last seen:3 years 10 months ago
Joined:2016-05-10 07:14
我有点混乱了,你较早前说过:

我有点混乱了,你较早前说过:
“enum arch_main_loop_callback_ret user_app_on_sytem_powered(void)里面只在收到中断的时候,发送消息出去,别的不用做”
现在又说:
“.app_on_sytem_powered = user_app_on_sytem_powered,//处理消息,写buffer,决定是否要发notificatiion消息”
究竟是要怎样,你再重新帮我捋顺下顺序,谢谢!

BR,

Young

Gongyu_Dialog
Offline
Last seen:1 week 3 days ago
Joined:2016-04-27 07:07
之前写错了函数名~~~

之前写错了函数名~~~

app_on_ble_powered里检查中断标记,然后发消息通知采集数据
app_on_system_powered里处理消息,写buffer,在这里发notification

young_dialog
Offline
Last seen:3 years 10 months ago
Joined:2016-05-10 07:14
Hi Gongyu_Dialog,

Hi Gongyu_Dialog,

按照你的方法试了下,结果还是一样的,connection interval 还是会变化。还有其它建议么?

BR,

Young

young_dialog
Offline
Last seen:3 years 10 months ago
Joined:2016-05-10 07:14
补充:

补充:
app_on_ble_powered跟app_on_system_powered两个return 要怎么处理,刚才的测试都是return GOTO_SLEEP,望知悉,谢谢!