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.
Install CircuitPython on Circuit Playground Bluefruit
Download the latest version of CircuitPython from the link below. If you need detailed help, follow these instructions.
Install CircuitPython on CLUE
Download the latest version of CircuitPython for CLUE from the link below. If you need detailed help, follow these instructions.
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 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 download 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.
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
Circuit Playground Bluefruit code.py
Download this file and copy it to CIRCUITPY, naming it code.py.
# 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
# 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
# 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
Text editor powered by tinymce.