I listened to a very interesting podcast the other day which was talking about sensory extensions for humans - basically, detecting something which is currently outside human sensory range and mapping it to one of our existing senses. For example, glasses which map UV frequencies to visible light, or - more possibly - magnetic fields e.g. a compass bearing, to little vibrators. The latter was the prime example on the podcast, with a university research project based on a belt with 16 vibrators connected to a microcontroller, that cooperated with one's smartphone to always indicate North, or to use GPS to buzz the motor in the direction one was to turn.
Time for the sensory hat - an idea nicked from the podcaster, but hey, why not?
Compass - microbit!! It has a compass, and digital ports - what could possibly go wrong? Port maximum output 5mA, at 3V.
Vibrator - tiny 12000 rpm 3V DC motor, which draws about 60mA when running. Problem - motor can generate huge back EMF, which would wipe out the microbit port, so we need to bypass that with a diode.
Since the microbit ports can't handle the current draw of the motor, we need a switch of some sort. Let's use a transistor!! I haven't done this before, but conceptually it's pretty simple. That requires a resistor between the base of the transistor and the microbit port, so we don't exceed the microbit current limit.
Let's get the motor running, so to speak...
![]() |
| Test Motor connection |
Circuit diagrams courtesy of DigiKey's excellent (for free!) web-based circuit diagrammer tool. I am very impressed.
from microbit import *
display.show(Image.HEART)
pin0.write_digital(0)
buzz = False
while True:
if button_a.was_pressed():
buzz = not buzz
if buzz:
display.show(Image.HEART_SMALL)
pin0.write_digital(1)
sleep(100)
display.show(Image.HEART)
pin0.write_digital(0)
sleep(500)
That worked ok, although the ludicrously tiny and short wires of the motor are a total PitA. It is possible to modify the motor speed a bit using an analog output pin, but it's better to use short bursts of a digital pin, which are of course a long burst versions of the PWM analog pins!
However, I want to control lots, possibly 8 motors. This is tricky because the microbit only supports 6 "proper" i.e. unencumbered ports, viz. 0, 1, 2, 3, 8, 12 and 16. Now I could do 8 from 6 by multiplexing the pins' output, say 2 rows of 4 columns, with a pin driving each row/column. That requires something like two switches at each node of the 2x4 grid... like a transistor! Time for the AND gate...
![]() |
| Test hardware AND gate |
This layout combined with the following code actually worked pretty much first time! The 1K resistors are required to limit the current from the microbit pins.
from microbit import *
display.show(Image.HEART)
pin1.write_digital(0)
pin2.write_digital(0)
# Allow experimenter to see the "I'm working!" HEART
sleep(500)
display.clear()
a_on = False
b_on = False
while True:
# Flip A&B states if buttons have been pressed
if button_a.was_pressed():
a_on = not a_on
if button_b.was_pressed():
b_on = not b_on
# If a state is on, turn on the port and
# a helpful display pixel :-)
# The AND gate does the summing in hardware
if a_on:
display.set_pixel(0, 0, 9)
pin1.write_digital(1)
else:
display.set_pixel(0, 0, 0)
pin1.write_digital(0)
if b_on:
display.set_pixel(4, 0, 9)
pin2.write_digital(1)
else:
display.set_pixel(4, 0, 0)
pin2.write_digital(0)
# Let's give it a rest
sleep(500)
And now... the multiplexer!
![]() |
| Multiplexer circuit |
This eventually worked on the breadboard - lots of problems just because I had to get some kind of sensible physical arrangement of all the wires, and I used an incorrect resistor value in one row location that caused the entire row to stay dark with insufficient base current. Cool though! I'm not sure how easily I'll be able to make this into a hat... and currently I've only got 6 motors!
from microbit import *
def setPin(pin_no: int, pinOn: bool):
pin_no = pin_no % 8 # Make sure we haven't been slipped a dud
col = pin_no % 4
row = pin_no // 4
cols[col].write_digital(1 if pinOn else 0)
rows[row].write_digital(1 if pinOn else 0)
display.set_pixel(col, row, 9 if pinOn else 0)
cols = [pin0, pin1, pin2, pin8]
rows = [pin12, pin16]
display.show(Image.HEART)
for i in range(0, len(cols)-1):
cols[i].write_digital(0)
for j in range(0, len(rows)-1):
rows[j].write_digital(0)
# Allow experimenter to see the "I'm working!" HEART
sleep(500)
display.clear()
a_on = False
b_on = False
count = -1
while True:
# Flip A&B states if buttons have been pressed
if button_a.was_pressed():
a_on = not a_on
if button_b.was_pressed():
b_on = not b_on
# If a state is on, turn on the port and
# a helpful display pixel :-)
# The AND gate does the summing in hardware
display.clear()
if a_on:
count = count+1
if count > 7:
count = 0
setPin(count, True)
sleep(1000)
setPin(count, False)
# Let's give it a rest
sleep(500)
![]() |
| Patch wire madness |



