Communication setup between nRF52840 Express and Jetson nano

General project help for Adafruit customers

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
elhari1
 
Posts: 6
Joined: Thu Apr 28, 2022 11:19 am

Communication setup between nRF52840 Express and Jetson nano

Post by elhari1 »

Hello,

For a project I'm currently working on, I just got a nRF52840 Express. My goal is, to send a string (NMEA GPS data to be precise) from my GNSS receiver via the nRF52840 Express to my host computer (jetson nano).
Into my Jetson, which would act as the Central, I would plug in a Bluetooth USB 4.0 Module to afterwards setup the connection to my nRF52840.
On the peripheral side, I planned to stream the NMEA string to the nRF52840 via UART TX/RX, which would then send the string to my jetson.

I did some research on my own but got a bit lost in all the API documentation of the nRF52840. After a while, I stumbled upon CircuitPython BLE libraries (https://learn.adafruit.com/circuitpytho ... r/overview) and BLE UART (https://learn.adafruit.com/circuitpytho ... rt-example) which sounds promising for my use-case.
Since it's my first Feather project and I'm quite new to the whole BLE world, I just wanted to be sure if that's the correct approach or if I'm heading in the completely wrong direction? Is there a similar example around achieving what I'm trying to do?

I'm very thankful for any help since I sadly don't have all the time in the world!

User avatar
neradoc
 
Posts: 542
Joined: Wed Apr 27, 2016 2:38 pm

Re: Communication setup between nRF52840 Express and Jetson

Post by neradoc »

Hi,
This code forwards the data received on UART to a UART BLE service.
I tested it working with the Adafruit Bluefruit Connect app, while the TX and RX pins were connected to another board repeatedly sending timestamps.
Note that it uses readline, which might or might not be what you need (you can remove it and uncomment the read line).
code.py
(1.18 KiB) Downloaded 2 times

Code: Select all

import board
import time
import busio

# setup UART
uart = busio.UART(board.TX, board.RX)

# setup bluetooth
from adafruit_bluefruit_connect.packet import Packet
from adafruit_bluefruit_connect.color_packet import ColorPacket
from adafruit_ble import BLERadio
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
from adafruit_ble.services.nordic import UARTService

ble = BLERadio()
ble.name = "UART With BLE"
uart_service = UARTService()
advertisement = ProvideServicesAdvertisement(uart_service)

was_connected = False
while True:
	# Advertise BLE when not connected.
	if not ble.connected:
		was_connected = False

		if not ble.advertising:
			print("Start advertising",time.monotonic())
			ble.start_advertising(advertisement, interval=0.5, timeout=5)

		# dismiss uart data when not connected
		if nbytes := uart.in_waiting:
			uart.reset_input_buffer()

	else:
		if not was_connected:
			was_connected = True
			print("Connected")
			ble.stop_advertising()

		# pass-through uart data when connected
		if nbytes := uart.in_waiting:
			# data = uart.read(nbytes)
			data = uart.readline()
			if data:
				print("Broadcasting", data)
				uart_service.write(data)

	time.sleep(0.1)
Note: if you have difficulty finding the board, you can to erase the Bluetooth pairings on the board by pressing reset then pressing again when the status LED blinks blue.

User avatar
elhari1
 
Posts: 6
Joined: Thu Apr 28, 2022 11:19 am

Re: Communication setup between nRF52840 Express and Jetson

Post by elhari1 »

Hi neradoc,

Thank you, I really appreciate your help! So it looks like CircuitPython is indeed the way to go, I'll install everything and give it a try asap.
This is probably an absolute basic question but just to be sure: So the code.py goes on the nRT52840, right? I assume that on the host side (jetson), the connection must be established. To do so, a code like this example should do the job, right? (example #2 on https://learn.adafruit.com/circuitpytho ... rt-example)

Code: Select all

from adafruit_ble import BLERadio
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
from adafruit_ble.services.nordic import UARTService

ble = BLERadio()

uart_connection = None

while True:
    if not uart_connection:
        print("Trying to connect...")
        for adv in ble.start_scan(ProvideServicesAdvertisement):
            if UARTService in adv.services:
                uart_connection = ble.connect(adv)
                print("Connected")
                break
        ble.stop_scan()

    if uart_connection and uart_connection.connected:
        uart_service = uart_connection[UARTService]
        while uart_connection.connected:
            s = input("Eval: ")
            uart_service.write(s.encode("utf-8"))
            uart_service.write(b'\n')
            print(uart_service.readline().decode("utf-8"))
By changing the last if-function of course.

Thank you!

User avatar
neradoc
 
Posts: 542
Joined: Wed Apr 27, 2016 2:38 pm

Re: Communication setup between nRF52840 Express and Jetson

Post by neradoc »

Oops I actually didn't think of what code you'd run on the computer !
That code would mostly do it, it doesn't seem to handle rescanning after a disconnection.

By the way, I was also trying to find a way to filter the devices found in case you have multiple UARTService around.
You can set advertisement.short_name (which is limited to 8 characters) and read it on the other side.
This is of course not secured in any way.

Those two scripts, one running on the feather and the other one on a Raspberry Pi were able to communicate and recover when either was reset, re-establishing the connection.

Code: Select all

import board
import time
import busio

# common configuration
SERVICE_NAME = "My GPS"

# setup UART
uart = busio.UART(board.TX, board.RX)

# setup bluetooth
from adafruit_bluefruit_connect.packet import Packet
from adafruit_bluefruit_connect.color_packet import ColorPacket
from adafruit_ble import BLERadio
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
from adafruit_ble.services.nordic import UARTService

ble = BLERadio()
ble.name = "My UART GPS board"
uart_service = UARTService()
advertisement = ProvideServicesAdvertisement(uart_service)
advertisement.short_name = SERVICE_NAME

was_connected = False
while True:
	# Advertise BLE when not connected.
	if not ble.connected:
		was_connected = False

		if not ble.advertising:
			print(f'Start advertising as "{SERVICE_NAME}"')
			ble.start_advertising(advertisement, interval=0.5, timeout=5)

		# dismiss uart buffer when not connected
		if uart.in_waiting:
			uart.reset_input_buffer()

	else:
		if not was_connected:
			was_connected = True
			print("Connected")
			ble.stop_advertising()

		# pass-through uart data when connected
		if nbytes := uart.in_waiting:
			# data = uart.read(nbytes)
			data = uart.readline()
			if data:
				print("Broadcasting", data)
				uart_service.write(data)

	time.sleep(0.1)
On the Computer:

Code: Select all

import time
from adafruit_ble import BLERadio
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
from adafruit_ble.services.nordic import UARTService

SERVICE_NAME = "My GPS"

ble = BLERadio()
uart_connection = None

while True:
	if not uart_connection or not uart_connection.connected:
		print(f'Trying to connect to "{SERVICE_NAME}"...')
		for adv in ble.start_scan(ProvideServicesAdvertisement):
			if UARTService in adv.services and adv.short_name == SERVICE_NAME:
				uart_connection = ble.connect(adv)
				print("Connected")
				break
		ble.stop_scan()

	if uart_connection and uart_connection.connected:
		uart_service = uart_connection[UARTService]
		if uart_BANNED_waiting:
			data = uart_service.readline().decode("utf-8").strip()
			if data:
				print(data)

	time.sleep(0.1)

User avatar
elhari1
 
Posts: 6
Joined: Thu Apr 28, 2022 11:19 am

Re: Communication setup between nRF52840 Express and Jetson

Post by elhari1 »

Hey neradoc,
Thanks again! In the last couple of hours, I tried establishing a connection between the nRF52840 and my Jetson Nano but both units seem to keep hanging in the searching/advertising loop. It looks like the problem could be the advertising part on the nRF52840. I feel like I need to change the ServiceAdvertising since I don't want to connect to the Bluefruit LE Connect App.
Do you have any idea that might solve this problem?

Best regards

User avatar
neradoc
 
Posts: 542
Joined: Wed Apr 27, 2016 2:38 pm

Re: Communication setup between nRF52840 Express and Jetson

Post by neradoc »

I'm not sure what could be the issue.
During tests I have had some issues with the code setting the advertisement name, you could remove the code setting and testing the short_name in case it's wonky.
You can also try resetting the board's pairings by pressing reset when the LED is blinking blue on boot.

As for the app, you just advertise the UART service, it does not relate to the app.
Still the app can be used to see if the board is properly advertising (without connecting to it).
You could always share your code to see if there's something we can spot.

User avatar
elhari1
 
Posts: 6
Joined: Thu Apr 28, 2022 11:19 am

Re: Communication setup between nRF52840 Express and Jetson

Post by elhari1 »

Ok, so I did some more testing and this is what I found out: On my Jetson Nano running Linux I didn't even detect the nRF52840, so I switched to my Laptop running Windows 11. There, the CIRCUITPY (nRF52840) board showed up as a Bluetooth device after advertising, so I tried connecting manually to it, which worked. After the nRF52840 prints "Connected" and the advertising stops, the code on my host computer, which runs in VSCode, is still in the loop and prints "Trying to connect to CircuitpyXXX". So it looks like that's where the code on my host computer keeps hanging.
Maybe the problem could indeed be setting the advertisement name?
Funny enough, I can't seem to detect the nRF52840 via the BluefruitConnect app on my phone. On my windows laptop, it works as I mentioned above.

Although I didn't change much, here's the code running on my devices:

nRF52840 board:

Code: Select all

import board
import time
import busio

# configuration
SERVICE_NAME = "CIRCUITPY070d"

# setup UART
uart = busio.UART(board.TX, board.RX)

# setup bluetooth
from adafruit_bluefruit_connect.packet import Packet
from adafruit_bluefruit_connect.color_packet import ColorPacket
from adafruit_ble import BLERadio
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
from adafruit_ble.services.nordic import UARTService

ble = BLERadio()
ble.name = "CIRCUITPY070d" # My UART-GNSS board
uart_service = UARTService()
advertisement = ProvideServicesAdvertisement(uart_service)
advertisement.short_name = SERVICE_NAME

was_connected = False
while True:
	# Advertise BLE when not connected.
	if not ble.connected:
		was_connected = False

		if not ble.advertising:
			print(f'Start advertising as "{SERVICE_NAME}"')
			ble.start_advertising(advertisement, interval=0.5, timeout=5)

		# dismiss uart data when not connected
		if uart.in_waiting: # otherwise: if nbytes := uart.in_waiting:
			uart.reset_input_buffer()


	else:
		if not was_connected:
			was_connected = True
			print("Connected")
			ble.stop_advertising()

		# send uart data when connected
		if nbytes := uart.in_waiting:
			# data = uart.read(nbytes)
			data = uart.readline()
			if data:
				print("Broadcasting", data)
				uart_service.write(data)

	time.sleep(0.1)
on my host laptop (windows / linux):

Code: Select all

from adafruit_ble import BLERadio
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
from adafruit_ble.services.nordic import UARTService
import time

# Establish BLE connection
SERVICE_NAME = "CIRCUITPY070d"

ble = BLERadio()
uart_connection = None

while True:
    if not uart_connection or not uart_connection.connected:
        print(f'Trying to connect to "{SERVICE_NAME}"')
        for adv in ble.start_scan(ProvideServicesAdvertisement):
            if UARTService in adv.services and adv.short_name == SERVICE_NAME:
                uart_connection = ble.connect(adv)
                print("Connected!")
                break
            ble.stop_scan()

    if uart_connection and uart_connection.connected:
        uart_service = uart_connection[UARTService]
        print("data dummy")
        if uart_BANNED_waiting:
            data = uart_service.readline().decode("utf-8").strip()
            if data:
                print(data)
    
    time.sleep(0.1)
Feel free to ask if you need more information

User avatar
neradoc
 
Posts: 542
Joined: Wed Apr 27, 2016 2:38 pm

Re: Communication setup between nRF52840 Express and Jetson

Post by neradoc »

There is one issue I see here, which is that the short_name can only be 8 characters long maximum.
When it's longer it should probably throw an exception or shorten it, but as it's implemented it seems the parameter is ignored and the short_name is None at the receiver end.

I tried using advertisement.complete_name instead of short_name, but if it was longer that 8 characters the advertisement was no longer seen. It seems that the library switches to "extended advertisements" because the whole data packet becomes longer than 31 bytes, and that might not work with the rest of the library, or with the example code as currently written at least.

So in short: try with a SERVICE_NAME of 8 characters or less.

User avatar
elhari1
 
Posts: 6
Joined: Thu Apr 28, 2022 11:19 am

Re: Communication setup between nRF52840 Express and Jetson

Post by elhari1 »

Hello neradoc,
First of all, I managed to establish the Bluetooth connection between my jetson nano and nRF52840. In the end, the short_name was too long as you suggested and it turned out, that my Bluetooth receiver plugged into my jetson wasn't compatible with Linux...

I have another question if you don't mind, maybe you can help me again:
I set up a UART connection between my nRF52840 and GPS module (simpleRTK2B from Ardusimple) to stream the NMEA messages to my Bluetooth device. To do so, I switched RX/TX on both boards, common GND and put IOREF to 3.3V.
The problem is, that the messages received by my Jetson are garbled:

DELETED OUTPUT

I set the baudrate on my nRF52840 and simpleRTK2B to 115200, but I'm not able to parse those messages because of the "wrong format". It looks like the messages are being separated incorrectly because the messages in brackets [] look cut off / not processed correctly.

Maybe you know something about that issue and can help me out!

Best regards

MOD EDIT:
Removed the GPS output. Will need to re-upload (with loc removed) if needed to help with continued troubleshooting.

User avatar
neradoc
 
Posts: 542
Joined: Wed Apr 27, 2016 2:38 pm

Re: Communication setup between nRF52840 Express and Jetson

Post by neradoc »

Hey, make sure that you are not sharing your actual GPS coordinates in your message.

Look at the data you transmit and check if you are transmitting the "\r\n" message end properly and not cutting it from the UART data when transmitting though BLE maybe ?
It does look like there's data missing though... hmmmm

Locked
Please be positive and constructive with your questions and comments.

Return to “General Project help”