Maker.io main logo

Using the Bluefruit Dashboard with Web Bluetooth in Chrome

2024-02-26 | By Adafruit Industries

License: See Original Project Bluetooth / BLE Circuit Playground

Courtesy of Adafruit

Guide by M. LeBlanc-Williams

Overview

Bluetooth LE (BLE) is a common way for mobile devices to connect ‎to accessories, watches, and toys. Getting that same connectivity on ‎the desktop has been really challenging - every platform does it ‎differently and it's still not very stable. Luckily, there's now a cross-‎platform way to connect to BLE devices on any computer - Web ‎Bluetooth lets you connect to BLE devices, right from your browser!‎

sensors_main_image

In this guide we'll show how you can test BLE devices from Adafruit ‎in the browser, streaming in sensor data, even controlling LEDs and ‎buzzers using the Adafruit Bluefruit Dashboard page.‎

It works by making a Bluetooth connection to a device, then it ‎queries which services are available and creates interactivity panels ‎in the dashboard for those services. The more services, the more ‎panels. So, the Circuit Playground Bluefruit will look different than ‎the Adafruit CLUE because the CLUE has more sensors. The ‎dashboard will then receive notifications from the Bluetooth device ‎and update the data on screen at regular intervals.‎

This guide will go over:‎

  • Installing the firmware
  • Preparing Chrome if you have Linux
  • Connecting to the dashboard and using it, and
  • Discuss taking the dashboard further

To get started, all you will need are a Bluetooth board with sensors ‎such as the Circuit Playground Bluefruit, Adafruit CLUE, or Feather ‎Bluefruit Sense.‎

Parts

Installing Firmware

The firmware that runs on your Bluetooth board is the same ‎firmware that is used with Bluefruit Playground. You may wish to ‎download the latest version below. There have been some recent ‎additions such as a quaternion service which allows you see a model ‎that is rotated in real time by the orientation of your board.‎

Download the Firmware

The first step is to download the firmware that is appropriate for your ‎board:‎

Download firmware for the Circuit Playground Bluefruit

Download firmware for the Feather Sense

Download firmware for the CLUE

Installing the Firmware

The file you downloaded is in the UF2 format, which makes ‎installation very easy. The procedure to install it is as follows:‎

install_1

  1. Connect a USB cable and put the power switch in the “on” ‎position‎
  2. Double tap the reset button‎
  3. Wait for the boot drive to appear! This will appear as a disk ‎drive with BOOT in the name‎
  4. Drag the UF2 file to the boot drive and wait for it to copy over‎
  5. The board will automatically reboot

Getting the Source Code

If you would like to find the source code, you will first need to install ‎the nRF52 Board Support Package. For more information, you can ‎follow the Arduino Support Setup page in our Introducing Adafruit ‎CLUE guide.‎

Once you have the package installed, select the appropriate board.‎

source_2

Open the example available at file→examples→Adafruit Bluefruit ‎nRF52 Libraries→Peripheral→bluefruit_playground.‎

source_3

CircuitPython

You can also use the Bluefruit Playground app and the Bluefruit ‎Bluetooth Web Dashboard with CircuitPython. There are ‎CircuitPython programs that do the same thing as the Arduino UF2s ‎listed in this Guide.‎

This firmware takes more effort to install, so we recommend the ‎Standalone Firmware UF2 for folks who just want to get started!‎

Install CircuitPython and Libraries

You'll need to install a version of CircuitPython and a number of ‎libraries specific to your board.‎

You need CircuitPython 6.0.0 or later. Version 5.3.1 will raise errors.‎

Install CircuitPython on Circuit Playground ‎Bluefruit

Download the latest version of CircuitPython from the link below. If ‎you need detailed help, follow these instructions.‎

play_4

Download CircuitPython for Circuit Playground Bluefruit from circuitpython.org

Install CircuitPython on CLUE

Download the latest version of CircuitPython for CLUE from the link ‎below. If you need detailed help, follow these instructions.‎

download_5

Download CircuitPython for CLUE from circuitpython.org

Install CircuitPython on Feather Bluefruit ‎Sense

Download the latest version of CircuitPython for Feather Bluefruit ‎Sense from the link below. If you need detailed help, follow these ‎instructions.‎

install_6

Download CircuitPython for Feather Bluefruit Sense

Install Libraries

Now you'll need to get the libraries. First download the library bundle ‎that matches your CircuitPython version from the link below. You'll ‎be downloading a zip file. Unzip the file, find the lib folder, and open ‎it. Then copy the libraries listed for your particular board to ‎the CIRCUITPY drive, which will show up when CircuitPython is ‎running.‎

Download the CircuitPython Library Bundle from circuitpython.org

Libraries for Circuit Playground Bluefruit

Copy these folders and files from the lib folder in the bundle to ‎the lib folder on CIRCUITPY. If you need detailed help, follow these ‎instructions. You may already have many of these libraries if you are ‎already using CircuitPython on the board, but make sure they are up ‎to date, particularly the BLE-related libraries.‎

  • adafruit_ble
  • adafruit_ble_adafruit (you may not have this already)
  • adafruit_circuitplayground
  • adafruit_lis3dh.mpy
  • adafruit_thermistor.mpy
  • neopixel.mpy‎ ‎

Libraries for CLUE and Feather Bluefruit ‎Sense

These boards have the same sensors, so the libraries you need are ‎the same. Copy these folders and files from the lib folder in the ‎bundle to the lib folder on CIRCUITPY. If you need detailed help, ‎follow these instructions. You may already have many of these ‎libraries if you are already using CircuitPython on the board, but ‎make sure they are up to date, particularly the BLE-related libraries.‎

  • adafruit_apds9960‎
  • adafruit_ble
  • adafruit_ble_adafruit (you may not have this already)
  • adafruit_bmp280.mpy
  • adafruit_bus_device
  • adafruit_clue.mpy
  • adafruit_lis3mdl.mpy
  • adafruit_lsm6ds.mpy
  • adafruit_register
  • adafruit_sht31d.mpy
  • neopixel.mpy

Add code.py

Finally, you'll add a code.py file that will talk to the Bluefruit ‎Playground app.‎

Circuit Playground Bluefruit code.py

Download this file and copy it to CIRCUITPY, naming it code.py.‎

Download Project Bundle

Copy Code
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT

# Adafruit Service demo for Adafruit CLUE Circuit Playground Bluefruit board.
# Accessible via Adafruit Bluefruit Playground app and Web Bluetooth Dashboard.

import time

import board
from digitalio import DigitalInOut
import neopixel_write

from adafruit_ble import BLERadio

from adafruit_circuitplayground import cp

from adafruit_ble_adafruit.adafruit_service import AdafruitServerAdvertisement

from adafruit_ble_adafruit.accelerometer_service import AccelerometerService
from adafruit_ble_adafruit.addressable_pixel_service import AddressablePixelService
from adafruit_ble_adafruit.button_service import ButtonService
from adafruit_ble_adafruit.light_sensor_service import LightSensorService
from adafruit_ble_adafruit.temperature_service import TemperatureService
from adafruit_ble_adafruit.tone_service import ToneService

accel_svc = AccelerometerService()
accel_svc.measurement_period = 100
accel_last_update = 0

# 3 RGB bytes * 10 pixels.
NEOPIXEL_BUF_LENGTH = 3 * 10
neopixel_svc = AddressablePixelService()
neopixel_buf = bytearray(NEOPIXEL_BUF_LENGTH)
# Take over NeoPixel control from cp.
cp._pixels.deinit() # pylint: disable=protected-access
neopixel_out = DigitalInOut(board.NEOPIXEL)
neopixel_out.switch_to_output()

button_svc = ButtonService()
button_svc.set_pressed(cp.switch, cp.button_a, cp.button_b)

light_svc = LightSensorService()
light_svc.measurement_period = 100
light_last_update = 0

temp_svc = TemperatureService()
temp_svc.measurement_period = 100
temp_last_update = 0

tone_svc = ToneService()

ble = BLERadio()
# The Web Bluetooth dashboard identifies known boards by their
# advertised name, not by advertising manufacturer data.
ble.name = "CPlay"

# The Bluefruit Playground app looks in the manufacturer data
# in the advertisement. That data uses the USB PID as a unique ID.
# Adafruit Circuit Playground Bluefruit USB PID:
# Arduino: 0x8045, CircuitPython: 0x8046, app supports either
adv = AdafruitServerAdvertisement()
adv.pid = 0x8046

while True:
# Advertise when not connected.
ble.start_advertising(adv)
while not ble.connected:
pass
ble.stop_advertising()

while ble.connected:
now_msecs = time.monotonic_ns() // 1000000 # pylint: disable=no-member

if now_msecs - accel_last_update >= accel_svc.measurement_period:
accel_svc.acceleration = cp.acceleration
accel_last_update = now_msecs

button_svc.set_pressed(cp.switch, cp.button_a, cp.button_b)

if now_msecs - light_last_update >= light_svc.measurement_period:
light_svc.light_level = cp.light
light_last_update = now_msecs

neopixel_values = neopixel_svc.values
if neopixel_values is not None:
start = neopixel_values.start
if start > NEOPIXEL_BUF_LENGTH:
continue
data = neopixel_values.data
data_len = min(len(data), NEOPIXEL_BUF_LENGTH - start)
neopixel_buf[start : start + data_len] = data[:data_len]
if neopixel_values.write_now:
neopixel_write.neopixel_write(neopixel_out, neopixel_buf)

if now_msecs - temp_last_update >= temp_svc.measurement_period:
temp_svc.temperature = cp.temperature
temp_last_update = now_msecs

tone = tone_svc.tone
if tone is not None:
freq, duration_msecs = tone
if freq != 0:
if duration_msecs != 0:
# Note that this blocks. Alternatively we could
# use now_msecs to time a tone in a non-blocking
# way, but then the other updates might make the
# tone interval less consistent.
cp.play_tone(freq, duration_msecs / 1000)
else:
cp.stop_tone()
cp.start_tone(freq)
else:
cp.stop_tone()
last_tone = tone

View on GitHub

CLUE code.py

Download this file and copy it to CIRCUITPY, naming it code.py.‎

Download Project Bundle

Copy Code
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT

# Adafruit Service demo for Adafruit CLUE board.
# Accessible via Adafruit Bluefruit Playground app and Web Bluetooth Dashboard.

import time

import board
from digitalio import DigitalInOut
import neopixel_write
from adafruit_ble import BLERadio

from ulab import numpy as np

from adafruit_clue import clue

from adafruit_ble_adafruit.adafruit_service import AdafruitServerAdvertisement

from adafruit_ble_adafruit.accelerometer_service import AccelerometerService
from adafruit_ble_adafruit.addressable_pixel_service import AddressablePixelService
from adafruit_ble_adafruit.barometric_pressure_service import BarometricPressureService
from adafruit_ble_adafruit.button_service import ButtonService
from adafruit_ble_adafruit.humidity_service import HumidityService
from adafruit_ble_adafruit.light_sensor_service import LightSensorService
from adafruit_ble_adafruit.microphone_service import MicrophoneService
from adafruit_ble_adafruit.temperature_service import TemperatureService
from adafruit_ble_adafruit.tone_service import ToneService

accel_svc = AccelerometerService()
accel_svc.measurement_period = 100
accel_last_update = 0

# CLUE has just one board pixel. 3 RGB bytes * 1 pixel.
NEOPIXEL_BUF_LENGTH = 3 * 1
neopixel_svc = AddressablePixelService()
neopixel_buf = bytearray(NEOPIXEL_BUF_LENGTH)
# Take over NeoPixel control from clue.
clue._pixel.deinit() # pylint: disable=protected-access
neopixel_out = DigitalInOut(board.NEOPIXEL)
neopixel_out.switch_to_output()

baro_svc = BarometricPressureService()
baro_svc.measurement_period = 100
baro_last_update = 0

button_svc = ButtonService()
button_svc.set_pressed(False, clue.button_a, clue.button_b)

humidity_svc = HumidityService()
humidity_svc.measurement_period = 100
humidity_last_update = 0

light_svc = LightSensorService()
light_svc.measurement_period = 100
light_last_update = 0

# Send 256 16-bit samples at a time.
MIC_NUM_SAMPLES = 256
mic_svc = MicrophoneService()
mic_svc.number_of_channels = 1
mic_svc.measurement_period = 100
mic_last_update = 0
mic_samples = np.zeros(MIC_NUM_SAMPLES, dtype=np.uint16)

temp_svc = TemperatureService()
temp_svc.measurement_period = 100
temp_last_update = 0

tone_svc = ToneService()

ble = BLERadio()
# The Web Bluetooth dashboard identifies known boards by their
# advertised name, not by advertising manufacturer data.
ble.name = "CLUE"

# The Bluefruit Playground app looks in the manufacturer data
# in the advertisement. That data uses the USB PID as a unique ID.
# Adafruit CLUE USB PID:
# Arduino: 0x8071, CircuitPython: 0x8072, app supports either
adv = AdafruitServerAdvertisement()
adv.pid = 0x8072

while True:
# Advertise when not connected.
ble.start_advertising(adv)
while not ble.connected:
pass
ble.stop_advertising()

while ble.connected:
now_msecs = time.monotonic_ns() // 1000000 # pylint: disable=no-member

if now_msecs - accel_last_update >= accel_svc.measurement_period:
accel_svc.acceleration = clue.acceleration
accel_last_update = now_msecs

if now_msecs - baro_last_update >= baro_svc.measurement_period:
baro_svc.pressure = clue.pressure
baro_last_update = now_msecs

button_svc.set_pressed(False, clue.button_a, clue.button_b)

if now_msecs - humidity_last_update >= humidity_svc.measurement_period:
humidity_svc.humidity = clue.humidity
humidity_last_update = now_msecs

if now_msecs - light_last_update >= light_svc.measurement_period:
# Return "clear" color value from color sensor.
light_svc.light_level = clue.color[3]
light_last_update = now_msecs

if now_msecs - mic_last_update >= mic_svc.measurement_period:
clue._mic.record( # pylint: disable=protected-access
mic_samples, len(mic_samples)
)
# Need to create an array of the correct type, because ulab
# seems to get broadcasting of builtin Python types wrong.
offset = np.array([32768], dtype=np.uint16)
# This subtraction yields unsigned values which are
# reinterpreted as signed after passing.
mic_svc.sound_samples = mic_samples - offset
mic_last_update = now_msecs

neopixel_values = neopixel_svc.values
if neopixel_values is not None:
start = neopixel_values.start
if start > NEOPIXEL_BUF_LENGTH:
continue
data = neopixel_values.data
data_len = min(len(data), NEOPIXEL_BUF_LENGTH - start)
neopixel_buf[start : start + data_len] = data[:data_len]
if neopixel_values.write_now:
neopixel_write.neopixel_write(neopixel_out, neopixel_buf)

if now_msecs - temp_last_update >= temp_svc.measurement_period:
temp_svc.temperature = clue.temperature
temp_last_update = now_msecs

tone = tone_svc.tone
if tone is not None:
freq, duration_msecs = tone
if freq != 0:
if duration_msecs != 0:
# Note that this blocks. Alternatively we could
# use now_msecs to time a tone in a non-blocking
# way, but then the other updates might make the
# tone interval less consistent.
clue.play_tone(freq, duration_msecs / 1000)
else:
clue.stop_tone()
clue.start_tone(freq)
else:
clue.stop_tone()
last_tone = tone

View on GitHub

Feather Bluefruit Sense code.py

Download Project Bundle

Copy Code
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT

# Adafruit Service demo for Adafruit Feather Bluefruit Sense board.
# Accessible via Adafruit Web Bluetooth Dashboard.
# (As of this writing, not yet accessible via Bluefruit Playground app.)

import time

import board

import digitalio
import neopixel_write

from ulab import numpy as np

from adafruit_ble import BLERadio

import audiobusio

import adafruit_apds9960.apds9960
import adafruit_bmp280
import adafruit_lsm6ds.lsm6ds33
import adafruit_sht31d

from adafruit_ble_adafruit.adafruit_service import AdafruitServerAdvertisement

from adafruit_ble_adafruit.accelerometer_service import AccelerometerService
from adafruit_ble_adafruit.addressable_pixel_service import AddressablePixelService
from adafruit_ble_adafruit.barometric_pressure_service import BarometricPressureService
from adafruit_ble_adafruit.button_service import ButtonService
from adafruit_ble_adafruit.humidity_service import HumidityService
from adafruit_ble_adafruit.light_sensor_service import LightSensorService
from adafruit_ble_adafruit.microphone_service import MicrophoneService
from adafruit_ble_adafruit.temperature_service import TemperatureService

# Accelerometer
lsm6ds33 = adafruit_lsm6ds.lsm6ds33.LSM6DS33(board.I2C())
# Used for pressure and temperature.
bmp280 = adafruit_bmp280.Adafruit_BMP280_I2C(board.I2C())
# Humidity.
sht31d = adafruit_sht31d.SHT31D(board.I2C())
# Used only for light sensor
apds9960 = adafruit_apds9960.apds9960.APDS9960(board.I2C())
apds9960.enable_color = True

mic = audiobusio.PDMIn(
board.MICROPHONE_CLOCK,
board.MICROPHONE_DATA,
sample_rate=16000,
bit_depth=16,
)

# Create and initialize the available services.

accel_svc = AccelerometerService()
accel_svc.measurement_period = 100
accel_last_update = 0

# Feather Bluefruit Sense has just one board pixel. 3 RGB bytes * 1 pixel
NEOPIXEL_BUF_LENGTH = 3 * 1
neopixel_svc = AddressablePixelService()
neopixel_buf = bytearray(NEOPIXEL_BUF_LENGTH)
neopixel_out = digitalio.DigitalInOut(board.NEOPIXEL)
neopixel_out.switch_to_output()

baro_svc = BarometricPressureService()
baro_svc.measurement_period = 100
baro_last_update = 0

button_svc = ButtonService()
button = digitalio.DigitalInOut(board.SWITCH)
button.pull = digitalio.Pull.UP
button_svc.set_pressed(False, not button.value, False)

humidity_svc = HumidityService()
humidity_svc.measurement_period = 100
humidity_last_update = 0

light_svc = LightSensorService()
light_svc.measurement_period = 100
light_last_update = 0

# Send 256 16-bit samples at a time.
MIC_NUM_SAMPLES = 256
mic_svc = MicrophoneService()
mic_svc.number_of_channels = 1
mic_svc.measurement_period = 100
mic_last_update = 0
mic_samples = np.zeros(MIC_NUM_SAMPLES, dtype=np.uint16)

temp_svc = TemperatureService()
temp_svc.measurement_period = 100
temp_last_update = 0

ble = BLERadio()
# The Web Bluetooth dashboard identifies known boards by their
# advertised name, not by advertising manufacturer data.
ble.name = "Sense"

# The Bluefruit Playground app looks in the manufacturer data
# in the advertisement. That data uses the USB PID as a unique ID.
# Feather Bluefruit Sense USB PID:
# This board is not yet support on the app.
# Arduino: 0x8087, CircuitPython: 0x8088
adv = AdafruitServerAdvertisement()
adv.pid = 0x8088

while True:
# Advertise when not connected.
ble.start_advertising(adv)
while not ble.connected:
pass
ble.stop_advertising()

while ble.connected:
now_msecs = time.monotonic_ns() // 1000000 # pylint: disable=no-member

if now_msecs - accel_last_update >= accel_svc.measurement_period:
accel_svc.acceleration = lsm6ds33.acceleration
accel_last_update = now_msecs

if now_msecs - baro_last_update >= baro_svc.measurement_period:
baro_svc.pressure = bmp280.pressure
baro_last_update = now_msecs

button_svc.set_pressed(False, not button.value, False)

if now_msecs - humidity_last_update >= humidity_svc.measurement_period:
humidity_svc.humidity = sht31d.relative_humidity
humidity_last_update = now_msecs

if now_msecs - light_last_update >= light_svc.measurement_period:
# Return "clear" color value from color sensor.
light_svc.light_level = apds9960.color_data[3]
light_last_update = now_msecs

if now_msecs - mic_last_update >= mic_svc.measurement_period:
mic.record(mic_samples, len(mic_samples))
# This subtraction yields unsigned values which are
# reinterpreted as signed after passing.
mic_svc.sound_samples = mic_samples - 32768
mic_last_update = now_msecs

neopixel_values = neopixel_svc.values
if neopixel_values is not None:
start = neopixel_values.start
if start > NEOPIXEL_BUF_LENGTH:
continue
data = neopixel_values.data
data_len = min(len(data), NEOPIXEL_BUF_LENGTH - start)
neopixel_buf[start : start + data_len] = data[:data_len]
if neopixel_values.write_now:
neopixel_write.neopixel_write(neopixel_out, neopixel_buf)

if now_msecs - temp_last_update >= temp_svc.measurement_period:
temp_svc.temperature = bmp280.temperature
temp_last_update = now_msecs

View on GitHub

Preparing Chrome

If you are using a recent version of Chrome with Windows or MacOS, ‎you should be good to go. To use Chrome with Web Bluetooth on ‎Linux will require a little more preparation. If you visit the dashboard ‎at https://adafruit-webbt-playground.glitch.me/ and see a message ‎stating that Web Bluetooth is not supported, this is how to fix it.‎

preparing_7

In the address bar for Chrome, type chrome://flags and press enter. ‎This will take you to the internal Chrome flags settings. In the search ‎box, type in enable-experimental-web-platform-features and you ‎should see only one result.‎

address_8

Change disabled to enabled and click the Relaunch button.‎

change_9

That's it! You should be ready to go.‎

Using the Dashboard

The dashboard is a pure JavaScript application that starts by ‎connecting to your board, then it queries which Bluetooth services ‎are supported, and dynamically generates the dashboard to only ‎show the services that are available. You can get to the dashboard ‎by navigating in Chrome ‎to https://adafruit.github.io/Adafruit_WebBluetooth_Dashboard/ or clicking ‎the button below.‎

Open the Web Bluetooth Dashboard

dashboard_10

Connecting

Connecting to the dashboard is pretty simple. Just click on the ‎button marked Connect. A dialog should come up showing you the ‎various Bluetooth Connections that are available.‎

connecting_11

By default, it will show only known boards. However, if you have a ‎different board, you can uncheck Show only known devices and it ‎will show you everything it detects.‎

webbt_12

Once you are connected, you should several panels appear. The ‎exact number depends on the board and firmware you are using. Try ‎playing around with the board and see what happens.‎

panels_13

Types of Panels

There are several different kinds of panels, and they are designed for ‎different purposes. Some types of data can be displayed on different ‎types of panels. For instance, sensor data could either be displayed ‎with a text panel, which will show the latest values, or it can be ‎graphed with a graph panel.‎

Text Panels

Text panels are your basic panel which will show the data value as ‎text. For each panel, a format field is applied so that it shows up in a ‎more meaningful way. At this time, no text panels are being used. ‎They are useful as a basis for testing new sensors.‎

text_14

Graph Panels

Graph panels allow you to display the data as a graph. It can show ‎either one data dataset as with the temperature or it can show ‎multiple datasets such as with the accelerometer. The latest data ‎will always show in the top half of the panel as indicated by the ‎circles.‎

graph_15

Color Panels

Color panels are designed for changing the color of NeoPixel LEDs. ‎They are less flexible than most of the other panels due to their need ‎to be pretty specific. It's possible to have multiple color pickers that ‎each change the same set of NeoPixels.‎

color_16

3D Panels

The 3D panel is meant for displaying the orientation of the board and ‎is also pretty inflexible since there is only one quaternion service, and ‎this displays the data from there.

panels_17

Custom Panels

The custom panel is for unique panels that are primarily used by a ‎single sensor that have controls that are unlike other panels. The ‎battery and tone panels are custom panels because of it made more ‎sense to go this route.

custom_18

Available Panels

There are over a dozen different panels currently available. These ‎panels are:‎

Battery

This will display the battery percentage as both a graphic and text. ‎The color of the battery will change depending on the charge level.‎

Temperature

This will display the current temperature in Celsius in a graph.‎

Light

This will display the current light level in a graph.‎

Accelerometer

This will display the X, Y, and Z axes in meters/second2 a graph.‎

Gyroscope

On older versions of the firmware, this will display the Gyroscope ‎values X, Y, and Z axes in radians in a graph.‎

Magnetometer

On older versions of the firmware, this will display the Magnetometer ‎values X, Y, and Z axes in micro-Teslas in a graph.‎

Buttons

This will display the current button or buttons as a graphical ‎representation The number of buttons displayed depends on the ‎type of board connected.‎

Switch

This will display the current switch position as a graphical ‎representation if the current board has a switch. This is tied into the ‎button service.‎

Humidity

This will display the relative humidity as a percentage in a graph.‎

Barometric Pressure

This will display the Barometric Pressure in hectoPascals.‎

Tone

Clicking the button in this panel will play a 440Hz tone for 1 second.‎

NeoPixel

This will give you a color picker and changing the color will change ‎the color of the NeoPixel LED(s) on the board. On the Circuit ‎Playground Bluefruit, it will light up the entire ring of NeoPixels.‎

3D Model‎

This will display a bunny and changing the orientation of the board ‎should change the orientation of the bunny.‎

The Log

At the bottom of the page is a log that will show you some of the ‎device information including some of the services and ‎characteristics that were found when the device connected as well ‎as messages about connecting and disconnecting.‎

log_19

There are a few other controls such as AutoScroll, which will ‎automatically scroll the log, Show Timestamp, which will print a ‎timestamp beside every line in the log, and a Clear Text button. The ‎Clear Text button will clear any data that has transferred but keep ‎the connection open. The application is targeting 30 frames per ‎second. It can actually run faster than this, but slowing it down gives ‎the browser time enough to respond to notifications.‎

Dark Mode

Finally, let's not forget about Dark Mode. The dashboard supports a ‎couple of different color themes, which are light and dark mode, and ‎you can alternate between them by checking and unchecking the ‎Dark Mode checkbox. As you can tell by the screenshots in this guide, ‎we like dark mode.‎

Taking it Further

We recently moved the Web Bluetooth dashboard from a service ‎called glitch over to GitHub pages. While not as easy to create a copy ‎as glitch, you can fork the repository to your own GitHub account or ‎submit Pull Requests to enhance the dashboard.‎

Adding new boards

In the code, you will find an object that defines the boards with a few ‎different options. Adding a new board is pretty easy with just a few ‎options such as the number of NeoPixels, the color order for ‎NeoPixels and whether it has a switch.‎

Adding new panels

Adding new panels is similar to adding a new board, but there are a ‎few more options. If you want to use one of the existing panel types, ‎all you need to do is add a new entry to the panels and it should ‎automatically appear, provided your board has a service and ‎characteristic that matches what you define.‎

Making it better

If you do remix the dashboard and make it even better, please let us ‎know. We would love to see what you've done with it and maybe we ‎can even incorporate some of your improvements in our dashboard.

制造商零件编号 4500
CLUE NRF52840 EXPRESS
Adafruit Industries LLC
¥365.90
Details
制造商零件编号 4333
CIRCUIT PLAYGROUND BLUEFRUIT BLE
Adafruit Industries LLC
¥203.09
Details
制造商零件编号 4516
FEATHER NRF52840 SENSE
Adafruit Industries LLC
¥321.53
Details
制造商零件编号 592
CABLE A PLUG TO MCR B PLUG 3'
Adafruit Industries LLC
¥24.01
Details
Add all DigiKey Parts to Cart
TechForum

Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.

Visit TechForum