Seeking product for bluetooth transmission of Sensor - BNO85

Hi there,

I’m seeking a product for bluetooth/wifi transmission of information from a sensor - BNO85 to a pico w. Ideally a small and simple set up, it will be used for wearable applications.

The end goal is to have 4 BNO85’s communicating via bluetooth/wifi to the Pico W.

2 Likes

Hi @Mitchell258024,

I think you’ll find this forum post very helpful!

The basics of this setup is having a Pico W act as a WiFi Access Point and another connect to it over WiFi. It will require a bit of modification of the code to get it working but it is really well laid out with lots of good error handling.

Hope this is a good starting point for your project

2 Likes

Thanks Aaron,

Is it possible to connect 4x Pico Ws to a Pico W via WiFi and have accurate data reading?

2 Likes

It’s certainly possible. Stay tuned for the next chapter of our Raspberry Pi Pico workshop where we will cover wireless features of the Pico W

4 Likes

Hey Mitchell,

What’s your definition of accurate data reading for this project? Do you have an idea of what the data would look like that you intend to transfer between these Pico’s?

It seems like the forum post that Aaron linked contains information to get this working between 2 Pico W’s but I can’t see why you couldn’t set this up to work with additional Pico’s if you are comfortable building off James46717’s code.

2 Likes

Accuracy of data transfer via WiFi would be the routine that checks the data as it comes in and detection of missing packets and asking for retransmission. Basically its a comms messaging system of which many have been created over the years. WiFi itself is pretty accurate for a data transmission system, it has built in checking and rejecting of invalid data. (or it should have, don’t know how good the micropython implementation is)

If you are just sending data I’d look at the PiicoDev TX/RX board. I have used it in a number of projects, it is simple and very easy to use. WiFi adds a complexity level you may not need.

As far as multiple Pico’s on the same WiFi network, it should not be a problem. As long as different IP Addresses are assigned to each Pico.

Cheers
Jim

2 Likes

Hi Samuel,

I am syncing the orientation of the IMU to the intensity of a vibration of a coin motor. When working via Wifi the data frequency as measured via the vibration feel is not responsive enough. When moving the IMU in a wired set up, a feeling of a gradual increase of vibration is felt when moving say from 0deg-100deg=0%-100% vibration intensity, over 0.3seconds. Where as over wifi there are noticeable steps in vibration in the Wifi setup (e.g; 0%, 25%, 50%, 75%, 100%). Is there a way to improve the response speed? Would bluetooth be a suitable options?..

RE Bluetooth: I’m having difficulty as the Pico Ws bluetooth doesn’t support circuit python and it seems the BNO8x may not support micro python? I am not able to find the supporting libraries I need

1 Like

Working receiver code:

import wifi
import socketpool
import time
import board
import busio

Set up the Pico W as an Access Point

ssid = ‘PicoW_AP’
password = ‘12345678’

wifi.radio.start_ap(ssid, password)
print(‘Access Point created with SSID:’, ssid)

Wait for the AP to be active

while not wifi.radio.ap_active:
time.sleep(1)

print(‘Access Point is active’)

Set up the server socket

pool = socketpool.SocketPool(wifi.radio)
server = pool.socket(pool.AF_INET, pool.SOCK_STREAM)
server.bind((“0.0.0.0”, 12345))
server.listen(1)
print(“Server listening on 0.0.0.0:12345”)

while True:
cl, addr = server.accept()
print(‘Client connected from’, addr)

# Receive data from the client
while True:
    try:
        data = bytearray(1024)
        num_bytes = cl.recv_into(data)
        if num_bytes == 0:
            break
        print("R:", data[:num_bytes].decode())
    except OSError as e:
        if e.args[0] == 28:  # If the buffer is full, continue receiving
            continue
        else:
            raise

cl.close()
print('Client disconnected')

motor1 = pwmio.PWMOut(board.GP14, frequency=5000, duty_cycle=0)
overdrive_applied1 = False # Flag to track if overdrive has been applied for motor 1

# Motor 1: Apply overdrive when y rotates below 0

if not overdrive_applied1 and x < 0:
motor1.duty_cycle = 65535 # Apply overdrive (full PWM)
time.sleep(0.02) # Apply for 20 ms
overdrive_applied1 = True # Set overdrive flag
elif x >= 0: # Reset overdrive flag when y goes above or equal to 0
overdrive_applied1 = False

# Calculate duty cycle based on absolute calculated y value for motor 2

duty1 = int(320675 * abs(x) + 14000)
duty1 = max(0, min(duty1, 65535)) # Clamp duty cycle to valid range

# Apply calculated duty cycle for motor 1

motor1.duty_cycle = duty1 if x < 0 else 0 # Only apply if calculated y is negative

2 Likes

Working sender code:

import wifi
import socketpool
import time
import board
import busio
import adafruit_bno08x
from adafruit_bno08x.i2c import BNO08X_I2C
from adafruit_bno08x import (
BNO_REPORT_ACCELEROMETER,
BNO_REPORT_GYROSCOPE,
BNO_REPORT_MAGNETOMETER,
BNO_REPORT_ROTATION_VECTOR,
)
import adafruit_requests

AP credentials

SSID = ‘PicoW_AP’
PASSWORD = ‘12345678’

Connect to the AP

wifi.radio.connect(SSID, PASSWORD)
print(“Connected to AP, IP address:”, wifi.radio.ipv4_address)

Server address (AP’s IP address)

SERVER_IP = ‘192.168.4.1’ # Default IP for Pico W AP
SERVER_PORT = 12345

Function definitions

def quaternion_to_rotation_matrix(w, x, y, z):
r = [[0]3 for _ in range(3)]
r[0][0] = 1 - 2
(yy + zz)
r[0][1] = 2*(xy - wz)
r[0][2] = 2*(xz + wy)
r[1][0] = 2*(xy + wz)
r[1][1] = 1 - 2*(xx + zz)
r[1][2] = 2*(yz - wx)
r[2][0] = 2*(xz - wy)
r[2][1] = 2*(yz + wx)
r[2][2] = 1 - 2*(xx + yy)
return r

def rotate_vector_by_matrix(vector, matrix):
result = [0]*3
for i in range(3):
for j in range(3):
result[i] += vector[j] * matrix[j][i]
return result

def get_compass_direction(rotated_x, rotated_y):
angle_rad = math.atan2(rotated_y, rotated_x)
angle_deg = math.degrees(angle_rad)
if angle_deg < 0:
angle_deg += 360
compass_direction = (90 - angle_deg) % 360
return compass_direction

Initialize IMU

i2c = busio.I2C(board.GP27, board.GP26, frequency=800000)
bno = BNO08X_I2C(i2c, address=0x4A)

bno.enable_feature(BNO_REPORT_ACCELEROMETER)
bno.enable_feature(BNO_REPORT_GYROSCOPE)
bno.enable_feature(BNO_REPORT_MAGNETOMETER)
bno.enable_feature(BNO_REPORT_ROTATION_VECTOR)

Set up the client socket

pool = socketpool.SocketPool(wifi.radio)
sock = pool.socket(pool.AF_INET, pool.SOCK_STREAM)
sock.connect((SERVER_IP, SERVER_PORT))

while True:
quat_i, quat_j, quat_k, quat_real = bno.quaternion
rotation_matrix = quaternion_to_rotation_matrix(quat_real, quat_i, quat_j, quat_k)

unit_x = [1, 0, 0]
unit_y = [0, 1, 0]
unit_z = [0, 0, 1]

rotated_x = rotate_vector_by_matrix(unit_x, rotation_matrix)[0]
rotated_y = rotate_vector_by_matrix(unit_y, rotation_matrix)[0]
rotated_z = rotate_vector_by_matrix(unit_z, rotation_matrix)[0]

message = "Values: X: {:.2f}, Y: {:.2f}, Z: {:.2f}".format(rotated_x, rotated_y, rotated_z)
print(message)
sock.send(message.encode())

I am syncing the orientation of the IMU to the intensity of a vibration of a coin motor. When working via Wifi the data frequency as measured via the vibration feel is not responsive enough. When moving the IMU in a wired set up, a feeling of a gradual increase of vibration is felt when moving say from 0deg-100deg=0%-100% vibration intensity, over 0.3seconds. Where as over wifi there are noticeable steps in vibration in the Wifi setup (e.g; 0%, 25%, 50%, 75%, 100%). Is there a way to improve the response speed? Would bluetooth be a suitable options?..

RE Bluetooth: I’m having difficulty as the Pico Ws bluetooth doesn’t support circuit python and it seems the BNO8x may not support micro python? I am not able to find the supporting libraries I need

WiFi is a packet technology and not really good enough for what you are trying to do. I don’t think you will get it any better due to how WiFi works.

Yep, the two iterations of python for the Pico W do not support Bluetooth. You could use C++ but that would mean writing a Bluetooth driver to suit the Pico W.

Suggest you look at the PiicoDev TX/RX board I mentioned before. It would allow instantaneous transmission of data. It would then be up to your program to react fast enough.

Regards
Jim

1 Like

Hey Mitchell,

It seems you have a great idea here, its just getting it realised for your project! Is there any reason you specifically need to use a Pi Pico for this one? I feel if you use something like the ESP32-S3/C3 you can use Bluetooth 5 as a standard integration into your project and even possibly use a mesh network protocol for this to have multiple devices interconnected.

Cheers,
Blayden

3 Likes

Thanks Blayden,

No reason I specifically need to use a Pi Pico.

Adafruit does warn: “The BNO08x I2C implementation violates the I2C protocol in some circumstances. This causes it not to work well with certain chip families. It does not work well with Espressif ESP32, ESP32-S3”. So I assume that includes the ESP32-C3.

I did read some potential work arounds, though think I will try the PicoDev Tranceiver-915mhz

1 Like

Great, thanks James.

And the picoDev TX/RX will be able to receive inputs from 4 other picoDev TX/RXs?

Or even better could the picoDev TX/RX be able to receive inputs from 4 other picoDev TX/RXs with 2 of these transceivers also sending to a different picoDev TX/RXs?

3 Likes

Each PiicoDev TX/RX can be part of a group with a unique radio address ID. The guide gives a beginners indication of what is possible. My weather station has one RX unit and 2 TX units. Works nicely. The main issue is 2 transmitting at the same time. The message would be garbled at the receiver. This can be solved by polling each unit. For my TX units to not transmit at the same time one listens for the other and sends after the other has finished.

You can make it as complex as you want within the timing limitations you have. Using different frequencies you can have separate TX/RX networks.

Another application I used them for was a joystick controller and and remote robot cart. I haven’t checked the latency but pressing a button on the controller the indicator on the cart responds immediately.

WiFi and Bluetooth add a complexity level that may not be desirable for your application. Previously I have used WiFi and Bluetooth for control, setup is not as easy as the TX/RX boards. Suggest getting a couple of boards and experiment.

Cheers
Jim

5 Likes

Hi Mitchell,

Jims spot on about the topography and definitely has one of the best examples I’ve seen of using them.

Out of the box you cant directly send data with a system like this:

Each system needs a microcontroller (like the bottom devices) to handle the I2C transactions.
If you want to spend some more time making this a bit cleaner you could re-program the MCU on the transceiver module to handle this themselves (but would take some work).

PS: Noting your other topic on selling a product - most of the parts Core sells are hobby level parts with no certification documents.
There is a big difference selling a hobbyist system (DIY themselves, they accept and understand the risks in making it themselves)
and a commercial product, if you’re keen on looking to make this a commercial project it might be worth investing or at least talking to an engineering consultancy - Saphi is one example based in Newcastle where Core is

4 Likes

Hi Mitchell,

James has a great answer and has linked our guide so I suggest reading both of those. In the guide we explore how you can specify which Pico/s to send commands to.

2 Likes

Could I use SPI or UART wiring to communicate between BNO85s and ESP32 and then transmit via bluetooth?

2 Likes

You certainly can. Here’s a guide on setting up Bluetooth and sending data. You’ll just need to make sure that you’re sending data in a way where your receiver board can understand it.

1 Like

Will that I use CircuitPython be an issue with using the PicoDev Transceiver? As the BNO85 is supported by CircuitPython, I am using it

1 Like