Page 1 of 1

【已提供】关于ADC采集速度慢的问题

Posted: 2022年 Nov 9日 15:25
by 走走停停

您好,我这边使用老版的Tuya os 版本2.3.3 bk7231n的
ADC 使用 tuya_adc_convert 收集数据的速度非常慢——每秒只有几百个样本
想问下有什么办法可以提高 ADC 的速度吗


Re: 【求助】关于ADC采集速度慢的问题

Posted: 2022年 Nov 9日 16:04
by chaser

bk7231n adc 实际上是一个adc,多个通道。 所以adc使用完需要close,把资源释放出来给其他通道使用。每次open->read->close, 会导致adc读取时速度变慢。具体代码如下:

Code: Select all

static int adc_dev_convert (tuya_adc_t *adc, uint16_t *result)
{
unsigned char i = 0;
unsigned int status;
int adc_hdl;
static unsigned short last_adc = 0;

unsigned char adc_channel = adc->cfg.pin;

if(!g_adc_init[adc_channel]){
LOG_ERR("adc not init!\r\n");
return OPRT_OS_ADAPTER_COM_ERROR;
}

GLOBAL_INT_DECLARATION();

*(unsigned short*)result = 0xFFFF;

memset(adc_desc[adc_channel].pData, 0, adc_desc[adc_channel].data_buff_size * SIZEOF(unsigned short));

GLOBAL_INT_DISABLE();

adc_hdl = ddev_open(SARADC_DEV_NAME, &status, (unsigned int)&adc_desc[adc_channel]);
if ((DD_HANDLE_UNVALID == adc_hdl) || (SARADC_SUCCESS != status))
{
if (SARADC_SUCCESS != status)
{
ddev_close(adc_hdl);
}
adc_hdl = DD_HANDLE_UNVALID;
GLOBAL_INT_RESTORE();
LOG_ERR("adv ddev_open err:%d\r\n", status);
return -1;
}
GLOBAL_INT_RESTORE();

while (adc_desc[adc_channel].all_done == 0)
{
i ++;
if (i > 100)
{
LOG_ERR("adc get timeout!\r\n");
break;
}
vTaskDelay(1);
}

if(adc_desc[adc_channel].current_sample_data_cnt >= 1) //此处简化直接就是采集1次,1这个数值后续可以优化
{
*(USHORT_T*)result = adc_desc[adc_channel].pData[0];
adc_desc[adc_channel].has_data = 0;
adc_desc[adc_channel].current_sample_data_cnt = 0;
last_adc = *(USHORT_T*)result;
} else {
*(USHORT_T*)result = last_adc;
}

ddev_close(adc_hdl);

saradc_ensure_close();

return OPRT_OS_ADAPTER_OK;
}

如果要求adc 采集速度快些, 可以自己重新封装下adc read接口,open->读取多个值->close. 可以参考下面代码:

Code: Select all

static int adc_dev_convert (tuya_adc_t *adc, uint16_t *result)
{
unsigned char i = 0;
unsigned int status, sum = 0;
int adc_hdl;
static unsigned short last_adc = 0;
unsigned short temp_adc_mv = 0;
unsigned int adc_max = 0, adc_min = 0;

unsigned char adc_channel = adc->cfg.pin;

if(!g_adc_init[adc_channel]){
LOG_ERR("adc not init!\r\n");
return OPRT_OS_ADAPTER_COM_ERROR;
}

GLOBAL_INT_DECLARATION();

*(unsigned short*)result = 0xFFFF;

memset(adc_desc[adc_channel].pData, 0, adc_desc[adc_channel].data_buff_size * SIZEOF(unsigned short));

GLOBAL_INT_DISABLE();

adc_hdl = ddev_open(SARADC_DEV_NAME, &status, (unsigned int)&adc_desc[adc_channel]);
if ((DD_HANDLE_UNVALID == adc_hdl) || (SARADC_SUCCESS != status))
{
if (SARADC_SUCCESS != status)
{
ddev_close(adc_hdl);
}
adc_hdl = DD_HANDLE_UNVALID;
GLOBAL_INT_RESTORE();
LOG_ERR("adv ddev_open err:%d\r\n", status);
return -1;
}
GLOBAL_INT_RESTORE();


while (1)
{
//bk_printf("d:%d,%d\r\n",saradc_desc->current_sample_data_cnt,p_ADC_drv_desc->current_sample_data_cnt);
if (adc_desc[adc_channel].current_sample_data_cnt == adc_desc[adc_channel].data_buff_size)
{
ddev_close(adc_hdl);
saradc_ensure_close();
break;
}
}

adc_max = adc_min = adc_desc[adc_channel].pData[34];

for (i = 32; i < 50; i++)
{
if(adc_max < adc_desc[adc_channel].pData[i])
adc_max = adc_desc[adc_channel].pData[i];
else if(adc_min > adc_desc[adc_channel].pData[i])
adc_min = adc_desc[adc_channel].pData[i];

sum += adc_desc[adc_channel].pData[i];
}

temp_adc_mv = saradc_calculate((UINT16)((sum - adc_max - adc_min) >> 4)) * 1000;
*(USHORT_T*)result = temp_adc_mv * ADC_REGISTER_VAL_MAX / ADC_VOLTAGE_MAX;

sum = 0;
adc_desc[adc_channel].current_read_data_cnt = 0;

return OPRT_OS_ADAPTER_OK;
}

Re: 【求助】关于ADC采集速度慢的问题

Posted: 2022年 Nov 9日 16:20
by 走走停停
chaser 2022年 Nov 9日 16:04

bk7231n adc 实际上是一个adc,多个通道。 所以adc使用完需要close,把资源释放出来给其他通道使用。每次open->read->close, 会导致adc读取时速度变慢。具体代码如下:

Code: Select all

static int adc_dev_convert (tuya_adc_t *adc, uint16_t *result)
{
unsigned char i = 0;
unsigned int status;
int adc_hdl;
static unsigned short last_adc = 0;

unsigned char adc_channel = adc->cfg.pin;

if(!g_adc_init[adc_channel]){
LOG_ERR("adc not init!\r\n");
return OPRT_OS_ADAPTER_COM_ERROR;
}

GLOBAL_INT_DECLARATION();

*(unsigned short*)result = 0xFFFF;

memset(adc_desc[adc_channel].pData, 0, adc_desc[adc_channel].data_buff_size * SIZEOF(unsigned short));

GLOBAL_INT_DISABLE();

adc_hdl = ddev_open(SARADC_DEV_NAME, &status, (unsigned int)&adc_desc[adc_channel]);
if ((DD_HANDLE_UNVALID == adc_hdl) || (SARADC_SUCCESS != status))
{
if (SARADC_SUCCESS != status)
{
ddev_close(adc_hdl);
}
adc_hdl = DD_HANDLE_UNVALID;
GLOBAL_INT_RESTORE();
LOG_ERR("adv ddev_open err:%d\r\n", status);
return -1;
}
GLOBAL_INT_RESTORE();

while (adc_desc[adc_channel].all_done == 0)
{
i ++;
if (i > 100)
{
LOG_ERR("adc get timeout!\r\n");
break;
}
vTaskDelay(1);
}

if(adc_desc[adc_channel].current_sample_data_cnt >= 1) //此处简化直接就是采集1次,1这个数值后续可以优化
{
*(USHORT_T*)result = adc_desc[adc_channel].pData[0];
adc_desc[adc_channel].has_data = 0;
adc_desc[adc_channel].current_sample_data_cnt = 0;
last_adc = *(USHORT_T*)result;
} else {
*(USHORT_T*)result = last_adc;
}

ddev_close(adc_hdl);

saradc_ensure_close();

return OPRT_OS_ADAPTER_OK;
}

如果要求adc 采集速度快些, 可以自己重新封装下adc read接口,open->读取多个值->close. 可以参考下面代码:

Code: Select all

static int adc_dev_convert (tuya_adc_t *adc, uint16_t *result)
{
unsigned char i = 0;
unsigned int status, sum = 0;
int adc_hdl;
static unsigned short last_adc = 0;
unsigned short temp_adc_mv = 0;
unsigned int adc_max = 0, adc_min = 0;

unsigned char adc_channel = adc->cfg.pin;

if(!g_adc_init[adc_channel]){
LOG_ERR("adc not init!\r\n");
return OPRT_OS_ADAPTER_COM_ERROR;
}

GLOBAL_INT_DECLARATION();

*(unsigned short*)result = 0xFFFF;

memset(adc_desc[adc_channel].pData, 0, adc_desc[adc_channel].data_buff_size * SIZEOF(unsigned short));

GLOBAL_INT_DISABLE();

adc_hdl = ddev_open(SARADC_DEV_NAME, &status, (unsigned int)&adc_desc[adc_channel]);
if ((DD_HANDLE_UNVALID == adc_hdl) || (SARADC_SUCCESS != status))
{
if (SARADC_SUCCESS != status)
{
ddev_close(adc_hdl);
}
adc_hdl = DD_HANDLE_UNVALID;
GLOBAL_INT_RESTORE();
LOG_ERR("adv ddev_open err:%d\r\n", status);
return -1;
}
GLOBAL_INT_RESTORE();


while (1)
{
//bk_printf("d:%d,%d\r\n",saradc_desc->current_sample_data_cnt,p_ADC_drv_desc->current_sample_data_cnt);
if (adc_desc[adc_channel].current_sample_data_cnt == adc_desc[adc_channel].data_buff_size)
{
ddev_close(adc_hdl);
saradc_ensure_close();
break;
}
}

adc_max = adc_min = adc_desc[adc_channel].pData[34];

for (i = 32; i < 50; i++)
{
if(adc_max < adc_desc[adc_channel].pData[i])
adc_max = adc_desc[adc_channel].pData[i];
else if(adc_min > adc_desc[adc_channel].pData[i])
adc_min = adc_desc[adc_channel].pData[i];

sum += adc_desc[adc_channel].pData[i];
}

temp_adc_mv = saradc_calculate((UINT16)((sum - adc_max - adc_min) >> 4)) * 1000;
*(USHORT_T*)result = temp_adc_mv * ADC_REGISTER_VAL_MAX / ADC_VOLTAGE_MAX;

sum = 0;
adc_desc[adc_channel].current_read_data_cnt = 0;

return OPRT_OS_ADAPTER_OK;
}

感谢 我这边测试下