The client code requires the following libraries from the CircuitPython Bundle:
- adafruit_ble
- adafruit_bluefruit_connect
- adafruit_debouncer
- adafruit_fancyled
- neopixel
The latest version can be obtained from the Adafruit CircuitPython BLE repo.
Plug in one Feather nRF52840 to your computer via a known good USB data + power cable. The board should show up as a disk drive named CIRCUITPY. Use this guide to update CircuitPython - you will want the latest version 5.0 or above.
Copy the 5 libraries to the lib folder on the Feather.
Here's the client code for the BLE peripheral. Click the download link and save to your computer. Then copy the client.py file to code.py on the Feather.
# SPDX-FileCopyrightText: 2019 Anne Barela for Adafruit Industries
#
# SPDX-License-Identifier: MIT
from binascii import unhexlify
from time import sleep
from micropython import const
from adafruit_ble import BLERadio
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
from adafruit_ble.services.nordic import UARTService
from adafruit_bluefruit_connect.packet import Packet
from adafruit_bluefruit_connect.button_packet import ButtonPacket
from adafruit_bluefruit_connect.color_packet import ColorPacket
from neopixel import NeoPixel
from board import NEOPIXEL, SWITCH
from adafruit_debouncer import Debouncer
from digitalio import DigitalInOut, Direction, Pull
import adafruit_fancyled.adafruit_fancyled as fancy
pin = DigitalInOut(SWITCH) # Set up built-in pushbutton switch
pin.direction = Direction.INPUT
pin.pull = Pull.UP
switch = Debouncer(pin)
pixels = NeoPixel(NEOPIXEL, 1) # Set up built-in NeoPixel
AQUA = const(0x00FFFF) # (0, 255, 255)
GREEN = const(0x00FF00) # (0, 255, 0)
ORANGE = const(0xFF8000) # (255, 128, 0)
RED = const(0xFF0000) # (255, 0, 0)
BLUE = const(0x0000FF) # (0, 0, 255)
gradients = {"Off": [(0.0, RED), (0.75, ORANGE)], "On": [(0.0, GREEN), (1.0, AQUA)]}
palette = fancy.expand_gradient(gradients["Off"], 30)
gamma_levels = (0.25, 0.3, 0.15)
color_index = 1
fade_direction = 1
TARGET = "f0:74:72:60:87:d2" # CHANGE TO YOUR BLE ADDRESS
target_address = TARGET.split(":") # Convert address string to list of bytes
target_address.reverse() # Reverse bytes to match Address class little-endian
target_address = unhexlify("".join(target_address)) # Convert list to bytes
button_packet = ButtonPacket("1", True) # Transmits pressed button 1
ble = BLERadio()
uart_client = None
while True:
uart_addresses = []
pixels[0] = BLUE # Blue LED indicates disconnected status
pixels.show()
if not uart_client:
print("Trying to connect to BLE server...")
# Keep trying to find target UART peripheral
for adv in ble.start_scan(ProvideServicesAdvertisement):
print(adv.address.address_bytes) # Print detected addresses
if adv.address.address_bytes == target_address:
uart_client = ble.connect(adv)
print("Connected")
break
ble.stop_scan()
if uart_client and uart_client.connected:
uart_service = uart_client[UARTService]
while uart_client and uart_client.connected: # Connected
switch.update()
if switch.fell: # Check for button press
try:
# Transmit press
uart_service.write(button_packet.to_bytes())
except OSError:
pass
# Check for LED status receipt
if uart_service.in_waiting:
packet = Packet.from_stream(uart_service)
if isinstance(packet, ColorPacket):
# Color match
if fancy.CRGB(*packet.color).pack() == GREEN:
# Green indicates on state
palette = fancy.expand_gradient(gradients["On"], 30)
else:
# Otherwise red indicates off
palette = fancy.expand_gradient(gradients["Off"], 30)
# NeoPixel color fading routing
color = fancy.palette_lookup(palette, color_index / 29)
color = fancy.gamma_adjust(color, brightness=gamma_levels)
c = color.pack()
pixels[0] = c
pixels.show()
if color_index in (0, 28):
fade_direction *= -1 # Change direction
color_index += fade_direction
sleep(0.02)
The program scans for BLE peripherals and connects once the target is located.
The user switch is debounced. Generally speaking, when a mechanical switch is pressed, it doesn’t just change from open to closed. The metal contacts oscillate for a few milliseconds. This can trick a microcontroller into reading multiple presses. The debouncer suppresses these erroneous readings. When the switch is pressed a button packet is sent to the server to activate the solenoid.
Next, the code monitors the UART buffer for color packets and uses FancyLED to generate smooth LED color fading for the corresponding color palette. The remote control fades green/aqua if the server is on. Otherwise, it fades red/orange.
Page last edited January 21, 2025
Text editor powered by tinymce.