This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

PSM current problem

Hello,

Today i try to measure PSM current on nrf9160 dk and SFR sim but i don't have good results..
With at_client FW i find (AT+CEREG=5 and AT+CPSMS=1) TAU= 00000110 and AT=  00100001.

After im using "udp_with_psm" from Rallare and i change udp by tcp (see below).  and it's works fine but no the PSM current...
On PSM, i have 970uA... I don't know what to modify..

my code and my prj.conf:

/*
 * Copyright (c) 2018 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic
 */

#include <zephyr.h>
#include <net/socket.h>
#include <stdio.h>
//#include <drivers/gpio.h>
//#include <uart.h>
#include <string.h>
#include <lte_lc.h>


#define HTTP_HOST "lapostexxxxxxx.fr"
#define HTTP_PORT 80
#define RECV_BUF_SIZE 8192

char recv_buf[RECV_BUF_SIZE + 1];
char cesq_buf[50];

/* As it is close to impossible to find
 * a proper UDP server, we just connect
 * to a ntp server and read the response
 */
struct ntp_format {
	u8_t flags;
	u8_t stratum; /* stratum */
	u8_t poll; /* poll interval */
	s8_t precision; /* precision */
	u32_t rootdelay; /* root delay */
	u32_t rootdisp; /* root dispersion */
	u32_t refid; /* reference ID */
	u32_t reftime_sec; /* reference time */
	u32_t reftime_frac; /* reference time */
	u32_t org_sec; /* origin timestamp */
	u32_t org_frac; /* origin timestamp */
	u32_t rec_sec; /* receive timestamp */
	u32_t rec_frac; /* receive timestamp */
	u32_t xmt_sec; /* transmit timestamp */
	u32_t xmt_frac; /* transmit timestamp */
};

int blocking_recv(int fd, u8_t *buf, u32_t size, u32_t flags)
{
	int err;

	do {
		err = recv(fd, buf, size, flags);
	} while (err < 0 && errno == EAGAIN);

	return err;
}

int blocking_recvfrom(int fd, void *buf, u32_t size, u32_t flags,
		      struct sockaddr *src_addr, socklen_t *addrlen)
{
	int err;

	do {
		err = recvfrom(fd, buf, size, flags, src_addr, addrlen);
	} while (err < 0 && errno == EAGAIN);

	return err;
}

int blocking_send(int fd, u8_t *buf, u32_t size, u32_t flags)
{
	int err;

	do {
		err = send(fd, buf, size, flags);
	} while (err < 0 && errno == EAGAIN);

	return err;
}

int blocking_connect(int fd, struct sockaddr *local_addr, socklen_t len)
{
	int err;

	do {
		err = connect(fd, local_addr, len);
	} while (err < 0 && errno == EAGAIN);

	return err;
}

void setup_psm(void)
{
	/*
	* GPRS Timer 3 value (octet 3)
	*
	* Bits 5 to 1 represent the binary coded timer value.
	*
	* Bits 6 to 8 defines the timer value unit for the GPRS timer as follows:
	* Bits 
	* 8 7 6
	* 0 0 0 value is incremented in multiples of 10 minutes 
	* 0 0 1 value is incremented in multiples of 1 hour 
	* 0 1 0 value is incremented in multiples of 10 hours
	* 0 1 1 value is incremented in multiples of 2 seconds
	* 1 0 0 value is incremented in multiples of 30 seconds
	* 1 0 1 value is incremented in multiples of 1 minute
	* 1 1 0 value is incremented in multiples of 320 hours (NOTE 1)
	* 1 1 1 value indicates that the timer is deactivated (NOTE 2).
	*/
	char psm_settings[] = CONFIG_LTE_PSM_REQ_RPTAU;
	printk("PSM bits: %c%c%c\n", psm_settings[0], psm_settings[1],
	       psm_settings[2]);
	printk("PSM Interval: %c%c%c%c%c\n", psm_settings[3], psm_settings[4],
	       psm_settings[5], psm_settings[6], psm_settings[7]);
	int err = lte_lc_psm_req(true);
	if (err < 0) {
		printk("Error setting PSM: %d Errno: %d\n", err, errno);
	}
}

/*void app_udp_start(void)
{
	struct addrinfo *res;
	socklen_t addrlen = sizeof(struct sockaddr_storage);

	int err = getaddrinfo(HOST, NULL, NULL, &res);
	if (err < 0) {
		printk("getaddrinfo err: %d\n\r", err);
		return;
	}
	((struct sockaddr_in *)res->ai_addr)->sin_port = htons(PORT);
	struct sockaddr_in local_addr;

	local_addr.sin_family = AF_INET;
	local_addr.sin_port = htons(0);
	local_addr.sin_addr.s_addr = 0;

	int client_fd = socket(AF_INET, SOCK_DGRAM, 0);
	if (client_fd < 0) {
		printk("client_fd: %d\n\r", client_fd);
		goto error;
	}

	err = bind(client_fd, (struct sockaddr *)&local_addr,
		   sizeof(local_addr));
	if (err < 0) {
		printk("bind err: %d errno: %d\n\r", err, errno);
		goto error;
	}

	err = connect(client_fd, (struct sockaddr *)res->ai_addr,
		      sizeof(struct sockaddr_in));
	if (err < 0) {
		printk("connect err: %d errno: %d\n\r", err, errno);
		goto error;
	}

	/* Just hard code the packet format */
	//u8_t send_buf[sizeof(struct ntp_format)] = { 0xe3 };
//

	/*err = sendto(client_fd, send_buf, sizeof(send_buf), 0,
		     (struct sockaddr *)res->ai_addr, addrlen);*/
	/*err = send(client_fd, send_buf, sizeof(send_buf), 0);
	printk("sendto ret: %d\n\r", err);
	if (err < 0) {
		printk("sendto err: %d errno: %d\n\r", err, errno);
		goto error;
	}

	err = blocking_recvfrom(client_fd, recv_buf, sizeof(recv_buf), 0,
				(struct sockaddr *)res->ai_addr, &addrlen);
	if (err < 0) {
		printk("recvfrom err: %d errno: %d\n\r", err, errno);
		goto error;
	} else {
		printk("Got data back: ");
		for (int i = 0; i < err; i++) {
			printk("%x ", recv_buf[i]);
		}
		printk("\n");
	}

error:
	freeaddrinfo(res);
	printk("Finished\n");
	(void)close(client_fd);
}*/

/****************************************************************************************************
*name: 
*to do:  Send send_buf[] to http post
*return: 
****************************************************************************************************/
void app_http_start(void) {
  struct sockaddr_in local_addr;
  struct addrinfo *res;

  local_addr.sin_family = AF_INET;
  local_addr.sin_port = htons(0);
  local_addr.sin_addr.s_addr = 0;

  printk("HTTP example\n\r");
  int err = getaddrinfo(HTTP_HOST, NULL, NULL, &res);

  printk("getaddrinfo err: %d\n\r", err);
  ((struct sockaddr_in *)res->ai_addr)->sin_port = htons(HTTP_PORT);
"POST / HTTP/1.0\r\nHost: lapostexxxxxxx.fr\r\nContent-Type: application/json\r\nContent-Length: 25\r\n\r\n\{\"payload\": \"9876543210\"\}\x1A";

  int send_data_len = strlen(send_buf);

  int client_fd = socket(AF_INET, SOCK_STREAM, 0);

 printk("client_fd: %d\n\r", client_fd);
  err = bind(client_fd, (struct sockaddr *)&local_addr,
      sizeof(local_addr));
  printk("bind err: %d\n\r", err);
  err = blocking_connect(client_fd, (struct sockaddr *)res->ai_addr,
      sizeof(struct sockaddr_in));

 printk("connect err: %d\n\r", err);

  int num_bytes = send(client_fd, send_buf, send_data_len, 0);

  printk("send err: %d\n\r", num_bytes);

  int tot_num_bytes = 0;

  do {
    /* TODO: make a proper timeout *
		 * Current solution will just hang 
		 * until remote side closes connection */
    num_bytes =
        blocking_recv(client_fd, recv_buf, RECV_BUF_SIZE, 0);
    tot_num_bytes += num_bytes;

    if (num_bytes <= 0) {
      break;
    }
    printk("%s", recv_buf);
  } while (num_bytes > 0);

  printk("\n\rFinished. Closing socket\n\r");
  freeaddrinfo(res);
 (void)close(client_fd);
  err = close(client_fd);
}
static volatile bool run_udp;

void app_timer_handler(struct k_timer *dummy)
{
	static u32_t minutes;

	minutes++;
	/* This shall match the PSM interval */
	if (minutes % 10 == 0) {
		run_udp = true;
	}
	printk("Elapsed time: %d\n", minutes);
}

K_TIMER_DEFINE(app_timer, app_timer_handler, NULL);

void timer_init(void)
{
	k_timer_start(&app_timer, K_MINUTES(1), K_MINUTES(1));
}

int main(void)
{

        
	if (!IS_ENABLED(CONFIG_AT_HOST_LIBRARY)) {
		/* Stop the UART RX for power consumption reasons */
		NRF_UARTE0_NS->TASKS_STOPRX = 0;
	}


	printk("DATA POST test with PSM\n");
	//app_udp_start();
        app_http_start();
	setup_psm();
	timer_init();
	while (1) {
		k_sleep(5000);
		if (run_udp == true) {
			printk("Run HTTP POST\n");
			run_udp = false;
			//app_udp_start();
                        app_http_start();
		}
	}
	return 1;
}


CONFIG_NEWLIB_LIBC=n
CONFIG_BSD_LIBRARY=y
CONFIG_GPIO=n
CONFIG_SERIAL=n
CONFIG_STDOUT_CONSOLE=n
CONFIG_UART_INTERRUPT_DRIVEN=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NETWORKING=y
CONFIG_NET_BUF_USER_DATA_SIZE=1
CONFIG_NET_SOCKETS_OFFLOAD=y
CONFIG_NET_SOCKETS=y
CONFIG_NET_SOCKETS_POSIX_NAMES=y
CONFIG_TRUSTED_EXECUTION_NONSECURE=y
CONFIG_LOG=n
# CONFIG_LOG_DEFAULT_LEVEL=4
CONFIG_HEAP_MEM_POOL_SIZE=1024

# LTE link control
CONFIG_LTE_LINK_CONTROL=y
CONFIG_LTE_LEGACY_PCO_MODE=n
CONFIG_LTE_NETWORK_MODE_NBIOT=y

# Main thread
CONFIG_MAIN_THREAD_PRIORITY=7
CONFIG_MAIN_STACK_SIZE=4096
CONFIG_LTE_PSM_REQ_RPTAU="00000110"
CONFIG_LTE_PSM_REQ_RAT="00100001"
CONFIG_AT_HOST_LIBRARY=n

Do you have an idea please to find a 3-7 uA psm current please ??

Parents Reply
  • Maxvi33 said:
    Oh thank's

    You're welcome!

    Maxvi33 said:
    Maybe it's sim alimentation ? Do you know to cut this?

    It fits very much into the current consumption you normally see when the SIM is idle and PSM is successfully entered.

    If you run your example without starting the modem, and having a main() function that only holds "while (1) k_sleep(some_interval);", it would give you your base-line current. If this is less than 10 uA, then the 35 uA is highly likely from the SIM.

    Kind regards,

    Håkon

Children
  • Hello, 

    i was try your tips:

    int main(void)
    {
            
    	if (!IS_ENABLED(CONFIG_AT_HOST_LIBRARY)) {
    		/* Stop the UART RX for power consumption reasons */
    		NRF_UARTE0_NS->TASKS_STOPRX = 1;
    	}
    
    	printk("DATA POST test with PSM\n");
    	//app_udp_start();
            app_http_start();
    	setup_psm();
    	timer_init();
            app_socket_start_OFF(); // AT+CFUN=4
    	while (1) {
    		k_sleep(5000);
    		/*if (run_udp == true) {
    			printk("Run HTTP POST\n");
    			run_udp = false;
    			//app_udp_start();
                            app_http_start();
    		}*/
    	}
    	return 1;
    }

    And i find ~35uA.. Do you have an idea to improve PSM current ? 
    On the datasheet, i read ~3uA!

    Thank's for your help :)

  • Hi,

     

    Maxvi33 said:
    And i find ~35uA.. Do you have an idea to improve PSM current ? 

    The modem is still enabled, thus the SIM is potentially powered as well.

     

    Could you try to take the sample zephyr/samples/basic/blinky/, and add CONFIG_SERIAL=n, configure the project for board nrf9160_pca10090 (note: no ns prefix when testing this) and see what the current consumption is when testing this ? Remember that you need to power cycle after initial programming.

     

    Kind regards,

    Håkon

  • Thank's for your quick reply !

    With this sample, i have between 100nA and 10uA, it's difficult to measure with my equipment..
    How deactivated modem with the prj.conf ? Because maybe it's my function to halt modem is bad...
     

  • Hi,

    Maxvi33 said:
    With this sample, i have between 100nA and 10uA, it's difficult to measure with my equipment..

    This is good. That example will wakeup and toggle a pin every second, so you'll see a bit of a "dynamic spike" when using a normal multimeter. 

    Maxvi33 said:
    How deactivated modem with the prj.conf ? Because maybe it's my function to halt modem is bad...

     You can deactivate the modem by placing it in flight mode (AT+CFUN=4), or by not initializing it on boot by setting this in your prj.conf:

    CONFIG_LTE_AUTO_INIT_AND_CONNECT=n
     
    Kind regards,
    Håkon
  • Thank you.

    This is good. That example will wakeup and toggle a pin every second, so you'll see a bit of a "dynamic spike" when using a normal multimeter. 

    Exctly what i see!

    I was try to increase the interval time (T3412) and take out the sim card during PSM mode but i see 35uA on PSM mode again...

    On the hardware file , i c'ant see short SBx to cut alimentation..

Related