The Adafruit Controllable Four Outlet Power Relay Module is a very neat piece of hardware (if you live in a 120 volt AC country). It has a pair of contacts on the side that can take a wide range of voltages to switch electrical loads on and off. This is just what my wife wanted, a method to remotely control power outlets to some gear in her office.
But how to switch it remotely. WiFi relies on connectivity that might get hacked over the internet in our view. Bluetooth seems more secure (maybe local hacking is possible, but our locality isn't a concern). I initially picked up an Adafruit Feather ESP32-S3. But CircuitPython Bluetooth doesn't work for UART/Serial profile. I want to, for proof of concept, use the Adafruit Bluefruit LE Connect application (available for iOS and Android) to send codes for on and off. That limits my choices to the Nordic nRF52840-based microcontroller boards.
Circuit Playground Bluefruit Setup
I had an early model with a firmware version less than 0.6.1. I needed to update that to load the latest versions of CircuitPython. I followed this guide to get version 0.8.0.
I connected my CPB to my computer with a known good data+power micro B USB cable (Adafruit sells many different ones). Press the Reset button twice and the board shows up as a USB thumb drive. I copied a new firmware file in UF2 format to the BOOT drive and it rebooted (if it doesn't reboot, it's likely an incorrect firmware file). Checking the text file on the new drive (pressing Reset twice once more), the firmware version was updated.
Then I loaded the latest version of CircuitPython via this guide. Great step-by-step guides. The board shows up now as a thumb drive called CIRCUITPY (no pressing Reset is needed).
Project Wiring
Luckily I had an Adafruit Circuit Playground Bluefruit handy. The nRF52840 Feather would work the same and likely be the board used going forward.
Refer to the picture at the top of this guide.
I connected the Power Relay contacts to the Circuit Playground Bluefruit (CPB) via breadboard to alligator wires to the ground and TX connection (any digital or analog pin should work). I connected power via the Power Relay always on outlet to a 5 volt USB transformer to the CPB USB micro B connector.
Be sure the ground pin on the Bluefruit Express board is connected to the "-" pin on the Relay box and the board.TX
connection goes to the "+" Relay box connection.
Code
I modified some example code on how to connect the nRF52840 board to the Connect app. In the Getting Started with CircuitPython and Bluetooth Low Energy guide, I modified the Button Press example to also toggle the button.TX
pin high when the up arrow is pressed, low when the down arrow is pressed.
I connected my CPB to my computer with a known good data+power micro B USB cable (Adafruit sells many different ones). I used the Mu editor to copy the example code and modify it to use digitalio for the pin toggling and neopixel to use two of the colorful RGB LEDs as status lights (one for Bluetooth connected, one for the switch state).
I needed to copy several libraries over to the /lib directory on the CIRCUITPY drive with File Explorer on my computer.
- neopixel
- adafruit_ble
- adafruit_bluefruit_connect
The latest Library Bundle is on the circuitpython.org website.
Next I used Mu to save the code to a file named code.py on the CIRCUITPY drive.
Here is the code:
# SPDX-FileCopyrightText: 2023 Anne Barela and Amy Lendian # # SPDX-License-Identifier: MIT import board import neopixel import digitalio 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 ble = BLERadio() uart = UARTService() advertisement = ProvideServicesAdvertisement(uart) contact = digitalio.DigitalInOut(board.TX) contact.direction = digitalio.Direction.OUTPUT contact.value = False pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=0.2) pixels[0] = (0, 0, 0) pixels[9] = (0, 0, 0) while True: ble.start_advertising(advertisement) while not ble.connected: pixels[9] = (0, 0, 0) pass # Now we're connected while ble.connected: pixels[9] = (0, 255, 0) if uart.in_waiting: packet = Packet.from_stream(uart) if isinstance(packet, ButtonPacket): if packet.pressed: if packet.button == ButtonPacket.BUTTON_1: # The 1 button was pressed. print("1 button pressed!") elif packet.button == ButtonPacket.UP: # The UP button was pressed. print("UP button pressed!") contact.value = True pixels[0] = (0, 0, 255) elif packet.button == ButtonPacket.DOWN: # The DOWN button was pressed print("DOWN button pressed!") contact.value = False pixels [0] = (0, 0, 0) # If we got here, we lost the connection. Go up to the top and start # advertising again and waiting for a connection.
Use
I opened the Adafruit Bluefruit Connect LE app on my phone. I found the Circuit Playground Bluefruit advertising itself as CIRCUITPY#### where #### is a random number. I connected to that. I then selected that I wanted to connect to the board using UART and Controller to get the control pad. Pressing the Up arrow turned the relay on and the down button turned it off. Success!
Final Thoughts
This all may seem like a lot of work. But I know that to do the same thing coding in a lower level language would require digging into manuals that are hundreds of pages thick. And writing mobile apps is a whole world unto itself. Having a precoded app and some example code, I got this project working in part of an afternoon.
The project demonstrates how Bluetooth commands can trigger a power relay safely, effectively and easily. A perfect start for my wife to further conceptualize her office project.
The final project will likely have an nRF52840 board instead of a phone and consist of multiple power relay boxes. I cannot wait to see what she designs.