Problems entering sleep/powersave mode on bc66/OpenCPU after reading DS18x20 sensors over UART

Hi,

We are using implementation of the Dallas 1-wire protocol to access DS18x20 sensors over UART connection on the bc66. Reading temperatures work OK, but afterwards the device will not enter sleep mode. The implementation for the protocol is available on GitHub

(https://github.com/visuallabel/DS18x20-uart-opencpu) if you want to take a look at the code.

Performing a simple “reset” signal does not cause problems, but searching for the sensors or reading the temperatures (with or without searching the sensors first) does. Another noticeable issue is, that some of the messages posted with Ql_OS_SendMessage() from the “execution branch” (timer callback) used to performed the sensor search/read operations are lost and cannot received by Ql_OS_GetMessage(() (in proc_main_task()). Other than that, the device appears to work normally, and other functions can be executed.

—>See the reference code used for enabling sleep…

static const char AT_CMD_WRITE_DISABLE_CEREG[] = "AT+CEREG=0\r\n";
static const char AT_CMD_WRITE_DISABLE_CFUN[] = "AT+CFUN=0\r\n";
static const char AT_CMD_WRITE_ENABLE_EDRX[] = "AT+CEDRXS=1\r\n";
static const char AT_CMD_WRITE_ENABLE_PSM[] = "AT+CPSMS=1\r\n";
static const char AT_CMD_WRITE_ENABLE_SLEEP[] = "AT+QSCLK=1\r\n";
static const int ID_WRITE_DISABLE_CEREG = 9;
static const int ID_WRITE_DISABLE_CFUN = 10;
static const int ID_WRITE_ENABLE_EDRX = 16;
static const int ID_WRITE_ENABLE_PSM = 17;
static const int ID_WRITE_ENABLE_SLEEP = 18;

/**
 * sleep up the device
 */
static void do_sleep(void){
	s32 ret = 0;
	APP_DEBUG("Running sleep.\n");

	Ql_Timer_Stop(STATUS_CHECK_TIMER_ID); // stop timer if running
	Ql_Timer_Stop(TCP_TIMER_ID); // stop timer if running
	Ql_Timer_Delete(STATUS_CHECK_TIMER_ID); // delete timer
	Ql_Timer_Delete(TCP_TIMER_ID); // delete timer

	APP_DEBUG("Disable cereg\n");
	if ((ret = send_at_command(AT_CMD_WRITE_DISABLE_CEREG, &ID_WRITE_DISABLE_CEREG, at_callback))){ 
		APP_DEBUG("Disable cereg error, code: %d\n", ret);
	}

	APP_DEBUG("Disable cfun\n");
	if ((ret = send_at_command(AT_CMD_WRITE_DISABLE_CFUN, &ID_WRITE_DISABLE_CFUN, at_callback))){
		APP_DEBUG("Disable cfun error, code: %d\n", ret);
	}

	APP_DEBUG("Enable psm\n");
	if ((ret = send_at_command(AT_CMD_WRITE_ENABLE_PSM, &ID_WRITE_ENABLE_PSM, at_callback))){
		APP_DEBUG("Enable psm error, code: %d\n", ret);
	}

	APP_DEBUG("Enable edrx\n");
	if ((ret = send_at_command(AT_CMD_WRITE_ENABLE_EDRX, &ID_WRITE_ENABLE_EDRX, at_callback))){
		APP_DEBUG("Enable edrx error, code: %d\n", ret);
	}

	APP_DEBUG("Enable sleep\n");
	if ((ret = send_at_command(AT_CMD_WRITE_ENABLE_SLEEP, &ID_WRITE_ENABLE_SLEEP, at_callback))){
		APP_DEBUG("Enable sleep error, code: %d\n", ret);
	}
	
	Ql_SleepEnable(); // this will not go to deep sleep
}



/**
 * send and process AT command
 * 
 * @param atCmd
 * @param id
 * @param atRsp_callBack
 * @return return value of Ql_RIL_SendATCmd
 */
static s32 send_at_command(const char* atCmd, const int* id, Callback_ATResponse atRsp_callBack){
	s32 ret = Ql_RIL_SendATCmd((char*)atCmd, Ql_strlen(atCmd), atRsp_callBack, (void*)id, AT_TIMEOUT);
	switch (ret){
		case RIL_AT_SUCCESS:
			// nothing needed
			break;
		case RIL_AT_FAILED:
			APP_DEBUG("AT command failed, code: %d\n", Ql_RIL_AT_GetErrCode());
			break;
		case RIL_AT_TIMEOUT:
			APP_DEBUG("AT Command timeout.\n");
			break;
		case RIL_AT_INVALID_PARAM:
			APP_DEBUG("Invalid AT command.\n");
			break;
		case RIL_AT_UNINITIALIZED:
			APP_DEBUG("RIL uninitialized.\n");
			break;
		default:
			APP_DEBUG("Unknown return code %d from AT.\n", ret);
			do_error(); // don't know what this could be, so call error handler just in case
			break;
	}
	return ret;
}

P.S. one “hack” to fix the issue seems to be simply to Ql_Reset(0) the device after reading temperatures. Do you know if repeatedly reseting the device (about every 5mins) might cause further issue in the long run?

Thanks in advance,

University of Tampere team & JarkkoM

try:
do_sleep();
Ql_Sleep(-1); // block thread

res = Ql_OS_SendMessage( … ); // check error… maybe too many messages