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.

  • Senchoi said:
    That's just how "the other" dongle is programmed. "the other" dongle listens ble signal and sends Serial signal to the computer. When python reads the other dongle and there's no data, it prints out 0 after timeout period that is set in Python code. It will print something other than 0 before timeout when "the other" dongle reads something.

    Aha, I misinterpreted your 's' as a shorthand for seconds, instead of plural, thank you for clarifying.

    Senchoi said:
    testing part in the dongle is below code in the main function out of loop.

    You are not checking the returned error code of app_uart_get. You should always check the returned error code - if you do not, you have no way of knowing whether the function succeeded or not. 

    Senchoi said:
    Arduino code looks like this

    I am not too familiar with arduino code personally, but it looks to me like your conditional statements check whether to write something only if it has already received something?
    Your conditionals use the .available() function, which only will evaluate to true if data has already been received over UART. It looks to me like none of those lines will ever run, unless the dongle starts out by sending something over UART to the arduino.
    Could you also have you arduino either toggle a LED or give some other indication that it is writing to UART? You could for example base this on the returned value from the .write() function. 

    Senchoi said:
    But it seems idle_state_handle() in the for loop constantly turns the dongle on and off for power management since "0 received" prints out about every half a second when the dongle is connected to Arduino.

    The idle_state_handler checks whether there are logs that needs processing, and if not it places the CPU in a low power SYSTEM_ON state (idle) to save power. It does not turn off the dongle (SYSTEM_OFF). Since you are not checking the error code returned by the app_uart_get function the function might never actually succeed, and this might be why you are seeing the repeated 0 (if this is the initialized value of the data variable).
    You could check this by either checking the returned error code - which you always should do -, or by initializing the data variable to a known other value, and seeing if this is the value you are seeing repeatedly.

    Looking forward to resolving this issue together!

    Best regards, 
    Karl

  • The error code is five which must be NRF_ERROR_NOT_FOUND.

    I guess arduino is not sending the uart signal for some reason.

    Here's my arduino code...

    #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?");
    }
    
    void loop() // run over and over
    {
      if (mySerial.available()){
        Serial.write(mySerial.read());
        mySerial.write(111);
      }
    }

    Here's my dongle code in the main function.

        uint8_t data;
        int retval;
        for (;;)
        {
            retval = app_uart_get(&data);
            printf("%u received. %d is the retval.\n", data, retval);
            //idle_state_handle();
            //nrf_pwr_mgmt_run();
            //NRF_LOG_FLUSH();
            nrf_delay_ms(500);
        }

    this setup constantly prints out "0 received. 5 is the retval." in every 500ms.

    I don't understand. Should I ask this in arduino community about how to send uart signal other than mySerial.write function?

    Also i'm not sure If it's because of connection. "0 received. 5 is the retval." message breaks like crazy.

    something like..

    0 recived.  is th retal.
    0 recdved. 5 s theretal.
    0 rece⸮⸮⸮s⸮~⸮.A⸮⸮⸮⸮g⸮[I⸮0 receved.5 Z.ݫ⸮⸮х⸮⸮
    0 reaeiv;⸮. 5 iq⸮⸮W&⸮va[⸮⸮0 received. 5 isthe reval.
    0 recewed. 5 is he reval.
    0 rY⸮YZY⸮	J́⸮⸮⸮⸮⸮х⸮⸮R0 received. 5 is th re:val.
    0 receve⸮. 5 is the 9eval.

  • Senchoi said:

    Also i'm not sure If it's because of connection. "0 received. 5 is the retval." message breaks like crazy.

    something like..

    The returned value of app_uart_get is an uint32_t, not an int, I am not sure that the arduino decodes it correctly in the printf statement.
    Take a look at this stackoverflow answer for a more indepth explanation of why it is important to be exact with these types.

    Senchoi said:
    I don't understand. Should I ask this in arduino community about how to send uart signal other than mySerial.write function?

    Keep in mind that the app_uart_get function retrieves one byte at the time.
    Reading the .write arduino documentation again seems to say that the .write takes an array, or a single value. In this case, a byte with value 111 should have been written.

    However, you are also first attempting to write what you have received last, with the .write(.read()) function. Then we need to look at what your arduino might be receiving over the UART. In this case, it looks like it will receive the cstring from your printf statement.
    This is certainly a little chaotic.

    I am not certain that the logic in your test is correct. Please write down what you tried to have happen in this code. If the goal was to periodically send a byte with value 111 that is not what you are currently doing.

    How about this instead:
    On the NRF side, implement the test as part of the uart RX event handler, have it retrieve the one byte using app_uart_get, and then send the same byte back by using app_uart_put for only that single byte, received over UART. Do not use printf for anything in this test, as the retargeting of printf will have its output be put on the UART, creating clutter.
    Let your main() loop only contain the idle_state_handler call.

    On the Arduino side, have the arduino send a single known byte periodically, for example a byte with value 111. Have the arduino check if it has received anything in its UART RX register by checking .available() with following .read() periodically, and if it has have the arduino toggle a LED or something similar - the arduino should also check the value of the byte it has received, to see if it matches the value of the byte it sent.

    Implement this test, and see if it results in the LED toggling every 500 ms period on the arduino, then you will know that their communication is working as it should.

    I think part of the issue here is that you have not checked your returned error codes, and that you have mixed up what is actually happening on the UART interface, since you are using printf on both sides in combination with your test byte. Additionally I think the test logic on the arduino side might not have achieved exactly what you hoped to.

    This is where a logical analyzer would make the work a lot easier, since we immediately would see what is going on on the UART - but we will find a way to make due without the analyzer.

    Looking forward to resolving this issue together!

    Best regards,
    Karl

  • On the Arduino side, have the arduino send a single known byte periodically, for example a byte with value 111. Have the arduino check if it has received anything in its UART RX register by checking .available() with following .read() periodically, and if it has have the arduino toggle a LED or something similar - the arduino should also check the value of the byte it has received, to see if it matches the value of the byte it sent.

    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.

    My goal is eventually to deliver series of uint8_t data periodically over ble.

    I can understand the importance of sending periodical data from arduino and let dongle's handler handle the data. 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 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?

  • And is there anything else that's helpful other than logic analyzer?

Related