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

how to send uart data over ble with nrf52840 dongle

I'm working on pca10059(nRF52840 dongle) to send UART data over bluetooth to another device.

My test environment is,

Arduino Uno to send uart signal using "mySerial.write("Hello World\n");",

pca10059 device that I'm trying to develop to send uart data above to another device over bluetooth,

another pca10059 device to receive the data over bluetooth and send Serial signal to see the data on PC to make sure the "Hello World" travels fine.

(1) I've modified the project in example/ble_peripheral/ble_app_uart to send arbitrary data(series of uint8_t signal) to another dongle and I could see the data in Python IDLE.

(2) I've checked the arduino wiring is correct by testing a project below link.

https://devzone.nordicsemi.com/f/nordic-q-a/56406/how-to-set-up-a-simple-uart-connection-between-nrf-52840-dongle-and-a-microcontroller-e-g-arduino

I've changed the code (1) a little bit to see if I could send uart to the other dongle. It didn't work.

Most of what I've done is changing the TX RX pin number to suit wiring setup.

What's hard to understand is the project already has uart_event_handle function in the main.c and it uses ble_nus_data_send function just like (1) but it seems it's not responding to uart signal sent from arduino or it's not sending the received uart signal.

uart_init() was also called to activate uart.

Although I couldn't check arduino's uart signal, I'm quite sure (2) project's success in test indicates it's not a problem of connection or arduino code. Correct me if I'm wrong.

  • Another thing,

    if uart_event_handle function is supposed to handle incoming uart data just fine and arduino is the only problem, figuring out what's exactly happening might be a waste of time because final product wouldn't work with arduino.

    What I could do is testing it with the actual final setup that's going to be in place of current arduino.

    is uart_event_handle function implemented and getting it used in uart_init enough to make it deliver the data just fine?

    if this works I might not even have to use logic analyzer.

  • After commenting out uart_init function. It seems the test I was doing works fine. The one with sending 111. Only if printf function would work without breaking texts.

    Still If I could not use uart_event_handle function I don't know how to send this uart data, 111 in this case, over bluetooth.

  • This is also interesting.

    With the code below, nothing prints out on arduino.

        uint8_t data;
        uint32_t retval;
        for (;;)
        {
            retval=app_uart_get(&data);
            if(retval==NRF_SUCCESS)
              app_uart_put(data);
            nrf_delay_ms(500);
        }

    But the code below this prints out on arduino just like it's expected.

        uint8_t data;
        uint32_t retval;
        for (;;)
        {
            retval=app_uart_get(&data);
            app_uart_put(data);
            nrf_delay_ms(500);
        }

    shouldn't retval be NRF_SUCCESS when it gets data from RX?

  • Senchoi said:

    I did not fully understand this part but as I tried app_uart_put it sends to arduino just fine.

    I'm a bit confused because the issue at this moment is arduino not sending uart signal to NRF. I'm not sure why arduino's RX register matters.

    Thats great to hear - so now we know that the issue is with the arduino sending over uart, not with the NRF and its RX/TX. This is great to know for the continued debugging effort.
    The reason I asked you to do this test was to figure out if the issue was with the nrf or the arduino.
    It was not clear to me that the issue was on the arduino's side prior to you confirming this.

    Senchoi said:
    I guess this issue is not going to end unless I can fully understand what's going on in UART. Would it help to get logic analyzer?

    There are always ways to get around it, but they are tedious and take a lot longer. Being enable to see exactly what is happening on the lines help tremendously when working with all serial protocols, since it is the only way to know what is actually happening. 

    Senchoi said:
    But modifying existing handler to send the received data back to arduino is a little out of my capability. I was kinda hoping to know a sure way to receive uart data from arduino since the error code is 5.

    I am sure you will be able to modify this if you had wanted - but since we now know that the issue is on the arduino side you do not have to make this modification, since we are past that part of the debugging. If the arduino is not sending correctly, there is nothing you can do on the nrf side to alleviate this, so we will have to look at the arduino side to resolve this.

    Senchoi said:
    if uart_event_handle function is supposed to handle incoming uart data just fine and arduino is the only problem, figuring out what's exactly happening might be a waste of time because final product wouldn't work with arduino.
    Senchoi said:
    is uart_event_handle function implemented and getting it used in uart_init enough to make it deliver the data just fine?

    Yes, you are right. The default uart_event_handler in the ble_app_uart example does exactly this - whenever it receives something through UART it queues it for sending over BLE.
    I was not aware that you do not intend to keep the arduino in your project. I suppose you could say that debugging the arduino is then a waste of time, but then again - what did you hope to achieve with the arduino in the first place? Certainly these goals will not be met if you abandon the arduino now.

    Senchoi said:
    if this works I might not even have to use logic analyzer.

    In the short term this looks to be the case then, yes. For future development it would however be very useful for you to have access to a logic analyzer when developing with serial protocols.
    Fortunately, logic analyzers are quite easy to come by these days, and there exists many cheap versions out there, so at least it might be something to look into, for you own future sake.

    Senchoi said:
    After commenting out uart_init function. It seems the test I was doing works fine. The one with sending 111. Only if printf function would work without breaking texts.

    I am not sure what you mean by this. Are you saying that if you comment out uart_init, you are able to pass the byte with value 111 back and forth as expected?
    As I mentioned earlier, the retargeted printf actually uses the app_uart_put function behind the curtains. You could check the retargeting library source code to see this for yourself. This means that if you use printf, it is the same as calling app_uart_put on a cstring containing whatever you tried to have print.
    If you refrain for using the retargeted printf function, this should not be an issue.

    Senchoi said:
    shouldn't retval be NRF_SUCCESS when it gets data from RX?

    Yes, it should be NRF_SUCCESS if it has successfully retrieved a byte from the UART RX buffer.
    This is the kind of issue we could easily avoid if we had a logic analyzer scope the communication, because suddenly it seems like the arduino is sending the data as expected.

    On a general note the returned error code should usually be passed to an APP_ERROR_CHECK for handling, but this is not necessary in this simple debugging test program. I just thought I should mention it for future development.

    Senchoi said:
    But the code below this prints out on arduino just like it's expected.

    Are you saying that you are then able to pass the same '111' valued byte back and forth?

    Senchoi said:
    With the code below, nothing prints out on arduino.

    On a general note you should always use braces around your conditional statements, it is considered bad practice for maintainability to leave the braces out just because you technically can. Please see this StackOverflow answer for more detail.

    Best regards,
    Karl

  • Although I felt very lucky to get these replies.

    I think I've found out why uart_event_handle didn't send the data.

    void uart_event_handle(app_uart_evt_t * p_event)
    {
        static uint8_t data_array[BLE_NUS_MAX_DATA_LEN];
        static uint8_t index = 0;
        uint32_t       err_code;
    
        switch (p_event->evt_type)
        {
            case APP_UART_DATA_READY:
                UNUSED_VARIABLE(app_uart_get(&data_array[index]));
                index++;
    
                if ((data_array[index - 1] == '\n') ||
                    (data_array[index - 1] == '\r') ||
                    (index >= m_ble_nus_max_data_len))
                {
                    if (index > 1)
                    {
                        NRF_LOG_DEBUG("Ready to send data over BLE NUS");
                        NRF_LOG_HEXDUMP_DEBUG(data_array, index);
    
                        do
                        {
                            uint16_t length = (uint16_t)index;
                            err_code = ble_nus_data_send(&m_nus, data_array, &length, m_conn_handle);
                            printf("%s\r\n", data_array);
                            if ((err_code != NRF_ERROR_INVALID_STATE) &&
                                (err_code != NRF_ERROR_RESOURCES) &&
                                (err_code != NRF_ERROR_NOT_FOUND))
                            {
                                APP_ERROR_CHECK(err_code);
                            }
                        } while (err_code == NRF_ERROR_RESOURCES);
                    }
    
                    index = 0;
                }
                break;
    
            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;
    
            default:
                break;
        }
    }

    The function above has certain condition for sending data over ble.

    if ((data_array[index - 1] == '\n') ||
    (data_array[index - 1] == '\r') ||
    (index >= m_ble_nus_max_data_len))

    this seems the part that I should've understood. When sending the data from Arduino I had to send '\n' at the end.

    It seems above handler waits for the condition above.

    This is the Arduino code that works now.

    #include <SoftwareSerial.h>
    
    SoftwareSerial mySerial(2, 3); // RX, TX
    
    void setup()
    {
      // Open serial communications and wait for port to open:
      Serial.begin(115200);
      while (!Serial) {
        ; // wait for serial port to connect. Needed for Native USB only
      }
    
    
      Serial.println("Goodnight moon!");
    
      // set the data rate for the SoftwareSerial port
      mySerial.begin(115200);
      mySerial.println("Hello, world?");
    }
    char c = 'a';
    void loop() // run over and over
    {
      
      if (mySerial.available()){
        Serial.write(mySerial.read());
        if (c == 'z' + 1)
          c = 'a';
        mySerial.write(c++);mySerial.write('\n');
      }
      delay(500);
    }

    I can see the sent data from python shell with the setup I had.

    I have tones of other questions but I guess I can wrap it up for now.

Related