Low Power on nRF5340 SoC with Zephyr & RTC Support

Hi dears,

I'm trying to reduce the power consumption of a custom board with a nRF5340 SoC. The application is a sensor node with an ADC and the BT support to transfer sampled data to a PC (server with BT support).

The Environment:
- nRFConnect SDK v2.2.0
- Zephyr OS

The application requirements are:
- The board provides an external Tuning Fork Crystal (32.768kHz) support to the SoC in order to permit the RTC use and/or a time reference.
- The SoC has to sleep all time (99.9% of the operating time). This need to be done by an Effective & Reliable Low Power Policy.
- One time/hour the SoC has to wake up to sample the analog entities by an external ADC.
- The SoC manages the external ADC by a SPI interface.
- The SoC transfers the sampled datas to a remote PC by the BT connection.

How can I implement that?

After the Optimizing Power on nRF5340 SoC Designs reading..
My understanding is:

- Modifiy the project.conf :

CONFIG_PM=y
CONFIG_PM_DEVICE=y
I don't know if that could be enough or I need of other configurations.

- include the headers for the PM control in the main.c

#include <zephyr/pm/pm.h>
#include <zephyr/pm/device.h>
#include <zephyr/pm/policy.h>

- Prevent from System OFF (no hardware support for the wakeup is present on board) 

	/* Prevent deep sleep (system off) from being entered */
    pm_policy_state_lock_get(PM_STATE_SOFT_OFF);

- Use the pm_device_action_run() function or somenthing lika that to switch the PM states.

My dubt is: without hardware events how can I use a RTC (I have a 32kHz crystal on board) or timers to put the in Sleep the module and how to WakeUp it after a certain time?

Many Thanks for your support and have a nice day,
Best Regards

  • Hi

    In the Zephyr RTOS, the device will by default go into a system ON IDLE mode when no threads are running, so this should not be an issue. If the only thing running in your project is the RTC, that should the nRF5340 should be in low power (system ON) mode by default and just wake up when the RTC is triggered. The PM library should not be required unless you want to go into other power modes than the "default" system ON IDLE mode, so that won't be necessary in your use case I believe.

    Best regards,

    Simon

  • Hi Simon.,

    when you talk about IDLE ON what do you refear to?

    /*
     * Copyright (c) 2018 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */
    
    ////////////////////////////////////// INCLUDE SECTION ///////////////////////////////////////////////
    #include <zephyr/types.h>
    #include <stddef.h>
    #include <string.h>
    #include <errno.h>
    #include <zephyr/sys/printk.h>
    #include <zephyr/sys/byteorder.h>
    #include <zephyr/kernel.h>
    /**************************************************************/
    #include <zephyr/init.h>
    /**************************************************************/
    #include <zephyr/drivers/gpio.h>
    #include <zephyr/drivers/spi.h>
    #include <zephyr/device.h>
    #include <zephyr/pm/pm.h>
    #include <zephyr/pm/device.h>
    #include <zephyr/pm/policy.h>
    /**************************************************************/
    #include <soc.h>
    
    #include <zephyr/bluetooth/bluetooth.h>
    #include <zephyr/bluetooth/hci.h>
    #include <zephyr/bluetooth/conn.h>
    #include <zephyr/bluetooth/uuid.h>
    #include <zephyr/bluetooth/gatt.h>
    
    #include <bluetooth/gatt_dm.h>
    
    #include <dk_buttons_and_leds.h>
    /**************************************************************/
    #include "MCP3562.h"
    #include "s1176_drvs.h"
    /**************************************************************/
    ///////////////////////////////////////////////////////////////////////////////////////////////////////
    /////////////////////////////////// DEFINE SECTION ////////////////////////////////////////////////////
    #define DEVICE_NAME             CONFIG_BT_DEVICE_NAME
    #define DEVICE_NAME_LEN         (sizeof(DEVICE_NAME) - 1)
    
    /* Key used to accept or reject passkey value */
    #define KEY_PAIRING_ACCEPT DK_BTN1_MSK
    #define KEY_PAIRING_REJECT DK_BTN2_MSK
    
    /**************************************************************/
    #define MY_SPI_MASTER DT_NODELABEL(my_spi_master)
    #define MAX_USER_DATA_LENGTH 1024
    /**************************************************************/
    #define RTC_PRESCALER 3276 //  fRTC [Hz] = 32768 / (PRESCALER + 1 ). Quindi 3276 10Hz oppure 327 per 100Hz
    						   // RTC_PRESCALER = ROUND(32768 Hz / 100 Hz) = 327 >> fRTC = 99.9 Hz
    #define RTC_COUNTERTOP 360000
    #define RTC_ALARM
    #define RTC_ALARM_SECONDS
    /**************************************************************/
    #define WAITTIME	3000		//WRC 3 seconds
    #define BUSY_WAIT_S 2U
    #define TESTSELCOM
    //#define SESAMPLING
    ///////////////////////////////////////////////////////////////////////////////////////////////////////
    /////////////////////////////////// GLOBAL SECTION ////////////////////////////////////////////////////
    static struct bt_conn *pairing_confirmation_conn;
    static const struct bt_data ad[] = {
    	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
    	BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
    };
    
    static void discover_all_completed(struct bt_gatt_dm *dm, void *ctx)
    {
    	char uuid_str[37];
    
    	const struct bt_gatt_dm_attr *gatt_service_attr =
    			bt_gatt_dm_service_get(dm);
    	const struct bt_gatt_service_val *gatt_service =
    			bt_gatt_dm_attr_service_val(gatt_service_attr);
    
    	size_t attr_count = bt_gatt_dm_attr_cnt(dm);
    
    	bt_uuid_to_str(gatt_service->uuid, uuid_str, sizeof(uuid_str));
    	printk("Found service %s\n", uuid_str);
    	printk("Attribute count: %d\n", attr_count);
    
    	bt_gatt_dm_data_print(dm);
    	bt_gatt_dm_data_release(dm);
    
    	bt_gatt_dm_continue(dm, NULL);
    }
    
    static void discover_all_service_not_found(struct bt_conn *conn, void *ctx)
    {
    	printk("No more services\n");
    }
    
    static void discover_all_error_found(struct bt_conn *conn, int err, void *ctx)
    {
    	printk("The discovery procedure failed, err %d\n", err);
    }
    
    static struct bt_gatt_dm_cb discover_all_cb = {
    	.completed = discover_all_completed,
    	.service_not_found = discover_all_service_not_found,
    	.error_found = discover_all_error_found,
    };
    
    static void connected(struct bt_conn *conn, uint8_t err)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	if (err) {
    		printk("Connection failed (err 0x%02x)\n", err);
    		return;
    	}
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    	printk("Connected %s\n", addr);
    
    	err = bt_gatt_dm_start(conn, NULL, &discover_all_cb, NULL);
    	if (err) {
    		printk("Failed to start discovery (err %d)\n", err);
    	}
    }
    
    static void disconnected(struct bt_conn *conn, uint8_t reason)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    	printk("Disconnected from %s (reason 0x%02x)\n", addr, reason);
    }
    
    static void security_changed(struct bt_conn *conn, bt_security_t level,
    			     enum bt_security_err err)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	if (!err) {
    		printk("Security changed: %s level %u\n", addr, level);
    	} else {
    		printk("Security failed: %s level %u err %d\n", addr, level,
    			err);
    	}
    }
    
    BT_CONN_CB_DEFINE(conn_callbacks) = {
    	.connected        = connected,
    	.disconnected     = disconnected,
    	.security_changed = security_changed,
    };
    
    static void auth_cancel(struct bt_conn *conn)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	printk("Pairing cancelled: %s\n", addr);
    }
    
    static void pairing_confirm(struct bt_conn *conn)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	__ASSERT_NO_MSG(!pairing_confirmation_conn);
    	pairing_confirmation_conn = bt_conn_ref(conn);
    
    	printk("Pairing confirmation required for %s\n", addr);
    	printk("Press Button 1 to confirm, Button 2 to reject.\n");
    }
    
    static void pairing_complete(struct bt_conn *conn, bool bonded)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	printk("Pairing completed: %s, bonded: %d\n", addr, bonded);
    }
    
    static void pairing_failed(struct bt_conn *conn, enum bt_security_err reason)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	printk("Pairing failed conn: %s, reason %d\n", addr, reason);
    
    	if (pairing_confirmation_conn) {
    		bt_conn_unref(pairing_confirmation_conn);
    		pairing_confirmation_conn = NULL;
    	}
    }
    
    static struct bt_conn_auth_cb conn_auth_callbacks = {
    	.cancel = auth_cancel,
    	.pairing_confirm = pairing_confirm,
    };
    
    static struct bt_conn_auth_info_cb conn_auth_info_callbacks = {
    	.pairing_complete = pairing_complete,
    	.pairing_failed = pairing_failed
    };
    
    static void button_changed(uint32_t button_state, uint32_t has_changed)
    {
    	int err;
    	uint32_t buttons = button_state & has_changed;
    
    	if (buttons & KEY_PAIRING_ACCEPT) {
    		struct bt_conn *conn = pairing_confirmation_conn;
    		pairing_confirmation_conn = NULL;
    
    		if (conn) {
    			err = bt_conn_auth_pairing_confirm(conn);
    			if (err) {
    				printk("Failed to confirm the pairing: %d\n", err);
    			} else {
    				printk("Pairing confirmed\n");
    			}
    
    			bt_conn_unref(conn);
    			conn = NULL;
    		}
    	}
    
    	if (buttons & KEY_PAIRING_REJECT) {
    		struct bt_conn *conn = pairing_confirmation_conn;
    		pairing_confirmation_conn = NULL;
    
    		if (conn) {
    			err = bt_conn_auth_cancel(conn);
    			if (err) {
    				printk("Failed to reject the pairing: %d\n", err);
    			} else {
    				printk("Pairing rejected\n");
    			}
    
    			bt_conn_unref(conn);
    			conn = NULL;
    		}
    	}
    }
    
    /**************************************************************/
    static struct k_poll_signal spi_done_sig = K_POLL_SIGNAL_INITIALIZER(spi_done_sig);
    
    struct spi_cs_control spim_cs = {
    	.gpio = SPI_CS_GPIOS_DT_SPEC_GET(DT_NODELABEL(mcp3562)),
    	.delay = 0,
    };
    
    static uint8_t data[MAX_USER_DATA_LENGTH], cmp_data[MAX_USER_DATA_LENGTH];
    //uint8_t data[MAX_USER_DATA_LENGTH], cmp_data[MAX_USER_DATA_LENGTH];
    /**************************************************************/
    
    /*********************************************************/
    /* 10.08.2023 Init GPIO app specific for S1176 */
    static void configure_gpio_s1176(void){
    	s1176_gpis_init();
    	s1176_gpos_init();
    }
    /*********************************************************/
    /******************* LowPower ****************************/
    static void idle_state_handle(void){
    	//if(NRF_LOG_PROCESS() == false){
    		// Enter System On Sleep Mode
    		//nrf_pwr_mgmt_run();
    		//__WFI(); //__WFE();
    	//}
    }
    /*********************************************************/
    uint32_t ds1_stat, ds2_stat;
    int indata;
    float vdiff, vsing, rx_ind;
    int temp;
    int temp1;
    uint8_t msbyte;
    
    
    //////////////////////////
    void mcp3562_minitialization(const struct device *spi, struct spi_config *spi_cfg, uint8_t *data);
    float mcp3562_rsensor_1_samp(const struct device *spi, struct spi_config *spi_cfg, uint8_t *data);
    /////////////////////////////////// MAIN FUNCTION ////////////////////////////////////////////////////
    void main(void)
    {
    	int err;
    	//float vdiff, vsing;
    	//signed int indata_tmp;
    	//float rx_ind;
    	//uint32_t ds1_stat, ds2_stat;
    	//int temp;
    	//uint32_t temp1;
    	//uint8_t msbyte;
    /////////////////////////////////// S1176 BOARD CONF SECTION ////////////////////////////////////////////////////
    	printk("Starting GATT Discovery Manager example\n");
    	/*********************************************************/
    	const struct device *spi;
    	struct spi_config spi_cfg = {0};
    	/*******************************/
    	//const struct device *rtc_dev;
    	//struct rtc_config config;
    	//struct rtc_config rtc_cfg;
    	/*********************************************************/
    	/*
    	rtc_dev = device_get_binding(DEVICE_DT_NAME(DT_NODELABEL(rtc0)));
    	if (!rtc_dev) {
    		printk("RTC device not found\n");
    		return;
    	}*/
    
    	/*rtc_cfg.init_val = 0;
    	rtc_cfg.prescaler = RTC_PRESCALER;
    	rtc_cfg.flags = RTC_COUNTERTOP;
    	rtc_cfg.callback = rtc_callback;
    	rtc_cfg.user_data = NULL;
    
    	if (rtc_configure(rtc_dev, &rtc_cfg) != 0) {
        	printk("Failed to configure RTC\n");
        	return;
    	}*/	
    
    	/*rtc_set_alarm(rtc_dev, RTC_ALARM, RTC_ALARM_SECONDS);
    	rtc_enable_interrupt(rtc_dev, RTC_ALARM);
    	void rtc_callback(const struct device *dev, void *user_data){
        	// Handle the RTC alarm interrupt (e.g., set a flag to indicate wakeup).
    	}
    	*/
    	/*********************************************************/
    	//spi = DEVICE_DT_GET(DT_ALIAS(spi4));
    	// MODIFICA COMPILAZIONE ANDREA
    	spi = device_get_binding(DEVICE_DT_NAME(DT_NODELABEL(my_spi_master)));
    
    	if (!device_is_ready(spi)) {
    			printk("SPI device %s is not ready\n", spi->name);
    			return;
    	}
    
    	spi_cfg.operation = SPI_WORD_SET(8) | SPI_OP_MODE_MASTER;
    	spi_cfg.frequency = 256000U;
    	spi_cfg.cs = &spim_cs;
    	/*********************************************************/
    	/* 10.08.2023 Init  app specific GPIOs for S1176 */
    	configure_gpio_s1176();
    	s1176_set_gpos(ADC_XO_EN_DIGOUT, 1);
    	s1176_set_gpos(ESWITCH_1_CTL_DIGOUT, 1);
    	s1176_set_gpos(ESWITCH_2_CTL_DIGOUT, 1);
    	/********************************************************/	
    
    	err = bt_enable(NULL);
    	if (err) {
    		printk("BLE init failed with error code %d\n", err);
    		return;
    	}
    
    	err = bt_conn_auth_cb_register(&conn_auth_callbacks);
    	if (err) {
    		printk("Failed to register authorization callbacks.\n");
    		return;
    	}
    
    	err = bt_conn_auth_info_cb_register(&conn_auth_info_callbacks);
    	if (err) {
    		printk("Failed to register authorization info callbacks.\n");
    		return;
    	}
    
    	err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad),
    			      NULL, 0);
    	if (err) {
    		printk("Advertising failed to start (err %d)\n", err);
    		return;
    	}
    
    	printk("Advertising successfully started\n");
    
    	#ifndef TESTSELCOM
    //////////////////////////////////////////////////////////////////////////////////
    		data[0] = 0xFF;
    	err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_CONFIG0_ADDR, data, 1);
    	if (err) {
    		printk("Error reading from ADC! error code (%d)\n", err);
    		//return;
    	} else {
    		printk("Read 0x%X from address 0x01.\n", data[0]);
    	}
    	data[14]=data[0];
    
    	data[0] = 0xFF;
    	err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_CONFIG1_ADDR, data, 1);
    	if (err) {
    		printk("Error reading from ADC! error code (%d)\n", err);
    		//return;
    	} else {
    		printk("Read 0x%X from address 0x01.\n", data[0]);
    	}
    	data[14]=data[0];
    
    	data[0] = 0xFF;
    	err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_CONFIG2_ADDR, data, 1);
    	if (err) {
    		printk("Error reading from ADC! error code (%d)\n", err);
    		//return;
    	} else {
    		printk("Read 0x%X from address 0x01.\n", data[0]);
    	}
    
    	data[0] = 0xFF;
    	err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_CONFIG3_ADDR, data, 1);
    	if (err) {
    		printk("Error reading from ADC! error code (%d)\n", err);
    		//return;
    	} else {
    		printk("Read 0x%X from address 0x01.\n", data[0]);
    	}
    
    	for(;;){
    		data[0] = 0x01; // CONFIGURE the internal MUX for DIFFERENTIAL READOUTs on Channels CH0 & CH1
    		err = mcp3562_mwrite_bytes(spi, &spi_cfg, MCP3562_MUX_ADDR, data, 1);
    			if (err) {
    				printk("Error writing to ADC! error code (%d)\n", err);
    				//return;
    			} else {
    				printk("Wrote 0x01 to address 0x06.\n");
    			}	
    
    		// PREPARE THE ADC TO READ
    		data[0] = (0xC0 | MCP3562_CONFIG0_CLK_SEL_EXT | MCP3562_CONFIG0_CS_SEL_NONE | MCP3562_CONFIG0_ADC_MODE_CONV);//0xC3;
    		err = mcp3562_mwrite_bytes(spi, &spi_cfg, MCP3562_CONFIG0_ADDR, data, 1);
    			if (err) {
    				printk("Error writing to ADC! error code (%d)\n", err);
    				//return;
    			} else {
    				printk("Wrote 0x01 to address 0x06.\n");
    			}		
    
    		data[0] = 0x00; // READ FROM ADCDATA Register 0x00
    		err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_ADCDATA_ADDR, data, 3);
    		if (err) {
    			printk("Error reading from ADC! error code (%d)\n", err);
    			//return;
    		} else {
    			printk("Read 0x%X from address 0x00.\n", data[0]);
    		}		
    	}
    /////////////////////////////////////////////////////////////////////////////////
    	#else
    		#ifndef SESAMPLING
    			/* Prevent deep sleep (system off) from being entered */
        		pm_policy_state_lock_get(PM_STATE_SOFT_OFF, PM_ALL_SUBSTATES);
    			//sys_pm_ctrl_disable_state(SYS_POWER_STATE_DEEP_SLEEP_1);
    //////////////////////////////////////// DIFF SAMPLING //////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////// CONFIGURATION ////////////////////////////
    			//data[0] = (0xC0 | MCP3562_CONFIG0_CLK_SEL_EXT | MCP3562_CONFIG0_CS_SEL_NONE | MCP3562_CONFIG0_ADC_MODE_CONV);//0xC3;
    			data[0] = 0xC3;
    			err = mcp3562_mwrite_bytes(spi, &spi_cfg, MCP3562_CONFIG0_ADDR, data, 1);
    			if (err) {
    				printk("Error writing to ADC! error code (%d)\n", err);
    				//return;
    			} else {
    				printk("Wrote 0x01 to address 0x06.\n");
    			}
    
    			data[0] = 0xFF;
    			err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_CONFIG0_ADDR, data, 1);
    			if (err) {
    				printk("Error reading from ADC! error code (%d)\n", err);
    				//return;
    			} else {
    				printk("Read 0x%X from address 0x01.\n", data[0]);
    			}
    			data[14]=data[0];
    			
    			//data[0] = (0xC0 | MCP3562_CONFIG0_CLK_SEL_EXT | MCP3562_CONFIG0_CS_SEL_NONE | MCP3562_CONFIG0_ADC_MODE_CONV);//0xC3;
    			data[0] = 0x0C;
    			err = mcp3562_mwrite_bytes(spi, &spi_cfg, MCP3562_CONFIG1_ADDR, data, 1);
    			if (err) {
    				printk("Error writing to ADC! error code (%d)\n", err);
    				//return;
    			} else {
    				printk("Wrote 0x01 to address 0x06.\n");
    			}
    
    			data[0] = 0xFF;
    			err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_CONFIG1_ADDR, data, 1);
    			if (err) {
    				printk("Error reading from ADC! error code (%d)\n", err);
    				//return;
    			} else {
    				printk("Read 0x%X from address 0x01.\n", data[0]);
    			}
    			
    			data[0] = 0x8B;
    			err = mcp3562_mwrite_bytes(spi, &spi_cfg, MCP3562_CONFIG2_ADDR, data, 1);
    			if (err) {
    				printk("Error writing to ADC! error code (%d)\n", err);
    				//return;
    			} else {
    				printk("Wrote 0x01 to address 0x06.\n");
    			}
    
    			data[0] = 0xFF;
    			err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_CONFIG2_ADDR, data, 1);
    			if (err) {
    				printk("Error reading from ADC! error code (%d)\n", err);
    				//return;
    			} else {
    				printk("Read 0x%X from address 0x01.\n", data[0]);
    			}
    			
    			data[0] = 0xE0; /// Rispetto allo 0xC0 il 0xC2 abilita il OFFSETCAL_EN bit
    			err = mcp3562_mwrite_bytes(spi, &spi_cfg, MCP3562_CONFIG3_ADDR, data, 1);
    			if (err) {
    				printk("Error writing to ADC! error code (%d)\n", err);
    				//return;
    			} else {
    				printk("Wrote 0x01 to address 0x06.\n");
    			}
    
    			data[0] = 0xFF;
    			err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_CONFIG3_ADDR, data, 1);
    			if (err) {
    				printk("Error reading from ADC! error code (%d)\n", err);
    				//return;
    			} else {
    				printk("Read 0x%X from address 0x01.\n", data[0]);
    			}
    ///////////////////////////////////////////////////////////////////////////////////////////////////			
    			mcp3562_initialization(spi, &spi_cfg, data);
    /////////////////////////////////////////////////////////////// OFFSETCAL //////////
    			//data[0] = 0x000771; // "-62 DEC" - OFFSET presumed Positive
    			data[0] = 0x80;
    			data[1] = 0xA2;
    			data[2] = 0x3D;
    
    			//temp1 = (data[0] << 16 | data[1] << 8 | data[2]);
    			//temp = (~temp1)+1;
    
    			//msbyte = data[0] & 0x80;	
    
    			err = mcp3562_mwrite_bytes(spi, &spi_cfg, MCP3562_OFFSETCAL_ADDR, data, 3);
    			if (err) {
    				printk("Error writing to ADC! error code (%d)\n", err);
    				//return;
    			} else {
    				printk("Wrote 0x01 to address 0x06.\n");
    			}
    
    			data[0] = 0xFF;
    			err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_OFFSETCAL_ADDR, data, 3);
    			if (err) {
    				printk("Error reading from ADC! error code (%d)\n", err);
    				//return;
    			} else {
    				printk("Read 0x%X from address 0x01.\n", data[0]);
    			}
    
    			data[0] = 0xE0;/// Rispetto allo 0xC0 il 0xC2 abilita il OFFSETCAL_EN bit
    			err = mcp3562_mwrite_bytes(spi, &spi_cfg, MCP3562_CONFIG3_ADDR, data, 1);
    			if (err) {
    				printk("Error writing to ADC! error code (%d)\n", err);
    				//return;
    			} else {
    				printk("Wrote 0x01 to address 0x06.\n");
    			}
    
    			data[0] = 0xFF;
    			err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_CONFIG3_ADDR, data, 1);
    			if (err) {
    				printk("Error reading from ADC! error code (%d)\n", err);
    				//return;
    			} else {
    				printk("Read 0x%X from address 0x01.\n", data[0]);
    			}
    
    /////////////////////////////////////////////////////////////// GAINCAL //////////
    			data[0] = 0x81; // Supponiamo un errore del 1% >> 0.99/8388608 = 8304721|10b >> 7EB851|16b
    			data[1] = 0xCA;
    			data[2] = 0xC0;
    			//err = mcp3562_mwrite_bytes(spi, &spi_cfg, MCP3562_GAINCAL_ADDR, data, 3);
    			if (err) {
    				printk("Error writing to ADC! error code (%d)\n", err);
    				//return;
    			} else {
    				printk("Wrote 0x01 to address 0x06.\n");
    			}
    
    			data[0] = 0xFF;
    			err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_GAINCAL_ADDR, data, 3);
    			if (err) {
    				printk("Error reading from ADC! error code (%d)\n", err);
    				//return;
    			} else {
    				printk("Read 0x%X from address 0x01.\n", data[0]);
    			}
    			temp = (data[0] << 16 | data[1] << 8 | data[2]);
    				/// ENABLE GAINCAL FEATURE ///
    			//data[0] = 0xC1; Se 0xC3 per Abilitazione sia di GAINCAL che OFFCAL
    			data[0] = 0xE0;
    			err = mcp3562_mwrite_bytes(spi, &spi_cfg, MCP3562_CONFIG3_ADDR, data, 1);
    			if (err) {
    				printk("Error writing to ADC! error code (%d)\n", err);
    				//return;
    			} else {
    				printk("Wrote 0x01 to address 0x06.\n");
    			}
    
    			data[0] = 0xFF;
    			err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_CONFIG3_ADDR, data, 1);
    			if (err) {
    				printk("Error reading from ADC! error code (%d)\n", err);
    				//return;
    			} else {
    				printk("Read 0x%X from address 0x01.\n", data[0]);
    			}			
    /////////////////////////////// MAIN LOOP /////////////////////////////////////////////////////////
    ////////////////////////// TEST //////////////////////////////////////////////////////////////////
    			/*data[0] = 0x80;
    			data[1] = 0xA2;
    			data[2] = 0x3D;
    
    			mcp3562_offcal_conf(spi, &spi_cfg, data);
    
    			
    			data[0] = 0x81; // Supponiamo un errore del 1% >> 0.99/8388608 = 8304721|10b >> 7EB851|16b
    			data[1] = 0xCA;
    			data[2] = 0xC0;
    			
    			mcp3562_gaincal_conf(spi, &spi_cfg, data);*/
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    			k_sleep(K_MSEC(1000));
    			
    			for (;;) {
    //////////////////////////////////////// RESTART S1176 //////////////////////////////////////////////////
    				// ReStart the S1176 enabling the LDO Power Rail, the Analog Power Domain and The ADC External Clock 
    				// Enable the LDO Power Rail
    				s1176_set_gpos(ESWITCH_1_CTL_DIGOUT, 1);
    				k_sleep(K_MSEC(500));
    				// Enable the 45.9152MHz Clock Domain (XTAL).
    				s1176_set_gpos(ADC_XO_EN_DIGOUT, 1);
    				k_sleep(K_MSEC(500));
    				// Enable the Analog LDO Rail
    				s1176_set_gpos(ESWITCH_2_CTL_DIGOUT, 1);
    				k_sleep(K_MSEC(500));				
    ////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    /////////////////////////////////////// RE-INITIALIZATION //////////////////////////////////////////////
    				mcp3562_initialization(spi, &spi_cfg, data);
    				//dk_set_led(RUN_STATUS_LED, (++blink_status) % 2);
    				k_sleep(K_MSEC(1000));
    				//k_busy_wait(BUSY_WAIT_S * USEC_PER_SEC);
    				//rc = pm_device_action_run(cons, PM_DEVICE_ACTION_RESUME);
    ////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    ///////////////////////////////// SENSOR 1 SAMPLING ////////////////////////////////////////////////////
    				/*data[0] = 0x01; // CONFIGURE the internal MUX for DIFFERENTIAL READOUTs on Channels CH0 & CH1
    				err = mcp3562_mwrite_bytes(spi, &spi_cfg, MCP3562_MUX_ADDR, data, 1);
    					if (err) {
    						printk("Error writing to ADC! error code (%d)\n", err);
    						//return;
    					} else {
    						printk("Wrote 0x01 to address 0x06.\n");
    					}	
    
    				data[0] = 0xFF;
    				err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_MUX_ADDR, data, 1);
    				if (err) {
    					printk("Error reading from ADC! error code (%d)\n", err);
    					//return;
    				} else {
    					printk("Read 0x%X from address 0x01.\n", data[0]);
    				}
    
    				// PREPARE THE ADC TO READ
    				//data[0] = (0xC0 | MCP3562_CONFIG0_CLK_SEL_EXT | MCP3562_CONFIG0_CS_SEL_NONE | MCP3562_CONFIG0_ADC_MODE_CONV);//0xC3;
    				data[0] = 0xC3;
    				err = mcp3562_mwrite_bytes(spi, &spi_cfg, MCP3562_CONFIG0_ADDR, data, 1);
    				if (err) {
    					printk("Error writing to ADC! error code (%d)\n", err);
    					//return;
    				} else {
    					printk("Wrote 0xC3 to address 0x01.\n");
    				}		
    
    				data[0] = 0xFF;
    				err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_CONFIG0_ADDR, data, 1);
    				if (err) {
    					printk("Error reading from ADC! error code (%d)\n", err);
    					//return;
    				} else {
    					printk("Read 0x%X from address 0x01.\n", data[0]);
    				}
    
    				data[0] = 0x00; // READ FROM ADCDATA Register 0x00
    				err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_ADCDATA_ADDR, data, 4);
    				if (err) {
    					printk("Error reading from ADC! error code (%d)\n", err);
    					//return;
    				} else {
    					printk("Read 0x%X from address 0x00.\n", data[0]);
    				}
    
    				indata = (data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]);
    				indata = indata - 0x00A23D;
    
    				vdiff = VREF * indata / FS / INSTAMP_GAIN_S1;
    				rx_ind = (RTOP * ((vdiff/VBIAS) + (R3/(RTOP+R3))) / (1-(vdiff/VBIAS)-(R3/(RTOP+R3))));*/
    
    				//data[100]=0x00;
    ////////////////////////////////////////////////////////////////////////////////////////////////////////
    				rx_ind = mcp3562_rsensor_1_dsamp(spi, &spi_cfg, data);
    ////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    ///////////////////////////////// SENSOR 2 SAMPLING ////////////////////////////////////////////////////
    				k_sleep(K_MSEC(1000));
    				/*data[0] = 0x23; // CONFIGURE the internal MUX for DIFFERENTIAL READOUTs on Channels CH0 & CH1
    				err = mcp3562_mwrite_bytes(spi, &spi_cfg, MCP3562_MUX_ADDR, data, 1);
    					if (err) {
    						printk("Error writing to ADC! error code (%d)\n", err);
    						//return;
    					} else {
    						printk("Wrote 0x01 to address 0x06.\n");
    					}	
    
    				data[0] = 0xFF;
    				err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_MUX_ADDR, data, 1);
    				if (err) {
    					printk("Error reading from ADC! error code (%d)\n", err);
    					//return;
    				} else {
    					printk("Read 0x%X from address 0x01.\n", data[0]);
    				}
    
    				// PREPARE THE ADC TO READ
    				//data[0] = (0xC0 | MCP3562_CONFIG0_CLK_SEL_EXT | MCP3562_CONFIG0_CS_SEL_NONE | MCP3562_CONFIG0_ADC_MODE_CONV);//0xC3;
    				data[0] = 0xC3;
    				err = mcp3562_mwrite_bytes(spi, &spi_cfg, MCP3562_CONFIG0_ADDR, data, 1);
    					if (err) {
    						printk("Error writing to ADC! error code (%d)\n", err);
    						//return;
    					} else {
    						printk("Wrote 0xC3 to address 0x01.\n");
    					}		
    
    				data[0] = 0xFF;
    				err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_CONFIG0_ADDR, data, 1);
    				if (err) {
    					printk("Error reading from ADC! error code (%d)\n", err);
    					//return;
    				} else {
    					printk("Read 0x%X from address 0x01.\n", data[0]);
    				}
    
    				data[0] = 0x00; // READ FROM ADCDATA Register 0x00
    				err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_ADCDATA_ADDR, data, 4);
    				if (err) {
    					printk("Error reading from ADC! error code (%d)\n", err);
    					//return;
    				} else {
    					printk("Read 0x%X from address 0x00.\n", data[0]);
    				}	
    				
    				indata = (data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]);
    				indata = indata - 0x00A23D;
    				//vdiff = 3 * indata / 8338608; // The Vdiff value, here calculated, espressed in [mV]
    				vdiff = VREF * indata / FS / INSTAMP_GAIN_S2;
    				rx_ind = (RTOP * ((vdiff/VBIAS) + (R3/(RTOP+R3))) / (1-(vdiff/VBIAS)-(R3/(RTOP+R3))));*/
    ////////////////////////////////////////////////////////////////////////////////////////////////////////
    				rx_ind = mcp3562_rsensor_2_dsamp(spi, &spi_cfg, data);
    ////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    //////////////////////////////////// DIGITAL SENSOR #1 SAMPLING ////////////////////////////////////////
    				ds1_stat = s1176_get_inputs(COND_SENSOR_1_DIGIN);
    				//k_sleep(K_MSEC(1000));
    ////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    //////////////////////////////////// DIGITAL SENSOR #2 SAMPLING ////////////////////////////////////////
    				ds2_stat = s1176_get_inputs(COND_SENSOR_2_DIGIN);
    ////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    ////////////////////////////////// S1176 SHUTDOWN //////////////////////////////////////////////////
    				k_sleep(K_MSEC(1000));
    				printk("Busy-wait %u s\n", BUSY_WAIT_S);
    				k_busy_wait(BUSY_WAIT_S * USEC_PER_SEC);
    
    				// Shut-Down the Analog Power Domain
    				s1176_set_gpos(ESWITCH_1_CTL_DIGOUT, 0);
    				k_sleep(K_MSEC(500));
    				//rc = pm_device_action_run(cons, PM_DEVICE_ACTION_SUSPEND);
    				//pm_power_state_force(0u, (struct pm_state_info){PM_STATE_SUSPEND_TO_IDLE, 0, 0});
    
    				// Shut-Down the 45.9152MHz Clock Domain (XTAL).
    				s1176_set_gpos(ADC_XO_EN_DIGOUT, 0);
    				k_sleep(K_MSEC(500));
    				// Shut-Down the Analog LDO Rail
    				s1176_set_gpos(ESWITCH_2_CTL_DIGOUT, 0);
    				pm_state_force(0u, &(struct pm_state_info){PM_STATE_SUSPEND_TO_IDLE, 0, 0});
    				k_sleep(K_MSEC(500));
    				//idle_state_handle();
    				//k_sleep(K_FOREVER);
    				printk("Busy-wait %u s\n", BUSY_WAIT_S);
    				//k_busy_wait(BUSY_WAIT_S * USEC_PER_SEC);
    
    				//pm_device_action_run(spi, PM_DEVICE_ACTION_SUSPEND);
    				k_sleep(K_SECONDS(3));
    				//pm_device_action_run(spi, PM_DEVICE_ACTION_RESUME);
    
    			} //END OF INFINITE LOOP
    //////////////////////////////////////////////////////////////////////////////////////////////////////
    
    		#else
    ////////////////////////////////////////// SINGLE ENDED SAMPLING ////////////////////////////////////
    			///////////////// CONFIGURATION ////////////////////////
    			data[0] = 0xC3;
    			err = mcp3562_mwrite_bytes(spi, &spi_cfg, MCP3562_CONFIG0_ADDR, data, 1);
    			if (err) {
    				printk("Error writing to ADC! error code (%d)\n", err);
    				//return;
    			} else {
    				printk("Wrote 0x01 to address 0x06.\n");
    			}
    
    			data[0] = 0xFF;
    			err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_CONFIG0_ADDR, data, 1);
    			if (err) {
    				printk("Error reading from ADC! error code (%d)\n", err);
    				//return;
    			} else {
    				printk("Read 0x%X from address 0x01.\n", data[0]);
    			}
    			data[14]=data[0];
    			
    			//data[0] = (0xC0 | MCP3562_CONFIG0_CLK_SEL_EXT | MCP3562_CONFIG0_CS_SEL_NONE | MCP3562_CONFIG0_ADC_MODE_CONV);//0xC3;
    			data[0] = 0x0C;
    			err = mcp3562_mwrite_bytes(spi, &spi_cfg, MCP3562_CONFIG1_ADDR, data, 1);
    			if (err) {
    				printk("Error writing to ADC! error code (%d)\n", err);
    				//return;
    			} else {
    				printk("Wrote 0x01 to address 0x06.\n");
    			}
    
    			data[0] = 0xFF;
    			err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_CONFIG1_ADDR, data, 1);
    			if (err) {
    				printk("Error reading from ADC! error code (%d)\n", err);
    				//return;
    			} else {
    				printk("Read 0x%X from address 0x01.\n", data[0]);
    			}
    			
    			data[0] = 0x8B;
    			err = mcp3562_mwrite_bytes(spi, &spi_cfg, MCP3562_CONFIG2_ADDR, data, 1);
    			if (err) {
    				printk("Error writing to ADC! error code (%d)\n", err);
    				//return;
    			} else {
    				printk("Wrote 0x01 to address 0x06.\n");
    			}
    
    			data[0] = 0xFF;
    			err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_CONFIG2_ADDR, data, 1);
    			if (err) {
    				printk("Error reading from ADC! error code (%d)\n", err);
    				//return;
    			} else {
    				printk("Read 0x%X from address 0x01.\n", data[0]);
    			}
    			
    			//data[0] = 0xC0;
    			data[0] = 0xC3;
    			err = mcp3562_mwrite_bytes(spi, &spi_cfg, MCP3562_CONFIG3_ADDR, data, 1);
    			if (err) {
    				printk("Error writing to ADC! error code (%d)\n", err);
    				//return;
    			} else {
    				printk("Wrote 0x01 to address 0x06.\n");
    			}
    
    			data[0] = 0xFF;
    			err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_CONFIG3_ADDR, data, 1);
    			if (err) {
    				printk("Error reading from ADC! error code (%d)\n", err);
    				//return;
    			} else {
    				printk("Read 0x%X from address 0x01.\n", data[0]);
    			}
    
    			k_sleep(K_MSEC(1000));
    
    			for (;;) {
    				//dk_set_led(RUN_STATUS_LED, (++blink_status) % 2);
    			/////////////////////// SENSOR 1 SE SAMPLING ///////////////////////
    				//mcp3562_oneshot_se_ch0_sampling(spi, &spi_cfg, data);
    				data[0] = 0x08; // CONFIGURE the internal MUX for SINGLE ENDED READOUTs on Channels CH0
    				err = mcp3562_mwrite_bytes(spi, &spi_cfg, MCP3562_MUX_ADDR, data, 1);
    					if (err) {
    						printk("Error writing to ADC! error code (%d)\n", err);
    						//return;
    					} else {
    						printk("Wrote 0x08 to address 0x06.\n");
    					}	
    				data[0] = 0xFF;
    				err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_MUX_ADDR, data, 1);
    				if (err) {
    					printk("Error reading from ADC! error code (%d)\n", err);
    					//return;
    				} else {
    					printk("Read 0x%X from address 0x08.\n", data[0]);
    				}
    				// PREPARE THE ADC TO READ - ENABLE: External Clock, No Current Source, Conversion mode
    				//data[0] = (0xC0 | MCP3562_CONFIG0_CLK_SEL_EXT | MCP3562_CONFIG0_CS_SEL_NONE | MCP3562_CONFIG0_ADC_MODE_CONV);//0xC3;
    				data[0] = 0xC3;
    				err = mcp3562_mwrite_bytes(spi, &spi_cfg, MCP3562_CONFIG0_ADDR, data, 1);
    					if (err) {
    						printk("Error writing to ADC! error code (%d)\n", err);
    						//return;
    					} else {
    						printk("Wrote 0xC3 to address 0x01.\n");
    					}	
    
    				data[0] = 0xFF;
    				err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_CONFIG0_ADDR, data, 1);
    				if (err) {
    					printk("Error reading from ADC! error code (%d)\n", err);
    					//return;
    				} else {
    					printk("Read 0x%X from address 0x01.\n", data[0]);
    				}
    
    				// CONFIG1 (Default) = 0x0C - AMCLK = MCLK, OSR: 256
    				// CONFIG2 (Default) = 0x8B - BOOST = x1, GAIN = 1x, AZ_MUX = DISABLED
    				// CONFIG3 (OneShot Sampling Mode) = 0x40 - One-shot Conversion Mode, 
    				//									 24-bit ADC data, CRC_FORMAT = 16b, EN_CRCCOM Disabled, 
    				//							  		 EN_OFFCAL Disabled, EN_GAINCAL Disabled
    				
    				data[0] = 0x00; // READ FROM ADCDATA Register 0x00
    				err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_ADCDATA_ADDR, data, 3);
    				if (err) {
    					printk("Error reading from ADC! error code (%d)\n", err);
    					//return;
    				} else {
    					printk("Read 0x%X from address 0x02.\n", data[0]);
    				}			
    				k_sleep(K_MSEC(1000));
    				indata = (data[0] << 16 | data[1] << 8 | data[2]);
    				vsing = 3 * indata / 8338608; // L'unità di misura è V
    				rx_ind = (100 * vsing / (50*(3.3 - vsing))); // Rx = [(R1 * Vch0 / VCC) / (1 - Vch0/VCC)]
    										  				// Da notare il fattore di scala per ottenere 
    														// una misura di resistenza espresa in Ohm 
    
    			/////////////////////// SENSOR 2 SE SAMPLING ///////////////////////
    				//mcp3562_oneshot_se_ch1_sampling(spi, &spi_cfg, data);
    				data[0] = 0x28; // CONFIGURE the internal MUX for SINGLE ENDED READOUTs on Channels CH0
    				err = mcp3562_mwrite_bytes(spi, &spi_cfg, MCP3562_MUX_ADDR, data, 1);
    					if (err) {
    						printk("Error writing to ADC! error code (%d)\n", err);
    						//return;
    					} else {
    						printk("Wrote 0x08 to address 0x06.\n");
    					}	
    				data[0] = 0xFF;
    				err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_MUX_ADDR, data, 1);
    				if (err) {
    					printk("Error reading from ADC! error code (%d)\n", err);
    					//return;
    				} else {
    					printk("Read 0x%X from address 0x08.\n", data[0]);
    				}
    				// PREPARE THE ADC TO READ - ENABLE: External Clock, No Current Source, Conversion mode
    				//data[0] = (0xC0 | MCP3562_CONFIG0_CLK_SEL_EXT | MCP3562_CONFIG0_CS_SEL_NONE | MCP3562_CONFIG0_ADC_MODE_CONV);//0xC3;
    				data[0] = 0xC3;
    				err = mcp3562_mwrite_bytes(spi, &spi_cfg, MCP3562_CONFIG0_ADDR, data, 1);
    					if (err) {
    						printk("Error writing to ADC! error code (%d)\n", err);
    						//return;
    					} else {
    						printk("Wrote 0xC3 to address 0x01.\n");
    					}	
    
    				data[0] = 0xFF;
    				err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_CONFIG0_ADDR, data, 1);
    				if (err) {
    					printk("Error reading from ADC! error code (%d)\n", err);
    					//return;
    				} else {
    					printk("Read 0x%X from address 0x01.\n", data[0]);
    				}
    
    				data[0] = 0x00; // READ FROM ADCDATA Register 0x00
    				err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_ADCDATA_ADDR, data, 3);
    				if (err) {
    					printk("Error reading from ADC! error code (%d)\n", err);
    					//return;
    				} else {
    					printk("Read 0x%X from address 0x02.\n", data[0]);
    				}			
    				k_sleep(K_MSEC(1000));
    				indata = (data[0] << 16 | data[1] << 8 | data[2]);
    				vsing = 3 * indata / 8338608; // The Vdiff value, here calculated, espressed in [V]
    				rx_ind = (100 * vsing / ((3.3 - vsing))); // Rx = [(R1 * Vch0 / VCC) / (1 - Vch0/VCC)]
    										  				// Da notare il fattore di scala per ottenere 
    														// una misura di resistenza espresa in Ohm 
    			///////////////// START PER DEBUGGARE E DA RIMUOVERE ///////////////////////
    				data[0] = 0x00; // READ FROM ADCDATA Register 0x00
    				err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_ADCDATA_ADDR, data, 3);
    				if (err) {
    					printk("Error reading from ADC! error code (%d)\n", err);
    					//return;
    				} else {
    					printk("Read 0x%X from address 0x02.\n", data[0]);
    				}			
    				k_sleep(K_MSEC(1000));
    			///////////////// END PER DEBUGGARE E DA RIMUOVERE ///////////////////////
    			}			
    		#endif
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////		
    	#endif
    }
    
    /////////////////////////////////////////////////////////////////////
    /*
    void mcp3562_minitialization(const struct device *spi, struct spi_config *spi_cfg, uint8_t *data){
    	int err;
    		data[0] = 0xC3;
    		err = mcp3562_mwrite_bytes(spi, &spi_cfg, MCP3562_CONFIG0_ADDR, data, 1);
    		if (err) {
    			printk("Error writing to ADC! error code (%d)\n", err);
    			//return;
    		} else {
    			printk("Wrote 0x01 to address 0x06.\n");
    		}
    
    		data[0] = 0xFF;
    		err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_CONFIG0_ADDR, data, 1);
    		if (err) {
    			printk("Error reading from ADC! error code (%d)\n", err);
    			//return;
    		} else {
    			printk("Read 0x%X from address 0x01.\n", data[0]);
    		}
    		data[14]=data[0];
    		
    		//data[0] = (0xC0 | MCP3562_CONFIG0_CLK_SEL_EXT | MCP3562_CONFIG0_CS_SEL_NONE | MCP3562_CONFIG0_ADC_MODE_CONV);//0xC3;
    		data[0] = 0x0C;
    		err = mcp3562_mwrite_bytes(spi, &spi_cfg, MCP3562_CONFIG1_ADDR, data, 1);
    		if (err) {
    			printk("Error writing to ADC! error code (%d)\n", err);
    			//return;
    		} else {
    			printk("Wrote 0x01 to address 0x06.\n");
    		}
    
    		data[0] = 0xFF;
    		err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_CONFIG1_ADDR, data, 1);
    		if (err) {
    			printk("Error reading from ADC! error code (%d)\n", err);
    			//return;
    		} else {
    			printk("Read 0x%X from address 0x01.\n", data[0]);
    		}
    		
    		data[0] = 0x8B;
    		err = mcp3562_mwrite_bytes(spi, &spi_cfg, MCP3562_CONFIG2_ADDR, data, 1);
    		if (err) {
    			printk("Error writing to ADC! error code (%d)\n", err);
    			//return;
    		} else {
    			printk("Wrote 0x01 to address 0x06.\n");
    		}
    
    		data[0] = 0xFF;
    		err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_CONFIG2_ADDR, data, 1);
    		if (err) {
    			printk("Error reading from ADC! error code (%d)\n", err);
    			//return;
    		} else {
    			printk("Read 0x%X from address 0x01.\n", data[0]);
    		}
    		
    		data[0] = 0xE0; /// Rispetto allo 0xC0 il 0xC2 abilita il OFFSETCAL_EN bit
    		err = mcp3562_mwrite_bytes(spi, &spi_cfg, MCP3562_CONFIG3_ADDR, data, 1);
    		if (err) {
    			printk("Error writing to ADC! error code (%d)\n", err);
    			//return;
    		} else {
    			printk("Wrote 0x01 to address 0x06.\n");
    		}
    
    		data[0] = 0xFF;
    		err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_CONFIG3_ADDR, data, 1);
    		if (err) {
    			printk("Error reading from ADC! error code (%d)\n", err);
    			//return;
    		} else {
    			printk("Read 0x%X from address 0x01.\n", err);
    		}
    }
    
    float mcp3562_rsensor_1_samp(const struct device *spi, struct spi_config *spi_cfg, uint8_t *data){
    	int indata, err;
    	uint8_t sdata[10];
    	float vdiff, vsing, rx_ind_local;
    
    	data[0] = 0x01; // CONFIGURE the internal MUX for DIFFERENTIAL READOUTs on Channels CH0 & CH1
    	err = mcp3562_mwrite_bytes(spi, &spi_cfg, MCP3562_MUX_ADDR, data, 1);
    	if (err) {
    		printk("Error writing to ADC! error code (%d)\n", err);
    		//return;
    	} else {
    		printk("Wrote 0x01 to address 0x06.\n");
    	}	
    
    	data[0] = 0xFF;
    	err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_MUX_ADDR, data, 1);
    	if (err) {
    		printk("Error reading from ADC! error code (%d)\n", err);
    		//return;
    	} else {
    		printk("Read 0x%X from address 0x01.\n", err);
    	}
    
    	// PREPARE THE ADC TO READ
    	//data[0] = (0xC0 | MCP3562_CONFIG0_CLK_SEL_EXT | MCP3562_CONFIG0_CS_SEL_NONE | MCP3562_CONFIG0_ADC_MODE_CONV);//0xC3;
    	data[0] = 0xC3;
    	err = mcp3562_mwrite_bytes(spi, &spi_cfg, MCP3562_CONFIG0_ADDR, data, 1);
    	if (err) {
    		printk("Error writing to ADC! error code (%d)\n", err);
    		//return;
    	} else {
    		printk("Wrote 0xC3 to address 0x01.\n");
    	}		
    
    	data[0] = 0xFF;
    	err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_CONFIG0_ADDR, data, 1);
    	if (err) {
    		printk("Error reading from ADC! error code (%d)\n", err);
    		//return;
    	} else {
    		printk("Read 0x%X from address 0x01.\n", err);
    	}
    
    	data[0] = 0x00; // READ FROM ADCDATA Register 0x00
    	err = mcp3562_mread_bytes(spi, &spi_cfg, MCP3562_ADCDATA_ADDR, data, 4);
    	if (err) {
    		printk("Error reading from ADC! error code (%d)\n", err);
    		//return;
    	} else {
    		printk("Read 0x%X from address 0x00.\n", err);
    	}
    
    	indata = (data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]);
    	indata = indata - 0x00A23D;
    
    	vdiff = VREF * indata / FS / INSTAMP_GAIN_S1;
    	rx_ind_local = (RTOP * ((vdiff/VBIAS) + (R3/(RTOP+R3))) / (1-(vdiff/VBIAS)-(R3/(RTOP+R3))));
    
    	return rx_ind_local;
    }
    */

    Attached my main.c file in which should be clear the logic.

    To be more precise, I have a 32kHz XTAL on the circuit connected to P0.00/XL1 and P0.01/XL2. and I would to set an alarm (its internal RTC would be the best choice) every hour to wake the board to sample the analog entities, send the datas by BT and come back to sleep (no retention is needed actually).

    It's not clear to me the way to enter and exit from the IDLE (or Sleep) mode.

    We have some example for the evaluation?

    Many Thanks

  • Hi

    System ON IDLE mode is the default sleep mode that the nRF5340 will be set to when no other threads in the RTOS is running. The current consumption of this mode is specified in the nRF5340 product specification.

    You can also let only the RTC peripheral run from the external LF crystal to stay in an almost as low sleep mode. When the RTC is the only thread running, it should be almost as low of a current consumption as the system ON IDLE mode. 

    We don't have a specific sample for going into sleep with the RTC, but we do have this System OFF sample that disables threads and puts the device into a system OFF mode where it will need to be restarted with a button press.

    Best regards,

    Simon

Related