MODBUS and serial disable

We use custom board with NRF52840 and a MODBUS CO2 sensor. We are struggling with power consumption when the serial is enabled. The goal is to take measurements and then put the board to sleep, after a certain time, wake board up and take new measurements. Currently, the idle power consumption is about 1.2 mA. When I disabled the serial in the config file, we got the power consumption down to 300 µA. However, MODBUS requires the serial. Is it possible to disable the serial before putting the board to sleep and reinitialize it after waking up so that MODBUS continues to work?

  • Hmm .. strange. OK .. I try again here,

  • Could you upload the logs, prj.conf and the modbus part of your application just in case there is something there 

    Regards

    Runar

  • Strange .. I did a test with DK and my sensor and it is working OK. It is something in my custom boards code then, that is not functioning. I will check what is the problem.

    I tried with that:

    #include <zephyr/kernel.h>
    #include <zephyr/sys/util.h>
    #include <zephyr/drivers/gpio.h>
    #include <zephyr/pm/pm.h>
    #include <zephyr/pm/device.h>
    #include <zephyr/pm/state.h>
    #include <zephyr/modbus/modbus.h>
    
    #include <zephyr/logging/log.h>
    LOG_MODULE_REGISTER(mbc_sample, LOG_LEVEL_DBG);
    
    static int client_iface;
    
    const static struct modbus_iface_param client_param = {
    	.mode = MODBUS_MODE_RTU,
    	.rx_timeout = 10000,
    	.serial = {
    		.baud = 9600,
    		.parity = UART_CFG_PARITY_NONE,
    		.stop_bits_client = UART_CFG_STOP_BITS_1,
    		},
    };
    
    #define SENSOR_UID 104
    #define MODBUS_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(zephyr_modbus_serial)
    
    static const struct device *const uart_modbus =  DEVICE_DT_GET(DT_NODELABEL(uart0));
    
    static int init_modbus_client(void)
    {
    	const char iface_name[] = {DEVICE_DT_NAME(MODBUS_NODE)};
    
    	client_iface = modbus_iface_get_by_name(iface_name);
    
    	return modbus_init_client(client_iface, client_param);
    }
    
    void measure_co2() {
    	uint16_t input_reg_data[4] = {0};
    	int err;
    
    	init_modbus_client();
    
    	while(true){
    		//Read CO2 value
    		err = modbus_read_input_regs(client_iface, SENSOR_UID, 0, input_reg_data, 4);
    		
    		if (err != 0) {
    			LOG_ERR("MODBUS error %d", err);
    			if(true){
    				LOG_INF("Trying once more...");
    			}else{
    			break;
    			}
    		} else {
    
    			uint16_t co2_value = input_reg_data[3];
    
    			if (input_reg_data[0] != 0)	{
    			}else{
    				LOG_INF("CO2 Level: %d", co2_value);
    
    			break;
    			}
    		}
    	k_sleep(K_MSEC(1000));
    	}
    }
    
    int main(void)
    {
    	int err = 0;
    	
    	for (int i=1;i<5;i++){
    		measure_co2();
    		
    		k_sleep(K_MSEC(1000));
    		
    		err = pm_device_action_run(uart_modbus, PM_DEVICE_ACTION_SUSPEND);
    		if(err) LOG_INF("PM Error: %d",err);
    		
    		k_sleep(K_MSEC(5000));
    		LOG_INF("Sleep 5 sec...");
    
    		err = pm_device_action_run(uart_modbus, PM_DEVICE_ACTION_RESUME);
    		if(err) LOG_INF("PM Error: %d",err);
    				
    		measure_co2();
    		
    		k_sleep(K_MSEC(1000));
    	}
    
    }

    And the log is:

    00> *** Booting nRF Connect SDK v3.5.99-ncs1 ***
    00> [00:00:00.538,177] <inf> modbus_serial: RTU timeout 4010 us
    00> [00:00:00.548,278] <wrn> modbus: Client wait-for-RX timeout
    00> [00:00:00.548,278] <err> mbc_sample: MODBUS error -116
    00> [00:00:00.548,278] <inf> mbc_sample: Trying once more...
    00> [00:00:01.558,471] <wrn> modbus: Client wait-for-RX timeout
    00> [00:00:01.558,502] <err> mbc_sample: MODBUS error -116
    00> [00:00:01.558,502] <inf> mbc_sample: Trying once more...
    00> [00:00:02.558,624] <inf> mbc_sample: CO2 Level: 674
    00> [00:00:08.558,746] <inf> mbc_sample: Sleep 5 sec...
    00> [00:00:08.558,776] <err> modbus: Interface already used
    00> [00:00:08.568,878] <wrn> modbus: Client wait-for-RX timeout
    00> [00:00:08.568,878] <err> mbc_sample: MODBUS error -116
    00> [00:00:08.568,878] <inf> mbc_sample: Trying once more...
    00> [00:00:09.568,969] <inf> mbc_sample: CO2 Level: 674
    00> [00:00:10.569,061] <err> modbus: Interface already used
    00> [00:00:10.579,193] <wrn> modbus: Client wait-for-RX timeout
    00> [00:00:10.579,193] <err> mbc_sample: MODBUS error -116
    00> [00:00:10.579,193] <inf> mbc_sample: Trying once more...
    00> [00:00:11.579,284] <inf> mbc_sample: CO2 Level: 674
    00> [00:00:17.579,437] <inf> mbc_sample: Sleep 5 sec...
    00> [00:00:17.579,467] <err> modbus: Interface already used
    00> [00:00:17.589,569] <wrn> modbus: Client wait-for-RX timeout
    00> [00:00:17.589,569] <err> mbc_sample: MODBUS error -116
    00> [00:00:17.589,569] <inf> mbc_sample: Trying once more...
    00> [00:00:18.589,660] <inf> mbc_sample: CO2 Level: 675
    00> [00:00:19.589,752] <err> modbus: Interface already used
    00> [00:00:19.599,884] <wrn> modbus: Client wait-for-RX timeout
    00> [00:00:19.599,884] <err> mbc_sample: MODBUS error -116
    00> [00:00:19.599,884] <inf> mbc_sample: Trying once more...
    00> [00:00:20.599,975] <inf> mbc_sample: CO2 Level: 675
    00> [00:00:26.600,128] <inf> mbc_sample: Sleep 5 sec...
    00> [00:00:26.600,158] <err> modbus: Interface already used
    00> [00:00:26.610,260] <wrn> modbus: Client wait-for-RX timeout
    00> [00:00:26.610,260] <err> mbc_sample: MODBUS error -116
    00> [00:00:26.610,260] <inf> mbc_sample: Trying once more...
    00> [00:00:27.610,351] <inf> mbc_sample: CO2 Level: 675
    00> [00:00:28.610,443] <err> modbus: Interface already used
    00> [00:00:28.620,574] <wrn> modbus: Client wait-for-RX timeout
    00> [00:00:28.620,574] <err> mbc_sample: MODBUS error -116
    00> [00:00:28.620,574] <inf> mbc_sample: Trying once more...
    00> [00:00:29.620,666] <inf> mbc_sample: CO2 Level: 675

    The sensor is not answering always in first try, and thats OK. 

    Anyway.. thanks for testing it and giving good advise.

  • I can get rid of Interface already used with modbus_disable and that is also working as expected on DK board.

Related