Page 1 of 2

低功耗设备使用硬件i2c驱动异常

Posted: 2024年 Mar 19日 21:19
by hzb

SDK版本:TLSR8258_TuyaOS-3.8.0
低功耗设备("dev_role":"sleep_end_dev"),在使用硬件i2c时,通过drv_i2c_read_series读取aht20传感器温湿度,发现读取失败(读取缓存pst->ReadByte全是0),但是通过逻辑分析仪抓取波形,是正常的。并且在代码原封不动的情况下,将appconfig.json中"dev_role"配置从改为"router",读取就正常了,数据也是对的。请问低功耗设备如何使用硬件i2c设备(尝试在__tuya_post_sleep_cb中重新初始化i2c和gpio配置(具体如下,还是不行):

Code: Select all

VOID_T __tuya_post_sleep_cb(VOID_T)
{
	tal_main_debug("post_sleep_cb!!!\r\n");
	drv_i2c_master_init(100000);
	drv_i2c_gpio_set(I2C_GPIO_GROUP_C0C1);
}

BOOL_T tkl_gpio_output_use_wakeup_mode(TUYA_GPIO_NUM_E pin_id)
{
    if((TUYA_GPIO_NUM_16 == pin_id) ||  (TUYA_GPIO_NUM_17 == pin_id) || (GPIO_APP_NET_LED == pin_id)){
        return TRUE;
    }
    else
    {
        return FALSE;        
} }

I2C代码主要摘录如下:

Code: Select all

#define AHT20_SAMPLE_PERIOD		5000	//单位:ms, 且不小于MinReadTim

/* I2C Clock */
#define I2C_CLOCK				100000//100K

/* I2C slave ID */
#define I2C_SLAVE_ID				0x38
#define I2C_SLAVE_ADDR_LEN			1

#define ATH20_ADDR					0x38

#define	AHT20_STATUS_REG			0x00	//状态字 寄存器地址
#define	AHT20_INIT_REG			0xBE	//初始化 寄存器地址
#define	AHT20_SOFTRESET_REG		0xBA	//软复位 单指令
#define	AHT20_MEASURE_REG		0xAC	//触发测量 寄存器地址

#define SENSOR_IDLE      			0  //
#define SENSOR_MEASURE   		1  //
#define SENSOR_COMPLETE  		2  //
//****************************************
// 定义 AHT20 内部地址
//****************************************
#define ATH20_ADDR				0x38

#define	AHT20_STATUS_REG		0x00	//状态字 寄存器地址
#define	AHT20_INIT_REG			0xBE	//初始化 寄存器地址
#define	AHT20_SOFTRESET_REG		0xBA	//软复位 单指令
#define	AHT20_MEASURE_REG		0xAC	//触发测量 寄存器地址
/*----------------------------------------------------------------------------
 Section: Type Definitions
 ----------------------------------------------------------------------------*/
typedef struct
{
	unsigned char Adrr;
	unsigned int  timcnt;
	unsigned char ErrFlag;
	unsigned char Step;	
	unsigned int  SetRTim;

unsigned char SendByte[16];
unsigned char ReadByte[16];	
float RH;//湿度
float T;//温度

}MYI2C_Struct;

static MYI2C_Struct SENx;
static TIMER_ID aht20_etimerid;
static TIMER_ID aht20_sample_etimerid;
/*******************************************************************************
* Function Name  :  
* Description    :  
* Input          :None
* Output         :None
* Return         :None
*******************************************************************************/
static void MYI2C_Handle(TIMER_ID timer_id, VOID_T *arg)
{
	MYI2C_Struct *pst = (MYI2C_Struct *)arg;
	
	pst->Step = SENSOR_IDLE;
	tal_sw_timer_start(aht20_sample_etimerid, 10, TAL_TIMER_ONCE);	
	//tkl_cpu_force_wakeup();
}

static void aht20_measure_handle(TIMER_ID timer_id, VOID_T *arg)
{
	unsigned char i;
   	unsigned long s32x;
   
MYI2C_Struct *pst = (MYI2C_Struct *)arg; TAL_PR_DEBUG("[%s] step = %d", __FUNCTION__, pst->Step); if(pst->Step == SENSOR_IDLE) { pst->SendByte[0]=0x33; pst->SendByte[1]=0x00; drv_i2c_write_series((I2C_SLAVE_ID<<1) | 0, AHT20_MEASURE_REG, I2C_SLAVE_ADDR_LEN, pst->SendByte, 2); pst->Step = SENSOR_MEASURE; //TODO: 开启定时器等待75ms测量完成 tal_sw_timer_start(aht20_sample_etimerid, 100, TAL_TIMER_ONCE); } else if(pst->Step == SENSOR_MEASURE) { pst->Step=SENSOR_COMPLETE; drv_i2c_read_series((I2C_SLAVE_ID<<1)|1, 0,I2C_SLAVE_ADDR_LEN, pst->ReadByte, 7); /* 换算温度和湿度 */ if(pst->ErrFlag==0) { //if((CheckCrc8(&pst->ReadByte[0],6)==pst->ReadByte[6])&&((pst->ReadByte[0]&0x98) == 0x18)) { s32x=pst->ReadByte[1];s32x=s32x<<8;s32x+=pst->ReadByte[2];s32x=s32x<<8;s32x+=pst->ReadByte[3];s32x=s32x>>4; pst->RH=s32x; pst->RH=pst->RH*100/1048576; s32x=pst->ReadByte[3]&0x0F;s32x=s32x<<8;s32x+=pst->ReadByte[4];s32x=s32x<<8;s32x+=pst->ReadByte[5]; pst->T=s32x; pst->T=pst->T*200/1048576-50; } TAL_PR_DEBUG("pst->ReadByte: %02x-%02x-%02x-%02x-%02x-%02x-%02x", pst->ReadByte[0], pst->ReadByte[1], pst->ReadByte[2],\ pst->ReadByte[3], pst->ReadByte[4], pst->ReadByte[5], pst->ReadByte[6]); TAL_PR_DEBUG("temp = %.2f, humi = %.2f", pst->T, pst->RH); } else { pst->RH=0; pst->T=0; } //tkl_cpu_allow_sleep(); } } int app_aht20_init(void) { drv_i2c_master_init(I2C_CLOCK); drv_i2c_gpio_set(I2C_GPIO_GROUP_C0C1); SENx.Adrr = ATH20_ADDR; SENx.Step = SENSOR_IDLE; //SENx.SetRTim=AHT20_SAMPLE_PERIOD; WaitMs(40); /* 定时启动读取温湿度用 */ OPERATE_RET ret = tal_sw_timer_create(MYI2C_Handle, &SENx, &aht20_etimerid); if(ret != OPRT_OK) { TAL_PR_DEBUG("[%s] timer create failed", __FUNCTION__); return ret; } /* 温湿度采集时动作延迟用 */ ret = tal_sw_timer_create(aht20_measure_handle, &SENx, &aht20_sample_etimerid); if(ret != OPRT_OK) { TAL_PR_DEBUG("[%s] timer create failed", __FUNCTION__); return ret; } // ret = tal_sw_timer_start(aht20_etimerid, AHT20_SAMPLE_PERIOD, TAL_TIMER_CYCLE); if(ret != OPRT_OK) { TAL_PR_DEBUG("[%s] timer create failed", __FUNCTION__); return ret; } return 0; }

附件图片:
1.异常情况下,逻辑分析仪抓到的波形正常
2.router配置时正常读取
3. sleep_end_dev配置时,读取异常


Re: 低功耗设备使用硬件i2c驱动异常

Posted: 2024年 Mar 19日 21:20
by hzb

附件如下:


Re: 低功耗设备使用硬件i2c驱动异常

Posted: 2024年 Mar 21日 16:57
by huanghuan

1.你好,低功耗设备如果不进去休眠硬件iic与router的库执行部分是一样的;建议你在 last init中调用 tkl_cpu_force_wakeup();并确保不调用 allow sleep 确认下不进入休眠的话 硬件iic是否功能正常
2.sdk有check兜底防止急速耗电机制,超过2min不进入休眠会自动重启一次,我们先确认是否是由于进入休眠导致的功能问题


Re: 低功耗设备使用硬件i2c驱动异常

Posted: 2024年 Mar 21日 19:48
by hzb

尝试了在tuya_init_last中调用tkl_cpu_force_wakeup,还是不正常,代码如下:

Code: Select all

OPERATE_RET tuya_init_last(VOID_T)
{
    tal_main_debug("/*********last init4*********/\r\n");
    // __tuya_uart_debug_init();

sys_init_finish_flag = TRUE;

__tuya_gpio_init();

__tuya_led_init();

__tuya_battery_init();
//heartbeat config
tal_heartbeat_type_set(HEARTBEAT_BATTERY_VOLTAGE);
tal_heartbeat_period_set(3 * 60 * 60 * 1000);//3小时
tal_heartbeat_start();

if(app_illuminance_init() != OPRT_OK)
{
	tal_main_debug("app_illuminance_init failed\r\n");
}

if(app_sensor_init() != OPRT_OK)
{
	tal_main_debug("app_sensor_init failed\r\n");
}

if(app_aht20_init() != OPRT_OK)
{
	tal_main_debug("app_aht20_init failed\r\n");
}

app_dpid_init();

//#endif
tal_sw_timer_start(power_on_event_id, 0, TAL_TIMER_ONCE);

tkl_cpu_force_wakeup();

return OPRT_OK;
}

Re: 低功耗设备使用硬件i2c驱动异常

Posted: 2024年 Mar 21日 20:01
by hzb

感觉调用了tkl_cpu_force_wakeup();还是会睡眠,因为根据打印信息看执行到tuya_init_last后,还是会打印tuya_post_sleep_cb中的tal_main_debug("post_sleep_cb!!!\r\n");, 并且如果没有在tuya_post_sleep_cb中重新初始化i2c驱动drv_i2c_master_init(100000);drv_i2c_gpio_set(I2C_GPIO_GROUP_C0C1);,连模组发出的i2c波形都没了。

Code: Select all

VOID_T __tuya_post_sleep_cb(VOID_T)
{
	tal_main_debug("post_sleep_cb!!!\r\n");
	drv_i2c_master_init(100000);
	drv_i2c_gpio_set(I2C_GPIO_GROUP_C0C1);
}

Re: 低功耗设备使用硬件i2c驱动异常

Posted: 2024年 Mar 21日 21:03
by iot_man

下面这样试试:

Code: Select all

#define AHT20_SAMPLE_PERIOD		5000	//单位:ms, 且不小于MinReadTim

/* I2C Clock */
#define I2C_CLOCK				100000//100K

/* I2C slave ID */
#define I2C_SLAVE_ID				0x38
#define I2C_SLAVE_ADDR_LEN			1

#define ATH20_ADDR					0x38

#define	AHT20_STATUS_REG			0x00	//状态字 寄存器地址
#define	AHT20_INIT_REG			0xBE	//初始化 寄存器地址
#define	AHT20_SOFTRESET_REG		0xBA	//软复位 单指令
#define	AHT20_MEASURE_REG		0xAC	//触发测量 寄存器地址

#define SENSOR_IDLE      			0  //
#define SENSOR_MEASURE   		1  //
#define SENSOR_COMPLETE  		2  //
//****************************************
// 定义 AHT20 内部地址
//****************************************
#define ATH20_ADDR				0x38

#define	AHT20_STATUS_REG		0x00	//状态字 寄存器地址
#define	AHT20_INIT_REG			0xBE	//初始化 寄存器地址
#define	AHT20_SOFTRESET_REG		0xBA	//软复位 单指令
#define	AHT20_MEASURE_REG		0xAC	//触发测量 寄存器地址
/*----------------------------------------------------------------------------
 Section: Type Definitions
 ----------------------------------------------------------------------------*/
typedef struct
{
	unsigned char Adrr;
	unsigned int  timcnt;
	unsigned char ErrFlag;
	unsigned char Step;	
	unsigned int  SetRTim;

unsigned char SendByte[16];
unsigned char ReadByte[16];	
float RH;//湿度
float T;//温度

}MYI2C_Struct;

static MYI2C_Struct SENx;
static TIMER_ID aht20_etimerid;
static TIMER_ID aht20_sample_etimerid;
/*******************************************************************************
* Function Name  :  
* Description    :  
* Input          :None
* Output         :None
* Return         :None
*******************************************************************************/
static void MYI2C_Handle(TIMER_ID timer_id, VOID_T *arg)
{
	MYI2C_Struct *pst = (MYI2C_Struct *)arg;
	
	pst->Step = SENSOR_IDLE;
	tal_sw_timer_start(aht20_sample_etimerid, 10, TAL_TIMER_ONCE);	
	//tkl_cpu_force_wakeup();
}

static void aht20_measure_handle(TIMER_ID timer_id, VOID_T *arg)
{
	unsigned char i;
   	unsigned long s32x;
   
MYI2C_Struct *pst = (MYI2C_Struct *)arg; TAL_PR_DEBUG("[%s] step = %d", __FUNCTION__, pst->Step); if(pst->Step == SENSOR_IDLE) { pst->SendByte[0]=0x33; pst->SendByte[1]=0x00; drv_i2c_write_series((I2C_SLAVE_ID<<1) | 0, AHT20_MEASURE_REG, I2C_SLAVE_ADDR_LEN, pst->SendByte, 2); pst->Step = SENSOR_MEASURE; //TODO: 开启定时器等待75ms测量完成 tal_sw_timer_start(aht20_sample_etimerid, 100, TAL_TIMER_ONCE); tkl_cpu_force_wakeup(); } else if(pst->Step == SENSOR_MEASURE) { pst->Step=SENSOR_COMPLETE; drv_i2c_read_series((I2C_SLAVE_ID<<1)|1, 0,I2C_SLAVE_ADDR_LEN, pst->ReadByte, 7); /* 换算温度和湿度 */ if(pst->ErrFlag==0) { //if((CheckCrc8(&pst->ReadByte[0],6)==pst->ReadByte[6])&&((pst->ReadByte[0]&0x98) == 0x18)) { s32x=pst->ReadByte[1];s32x=s32x<<8;s32x+=pst->ReadByte[2];s32x=s32x<<8;s32x+=pst->ReadByte[3];s32x=s32x>>4; pst->RH=s32x; pst->RH=pst->RH*100/1048576; s32x=pst->ReadByte[3]&0x0F;s32x=s32x<<8;s32x+=pst->ReadByte[4];s32x=s32x<<8;s32x+=pst->ReadByte[5]; pst->T=s32x; pst->T=pst->T*200/1048576-50; } TAL_PR_DEBUG("pst->ReadByte: %02x-%02x-%02x-%02x-%02x-%02x-%02x", pst->ReadByte[0], pst->ReadByte[1], pst->ReadByte[2],\ pst->ReadByte[3], pst->ReadByte[4], pst->ReadByte[5], pst->ReadByte[6]); TAL_PR_DEBUG("temp = %.2f, humi = %.2f", pst->T, pst->RH); } else { pst->RH=0; pst->T=0; } tkl_cpu_allow_sleep(); } } int app_aht20_init(void) { drv_i2c_master_init(I2C_CLOCK); drv_i2c_gpio_set(I2C_GPIO_GROUP_C0C1); SENx.Adrr = ATH20_ADDR; SENx.Step = SENSOR_IDLE; //SENx.SetRTim=AHT20_SAMPLE_PERIOD; WaitMs(40); /* 定时启动读取温湿度用 */ OPERATE_RET ret = tal_sw_timer_create(MYI2C_Handle, &SENx, &aht20_etimerid); if(ret != OPRT_OK) { TAL_PR_DEBUG("[%s] timer create failed", __FUNCTION__); return ret; } /* 温湿度采集时动作延迟用 */ ret = tal_sw_timer_create(aht20_measure_handle, &SENx, &aht20_sample_etimerid); if(ret != OPRT_OK) { TAL_PR_DEBUG("[%s] timer create failed", __FUNCTION__); return ret; } // ret = tal_sw_timer_start(aht20_etimerid, AHT20_SAMPLE_PERIOD, TAL_TIMER_CYCLE); if(ret != OPRT_OK) { TAL_PR_DEBUG("[%s] timer create failed", __FUNCTION__); return ret; } return 0; }

Re: 低功耗设备使用硬件i2c驱动异常

Posted: 2024年 Mar 21日 21:05
by huanghuan

1.你好,试下用 VOID hardware_set_wakeup(UINT32_T bit_map) 这个函数保持唤醒试下
填入的参数可以填 0x00000002


Re: 低功耗设备使用硬件i2c驱动异常

Posted: 2024年 Mar 22日 11:36
by hzb
iot_man 2024年 Mar 21日 21:03

下面这样试试:

Code: Select all

#define AHT20_SAMPLE_PERIOD		5000	//单位:ms, 且不小于MinReadTim

/* I2C Clock */
#define I2C_CLOCK				100000//100K

/* I2C slave ID */
#define I2C_SLAVE_ID				0x38
#define I2C_SLAVE_ADDR_LEN			1

#define ATH20_ADDR					0x38

#define	AHT20_STATUS_REG			0x00	//状态字 寄存器地址
#define	AHT20_INIT_REG			0xBE	//初始化 寄存器地址
#define	AHT20_SOFTRESET_REG		0xBA	//软复位 单指令
#define	AHT20_MEASURE_REG		0xAC	//触发测量 寄存器地址

#define SENSOR_IDLE      			0  //
#define SENSOR_MEASURE   		1  //
#define SENSOR_COMPLETE  		2  //
//****************************************
// 定义 AHT20 内部地址
//****************************************
#define ATH20_ADDR				0x38

#define	AHT20_STATUS_REG		0x00	//状态字 寄存器地址
#define	AHT20_INIT_REG			0xBE	//初始化 寄存器地址
#define	AHT20_SOFTRESET_REG		0xBA	//软复位 单指令
#define	AHT20_MEASURE_REG		0xAC	//触发测量 寄存器地址
/*----------------------------------------------------------------------------
 Section: Type Definitions
 ----------------------------------------------------------------------------*/
typedef struct
{
	unsigned char Adrr;
	unsigned int  timcnt;
	unsigned char ErrFlag;
	unsigned char Step;	
	unsigned int  SetRTim;

unsigned char SendByte[16];
unsigned char ReadByte[16];	
float RH;//湿度
float T;//温度

}MYI2C_Struct;

static MYI2C_Struct SENx;
static TIMER_ID aht20_etimerid;
static TIMER_ID aht20_sample_etimerid;
/*******************************************************************************
* Function Name  :  
* Description    :  
* Input          :None
* Output         :None
* Return         :None
*******************************************************************************/
static void MYI2C_Handle(TIMER_ID timer_id, VOID_T *arg)
{
	MYI2C_Struct *pst = (MYI2C_Struct *)arg;
	
	pst->Step = SENSOR_IDLE;
	tal_sw_timer_start(aht20_sample_etimerid, 10, TAL_TIMER_ONCE);	
	//tkl_cpu_force_wakeup();
}

static void aht20_measure_handle(TIMER_ID timer_id, VOID_T *arg)
{
	unsigned char i;
   	unsigned long s32x;
   
MYI2C_Struct *pst = (MYI2C_Struct *)arg; TAL_PR_DEBUG("[%s] step = %d", __FUNCTION__, pst->Step); if(pst->Step == SENSOR_IDLE) { pst->SendByte[0]=0x33; pst->SendByte[1]=0x00; drv_i2c_write_series((I2C_SLAVE_ID<<1) | 0, AHT20_MEASURE_REG, I2C_SLAVE_ADDR_LEN, pst->SendByte, 2); pst->Step = SENSOR_MEASURE; //TODO: 开启定时器等待75ms测量完成 tal_sw_timer_start(aht20_sample_etimerid, 100, TAL_TIMER_ONCE); tkl_cpu_force_wakeup(); } else if(pst->Step == SENSOR_MEASURE) { pst->Step=SENSOR_COMPLETE; drv_i2c_read_series((I2C_SLAVE_ID<<1)|1, 0,I2C_SLAVE_ADDR_LEN, pst->ReadByte, 7); /* 换算温度和湿度 */ if(pst->ErrFlag==0) { //if((CheckCrc8(&pst->ReadByte[0],6)==pst->ReadByte[6])&&((pst->ReadByte[0]&0x98) == 0x18)) { s32x=pst->ReadByte[1];s32x=s32x<<8;s32x+=pst->ReadByte[2];s32x=s32x<<8;s32x+=pst->ReadByte[3];s32x=s32x>>4; pst->RH=s32x; pst->RH=pst->RH*100/1048576; s32x=pst->ReadByte[3]&0x0F;s32x=s32x<<8;s32x+=pst->ReadByte[4];s32x=s32x<<8;s32x+=pst->ReadByte[5]; pst->T=s32x; pst->T=pst->T*200/1048576-50; } TAL_PR_DEBUG("pst->ReadByte: %02x-%02x-%02x-%02x-%02x-%02x-%02x", pst->ReadByte[0], pst->ReadByte[1], pst->ReadByte[2],\ pst->ReadByte[3], pst->ReadByte[4], pst->ReadByte[5], pst->ReadByte[6]); TAL_PR_DEBUG("temp = %.2f, humi = %.2f", pst->T, pst->RH); } else { pst->RH=0; pst->T=0; } tkl_cpu_allow_sleep(); } } int app_aht20_init(void) { drv_i2c_master_init(I2C_CLOCK); drv_i2c_gpio_set(I2C_GPIO_GROUP_C0C1); SENx.Adrr = ATH20_ADDR; SENx.Step = SENSOR_IDLE; //SENx.SetRTim=AHT20_SAMPLE_PERIOD; WaitMs(40); /* 定时启动读取温湿度用 */ OPERATE_RET ret = tal_sw_timer_create(MYI2C_Handle, &SENx, &aht20_etimerid); if(ret != OPRT_OK) { TAL_PR_DEBUG("[%s] timer create failed", __FUNCTION__); return ret; } /* 温湿度采集时动作延迟用 */ ret = tal_sw_timer_create(aht20_measure_handle, &SENx, &aht20_sample_etimerid); if(ret != OPRT_OK) { TAL_PR_DEBUG("[%s] timer create failed", __FUNCTION__); return ret; } // ret = tal_sw_timer_start(aht20_etimerid, AHT20_SAMPLE_PERIOD, TAL_TIMER_CYCLE); if(ret != OPRT_OK) { TAL_PR_DEBUG("[%s] timer create failed", __FUNCTION__); return ret; } return 0; }

尝试了,还是不行


Re: 低功耗设备使用硬件i2c驱动异常

Posted: 2024年 Mar 22日 11:38
by hzb
huanghuan 2024年 Mar 21日 21:05

1.你好,试下用 VOID hardware_set_wakeup(UINT32_T bit_map) 这个函数保持唤醒试下
填入的参数可以填 0x00000002

在last_init中调用:hardware_set_wakeup(0x00000002); 现象:确实不会回调__tuya_post_sleep_cb, 但是读取传感器还是失败


Re: 低功耗设备使用硬件i2c驱动异常

Posted: 2024年 Mar 25日 16:21
by hzb

能帮忙提供下处理办法嘛?项目比较着急