Making RAK4631 and RAK5802 work in Zephyr

I'm interested in connecting a device to a combination of RAK4631 and RAK5802 using RS485 interface.

I write the code in the Zephyr environment and I cant seem to make it work.

Here is the source code (main.c):

#include <zephyr/drivers/gpio.h>
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/uart.h>

// chip used in the RS485 module:
//   http://file.3peakic.com.cn:8080/product/Datasheet_TP8485E.pdf

// RAK4631 Schematics:
//   https://images.docs.rakwireless.com/wisblock/rak4631/datasheet/schematic.png

// RAK5802 Schmatics:
//   https://images.docs.rakwireless.com/wisblock/rak5802/datasheet/schematic.png

// Example Arduio code:
//   https://github.com/RAKWireless/WisBlock/tree/master/examples/RAK4630/IO/RAK5802_RS485

// RAK4631 UART connected to RS485 module
#define RS485 DEVICE_DT_GET(DT_CHOSEN(uart_rs485))

static const struct device *rs485 = RS485;

static void configure_uicr(void) {
  if ((NRF_UICR->REGOUT0 & UICR_REGOUT0_VOUT_Msk) != (UICR_REGOUT0_VOUT_3V3 << UICR_REGOUT0_VOUT_Pos)) {
    NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
    while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {}

    NRF_UICR->REGOUT0 =
        (NRF_UICR->REGOUT0 & ~((uint32_t)UICR_REGOUT0_VOUT_Msk)) |
        (UICR_REGOUT0_VOUT_3V3 << UICR_REGOUT0_VOUT_Pos);

    NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
    while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {}

    // System reset is needed to update UICR registers.
    NVIC_SystemReset();
  }
}

int main(void) {
  uint8_t ch = 1;
  int ret;

  printk("** Starting\n");

  // am not sure if I need this or not (?)
  configure_uicr();

  // echo loop
  while (true) {
    // poll for input
    if ((ret = uart_poll_in(rs485, &ch)) == 0) {
      // print what we've got
      printk("> 0x%02x\n", ch);
      
      // echo back to peer
      uart_poll_out(rs485, ch);
    
    } else if (ret < -1) {
      printk("EE Error polling in: %d\n", ret);
      k_sleep(K_SECONDS(1));
    }

    // sleep for 1 ms just for funzies
    k_sleep(K_MSEC(1));
  }
  
  return 0;
}

Here is the project configuration file (prj.conf):

CONFIG_STDOUT_CONSOLE=y
CONFIG_USB_CDC_ACM=y
CONFIG_USB_DEVICE_STACK=y
CONFIG_USB_DEVICE_PRODUCT="RAK4631 Zephyr"
CONFIG_USB_DEVICE_MANUFACTURER="RAKwireless"
CONFIG_USB_DEVICE_VID=0x1915
CONFIG_USB_DEVICE_PID=0x5300
CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=y
CONFIG_UART_LINE_CTRL=y

# We need to control GPIO pins
CONFIG_GPIO=y

# We need to work with a UART (connected to RS485)
CONFIG_SERIAL=y

Here is the overlay file (rak4631_nrf52840.overlay):

/ {
	chosen {
		/delete-property/ zephyr,uart-mcumgr;
		/* uart1 is used by RS485. */
		/delete-property/ zephyr,bt-mon-uart;
		/delete-property/ zephyr,bt-c2h-uart;

		uart,rs485 = &uart1;
		zephyr,console = &cdc_acm_uart0;
	};
};

&uart1 {
	current-speed = <57600>;
	compatible = "nordic,nrf-uarte";
	status = "okay";

	tp8485e: tp8485e {
		compatible = "tp8485e";
		enable-gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>;
		status = "okay";
	};
};

&zephyr_udc0 {
	cdc_acm_uart0: cdc_acm_uart0 {
		compatible = "zephyr,cdc-acm-uart";
	};
};

I build (with "west build -p always -b rak4631/nrf52840 ." in the app folder)
.. and flash (with "west flash")
.. and open a serial terminal to an RS485 dongle I have connected to my desktop (I tested it and it works with other RS485 devices)
.. and nothing I type in my terminal makes it through .. as if the RAK4631 doesnt get the input.

When I change the code to only write to the UART (loop of only "uart_poll_out()") I see nothing in the serial terminal.

Some of the code I used in the overlay file was borrowed from:
https://github.com/retfie/helium_mapper

What am I missing here ? why cant I make this RS485 module to work ?

Related