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

Configuring UART_1 for nRF9160

Hi Dev Team,

I was working with the nRF9160 and started off with the basic UART sample found here : https://github.com/Rallare/fw-nrfconnect-nrf/tree/nrf9160_samples/samples/nrf9160/uart

I wanted to configure the UART_1 to connect to an external sensor, and I followed some links : https://devzone.nordicsemi.com/f/nordic-q-a/45476/connecting-uart1-to-a-periph-on-nrf9160-dk/178988#178988, https://devzone.nordicsemi.com/f/nordic-q-a/57199/using-the-nrf9160-to-send-and-receive-data-over-rs485-using-uart and changed the prj.conf file and the overlays file. 

prj.conf:

CONFIG_NEWLIB_LIBC=y
CONFIG_LIBLIGHTMODBUS=y


CONFIG_SERIAL=y
CONFIG_TRUSTED_EXECUTION_NONSECURE=y
CONFIG_UART_INTERRUPT_DRIVEN=y
CONFIG_MAIN_STACK_SIZE=4096

CONFIG_COMPILER_OPT="-DNRFX_UARTE_ENABLED=1 -DNRFX_UARTE0_ENABLED=1"


CONFIG_UART_1_NRF_UARTE=y

CONFIG_UART_1_NRF_FLOW_CONTROL=y

#CONFIG_BOARD_NRF9160DK_UART0_ARDUINO=y

#CONFIG_BOARD_NRF9160DK_UART0_VCOM=n

nrf9160dk_nrf9160ns.overlay:

/* Needed to get NRF_PWMn defined. */
&pwm1 {
	status = "okay";
};

&pwm2 {
	status = "okay";
};

&pwm3 {
	status = "okay";
};


&uart1 {
	current-speed = <9600>;
	status = "okay";
	tx-pin = <1>;
	rx-pin = <0>;
	rts-pin = <14>;
	cts-pin = <15>;
};

&uart0 {
	current-speed = <9600>;
	status = "ok";
	tx-pin = <10>;
	rx-pin = <11>;
	rts-pin = <12>;
	cts-pin = <13>;
};

The same is defined as an nrf9160dk_nrf9160.overlay file in the SPM folder.

When I try to build my application, I get a Kconfig error regarding the CONFIG_UART_1_NRF_UARTE=y. Could you help me understand what more could be required to change for it to work for UART_0.

Regards,

Adeel.

Parents
  • In NCS v1.3.0 the configurations CONFIG_UART_<x>_NRF_UARTE are not directly user-configurable and you can not set them in the prj.conf file. These configurations will get their value from the Device Tree. E.g. if you have enabled uart1 in the overlay file (status="okay"), the configuration UART_1_NRF_UARTE will get enabled here.

    So in short, just removed CONFIG_UART_1_NRF_UARTE from prj.conf.

    Another thing to be aware of is that UART1 will automatically get routed to VCOM2 due to this. In order to avoid this, flash the nRF9160dk_nrf52840 (on the nRF9160DK) with a hello world sample with this configuration:

    BOARD_NRF9160DK_UART1_ARDUINO=y
    BOARD_NRF9160DK_UART1_VCOM=n

    Best regards,

    Simon

  • Hi Simon,

    Okay. I understood the first part.

    I try to flash the hello world example and I first switch the SW5 to nrf52. Then I add your configurations to the prj.conf file. But when I load the project, it again gives me KConfig errors here as well.

    This is when I try to build the hello world sample to flash for nRF9160dk_nrf52840. Is there something I am missing again.

    2287.board_controller_uart1.hex . I found this file from another post : https://devzone.nordicsemi.com/f/nordic-q-a/45476/connecting-uart1-to-a-periph-on-nrf9160-dk/178988#178988. Could I use this directly to flash the nRF9160dk_nrf52840 board ?

    Regards,

    Adeel.

  • Hi Simon,

    It tried it but unfortunately it did not work :(.

    Right now, I have my RE connected to ground and DE (Pin 12) set as high to enable transmit. I read a blog post that explained it quite clearly: https://electronics.stackexchange.com/questions/153500/correctly-using-re-and-de-with-rs485/153508 

    I did it so as to check whether I am receiving what I am sending. With this, I get some random transmission on my console but I receive the same on my nRF terminal as Received data: (which is through my uart_buf).

    This happens when I move my DE pin a bit on pin 12 (Taking it out and putting it back in) :). That is when the data gets transmitted but it is random bits and not what I am sending. 

    I am a bit confused with the functionality.

    Regards,

    Adeel.

  • Hi Simon,

    I tried to follow this example to get an idea of how to work with RS-485 here.

    https://devzone.nordicsemi.com/f/nordic-q-a/55059/nrf51822-with-modbus-ttl-to-rs485

    I tried to configure the DE and RE as output through : nrf_gpio_cfg_output().

    Then, before sending the string, I set DE high as: nrf_gpio_pin_set().

    5355.hello_world.rar

    This is the example I am trying to modify. Can you just have a look to see if this is the right way to configure the DE/RE pins. Thanks for looking into this.

    Regards,

    Adeel.

  • Try to set RE high using nrf_gpio_pin_set() as well. As you can see here, setting RE high will disable the receiver (RE is LOW enable whle DE is high enable).

    Do you have a logic analyzer? Try attaching it to the lines to see what's actually going on.

    Best regards,

    Simon

  • Hi Simon,

    I did that as well. I tried to set both the pins (RE-DE) to high before transmission so that DE is enabled and RE is disabled. Then after the transmission, I tried to give a bit of a delay and then cleared both the pins to low so that DE is disabled and RE gets enabled. 

    I dont have a logic analyzer right now but will try to manage it. 

    Are there any examples of RS485 communication for nRF9160DK that I could refer to for more info.

    Regards,

    Adeel.

  • Hi Simon,

    As I understood from the RS-485 transmit and receive logic, I tried to implement it in the following way:

    #include <zephyr.h>
    #include <sys/printk.h>
    #include <zephyr.h>
    #include <string.h>
    #include <drivers/uart.h>
    #include "nrf.h"
    #include <hal/nrf_gpio.h>
    
    #include <drivers/gpio.h>
    
    #define GPIO_PORT "GPIO_0"
    
    #define RS485_TRANSMIT       1
    #define RS485_RECEIVE        0
    #define RS485_SWITCH_PIN1    10  // Tx
    #define RS485_SWITCH_PIN2    11  // Rx
    #define MAX485_DE      12    // DE pin (rts)
    #define MAX485_RE_NEG  13    // RE pin (cts)
    
    static u8_t uart_buf[1024];
    static struct device *uart_dev;
    
    
    void uart_cb(struct device *_uart)
    {
    	uart_irq_update(_uart); // Start processing interrupts in ISR.
    	int data_length = 0;
            
    
    	if (uart_irq_rx_ready(_uart)) { // Check if UART RX buffer has a received char.               
    		data_length = uart_fifo_read(_uart, uart_buf, sizeof(uart_buf)); // Read data from FIFO.
    		uart_buf[data_length] = 0;
                    }
                    printk("Received data is:%s\r\n", uart_buf); // Output received here
    
    }
    
    
    void uart_send_str(struct device *uart, char *str){
       
        printk("callback!\r\n");  
        
        nrf_gpio_pin_set(MAX485_DE);   // Setting it High before Tx
        nrf_gpio_pin_set(MAX485_RE_NEG);  // Setting it low before Tx
        u32_t len = strlen(str);
        while (len--) {
            uart_poll_out(uart, *str++); // Transmission
            //uart_fifo_fill(uart, str, 2);
    
        k_sleep(K_MSEC(5000));   // Delay 
        nrf_gpio_pin_clear(MAX485_DE);  // Setting low for reception
        nrf_gpio_pin_clear(MAX485_RE_NEG);  // Setting High for reception
        
        }
    }
    
    void main(void)
    {
            char *command = "OKAZZZ";      // String to be transmitted out
            printk("Hello, World!\r\n");
    
            uart_dev = device_get_binding("UART_2"); 
            if (!uart_dev) {
    		printk("error\r\n");
    	}          
    
            uart_irq_rx_disable(uart_dev);
            uart_irq_callback_set(uart_dev, uart_cb); // Set UART interrupt callback
            uart_irq_rx_enable(uart_dev);
    
            nrf_gpio_cfg_output(MAX485_DE); // Set DE as Output
            nrf_gpio_cfg_output(MAX485_RE_NEG); // Set RE as Output
    
    	while (1) {
                    printk("loop head\r\n");
                    uart_send_str(uart_dev, command); // Function to transmit the data
    	}
    }

    My overlay file is as follows: nrf9160dk_nrf9160ns.overlay

    &uart2 {
    	compatible = "nordic,nrf-uarte";
    	status = "okay";
    	current-speed = <115200>;
    	tx-pin = <10>;
    	rx-pin = <11>;
    	rts-pin = <12>;
    	cts-pin = <13>;
    	hw-flow-control;
    };
    
    &uart1 {
    	status = "disabled";
    };

    Could you look at the logic to see if this is the right way to enable / disable the DE/RE pins. The hardware connections are as per the overlay file.

    The loopback works when I only connect Tx to Rx directly, so I guess the issue is only with the DE/RE pins. The loopback data is:

    I think I am close but just need some advice in enabling / disabling DE/RE pins in the code. Thanks for the help Slight smile.

    Regards,

    Adeel.

Reply
  • Hi Simon,

    As I understood from the RS-485 transmit and receive logic, I tried to implement it in the following way:

    #include <zephyr.h>
    #include <sys/printk.h>
    #include <zephyr.h>
    #include <string.h>
    #include <drivers/uart.h>
    #include "nrf.h"
    #include <hal/nrf_gpio.h>
    
    #include <drivers/gpio.h>
    
    #define GPIO_PORT "GPIO_0"
    
    #define RS485_TRANSMIT       1
    #define RS485_RECEIVE        0
    #define RS485_SWITCH_PIN1    10  // Tx
    #define RS485_SWITCH_PIN2    11  // Rx
    #define MAX485_DE      12    // DE pin (rts)
    #define MAX485_RE_NEG  13    // RE pin (cts)
    
    static u8_t uart_buf[1024];
    static struct device *uart_dev;
    
    
    void uart_cb(struct device *_uart)
    {
    	uart_irq_update(_uart); // Start processing interrupts in ISR.
    	int data_length = 0;
            
    
    	if (uart_irq_rx_ready(_uart)) { // Check if UART RX buffer has a received char.               
    		data_length = uart_fifo_read(_uart, uart_buf, sizeof(uart_buf)); // Read data from FIFO.
    		uart_buf[data_length] = 0;
                    }
                    printk("Received data is:%s\r\n", uart_buf); // Output received here
    
    }
    
    
    void uart_send_str(struct device *uart, char *str){
       
        printk("callback!\r\n");  
        
        nrf_gpio_pin_set(MAX485_DE);   // Setting it High before Tx
        nrf_gpio_pin_set(MAX485_RE_NEG);  // Setting it low before Tx
        u32_t len = strlen(str);
        while (len--) {
            uart_poll_out(uart, *str++); // Transmission
            //uart_fifo_fill(uart, str, 2);
    
        k_sleep(K_MSEC(5000));   // Delay 
        nrf_gpio_pin_clear(MAX485_DE);  // Setting low for reception
        nrf_gpio_pin_clear(MAX485_RE_NEG);  // Setting High for reception
        
        }
    }
    
    void main(void)
    {
            char *command = "OKAZZZ";      // String to be transmitted out
            printk("Hello, World!\r\n");
    
            uart_dev = device_get_binding("UART_2"); 
            if (!uart_dev) {
    		printk("error\r\n");
    	}          
    
            uart_irq_rx_disable(uart_dev);
            uart_irq_callback_set(uart_dev, uart_cb); // Set UART interrupt callback
            uart_irq_rx_enable(uart_dev);
    
            nrf_gpio_cfg_output(MAX485_DE); // Set DE as Output
            nrf_gpio_cfg_output(MAX485_RE_NEG); // Set RE as Output
    
    	while (1) {
                    printk("loop head\r\n");
                    uart_send_str(uart_dev, command); // Function to transmit the data
    	}
    }

    My overlay file is as follows: nrf9160dk_nrf9160ns.overlay

    &uart2 {
    	compatible = "nordic,nrf-uarte";
    	status = "okay";
    	current-speed = <115200>;
    	tx-pin = <10>;
    	rx-pin = <11>;
    	rts-pin = <12>;
    	cts-pin = <13>;
    	hw-flow-control;
    };
    
    &uart1 {
    	status = "disabled";
    };

    Could you look at the logic to see if this is the right way to enable / disable the DE/RE pins. The hardware connections are as per the overlay file.

    The loopback works when I only connect Tx to Rx directly, so I guess the issue is only with the DE/RE pins. The loopback data is:

    I think I am close but just need some advice in enabling / disabling DE/RE pins in the code. Thanks for the help Slight smile.

    Regards,

    Adeel.

Children
  • Hi Simon,

    I tried another example that looked much simpler and I just wanted to transmit things out of the UART. 

    The code is pretty straight forward as well to understand. 

    static K_FIFO_DEFINE(fifo_uart_tx_data);
    static K_FIFO_DEFINE(fifo_uart_rx_data);
    
    struct uart_data_t {
    	void  *fifo_reserved;
    	u8_t    data[1024];
    	u16_t   len;
    };
    
    static struct device *uart_dev;
    
    
    void uart_cb(struct device *x)
    {
    	uart_irq_update(x); // Start processing interrupts in ISR.
    	int data_length = 0;
    
    	if (uart_irq_rx_ready(x)) { // Check if UART RX buffer has a received char.               
    		data_length = uart_fifo_read(x, uart_buf, sizeof(uart_buf)); // Read data from FIFO.
    		uart_buf[data_length] = 0;
                    }
                    printk("Received data is:%s\r\n", uart_buf);
    
                if (uart_irq_tx_ready(x)) {
                
                    struct uart_data_t *buf = 
                    k_fifo_get(&fifo_uart_tx_data, K_NO_WAIT);
                  u16_t written = 0;
    
                  /* Nothing in the FIFO, nothing to send */
    		if (!buf) {
    			uart_irq_tx_disable(x);
    			return;
    		}
    
                    while (buf->len > written) {
    			written += uart_fifo_fill(x,
    						  &buf->data[written],
    						  buf->len - written);
                           uart_tx(uart_dev, buf, 5, 5000);
    		}
    
                    while (!uart_irq_tx_complete(x)) {
    			/* Wait for the last byte to get
    			 * shifted out of the module
    			 */
    		}
    
    		if (k_fifo_is_empty(&fifo_uart_tx_data)) {
    			uart_irq_tx_disable(x);
    		}
    
                    k_free(buf);
    
          
                  
    }
    }
    
    void main(void)
    {
           
    
            uart_dev = device_get_binding("UART_2"); 
            if (!uart_dev) {
    		printk("error\r\n");
    	}          
    
            uart_irq_rx_disable(uart_dev);
            uart_irq_callback_set(uart_dev, uart_cb); // Set UART interrupt callback
            uart_irq_rx_enable(uart_dev);
    
            uart_irq_tx_enable(uart_dev);
    
            printk("Testing1: \n");              
            uart_fifo_fill(uart_dev, "AB" ,sizeof("AB"));
            
            k_sleep(K_MSEC(100));
    
    
            
    	while (1) {
                    
                      k_cpu_idle();             
                    
    	}
    }

    Still, I don't see the data out on my analyzer. I have a serial interface analyzer where I view the string. I tried with Arduino and that worked just by a transmit signal.  

    So, I am unsure as to what could be the causes for it. I can see the loopback data in this example as well when I connect my Tx to Rx. 

    (1). I have the correct overlay files both in spm (nrf9160dk_nrf9160) as well as in my folder (nrf9160dk_nrf9160ns)

    &uart2 {
    	compatible = "nordic,nrf-uarte";
    	status = "okay";
    	current-speed = <9600>;
    	tx-pin = <10>;
    	rx-pin = <11>;
    	rts-pin = <12>;
    	cts-pin = <13>;
    	hw-flow-control;
    };
    
    &uart1 {
    	status = "disabled";
    };

    I have also changed the configuration in the nrf9160dk_nrf9160_common.dts file in : C:\Users\adeel\ncs\v1.3.0\zephyr\boards\arm\nrf9160dk_nrf9160.

    My prj config file is :

    CONFIG_UART_INTERRUPT_DRIVEN=y
    CONFIG_UART_ASYNC_API=y
    CONFIG_TRUSTED_EXECUTION_NONSECURE=y
    CONFIG_UART_INTERRUPT_DRIVEN=y
    CONFIG_MAIN_STACK_SIZE=4096
    CONFIG_UART_2_NRF_FLOW_CONTROL=y

    I am unsure of what could be the issue ? The configuration or the code.

    I just want to transmit the string set in uart_fifo_fill() function in my code to check the UART connection. 

    Regards,

    Adeel. 

  • Sorry for the delay on this, I've been quite busy lately. I will look into it today. Have you made any progress?

    Best regards,

    Simon

  • Hi Simon,

    Not really. I could not figure out the exact trouble with it. The loopback works with Tx to Rx. So I assume that the string is atleast reaching the Tx. 

    I followed this post and got a simple example : https://devzone.nordicsemi.com/f/nordic-q-a/47218/continuously-package-send-on-uart

    The string transmission to an outside serial interface is not happening. I wonder what could be the cause. 

    When I just take out and put back my Tx pin on the board, I see random data on the serial analyser. I am sure the RS485 configuration is correct because for now, I just want to transmit the string. The DE is kept high for that and RE high as well (Negative logic). Any insights would be helpful. 

    I hope there is no mistake in my UART config atleast.

    Regards,

    Adeel.

  • Hi Simon, 

    Just to catch up on this, I read about the enable and the blocking mode. I believe the blocking mode after transmission is not being set up. 

    I have enabled the DE and RE pin before transmission and I wait for a certain time before making it low. 

    I found this case quite relevant: https://devzone.nordicsemi.com/f/nordic-q-a/55059/nrf51822-with-modbus-ttl-to-rs485/223289#223289

    But it has handlers which I did not find compatible with nrf9160. Its for the nRF52 series.

    Could you just help me in modifying my above attached example that could be compatible with the nrf9160DK. I would really appreciate the help in this.

    Regards,

    Adeel. 

  • Hi Simon,

    Any help on this would be very useful :).

    Regards,

    Adeel.

Related