Mmmmm, bacon.....

What?

Oh. Beacons? Yes, beacons!

Beacons are low power, low cost Bluetooth LE devices that can be used for a very simple job: to advertise a URL to users running an app on their mobile device within range of the device!

Technically, beacons can also be used for a few different scenarios where a localized, wireless data broadcast is desirable, such as indoor location tracking, point of sales/marketing, and experience personalization.

We'll create two version -- first, a simple beacon that can run on any CircuitPython capable nRF52840 board. Second, a custom version for the CLUE board that also shows QR codes and allows you to scroll among multiple beacon URL choices to advertise!

Parts

All you need to advertise your own BLE beacons is any Adafruit Bluefruit nRF52840 board:

What's smaller than a Feather but larger than a Trinket? It's an Adafruit ItsyBitsy nRF52840 Express featuring the Nordic nRF52840 Bluetooth LE...
$19.95
In Stock
Do you feel like you just don't have a CLUE? Well, we can help with that - get a CLUE here at Adafruit by picking up this sensor-packed development board. We wanted to build some...
$44.95
In Stock
The Adafruit Feather nRF52840 Express is the new Feather family member with Bluetooth Low Energy and native USB support featuring the nRF52840!  It's...
$24.95
In Stock
Circuit Playground Bluefruit is our third board in the Circuit Playground series, another step towards a perfect introduction to electronics and programming. We've...
$24.95
In Stock

You'll also want a USB cable for programming it and power, or you can use a LiPoly battery for remote powering.

This here is your standard A to micro-B USB cable, for USB 1.1 or 2.0. Perfect for connecting a PC to your Metro, Feather, Raspberry Pi or other dev-board or...
$2.95
In Stock
Lithium-ion polymer (also known as 'lipo' or 'lipoly') batteries are thin, light, and powerful. The output ranges from 4.2V when completely charged to 3.7V. This...
$7.95
In Stock
Oh so adorable, this is the tiniest little lipo charger, so handy you can keep it any project box! Its also easy to use. Simply plug in the gold plated contacts into any USB port and a...
$5.95
In Stock
If you have an ItsyBitsy or Pro Trinket you probably know it's the perfect little size for a portable project. This LiPoly backpack makes it really easy to do! Instead of wiring 2...
$4.95
In Stock

Additionally, you'll need a mobile device running an Eddystone beacon discovery app, such as Physical Web:

Bluetooth LC beacons are low power devices that are used to broadcast a tiny amount of data to any device that's listening. This often takes the form of a mobile device running an app, such as Physical Web, that can read the beacon's advertising broadcast and display a URL the user can then visit.

There are two primary BLE beacon standards: Apple's iBeacon, and Google's Eddystone. In this guide, we'll use the Eddystone standard to create a beacon that advertises a website URL (which you can customize to any URL you like).

Advertising

When an Eddystone beacon is running, it transmits a packet of information that includes a Unique Identifier (UID), and another packet of information that includes a website URL.

Note, this data is transmitted with no need for connecting, pairing, or bonding with a mobile device. The beacon is pretty much just always sitting there yelling, "Hey! I'm a beacon! This is my name, and this is a URL I think you should visit!"

Other Uses

This guide focuses solely on using beacons to advertise a URL, however there are a few other common uses for beacons. These include indoor navigation, tracking (such as lost key finders like Tile), and interaction notifications, such as interactive museum tours.

CircuitPython Setup

For our simple beacon example, we'll use the ItsyBitsy nRF52840. We'll show you how to set it up with the proper libraries and code to use on the Itsy, but you can apply these instructions to the Feather nRF52840, Circuit Playground Bluefruit, or CLUE boards as well by downloading the appropriate version of CircuitPython for those boards.

CircuitPython is a derivative of MicroPython designed to simplify experimentation and education on low-cost microcontrollers. It makes it easier than ever to get prototyping by requiring no upfront desktop software downloads. Simply copy and edit files on the CIRCUITPY drive to iterate.

Set up CircuitPython Quick Start!

Follow this quick step-by-step for super-fast Python power :)

Further Information

For more detailed info on installing CircuitPython, check out Installing CircuitPython.

Click the link above and download the latest UF2 file.

Download and save it to your desktop (or wherever is handy).

Plug your Itsy nRF52840 into your computer using a known-good USB cable.

A lot of people end up using charge-only USB cables and it is very frustrating! So make sure you have a USB cable you know is good for data sync.

In the image, the Reset button is indicated by the magenta arrow, and the BTLE status LED is indicated by the green arrow.

Double-click the Reset button on your board (magenta arrow), and you will see the BTLE LED (green arrow) will pulse quickly then slowly blue. If the DotStar LED turns red, check the USB cable, try another USB port, etc.

If double-clicking doesn't work the first time, try again. Sometimes it can take a few tries to get the rhythm right!

You will see a new disk drive appear called ITSY840BOOT.

Drag the adafruit_circuitpython_etc.uf2 file to ITSY840BOOT.

The LED will flash. Then, the ITSY840BOOT drive will disappear and a new disk drive called CIRCUITPY will appear.

That's it, you're done! :)

As CircuitPython development continues and there are new releases, Adafruit will stop supporting older releases. Visit https://circuitpython.org/downloads to download the latest version of CircuitPython for your board. You must download the CircuitPython Library Bundle that matches your version of CircuitPython. Please update CircuitPython and then visit https://circuitpython.org/libraries to download the latest Library Bundle.

Each CircuitPython program you run needs to have a lot of information to work. The reason CircuitPython is so simple to use is that most of that information is stored in other files and works in the background. These files are called libraries. Some of them are built into CircuitPython. Others are stored on your CIRCUITPY drive in a folder called lib. Part of what makes CircuitPython so great is its ability to store code separately from the firmware itself. Storing code separately from the firmware makes it easier to update both the code you write and the libraries you depend.

Your board may ship with a lib folder already, it's in the base directory of the drive. If not, simply create the folder yourself. When you first install CircuitPython, an empty lib directory will be created for you.

CircuitPython libraries work in the same way as regular Python modules so the Python docs are an excellent reference for how it all should work. In Python terms, you can place our library files in the lib directory because it's part of the Python path by default.

One downside of this approach of separate libraries is that they are not built in. To use them, one needs to copy them to the CIRCUITPY drive before they can be used. Fortunately, there is a library bundle.

The bundle and the library releases on GitHub also feature optimized versions of the libraries with the .mpy file extension. These files take less space on the drive and have a smaller memory footprint as they are loaded.

Due to the regular updates and space constraints, Adafruit does not ship boards with the entire bundle. Therefore, you will need to load the libraries you need when you begin working with your board. You can find example code in the guides for your board that depends on external libraries.

Either way, as you start to explore CircuitPython, you'll want to know how to get libraries on board.

The Adafruit CircuitPython Library Bundle

Adafruit provides CircuitPython libraries for much of the hardware they provide, including sensors, breakouts and more. To eliminate the need for searching for each library individually, the libraries are available together in the Adafruit CircuitPython Library Bundle. The bundle contains all the files needed to use each library.

Downloading the Adafruit CircuitPython Library Bundle

You can download the latest Adafruit CircuitPython Library Bundle release by clicking the button below. The libraries are being constantly updated and improved, so you'll always want to download the latest bundle. 

Match up the bundle version with the version of CircuitPython you are running. For example, you would download the 6.x library bundle if you're running any version of CircuitPython 6, or the 7.x library bundle if you're running any version of CircuitPython 7, etc. If you mix libraries with major CircuitPython versions, you will get incompatible mpy errors due to changes in library interfaces possible during major version changes.

Download the bundle version that matches your CircuitPython firmware version. If you don't know the version, check the version info in boot_out.txt file on the CIRCUITPY drive, or the initial prompt in the CircuitPython REPL. For example, if you're running v7.0.0, download the 7.x library bundle.

There's also a py bundle which contains the uncompressed python files, you probably don't want that unless you are doing advanced work on libraries.

The CircuitPython Community Library Bundle

The CircuitPython Community Library Bundle is made up of libraries written and provided by members of the CircuitPython community. These libraries are often written when community members encountered hardware not supported in the Adafruit Bundle, or to support a personal project. The authors all chose to submit these libraries to the Community Bundle make them available to the community.

These libraries are maintained by their authors and are not supported by Adafruit. As you would with any library, if you run into problems, feel free to file an issue on the GitHub repo for the library. Bear in mind, though, that most of these libraries are supported by a single person and you should be patient about receiving a response. Remember, these folks are not paid by Adafruit, and are volunteering their personal time when possible to provide support.

Downloading the CircuitPython Community Library Bundle

You can download the latest CircuitPython Community Library Bundle release by clicking the button below. The libraries are being constantly updated and improved, so you'll always want to download the latest bundle.

The link takes you to the latest release of the CircuitPython Community Library Bundle on GitHub. There are multiple versions of the bundle available. Download the bundle version that matches your CircuitPython firmware version. If you don't know the version, check the version info in boot_out.txt file on the CIRCUITPY drive, or the initial prompt in the CircuitPython REPL. For example, if you're running v7.0.0, download the 7.x library bundle.

Understanding the Bundle

After downloading the zip, extract its contents. This is usually done by double clicking on the zip. On Mac OSX, it places the file in the same directory as the zip.

Open the bundle folder. Inside you'll find two information files, and two folders. One folder is the lib bundle, and the other folder is the examples bundle.

Now open the lib folder. When you open the folder, you'll see a large number of .mpy files, and folders.

Example Files

All example files from each library are now included in the bundles in an examples directory (as seen above), as well as an examples-only bundle. These are included for two main reasons:

  • Allow for quick testing of devices.
  • Provide an example base of code, that is easily built upon for individualized purposes.

Copying Libraries to Your Board

First open the lib folder on your CIRCUITPY drive. Then, open the lib folder you extracted from the downloaded zip. Inside you'll find a number of folders and .mpy files. Find the library you'd like to use, and copy it to the lib folder on CIRCUITPY.

If the library is a directory with multiple .mpy files in it, be sure to copy the entire folder to CIRCUITPY/lib.

This also applies to example files. Open the examples folder you extracted from the downloaded zip, and copy the applicable file to your CIRCUITPY drive. Then, rename it to code.py to run it.

If a library has multiple .mpy files contained in a folder, be sure to copy the entire folder to CIRCUITPY/lib.

Understanding Which Libraries to Install

You now know how to load libraries on to your CircuitPython-compatible microcontroller board. You may now be wondering, how do you know which libraries you need to install? Unfortunately, it's not always straightforward. Fortunately, there is an obvious place to start, and a relatively simple way to figure out the rest. First up: the best place to start.

When you look at most CircuitPython examples, you'll see they begin with one or more import statements. These typically look like the following:

  • import library_or_module

However, import statements can also sometimes look like the following:

  • from library_or_module import name
  • from library_or_module.subpackage import name
  • from library_or_module import name as local_name

They can also have more complicated formats, such as including a try / except block, etc.

The important thing to know is that an import statement will always include the name of the module or library that you're importing.

Therefore, the best place to start is by reading through the import statements.

Here is an example import list for you to work with in this section. There is no setup or other code shown here, as the purpose of this section involves only the import list.

import time
import board
import neopixel
import adafruit_lis3dh
import usb_hid
from adafruit_hid.consumer_control import ConsumerControl
from adafruit_hid.consumer_control_code import ConsumerControlCode

Keep in mind, not all imported items are libraries. Some of them are almost always built-in CircuitPython modules. How do you know the difference? Time to visit the REPL.

In the Interacting with the REPL section on The REPL page in this guide, the help("modules") command is discussed. This command provides a list of all of the built-in modules available in CircuitPython for your board. So, if you connect to the serial console on your board, and enter the REPL, you can run help("modules") to see what modules are available for your board. Then, as you read through the import statements, you can, for the purposes of figuring out which libraries to load, ignore the statement that import modules.

The following is the list of modules built into CircuitPython for the Feather RP2040. Your list may look similar or be anything down to a significant subset of this list for smaller boards.

Now that you know what you're looking for, it's time to read through the import statements. The first two, time and board, are on the modules list above, so they're built-in.

The next one, neopixel, is not on the module list. That means it's your first library! So, you would head over to the bundle zip you downloaded, and search for neopixel. There is a neopixel.mpy file in the bundle zip. Copy it over to the lib folder on your CIRCUITPY drive. The following one, adafruit_lis3dh, is also not on the module list. Follow the same process for adafruit_lis3dh, where you'll find adafruit_lis3dh.mpy, and copy that over.

The fifth one is usb_hid, and it is in the modules list, so it is built in. Often all of the built-in modules come first in the import list, but sometimes they don't! Don't assume that everything after the first library is also a library, and verify each import with the modules list to be sure. Otherwise, you'll search the bundle and come up empty!

The final two imports are not as clear. Remember, when import statements are formatted like this, the first thing after the from is the library name. In this case, the library name is adafruit_hid. A search of the bundle will find an adafruit_hid folder. When a library is a folder, you must copy the entire folder and its contents as it is in the bundle to the lib folder on your CIRCUITPY drive. In this case, you would copy the entire adafruit_hid folder to your CIRCUITPY/lib folder.

Notice that there are two imports that begin with adafruit_hid. Sometimes you will need to import more than one thing from the same library. Regardless of how many times you import the same library, you only need to load the library by copying over the adafruit_hid folder once.

That is how you can use your example code to figure out what libraries to load on your CircuitPython-compatible board!

There are cases, however, where libraries require other libraries internally. The internally required library is called a dependency. In the event of library dependencies, the easiest way to figure out what other libraries are required is to connect to the serial console and follow along with the ImportError printed there. The following is a very simple example of an ImportError, but the concept is the same for any missing library.

Example: ImportError Due to Missing Library

If you choose to load libraries as you need them, or you're starting fresh with an existing example, you may end up with code that tries to use a library you haven't yet loaded.  This section will demonstrate what happens when you try to utilise a library that you don't have loaded on your board, and cover the steps required to resolve the issue.

This demonstration will only return an error if you do not have the required library loaded into the lib folder on your CIRCUITPY drive.

Let's use a modified version of the Blink example.

import board
import time
import simpleio

led = simpleio.DigitalOut(board.LED)

while True:
    led.value = True
    time.sleep(0.5)
    led.value = False
    time.sleep(0.5)

Save this file. Nothing happens to your board. Let's check the serial console to see what's going on.

You have an ImportError. It says there is no module named 'simpleio'. That's the one you just included in your code!

Click the link above to download the correct bundle. Extract the lib folder from the downloaded bundle file. Scroll down to find simpleio.mpy. This is the library file you're looking for! Follow the steps above to load an individual library file.

The LED starts blinking again! Let's check the serial console.

No errors! Excellent. You've successfully resolved an ImportError!

If you run into this error in the future, follow along with the steps above and choose the library that matches the one you're missing.

Library Install on Non-Express Boards

If you have an M0 non-Express board such as Trinket M0, Gemma M0, QT Py M0, or one of the M0 Trinkeys, you'll want to follow the same steps in the example above to install libraries as you need them. Remember, you don't need to wait for an ImportError if you know what library you added to your code. Open the library bundle you downloaded, find the library you need, and drag it to the lib folder on your CIRCUITPY drive.

You can still end up running out of space on your M0 non-Express board even if you only load libraries as you need them. There are a number of steps you can use to try to resolve this issue. You'll find suggestions on the Troubleshooting page.

Updating CircuitPython Libraries and Examples

Libraries and examples are updated from time to time, and it's important to update the files you have on your CIRCUITPY drive.

To update a single library or example, follow the same steps above. When you drag the library file to your lib folder, it will ask if you want to replace it. Say yes. That's it!

A new library bundle is released every time there's an update to a library. Updates include things like bug fixes and new features. It's important to check in every so often to see if the libraries you're using have been updated.

Libraries

Once your ItsyBitsy nRF52840 is set up with CircuitPython, we'll add libraries from the bundle. You can read up on how to download libraries here.

From the library bundle, transfer these libraries onto the Itsy's /lib directory on the CIRCUITPY drive:

  • adafruit_ble
  • adafruit_ble_eddystone

Text Editor

Adafruit recommends using the Mu editor for using your CircuitPython code with Adafruit boards. You can get more info in this guide.

Alternatively, you can use any text editor that saves files.

Code.py

Copy the code shown below, paste it into Mu. Plug your ItsyBitsy into your computer via a known good USB cable. In your operating system's file explorer/finder, you should see a new flash drive named CIRCUITPY. Save the code from Mu to the Itsy's CIRCUITPY drive as code.py

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

"""This example broadcasts our Mac Address as our Eddystone ID and a link to the Adafruit Discord
   server."""

import time

import adafruit_ble
from adafruit_ble_eddystone import uid, url

radio = adafruit_ble.BLERadio()

# Reuse the BLE address as our Eddystone instance id.
eddystone_uid = uid.EddystoneUID(radio.address_bytes)
eddystone_url = url.EddystoneURL("https://adafru.it/discord")

while True:
    # Alternate between advertising our ID and our URL.
    radio.start_advertising(eddystone_uid)
    time.sleep(0.5)
    radio.stop_advertising()

    radio.start_advertising(eddystone_url)
    time.sleep(0.5)
    radio.stop_advertising()

    time.sleep(4)

Code Explainer

Libraries

Here's how this code works. First we import the time and adafruit_ble libraries.

Then, we import uid and url from the adafruit_ble_eddystone library. These two give us the capability to advertise a unique identifier (UID) and a website URL.

import time
 
import adafruit_ble
from adafruit_ble_eddystone import uid, url

Radio & Eddystone Setup

Next we'll create an instance of the BLERadio() and then create a variable for the eddystone_uid. This is the unique ID that is used to differentiate beacons when multiple of them are present. We can re-use the BLE radio.address_bytes as our UID.

We'll also create a variable for the website URL we want to be advertised from our beacon, eddystone_url.

In this case, we are using https://adafru.it/discord as the beacon URL, but you can swap in a URL of your choosing. Just be careful it isn't too long -- anything under 18 characters will work, otherwise you can use a URL shortener service, such as bit.ly.

radio = adafruit_ble.BLERadio()
 
# Reuse the BLE address as our Eddystone instance id.
eddystone_uid = uid.EddystoneUID(radio.address_bytes)
eddystone_url = url.EddystoneURL("https://adafru.it/discord")
You may get away with a longer URL than you think you should -- this is because for certain common URL prefixes ('https://www.' for example) and domains ('.com', '.org', etc.) we substitute them for a single non-printing byte.

Advertising

With setup complete, the main, ever-repeating loop of the code now takes over. Here, we alternate between advertising the beacon's UID and the beacon's URL, pause for four seconds, and repeat.

while True:
        # Alternate between advertising our ID and our URL.
        radio.start_advertising(eddystone_uid)
        time.sleep(0.5)
        radio.stop_advertising()
     
        radio.start_advertising(eddystone_url)
        time.sleep(0.5)
        radio.stop_advertising()
     
        time.sleep(4)

Usage

To use it, simply power up the beacon and then launch your Physical Web app (or other beacon-aware app) on your mobile device. You'll see the app scan for beacons.

When the beacon is found, you will see some info about it, including a clickable link to take you to the advertised URL.

Any icons and descriptive text are scraped from the website itself, and not part of the data delivered by the beacon.

That's all there is to it! Next we'll create a more sophisticated version on the CLUE.

First, set up CircuitPython on the CLUE following the instructions on this page.

Libraries

Next, install the libraries needed. This guide page will show you where to download them.

You'll need the following libraries for this project:

  • adafruit_bitmap_font
  • adafruit_ble
  • adafruit_ble_eddystone
  • adafruit_bus_device
  • adafruit_display_shapes
  • adafruit_display_text
  • adafruit_pybadger
  • adafruit_register
  • adafruit_lis3mdl.mpy
  • adafruit_lsm6ds.mpy
  • adafruit_miniqr.mpy
  • neopixel.mpy

Text Editor

Adafruit recommends using the Mu editor for using your CircuitPython code with the Feather boards. You can get more info in this guide.

Alternatively, you can use any text editor that saves files.

Image Files and Code.py

This project uses a couple of .bmp image files -- you can get them by downloading the Project Zip link in the embed below. Unzip the downloaded zip archive and then drag the two image files to your CLUE board's CIRCIUTPY drive.

Copy the code shown below, paste it into Mu. Save the code from Mu to the CLUE's CIRCUITPY drive as code.py

"""
Eddystone Beacon for CLUE
This example broadcasts our Mac Address as our Eddystone ID and a link to a URL of your choice.
Hold the A button to display QR code, use B button to pick URL from the list.
"""

import time
from adafruit_pybadger import pybadger
import adafruit_ble
from adafruit_ble_eddystone import uid, url

radio = adafruit_ble.BLERadio()

# Reuse the BLE address as our Eddystone instance id.
eddystone_uid = uid.EddystoneUID(radio.address_bytes)

# List of URLs to broadcast here:
ad_url = [("https://circuitpython.org", "CirPy"),
          ("https://adafru.it/discord","DISCORD"),
          ("https://forums.adafruit.com", "Forums"),
          ("https://learn.adafruit.com", "Learn")
         ]
pick = 0  # use to increment url choices

pybadger.play_tone(1600, 0.25)
pybadger.show_business_card(image_name="cluebeacon.bmp")

while True:
    pybadger.auto_dim_display(delay=3, movement_threshold=4)
    eddystone_url = url.EddystoneURL(ad_url[pick][0])

    if pybadger.button.a and not pybadger.button.b:  # Press button A to show QR code
        pybadger.play_tone(1200, 0.1)
        pybadger.brightness = 1
        pybadger.show_qr_code(data=ad_url[pick][0])  # Tests QR code
        time.sleep(0.1)  # Debounce

    elif pybadger.button.b and not pybadger.button.a:  # iterate through urls to broadcast
        pybadger.play_tone(1600, 0.2)
        pick = (pick + 1) % len(ad_url)
        pybadger.brightness = 1
        pybadger.show_business_card(image_name="bg.bmp", name_string=ad_url[pick][1], name_scale=5,
                                    email_string_one="", email_string_two=ad_url[pick][0])
        time.sleep(0.1)

    elif pybadger.button.a and pybadger.button.b:
        pybadger.play_tone(1000, 0.2)
        pybadger.brightness = 1
        pybadger.show_business_card(image_name="cluebeacon.bmp")
        time.sleep(0.1)

    # Alternate between advertising our ID and our URL.
    radio.start_advertising(eddystone_uid)
    time.sleep(0.5)
    radio.stop_advertising()

    radio.start_advertising(eddystone_url)
    time.sleep(0.5)
    radio.stop_advertising()

    time.sleep(1)

How It Works

Like the simple example before, we will import libraries for time, ble, and eddystone support. We will also import the adafruit_pybadger library which makes it convenient to use the buttons, speaker, and screen on the CLUE.

import time
from adafruit_pybadger import pybadger
import adafruit_ble
from adafruit_ble_eddystone import uid, url

Setup

We'll set up the radio and eddystone_uid as before, but this time instead of a single URL, we'll create a list of few to pick through.

This is a list of tuples, which each entry containing both a URL and a "nice name".

The pick variable will be used to select a URL from the list when the B button is pressed.

radio = adafruit_ble.BLERadio()
 
# Reuse the BLE address as our Eddystone instance id.
eddystone_uid = uid.EddystoneUID(radio.address_bytes)
 
# List of URLs to broadcast here:
ad_url = [("https://circuitpython.org", "CirPy"),
          ("https://adafru.it/discord","DISCORD"),
          ("https://forums.adafruit.com", "Forums"),
          ("https://learn.adafruit.com", "Learn")
         ]
pick = 0  # use to increment url choices

We'll use the pybadger.play_tone() command to beep the on-board speaker, and the pybadger.show_business_card() command to display a .bmp image.

pybadger.play_tone(1600, 0.25)
pybadger.show_business_card(image_name="cluebeacon.bmp")

Main Loop

In the main loop of the program we will set the display to auto dim after three seconds, and set the movement threshold so you can shake it a little to wake up the CLUE and undim it.

The eddystone_url is set to the first one in the list.

pybadger.auto_dim_display(delay=3, movement_threshold=4)
eddystone_url = url.EddystoneURL(ad_url[pick][0])

Buttons

When the A button is pressed by itself, the pybadger.show_qr_code() command is run, displaying the automatically generated QR code image for the currently selected URL.

if pybadger.button.a and not pybadger.button.b:  # Press button A to show QR code
        pybadger.play_tone(1200, 0.1)
        pybadger.brightness = 1
        pybadger.show_qr_code(data=ad_url[pick][0])  # Tests QR code
        time.sleep(0.1)  # Debounce

When the B button is pressed, the next URL in the list is selected, and this info is displayed on the screen using the pybadger.show_business_card() command.

elif pybadger.button.b and not pybadger.button.a:  # iterate through urls to broadcast
        pybadger.play_tone(1600, 0.2)
        pick = (pick + 1) % len(ad_url)
        pybadger.brightness = 1
        pybadger.show_business_card(image_name="bg.bmp", name_string=ad_url[pick][1], name_scale=5,
                                    email_string_one="", email_string_two=ad_url[pick][0])
        time.sleep(0.1)

When both A and B buttons are pressed at the same time, the display returns to the initial screen image.

elif pybadger.button.a and pybadger.button.b:
        pybadger.play_tone(1000, 0.2)
        pybadger.brightness = 1
        pybadger.show_business_card(image_name="cluebeacon.bmp")
        time.sleep(0.1)

Beacon Advertising

Finally, we have the beacon advertising code, just as with the simple example. The beacon UID is advertised, then the URL is, and this repeats every second.

# Alternate between advertising our ID and our URL.
    radio.start_advertising(eddystone_uid)
    time.sleep(0.5)
    radio.stop_advertising()
 
    radio.start_advertising(eddystone_url)
    time.sleep(0.5)
    radio.stop_advertising()
 
    time.sleep(1)

CLUE Beacon Usage

Power up the CLUE and you'll see the welcome screen.

Pick Beacon Advertisment

Press the B button to pick a URL from your list. There is a small beep when the button press is recognized -- you may need to hold it for a second first.

The current beacon name and URL will be displayed.

QR Code

Press the A button to go to QR code mode. This is great for any users without a BLE beacon app who want to use their camera to scan the URL instead.

Here is the auto-generated QR code. All made in CircuitPython!

You can press the B button to switch to the other URLs which will change the beacon advertisements almost instantly.

NOTE: Depending on the beacon app you're running, you may need to refresh or delete the beacon cache in order to see the changed advertisement URL show up.

circuitpython_IMG_0959.jpg

circuitpython_IMG_0960.jpg

circuitpython_IMG_0961.jpg

This guide was first published on Feb 26, 2020. It was last updated on Feb 26, 2020.