Using micro:bit and CRICKIT with MicroPython
2019-06-18 | By Adafruit Industries
License: See Original Project Breadboards Potentiometers Programmers Switches micro:bit
Courtesy of Adafruit
Guide by Anne Barela
Overview
The Adafruit CRICKIT for micro:bit is a very nifty add-on. With it, you can extend the capabilities of the micro:bit to include additional inputs/outputs, capacitive touch input, servo control and DC motor control.
These functions can be accessed via the Arduino IDE with the following tutorials:
This guide presents using CRICKIT functions via MicroPython. MicroPython was started by author Damien George to allow Python programming on microcontrollers like the micro:bit. CircuitPython is a fork of MicroPython that Adafruit started to make Python on microcontrollers easier for beginners. Unfortunately, CircuitPython will not fit onto the limited memory of the micro:bit.
There are significant differences between MicroPython and CircuitPython. This tutorial focuses on using MicroPython on micro:bit with an Adafruit CRICKIT robotics controller attached.
Parts
- BBC micro:bit
- Adafruit CRICKIT for micro:bit
- USB A/Micro Cable - 2m
- 5V 2A (2000mA) switching power supply - UL Listed
A breadboard and some parts are used to demonstrate certain functions - feel free to only get the parts you may want to use for your project.
- 1 x Half Breadboard
- 1 x Micro Servo
- 1 x DC Motor
- 1 x 10K potentiometer
- 1 x LEDs
- 1 x Breadboard Buttons
Installing MicroPython on the micro:bit
We highly recommend you install the Mu Python editor. Mu has versions for PC, mac, and Linux, it is open source / free, and it is tailored to learning and microcontrollers such as the micro:bit and others.
Download Mu
Download Mu from https://codewith.mu. Click the Download or Start Here links there for downloads and installation instructions. The website has a wealth of other information, including extensive tutorials and and how-to's.
Starting up Mu
It would be best to plug your micro:bit into your computer before starting Mu, as the Mu menu changes depending on which board it detects on startup.
For Mu starting up in micro:bit mode, you should get a display like this.
The menu bar looks like the one below:
If you are familiar with Mu with CircuitPython, you are not seeing strange things. There are buttons on the menu that are different than when Mu is in CircuitPython (Adafruit) mode.
The first time you start Mu, you will be prompted to select your 'mode' - you can always change your mind later. For now please select BBC Microbit!
The current mode is displayed in the lower right corner of the window, next to the "gear" icon. If the mode says Adafruit or something else, click on that (or the leftmost menu icon Mode and then choose BBC Microbit in the dialog box that appears.
Installing MicroPython
Mu will install MicroPython for you. It is not intuitive that it does so, but it does work.
Create a new blank file/program. Ensure your micro:bit is plugged in to your computer's USB port and recognized with Mu being in Microbit mode.
Click the Flash icon shown at left.
The text in the lower left will say "Flashing MicroPython (or untitled") to the micro:bit. The micro:bit yellow LED should be flashing during this process.
Then Mu will say "Finished Flashing" in the lower left corner of its window.
MicroPython is now on your micro:bit.
The flash drive that shows up on plugging your micro:bit into the computer will NOT change at all, re. you cannot tell if MicroPython is installed on your board by looking at the flash drive representing the micro:bit (unlike CircuitPython which changes the drive name to CIRCUITPY, this does NOT happen with MicroPython).
Loading Programs
Loading MicroPython programs onto the micro:bit is different than with CircuitPython also. this will be explained next when we create a MicroPython program for Crickit.
The Seesaw Driver
To use the CRICKIT with MicroPython, you will need the Adafruit seesaw.py driver code loaded onto the board in addition to your user program named main.py.
The seesaw driver code is below. You can use the Download function to put it on your computer. The best location to download seesaw.py depends on your operating system.
Place the file seesaw.py into your mu_code folder, which might be in:
- C:\Users\YourUserName\mu_code on Windows
- /Users/YourUserName/mu_code on macOS
Putting it in the mu_code folder makes it much easier to copy the files onto the micro:bit on the next page.
Download: Project Zip or seesaw.py | View on Github
# Adafruit Seesaw / CRICKIT driver for MicroPython
# MIT License by Adafruit Industries Limor Fried
# Copy onto the micro:bit with main.py using Mu Files icon
from microbit import i2c
import struct
import time
_SIGNALS = (2, 3, 40, 41, 11, 10, 9, 8)
_PWMS = (14, 15, 16, 17, 19, 18, 22, 23, 42, 43, 12, 13)
_SERVOS = (17, 16, 15, 14)
_MOTORS = (22, 23, 19, 18)
_DRIVES = (13, 12, 43, 42)
_TOUCHES = (0, 1, 2, 3)
_ADDR = 0x49
reg_buf = bytearray(2)
pwm_buf = bytearray(3)
def _read(reghi, reglo, n, delay_s=0.01):
reg_buf[0] = reghi
reg_buf[1] = reglo
i2c.write(_ADDR, reg_buf)
time.sleep(delay_s)
return i2c.read(_ADDR, n)
def _write(reghi, reglo, cmd):
reg_buf[0] = reghi
reg_buf[1] = reglo
#print("sswrite: ", [hex(i) for i in reg_buf+cmd])
i2c.write(_ADDR, reg_buf+cmd)
# t is between 1 and 4
def read_touch(t):
return struct.unpack(">H", _read(0x0F, 0x10+_TOUCHES[t-1], 2))[0]
def pwm_write(pwm, val):
pwm_buf[0] = _PWMS.index(pwm)
pwm_buf[1] = val >> 8
pwm_buf[2] = val & 0xFF
_write(0x08, 0x01, pwm_buf)
def set_pwmfreq(pwm, freq):
pwm_buf[0] = _PWMS.index(pwm)
pwm_buf[1] = freq >> 8
pwm_buf[2] = freq & 0xFF
_write(0x08, 0x02, pwm_buf)
# signal is between 1 and 8
def analog_read(signal):
return struct.unpack(">H", _read(0x09, 0x07+signal-1, 2))[0]
def pin_config(pin, mode, pull=None, val=None):
if pin >= 32:
cmd = struct.pack(">I", 1 << (pin - 32))
cmd = bytearray(4) + cmd
else:
cmd = struct.pack(">I", 1 << pin)
if 0 <= mode <= 1:
_write(0x01, 0x03-mode, cmd)
if pull is not None and 0 <= pull <= 1:
_write(0x01, 0x0C-pull, cmd)
if val is not None and 0 <= val <= 1:
_write(0x01, 0x06-val, cmd)
def init():
i2c.init()
while not _ADDR in i2c.scan():
print("Crickit not found!")
time.sleep(1)
reg_buf[0] = 0x7F
reg_buf[1] = 0xFF
i2c.write(_ADDR, reg_buf)
# s is between 1 and 4
def servo(s, degree, min=1.0, max=2.0):
set_pwmfreq(_SERVOS[s-1], 50)
val = 3276*min + (max-min)*3276*degree/180
pwm_write(_SERVOS[s-1], int(val))
# d is between 1 and 4
def drive(d, frac, freq=1000):
set_pwmfreq(_DRIVES[d-1], freq)
pwm_write(_DRIVES[d-1], int(frac*65535))
# m is 1 or 2
def motor(m, frac, freq=1000):
m -= 1 # start with 1
pin1,pin2 = _MOTORS[m*2:m*2+2]
set_pwmfreq(pin1, freq)
set_pwmfreq(pin2, freq)
if frac < 0:
pin1, pin2 = pin2, pin1
pwm_write(pin1, 0)
pwm_write(pin2, abs(int(frac*65535)))
# signal is between 1 and 8, val is 0 or 1
def write_digital(signal, val):
pin_config(_SIGNALS[signal-1], 1, 0, val) # output, pullup, value
# signal is between 1 and 8
def read_digital(signal):
pin = _SIGNALS[signal-1]
pin_config(pin, 0, 1, 1) # input, pullup, pullvalue
ret = _read(0x01, 0x04, 8)
b = 0
if pin > 32:
b = 4
pin -= 32
b += 3 - (pin // 8)
return (ret[b] & 1<<(pin % 8)) != 0
Testing CRICKIT's Features
Connections
We can test connections using the parts in the diagram below. Feel free to omit anything you do not wish to control, this example shows testing a number of things to give you an idea what can be done.
Signals
Signal 2 to LED (long lead +), LED (short lead -) to GND (breadboard common ground)
Signal 7 to leg of switch, opposite diagonal switch leg to ground
Signal 8 to Potentiometer middle pin. Ground to one outer pin, 3.3V to the other outer pin.
Servo
Servo connected to Servo block port 1, darkest wires facing towards micro:bit slot
Motor
Motor connected to Motor port 1 (color connections do not matter)
Plug in the micro:bit and Power
The micro:bit unfortunately fits into Crickit in either orientation but only one is correct. See the board markings which says "Micro:bit LED grid facing this way" - ensure the micro:bit LEDs face the direction shown.
Use a 5 volt 2A power supply plugged into the barrel jack of the Crickit. Ensure the tiny switch next to the barrel jack is in the On position. The green LED on CRICKIT with the smiley face (shown below) shows that CRICKIT is happy with its power supply.
Do not try to power the Crickit through the micro:bit USB jack (but you can connect it to a computer for communications).
Do not try to power the Crickit through the micro-USB jack on the Crickit marked "Seesaw ONLY", that jack is not for power and it is very rarely used.
An Example: the Test Program
The following MicroPython program tests the CRICKIT and micro:bit:
- The Motor drive
- The Digital In on the Signals block
- The Digital Out on the Signals block
- The Analog In on the Signals block
- Servo drive on the Servo block
The code also has a demonstration of the Drive block setting various levels not used here.
The following capabilities are currently not written into the seesaw.py driver:
- Sound (this does not need a driver, use the standard micro:bit sound pin 0 to output sound to the CRICKIT amplifier).
- NeoPixel control via micro:bit pin 16 (use the default micropython NeoPixel driver and use pin #16!)
- Stepper motor control on either the Motor or Drive blocks. (We wanted to keep things simple)
Code
Click download to get the main.py file below via the tutorial GitHub repo. Save the file as main.py in your mu_code folder mentioned on the previous page.
Download: Project Zip or main.py | View on Github
# main.py - code to test the Adafruit CRICKIT board with
# the BBC micro:bit and MicroPython (NOT CircuitPython)
# MIT License by Limor Fried and Mike Barela, 2019
# This code requires the seesaw.py module as a driver
import time
import seesaw
seesaw.init()
while True:
# Touch test - check with the Mu plotter!
print("Touch: \n(", end="")
for i in range(1, 5):
print(seesaw.read_touch(i), end=", \t")
print(")")
# analog read signal test - assumes analog input pin 8
print("Analog signal:\n(", end="")
print(seesaw.analog_read(8), end=", \t")
print(")")
seesaw.write_digital(2, 0) # Assumes LED on Signal pin 2
time.sleep(0.1)
seesaw.write_digital(2, 1)
time.sleep(0.1)
if seesaw.read_digital(7): # Assumes button on Signal pin 7
print("pin high")
else:
print("pin low")
# Servo test - assumes servo on Servo position 1 on CRICKIT
seesaw.servo(1, 0, min=0.5, max=2.5)
time.sleep(0.5)
seesaw.servo(1, 90, min=0.5, max=2.5)
time.sleep(0.5)
seesaw.servo(1, 180, min=0.5, max=2.5)
time.sleep(0.5)
# Drive test
# seesaw.drive(1, 0.2)
# seesaw.drive(2, 0.4)
# seesaw.drive(3, 0.6)
# seesaw.drive(4, 0.8)
# motor test - assumes a DC motor on CRICKIT Motor 1 terminals
seesaw.motor(1, 1)
time.sleep(0.5)
seesaw.motor(1, 0)
time.sleep(0.5)
seesaw.motor(1, -1)
time.sleep(0.5)
seesaw.motor(1, 0)
time.sleep(0.1)
Moving the Code to the micro:bit
Click the Mu Files icon. Your files that are in your mu_code folder will show up to the right. Using your cursor, drag seesaw.py to the left pane. Then do the same for main.py. This will copy the files onto the micro:bit.
The code should run. It might take a reset of the micro:bit and/or CRICKIT (both have reset buttons on them) to work.
To use the REPL to see the output of the code, click the Files icon once more to close that window, then click the REPL button. The program output can now be viewed. If the code isn't running and you've reset the boards, press on the keyboard to do a soft reboot.
When you copy the files onto the micro:bit using Mu, they will NOT appear on the flash drive that appeared when the micro:bit was plugged into your computer. This is normal for MicroPython, you cannot see the files on the drive unlike CircuitPython.
Use
The program will continually be testing various functions as a demonstration. The LED will blink, the servo will turn, and the motor will turn on and off.
Values for the capacitive touch pads, the potentiometer, and the status of the switch will be printed out in the REPL window.
Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.
Visit TechForum