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

Zigbee and Serial communication issue

Hello Nordic!

I have been developing a Zigbee application and now, I need to connect via Serial communication with another device. I just need to listen to the port, not send any data. Unfortunately I don't have that device so I am simulating it with an Arduino Uno. It is configured as the original device at 19200baud, 8bit, 1 stop bit. First of al, is there any other better way to read data through RX/TX? Any other libraries instead of libuarte?

I found the libuarte example which I modified and make it work for my needs. It reads my Arduino via Serial communication correctly and I obtain the characters nicely. My problem occurs when I try to implement the libuarte code into mine. I have had several problems with the sdk_config file. But once the errors have faded out and the code have compiled, I have flashed it into the nrf52840DK board but the Zigbee and Serial communication suddenly stopped working. Could it be that they share some timer or some other peripheral?

I have tried changing the timer for the serial communication but achieved nothing. What may be causing this issue?

The modified code of the libuarte's example is as follows:

/**
 * Copyright (c) 2018 - 2020, Nordic Semiconductor ASA
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form, except as embedded into a Nordic
 *    Semiconductor ASA integrated circuit in a product or a software update for
 *    such product, must reproduce the above copyright notice, this list of
 *    conditions and the following disclaimer in the documentation and/or other
 *    materials provided with the distribution.
 *
 * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
 *    contributors may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * 4. This software, with or without modification, must only be used with a
 *    Nordic Semiconductor ASA integrated circuit.
 *
 * 5. Any software provided in binary form under this license must not be reverse
 *    engineered, decompiled, modified and/or disassembled.
 *
 * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
/** @file
 * @defgroup libuarte_example_main main.c
 * @{
 * @ingroup libuarte_example
 * @brief Libuarte Example Application main file.
 *
 * This file contains the source code for a sample application using libuarte.
 *
 */

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "nrf_libuarte_async.h"
#include "nrf_drv_clock.h"
#include <bsp.h>
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#include "nrf_queue.h"

NRF_LIBUARTE_ASYNC_DEFINE(libuarte, 0, 0, 0, NRF_LIBUARTE_PERIPHERAL_NOT_USED, 255, 3);

static uint8_t text[] = "UART example started.\r\n Loopback:\r\n";
static uint8_t text_size = sizeof(text);
static volatile bool m_loopback_phase;

typedef struct {
    uint8_t * p_data;
    uint32_t length;
} buffer_t;

NRF_QUEUE_DEF(buffer_t, m_buf_queue, 10, NRF_QUEUE_MODE_NO_OVERFLOW);

void uart_event_handler(void * context, nrf_libuarte_async_evt_t * p_evt)
{
    nrf_libuarte_async_t * p_libuarte = (nrf_libuarte_async_t *)context;
    ret_code_t ret;

    switch (p_evt->type)
    {
        case NRF_LIBUARTE_ASYNC_EVT_ERROR:
            bsp_board_led_invert(0);
            break;
        case NRF_LIBUARTE_ASYNC_EVT_RX_DATA:
            ret = nrf_libuarte_async_tx(p_libuarte,p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);
            if (ret == NRF_ERROR_BUSY)
            {
                buffer_t buf = {
                    .p_data = p_evt->data.rxtx.p_data,
                    .length = p_evt->data.rxtx.length,
                };

                ret = nrf_queue_push(&m_buf_queue, &buf);
                APP_ERROR_CHECK(ret);
            }
            else
            {
                APP_ERROR_CHECK(ret);
            }
            bsp_board_led_invert(1);
            m_loopback_phase = true;
            break;
        case NRF_LIBUARTE_ASYNC_EVT_TX_DONE:
            if (m_loopback_phase)
            {
                nrf_libuarte_async_rx_free(p_libuarte, p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);
                if (!nrf_queue_is_empty(&m_buf_queue))
                {
                    buffer_t buf;
                    ret = nrf_queue_pop(&m_buf_queue, &buf);
                    APP_ERROR_CHECK(ret);
                    UNUSED_RETURN_VALUE(nrf_libuarte_async_tx(p_libuarte, buf.p_data, buf.length));
                }
            }
            bsp_board_led_invert(2);
            break;
        default:
            break;
    }
}

/**
 * @brief Function for main application entry.
 */
int main(void)
{
    bsp_board_init(BSP_INIT_LEDS);
    
    ret_code_t ret = nrf_drv_clock_init();
    APP_ERROR_CHECK(ret);
  
    nrf_drv_clock_lfclk_request(NULL);

    ret_code_t err_code = NRF_LOG_INIT(app_timer_cnt_get);
    APP_ERROR_CHECK(err_code);

    NRF_LOG_DEFAULT_BACKENDS_INIT();

    nrf_libuarte_async_config_t nrf_libuarte_async_config = {
            .tx_pin     = TX_PIN_NUMBER,
            .rx_pin     = RX_PIN_NUMBER,
            .baudrate   = NRF_UARTE_BAUDRATE_19200,
            .parity     = NRF_UARTE_PARITY_EXCLUDED,
            .hwfc       = NRF_UARTE_HWFC_DISABLED,
            .timeout_us = 100,
            .int_prio   = APP_IRQ_PRIORITY_LOW
    };

    err_code = nrf_libuarte_async_init(&libuarte, &nrf_libuarte_async_config, uart_event_handler, (void *)&libuarte);

    APP_ERROR_CHECK(err_code);

    nrf_libuarte_async_enable(&libuarte);

    err_code = nrf_libuarte_async_tx(&libuarte, text, text_size);
    APP_ERROR_CHECK(err_code);

    while (true)
    {
        NRF_LOG_FLUSH();
    }
}


/** @} */

Thanks to all in advance!

Cheers!

Parents
  • Hello,

    Perhaps you can look into the Zigbee CLI example found in:

    SDK_for_thread_and_zigbee_v4.1.0\examples\zigbee\experimental\cli\cli_agent_router, which is an example where a lot of the zigbee api is serialized.

    If you want to continue on the libuarte path, did you try writing something to the log? Try adding:

    NRF_LOG_INFO("starting application"); right after NRF_LOG_DEFAULT_BACKENDS_INIT(). Do you see the log anywhere? (RTT perhaps, if you are using UART for your application).

    If you see the log, does the log say anything when your application isn't working?

    BR,
    Edvin

  • Hello Edvin!

    Thanks for your quick reply!

    Could you specify a bit more what should I look at in the cli_agent_router example? The code is too short...

    About the log, I haven't had time to learn how to use the NRF_LOG so what I am using is the printf function to show some info via Debug Terminal (in Segger). May you link some information about how to use it? I guess it is more useful than the printf function that I am currently using.

    Anyway, I placed the printf function right under the NRF_LOG_DEFAULT_BACKENDS_INIT() call and it didn't show in the debug terminal... What could be causing this  issue?

    What I found is that the call to nrf_drv_clock_init() is failing, it is returning 0x85 error code. I will debug a bit more this...

    EDIT: I just found out that the error code 0x0085 means that the module is already initialized. So I think I can either remove that call or remove the call to the APP_ERROR_CHECK function. Am I right? Unfortunately the code still fails in the call to NRF_LOG_DEFAULT_BACKENDS_INIT()... I will continue to investigate this issue...

    Thanks in advance!

  • I have asked the Zigbee expert to shed some light on the BLE, Zigbee and UART compatibility. She is on holiday today but will respond most likely on Tuesday as Monday is also holiday (Norwegian National Day)

  • I am now talked to the Zigbee developer in support and she says that she does not see any reason that UART will have any compatibility issues when used with BLE and Zigbee. There is also a BLE UART/Zigbee doorlock, that uses uart gor logging.

    there is also a template you should follow if you wants to run both BLE and Zigbee, adding UART peripheral to this example and then the rest of his application will be much easier for you than adding BLE to an existing Zigbee project:
  • Hello Susheel!

    There is also a BLE UART/Zigbee doorlock, that uses uart gor logging.

    I think the example you said is the same example I am using as a guide for my project. In fact, what I am trying to make is a Zigbee doorlock but with a lot of features. That example uses NUS for sending data over BLE, could that be my problem?

     I've been trying unsuccesfully to add uart communication to the template you mention but I am not able to do it. I am using the same code that is working in my current board (with BLE and Zigbee deactivated) but it refuses to work. Below I show yo the code I am using (it is written in spanish, sorry):

    void uart_event_handle(app_uart_evt_t * p_event)
    {
        static uint8_t buffer[LONGITUD_MAX_MENSAJE];
        static uint8_t index = 0;
        uint32_t err_code;
    
        switch (p_event->evt_type)
        {
            case APP_UART_COMMUNICATION_ERROR:
                APP_ERROR_HANDLER(p_event->data.error_communication);
                break;
    
            case APP_UART_FIFO_ERROR:
                //APP_ERROR_HANDLER(p_event->data.error_code);
                break;
    
            case APP_UART_DATA:
                UNUSED_VARIABLE(app_uart_get(&buffer[index]));
                if ((buffer[index] == 0x0a) || (buffer[index] == 0x0d) || index >= LONGITUD_MAX_MENSAJE)
                {
                    // Do something
                    index = 0;
                }
                else
                {
                    index++;
                }
                break;
    
            default:
                break;
        }
    }
    
    
    static void uart_init(void)
    {
        uint32_t err_code;
        app_uart_comm_params_t const comm_params =
        {
            .rx_pin_no    = RX_PIN,
            .tx_pin_no    = TX_PIN,
            .rts_pin_no   = RTS_PIN,
            .cts_pin_no   = CTS_PIN,
            .flow_control = FLOW_CONTROL,
            .use_parity   = USE_PARITY,
            .baud_rate    = BAUDRATE
        };
    
        APP_UART_INIT(&comm_params,
                      uart_event_handle,
                      APP_IRQ_PRIORITY_HIGH,
                      err_code);
    
        APP_ERROR_CHECK(err_code);
    }

    I also modified the sdk_config file to define UART_ENABLED to 1 and used the APP_UART_DRIVER_INSTANCE 0, the sdk_donfig file is pretty similar to mine. But I don't discard that the error may be in that file.

    Cheers!

    EDIT: I realised that the problem was having both the log and the uart, so I commented out the initialisation function for the log and everything seems to work. I have yet to test the full functionality, but it looks promising.

  • Hello Susheel!

    I have continued and realised the cause of the error. I am posting the info in case someone else has the same problem in the future.

    After a week of debugging, I find out that the library "libzboss.ed.a" located in "external/zboss/lib/gcc/" was causing the code to fail. If I use the "libzboss.a" library instead of the "libzboss.ed.a" (note the difference between .ed.a and just .a) it works like a charm.

    In fact, as Susheel told me, there is no incompatibilities between Zigbee and UART. And I simply changed that library and everything started working. There is also one little thing to modify, and that is to remove the "ZB_ED_ROLE" from the Preprocessor definitions, but if you don't do that, Segger (or whatever you use) will throw an error.

    To close the thread, I just want to know why was happening this error. I would appreciate it if someone could explain a bit more about why this problem is occurring.

    Cheers!

  • Hello again!

    I have been experiencing some problems with Serial and Zigbee communication. The previous solution I found about "libzboss.a" library is not suitable, that library is not used on Zigbee End Devices (I need to use libzboss.ed.a) so when I try to reconnect to my Coordinator it connects as a device with GreenPower cluster only (when I don't use it).

    Please, I need to fix this issue as soon as possible, it's been 3 months since the beginning of the question and I still have the UART working.

    Regards.

Reply
  • Hello again!

    I have been experiencing some problems with Serial and Zigbee communication. The previous solution I found about "libzboss.a" library is not suitable, that library is not used on Zigbee End Devices (I need to use libzboss.ed.a) so when I try to reconnect to my Coordinator it connects as a device with GreenPower cluster only (when I don't use it).

    Please, I need to fix this issue as soon as possible, it's been 3 months since the beginning of the question and I still have the UART working.

    Regards.

Children
  • Hi Alejandro,

    I have taken over this case from Susheel. I don't think you should delete the ZBOSS libraries provided. Could it be that you are having problems adding a new UART instance since the Zigbee examples also use UART for nrf log output?

    Have you tried changing APP_UART_DRIVER_INSTANCE to 1 in sdk_config.h and set UART1_ENABLED?

    nRF logging module in the examples will use UART0 as default.

    Best regards,

    Marjeris

Related