Feather and Crickit Prep
We'll be using CircuitPython for this project. Are you new to using CircuitPython? No worries, there is a full getting started guide here.
For more info on the Feather nRF52840 Express, check out this guide.
Adafruit suggests using the Mu editor to edit your code and have an interactive REPL in CircuitPython. You can learn about Mu and its installation in this tutorial.
Follow this guide for instructions on installing the latest release version of CircuitPython for the Feather nRF52840 Express:
Libraries
You'll also need to add the following libraries for this project. Follow this guide on adding libraries.
Plug your nRF Feather board into your computer via a USB cable. Please be sure the cable is a good power+data cable so the computer can talk to the board.
A new disk should appear in your computer's file explorer/finder called CIRCUITPY. This is the place we'll copy the code and code library. If you can only get a drive named FTHR840BOOT, load CircuitPython per the guide above.
Make a folder on the CIRCUITPY drive named lib.
Now, download the latest CircuitPython libraries to your computer using the green button below. Match the library you get to the version of CircuitPython you are using. Save to your computer's hard drive where you can find it.
With your file explorer/finder, browse to the bundle and open it up. Copy the following folders and files from the library bundle to your CIRCUITPY lib directory you made earlier:
The ones you'll need are:
- adafruit_ble (folder)
-
adafruit_bluefruit_connect (folder)
- adafruit_bus_device (folder)
- adafruit_crickit.mpy (file)
- adafruit_motor (folder)
-
adafruit_seesaw (folder)
All of the other necessary code is baked into CircuitPython!
CircuitPython Code
Copy the program below and paste it into a new document in Mu. Then, save it from Mu onto your CIRCUITPY flash drive as code.py. As soon as CircuitPython restarts, the NeoPixel ring will light up purple-ish and await your Bluetooth connection!
# SPDX-FileCopyrightText: 2019 John Edgar Park for Adafruit Industries # # SPDX-License-Identifier: MIT # CircuitPython BLE Rover # Use with the Adafruit BlueFruit LE Connect app # Works with CircuitPython 4.0.0-beta.1 and later # running on an nRF52840 Feather board and Crickit FeatherWing import time import board import digitalio from adafruit_crickit import crickit 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 # Only the packet classes that are imported will be known to Packet. from adafruit_bluefruit_connect.button_packet import ButtonPacket from adafruit_bluefruit_connect.color_packet import ColorPacket # Prep the status LEDs on the Feather blue_led = digitalio.DigitalInOut(board.BLUE_LED) red_led = digitalio.DigitalInOut(board.RED_LED) blue_led.direction = digitalio.Direction.OUTPUT red_led.direction = digitalio.Direction.OUTPUT ble = BLERadio() uart_service = UARTService() advertisement = ProvideServicesAdvertisement(uart_service) # motor setup motor_1 = crickit.dc_motor_1 motor_2 = crickit.dc_motor_2 FWD = -1.0 REV = 0.7 crickit.init_neopixel(24, brightness = 0.2) # create Crickit neopixel object RED = (200, 0, 0) GREEN = (0, 200, 0) BLUE = (0, 0, 200) PURPLE = (120, 0, 160) YELLOW = (100, 100, 0) AQUA = (0, 100, 100) color = PURPLE # current NeoPixel color prior_color = PURPLE # to store state of previous color when changing them crickit.neopixel.fill(color) print("BLE Rover") print("Use Adafruit Bluefruit app to connect") while True: blue_led.value = False ble.start_advertising(advertisement) while not ble.connected: # Wait for a connection. pass blue_led.value = True # turn on blue LED when connected while ble.connected: if uart_service.in_waiting: # Packet is arriving. red_led.value = False # turn off red LED packet = Packet.from_stream(uart_service) if isinstance(packet, ColorPacket): # Change the color. color = packet.color crickit.neopixel.fill(color) # do this when buttons are pressed if isinstance(packet, ButtonPacket) and packet.pressed: red_led.value = True # blink to show a packet has been received if packet.button == ButtonPacket.UP: # UP button pressed crickit.neopixel.fill(color) motor_1.throttle = FWD motor_2.throttle = FWD elif packet.button == ButtonPacket.DOWN: # DOWN button crickit.neopixel.fill(color) motor_1.throttle = REV motor_2.throttle = REV elif packet.button == ButtonPacket.RIGHT: prior_color = color color = YELLOW crickit.neopixel.fill(color) motor_1.throttle = FWD motor_2.throttle = FWD * 0.5 elif packet.button == ButtonPacket.LEFT: prior_color = color color = YELLOW crickit.neopixel.fill(color) motor_1.throttle = FWD * 0.5 motor_2.throttle = FWD elif packet.button == ButtonPacket.BUTTON_1: crickit.neopixel.fill(RED) motor_1.throttle = 0.0 motor_2.throttle = 0.0 time.sleep(0.5) crickit.neopixel.fill(color) elif packet.button == ButtonPacket.BUTTON_2: color = GREEN crickit.neopixel.fill(color) elif packet.button == ButtonPacket.BUTTON_3: color = BLUE crickit.neopixel.fill(color) elif packet.button == ButtonPacket.BUTTON_4: color = PURPLE crickit.neopixel.fill(color) # do this when some buttons are released elif isinstance(packet, ButtonPacket) and not packet.pressed: if packet.button == ButtonPacket.RIGHT: print("released right") color = prior_color crickit.neopixel.fill(color) motor_1.throttle = FWD motor_2.throttle = FWD if packet.button == ButtonPacket.LEFT: print("released left") color = prior_color crickit.neopixel.fill(color) motor_1.throttle = FWD motor_2.throttle = FWD
How the Code Works
The first part of the program sets up a UARTServer
, which is a BLE service that wirelessly sends streams of characters between a BLE device and a client computer (which could be a phone or tablet). The program then starts advertising its UART service to anyone listening. The client computer receives the advertisement, and tells the user it's available. The user can then choose to connect as a client of the service.
One a connection is established, the program code waits for incoming command packets from the client, either a ColorPacket
or a ButtonPacket
. When one arrives, the program waits to see which button has been pressed or which color value is sent and then either runs the motors or changes the colors on the NeoPixels.
Motor Movement
We set up a couple of variables -- FWD
and REV
-- that tell the program which base values to send for forward and reverse. Depending on how you wired the motors, and which way you want to consider "forward" on the cart, you can adjust these values anywhere from -1.0
to 1.0
.
When you test the rover, if it goes backwards when you press the up button, you can switch the FWD
variable from -1.0
to 1.0
and flip the REV
value from 0.7
to -0.7
.
If you find the rover spinning in circle when you press up or down on the remote app, then one of the motors is wired "backwards". Simply swap the two wires of that motor into each others' ports on the Crickit!
Control the Rover with the Bluefruit LE Connect App
Download the App
To control the motors and NeoPixels in from a client device (phone or tablet), you use the Adafruit Bluefruit LE Connect App. Install it from the Apple App Store or Google Play App Store.
Connect to Feather
With the Crickit plugged into DC power and turned on with its on-board power switch, the Feather will also get power and automatically start running your code. Then start up the Bluefruit LE Connect app, and make sure it's in Central Mode (left button on the bottom). When you start the app, you should see a device named CIRCU or CIRCUITPY. If there's a long list of devices, you can shorten it by turning on the "Must have UART Service" switch.
To connect to the Light Switch, touch the Connect button. You should see Connecting and then Discovering Services.
Once connected, you can use the Controllers > Control Pad to drive with the arrow buttons, stop with the 1 button, and change to some preset colors on 2, 3, & 4.
Troubleshooting
If you don't see CIRCU or CIRCUITPY right away, try pulling down to refresh. If that doesn't work, try turning Bluetooth off and back on on your phone or tablet and restarting the app.
Device Menu
After you connect, you'll see a menu of how you can interact with the device. Choose Controller.
Controller Menu
After you choose Controller, you'll see another screen with more choices. Control Pad is used for this project.
Change Color
To change the color of the NeoPixels, use the Color Picker screen. Choose a color and press Send Selected Color.
Text editor powered by tinymce.