Raspberry Pi Pico
Pimoroni enviro:bit
The enviro:bit is a compact but powerful sensor board from Pimoroni. It has a microphone for detecting sound, a TCS3472 light and colour sensor and a BME280 temperature, pressure and humidity sensor.

You need to connect the 3V and GND pins to power pins on the Pico. You also need to connect the I2C pins (19 SCL, 20 SDA) from the micro:bit to two of the many I2C pins of the Pico. I connected 19 to GP17 and 20 to GP16 for my test circuit. You also need to connect pin0 from the micro:bit to an ADC pin on the Pico. I used GP26 for this. There is an LED for the colour sensor. This is on pin8 of the micro:bit and I connected it to GP15.
My approach to this was to copy the Pimoroni libraries and make the minor adjustments needed for them to work on the Pico. They were written to be as compact as possible given the memory limitations of the micro:bit.
Sound
In this program, I am testing out the single and double clap code from the Pimoroni library. I played around with the numbers from the original library to get this working reasonably.
from machine import ADC
from time import sleep, ticks_ms, ticks_diff
from micropython import const
_offset = const(36000)
adc = ADC(26)
def read_sound():
return max(0, adc.read_u16() - _offset)
def wait_for_clap(timeout = 1000, sensitivity = 15000):
start = ticks_ms()
while ticks_diff(ticks_ms(), start) < timeout:
if read_sound() > sensitivity:
return True
return False
def wait_for_double_clap(timeout = 1000, spread = 500, sensitivity = 15000):
clap_once = None
start = ticks_ms()
while ticks_diff(ticks_ms(), start) < timeout:
if read_sound() > sensitivity:
while read_sound() > sensitivity:
pass
sleep(0.1)
if clap_once is not None and ticks_diff(ticks_ms(), clap_once) < spread:
return True
else:
clap_once = ticks_diff
return False
# single clap
print("Clap")
while True:
if wait_for_clap():
print("Clapped")
break
sleep(3)
# double clap
print("Clap Twice")
while True:
if wait_for_double_clap():
print("Double clapped")
break
In this next program, I turned the LED on and off using double claps.
from machine import ADC, Pin
from time import sleep, ticks_ms, ticks_diff
from micropython import const
_offset = const(36000)
adc = ADC(26)
led = Pin(15, Pin.OUT)
def read_sound():
return max(0, adc.read_u16() - _offset)
def wait_for_clap(timeout = 1000, sensitivity = 15000):
start = ticks_ms()
while ticks_diff(ticks_ms(), start) < timeout:
if read_sound() > sensitivity:
return True
return False
def wait_for_double_clap(timeout = 1000, spread = 500, sensitivity = 15000):
clap_once = None
start = ticks_ms()
while ticks_diff(ticks_ms(), start) < timeout:
if read_sound() > sensitivity:
while read_sound() > sensitivity:
pass
sleep(0.1)
if clap_once is not None and ticks_diff(ticks_ms(), clap_once) < spread:
return True
else:
clap_once = ticks_diff
return False
while True:
if wait_for_double_clap():
print("Double clapped")
led.toggle()
Colour And Light
Here is the converted library. I saved this as tcs3472.py.
from micropython import const
import struct
_addr = 0x29
_level = 65.535
class TCS3472:
def __init__(self, i2c, led):
self.i2c = i2c
self.led = led
self.i2c.writeto(_addr, b'\x80\x03')
self.i2c.writeto(_addr, b'\x81\x2b')
def scaled(self):
crgb = self.raw()
if crgb[0] > 0:
return tuple(float(x) / crgb[0] for x in crgb[1:])
return (0,0,0)
def rgb(self):
return tuple(int(x * 255) for x in self.scaled())
def light(self):
return self.raw()[0]
def brightness(self, level=_level):
return int((self.light() / level))
def valid(self):
self.i2c.writeto(_addr, b'\x93')
return self.i2c.readfrom(_addr, 1)[0] & 1
def raw(self):
self.i2c.writeto(_addr, b'\xb4')
return struct.unpack("<HHHH", self.i2c.readfrom(_addr, 8))
def set_leds(self, state):
self.led.value(state)
And this was some code that can be used for testing the colours.
from machine import Pin, I2C
from time import sleep
from tcs3472 import TCS3472
i2c = I2C(0,sda=Pin(16), scl=Pin(17))
led = Pin(15, Pin.OUT)
t = TCS3472(i2c, led)
while True:
t.set_leds(1)
sleep(0.2)
r, g, b = t.rgb()
t.set_leds(0)
print("#{:02x}{:02x}{:02x}".format(r, g, b))
sleep(0.5)
Temperature, Pressure and Altitude
Here is the library, with minor adjustments.Save to the libraries folder as bme280.py.
from micropython import const
from time import sleep
import struct
import gc
ADDR = const(0x76)
# 500ms standby time, 16 filter coef
CONFIG = const(0b10010000)
# x16 oversampling, normal mode
CTRL_MEAS = const(0b10110111)
# x16 humidity oversampling
CTRL_HUM = const(0b00000101)
R_CHIPID = const(0xD0)
R_VERSION = const(0xD1)
R_SOFTRESET = const(0xE0)
R_CONTROL = const(0xF4)
R_HCONTROL = const(0xF2)
R_CONFIG = const(0xF5)
R_STATUS = const(0xF3)
class BME280():
def __init__(self, i2c):
self.i2c = i2c
self._temperature = 0
self._pressure = 0
self._altitude = 0
self._qnh = 1013.25 # hPa
self._w(R_SOFTRESET, 0xb6)
sleep(0.2)
self._w(R_HCONTROL, CTRL_HUM)
sleep(0.2)
self._w(R_CONTROL, CTRL_MEAS)
sleep(0.2)
self._w(R_CONFIG, CONFIG)
sleep(0.2)
self.compensation = self.i2c.readfrom_mem(ADDR, 0x88, 26)
self.compensation += self.i2c.readfrom_mem(ADDR, 0xe1, 7)
def set_qnh(self, qnh):
self._qnh = qnh
def temperature(self):
self.update()
gc.collect()
return self._temperature
def pressure(self):
self.update()
gc.collect()
return self._pressure
def humidity(self):
self.update()
gc.collect()
return self._humidity
def altitude(self):
self.update()
gc.collect()
return self._altitude
def read_all(self):
self.update()
gc.collect()
return self._temperature, self._pressure, self._humidity, self._altitude
def _w(self, reg, value):
self.i2c.writeto_mem(ADDR, reg, bytes([value]))
def update(self):
dig_T1, dig_T2, dig_T3, \
dig_P1, dig_P2, dig_P3, \
dig_P4, dig_P5, dig_P6, \
dig_P7, dig_P8, dig_P9, \
_, \
dig_H1, dig_H2, dig_H3, \
reg_E4, reg_E5, reg_E6, \
dig_H6 = struct.unpack("<HhhHhhhhhhhhbBhBbBbb", self.compensation)
dig_H4 = (reg_E5 & 0x0f) | (reg_E4 << 4)
dig_H5 = (reg_E5 >> 4) | (reg_E6 << 4)
if dig_H4 & (1 << 12):
dig_H4 -= 1 << 12
if dig_H5 & (1 << 11):
dig_H5 -= 1 << 12
raw = self.i2c.readfrom_mem(ADDR, 0xF7, 8)
raw_temp=(raw[3]<<12)|(raw[4]<<4)|(raw[5]>>4)
raw_press=(raw[0]<<12)|(raw[1]<<4)|(raw[2]>>4)
raw_hum=(raw[6]<<8)|raw[7]
var1=(raw_temp/16384.0-dig_T1/1024.0)*dig_T2
var2=(raw_temp/131072.0-dig_T1/8192.0)*(raw_temp/131072.0-dig_T1/8192.0)*dig_T3
temp=(var1+var2)/5120.0
t_fine=(var1+var2)
var1=t_fine/2.0-64000.0
var2=var1*var1*dig_P6/32768.0
var2=var2+var1*dig_P5*2
var2=var2/4.0+dig_P4*65536.0
var1=(dig_P3*var1*var1/524288.0+dig_P2*var1)/524288.0
var1=(1.0+var1/32768.0)*dig_P1
press=1048576.0-raw_press
press=(press-var2/4096.0)*6250.0/var1
var1=dig_P9*press*press/2147483648.0
var2=press*dig_P8/32768.0
press=press+(var1+var2+dig_P7)/16.0
var1 = t_fine - 76800.0
var2 = dig_H4 * 64.0 + (dig_H5 / 16384.0) * var1
var3 = raw_hum - var2
var4 = dig_H2 / 65536.0
var5 = 1.0 + (dig_H3 / 67108864.0) * var1
var6 = 1.0 + (dig_H6 / 67108864.0) * var1 * var5
var6 = var3 * var4 * (var5 * var6)
h = var6 * (1.0 - dig_H1 * var6 / 524288.0)
h = max(0, min(100, h))
self._temperature = temp
self._pressure = press / 100.0
self._humidity = h
self._altitude = 44330.0 * (1.0 - pow(self._pressure / self._qnh, (1.0/5.255)))
Here is some test code,
from machine import Pin, I2C
from time import sleep
from bme280 import BME280
i2c = I2C(0,sda=Pin(16), scl=Pin(17))
b = BME280(i2c)
while True:
t, p, h, a = b.read_all()
print("T: {t}, P: {p}, H: {h}, A: {a}".format(t=t,p=p,h=h,a=a))
sleep(1)

