mygekko.si/mip

MicroPython drivers for the parts Gekko knows

Install a driver straight onto a Pico W or an ESP32 over Wi-Fi, or from a PC with mpremote. Every file is pinned to an upstream commit and checked against its sha256 when the store is built, and only drivers whose licence allows it are hosted here.

Packages
41
Files
73
Ports
rp2 · esp32 · esp8266
Updated
2026-11-01
01Install

Three ways to install a driver

Each package installs its files into /lib on the board. The licence text is served next to every package but never copied onto the board.

  1. a

    On the board

    Connect to Wi-Fi first (network.WLAN), then at the REPL or in your script:

    import mip
    mip.install("https://mygekko.si/mip/bme280")
  2. b

    From a PC

    With the board on USB and mpremote installed:

    mpremote mip install https://mygekko.si/mip/bme280
  3. c

    By name

    Point mip at this store's index and use the bare package name:

    import mip; mip.install("bme280", index="https://mygekko.si/mip")
    mpremote mip install --index https://mygekko.si/mip bme280
02Packages

41 packages, by kind of part

Open a row for an example, the known issues and the exact files. The licence link shows the text each package ships under.

Sensors15

Sensors
PackageDrivesLicence, portsInstall on a board, or from a PC
adxl34511cf142

ADXL345 3-axis accelerometer over I2C

part adxl345 · import adxl345

Example and notes
import adxl345; a = adxl345.ADXL345(machine.I2C(0)); a.start_measurements(); x, y, z = a.get_readings()  # m/s^2

ADXL345(i2c, address=0x53, range=RANGE_2G to RANGE_16G) in full-resolution mode; pass address=0x1D when SDO is high. check_connection() compares the device id with 0xE5.

  • Needs MicroPython 1.19 or newer (float-valued const()).
  • The constructor talks to the sensor straight away (OSError if it does not answer), and readings stay zero until start_measurements() is called.
  • I2C only: no SPI, interrupts, FIFO or tap detection.

From zNitche/pico-adxl345 at 11cf142. Files: adxl345.py (3,486 bytes). package.json

MITrp2 · esp32 · esp8266import mip; mip.install("https://mygekko.si/mip/adxl345")mpremote mip install https://mygekko.si/mip/adxl345
ahtx0d61a3c0

AHT10 and AHT20 temperature and humidity sensors over I2C

parts aht20, aht10 · import ahtx0

Example and notes
import ahtx0; s = ahtx0.AHT20(machine.I2C(0)); print(s.temperature, s.relative_humidity)

Classes AHT10 and AHT20, address 0x38 (an AHT10 with ADR high needs address=0x39). Each property read starts its own measurement and polls the busy bit every 5 ms.

  • _wait_for_idle() has no timeout, so a sensor whose busy bit never clears hangs the caller.

From targetblank/micropython_ahtx0 at d61a3c0. Files: ahtx0.py (4,505 bytes). package.json

MITrp2 · esp32 · esp8266import mip; mip.install("https://mygekko.si/mip/ahtx0")mpremote mip install https://mygekko.si/mip/ahtx0
bh1750a66f11f

BH1750 ambient light sensor (GY-30, GY-302), lux over I2C

part bh1750 · import bh1750fvi

Example and notes
import bh1750fvi; lux = bh1750fvi.sample(machine.I2C(0))  # one-shot high resolution, address 0x23

One function over any machine.I2C; it only imports time. Pass i2c_addr=0x5C when ADDR is high, or mode=bh1750fvi.OP_SINGLE_LRES for the 24 ms low-resolution mode. Each call blocks about 180 ms and returns whole lux. Despite the repository name it is not ESP8266-specific.

  • sample(mode=OP_SINGLE_HRES2) reads twice the real lux: high-resolution mode 2 counts 0.5 lx per step but the driver always divides by 1.2. OP_SINGLE_HRES1 (the default) and OP_SINGLE_LRES are correct.

From catdog2/mpy_bh1750fvi_esp8266 at a66f11f. Files: bh1750fvi.py (1,355 bytes). package.json

Apache-2.0rp2 · esp32 · esp8266import mip; mip.install("https://mygekko.si/mip/bh1750")mpremote mip install https://mygekko.si/mip/bh1750
bme280a9a7080

BME280 temperature, humidity and pressure sensor over I2C (float and integer versions)

part bme280 · import bme280_float

Example and notes
import bme280_float; b = bme280_float.BME280(i2c=machine.I2C(0)); print(b.values)

bme280_float gives floats (C, Pa, %RH); bme280_int gives fixed-point integers. Forced-mode reads. The default address is 0x76; pass address=0x77 for Adafruit boards. Humidity is meaningless on a BMP280.

  • Imports ustruct, the deprecated alias of struct (it still works on current MicroPython).

From robert-hh/BME280 at a9a7080. Files: bme280_float.py (10,022 bytes), bme280_int.py (10,176 bytes). package.json

MITrp2 · esp32 · esp8266import mip; mip.install("https://mygekko.si/mip/bme280")mpremote mip install https://mygekko.si/mip/bme280
bmp28083dfdd6

BMP280 pressure and temperature sensor over I2C

part bmp280 · import bmp280

Example and notes
import bmp280; b = bmp280.BMP280(machine.I2C(0), addr=0x76); print(b.temperature, b.pressure)  # C, Pa

The constructor reads the calibration data and selects the HANDHELD_DYN use case (normal mode) unless use_case=None. Pressure uses Bosch's 64-bit integer formula. I2C only.

  • The default address is 0x76; boards strapped to 0x77 (Adafruit, for example) need addr=0x77.
  • There is no chip-id check, so a different device at that address is used silently.

From dafvid/micropython-bmp280 at 83dfdd6. Files: bmp280.py (9,983 bytes). package.json

MITrp2 · esp32 · esp8266import mip; mip.install("https://mygekko.si/mip/bmp280")mpremote mip install https://mygekko.si/mip/bmp280
hcsr0417eafe3

HC-SR04 ultrasonic distance sensor

part hc-sr04 · import hcsr04

Example and notes
from hcsr04 import HCSR04; s = HCSR04(trigger_pin=5, echo_pin=18, echo_timeout_us=30000); cm = s.distance_cm()

distance_cm() returns a float, distance_mm() an int without float maths. ECHO is a 5 V signal: put a divider or level shifter between it and a 3.3 V board.

  • On an echo timeout (nothing in range, or a wiring fault) it returns about 250 cm / 2500 mm instead of raising: current firmware's time_pulse_us returns a negative code, which the driver turns into a fixed 14,550 us pulse. Treat about 250 cm as 'no echo'.

From rsc1975/micropython-hcsr04 at 17eafe3. Files: hcsr04.py (3,400 bytes). package.json

Apache-2.0rp2 · esp32 · esp8266import mip; mip.install("https://mygekko.si/mip/hcsr04")mpremote mip install https://mygekko.si/mip/hcsr04
hx711a5502c9

HX711 load-cell amplifier (24-bit ADC)

part hx711 · import hx711_gpio

Example and notes
from hx711_gpio import HX711; hx = HX711(machine.Pin(14, machine.Pin.OUT), machine.Pin(15, machine.Pin.IN)); hx.tare(); print(hx.get_value())

Three interchangeable classes with the same methods (read, tare, get_value, get_units, read_lowpass, power_down, power_up): hx711_gpio on any port, hx711_pio on rp2 (PIO clocking, immune to interrupt latency; pass state_machine= to avoid clashes) and hx711_spi over SPI.

  • hx711_pio imports rp2, so it only works on the Pico; use hx711_gpio elsewhere.
  • set_gain() compares with 'is', so any value other than the plain integers (128.0, for example) silently leaves the gain unset.
  • Upstream points to its successor repository, HX71X.
  • hx711_spi power_down() and power_up() may only work with SoftSPI.

From robert-hh/hx711 at a5502c9. Files: hx711_gpio.py (4,506 bytes), hx711_pio.py (5,346 bytes), hx711_spi.py (4,200 bytes). package.json

MITrp2 · esp32 · esp8266import mip; mip.install("https://mygekko.si/mip/hx711")mpremote mip install https://mygekko.si/mip/hx711
lis3dhda3b9da

LIS3DH 3-axis accelerometer over I2C

part lis3dh · import micropython_lis3dh.lis3dh

Example and notes
from micropython_lis3dh import lis3dh; acc = lis3dh.LIS3DH(machine.I2C(0)); print(acc.acceleration)

Installs the micropython_lis3dh package. Address 0x18; raises RuntimeError unless WHO_AM_I is 0x33; sets 400 Hz, high-resolution mode and block data update.

  • Upstream marks the repository deprecated and unmaintained.
  • Register access uses descriptors (MICROPY_PY_DESCRIPTORS): on in the standard rp2, esp32 and esp8266 builds, possibly off in minimal custom builds.
  • I2C and acceleration only: no tap or click detection, interrupts, ADC or temperature.

From jposada202020/MicroPython_LIS3DH at da3b9da. Files: micropython_lis3dh/__init__.py (0 bytes), micropython_lis3dh/i2c_helpers.py (2,084 bytes), micropython_lis3dh/lis3dh.py (9,609 bytes). package.json

MITrp2 · esp32 · esp8266import mip; mip.install("https://mygekko.si/mip/lis3dh")mpremote mip install https://mygekko.si/mip/lis3dh
mpu6050ae68046

MPU-6050 6-axis accelerometer and gyroscope (GY-521) over I2C

part mpu6050 · import imu

Example and notes
from imu import MPU6050; m = MPU6050(machine.I2C(0)); print(m.accel.xyz, m.gyro.xyz, m.temperature)

imu.py (class MPU6050, the base of the MPU9150/9250 drivers) needs vector3d.py; both are installed. The constructor waits 200 ms, finds the chip at 0x68 or 0x69, wakes it and selects +/-2 g and +/-250 dps. Clones with another WHO_AM_I print a warning and keep working.

  • device_addr is an index (0 for 0x68, 1 for 0x69), not an address: MPU6050(i2c, device_addr=0x68) raises ValueError. Leave it out to auto-detect.
  • imu and vector3d are generic module names in /lib.
  • The chip_id property uses an f-string (MicroPython 1.17 or newer).
  • Every accel or gyro update re-reads the range register: slow, but correct.

From micropython-IMU/micropython-mpu9x50 at ae68046. Files: imu.py (14,299 bytes), vector3d.py (4,784 bytes). package.json

MITrp2 · esp32 · esp8266import mip; mip.install("https://mygekko.si/mip/mpu6050")mpremote mip install https://mygekko.si/mip/mpu6050
mq21.0.0

MQ-2 smoke and combustible gas sensor on an ADC pin

part mq-2 · import mq2

Example and notes
from mq2 import MQ2; gas = MQ2(26); print(gas.voltage(), gas.rs())

Undoes the 10k/20k divider that keeps AO under 3.3 V. calibrate() in clean air (ratio 9.83), then ratio and ppm estimates for LPG, CO and smoke from the datasheet curves, meaningful only between 200 and 10000 ppm. Let the heater warm up first. Gekko's own helper. Lines 1-21 of the file are its MIT licence, also served as LICENSE.

  • Not yet run on a board: tested under CPython against simulated machine and time modules.

From Gekko helper, MIT. Files: mq2.py (6,320 bytes). package.json

MITrp2 · esp32import mip; mip.install("https://mygekko.si/mip/mq2")mpremote mip install https://mygekko.si/mip/mq2
rcwl05161.0.0

RCWL-0516 microwave radar motion sensor on one GPIO

part rcwl-0516 · import rcwl0516

Example and notes
from rcwl0516 import RCWL0516; radar = RCWL0516(15, callback=lambda s: print('motion'), holdoff_ms=10000); print(radar.motion())

motion() reads the output; an optional rising-edge callback with a hold-off time reports new motion. A failing callback is printed and does not switch the IRQ off. Gekko's own helper. Lines 1-21 of the file are its MIT licence, also served as LICENSE.

  • Not yet run on a board: tested under CPython against simulated machine and time modules.

From Gekko helper, MIT. Files: rcwl0516.py (3,563 bytes). package.json

MITrp2 · esp32import mip; mip.install("https://mygekko.si/mip/rcwl0516")mpremote mip install https://mygekko.si/mip/rcwl0516
sgp3045ad46b

SGP30 TVOC and eCO2 air quality sensor over I2C

part sgp30 · import adafruit_sgp30

Example and notes
import adafruit_sgp30; s = adafruit_sgp30.Adafruit_SGP30(machine.I2C(0)); eco2, tvoc = s.iaq_measure()

The constructor checks the serial number and feature set and already calls iaq_init(). Measure once a second so the sensor's baseline compensation works.

  • set_iaq_baseline() and set_iaq_humidity() pack values with bytes() without range checks, so out-of-range values raise a bare ValueError.
  • The upstream README and example use Pycom's I2C syntax; follow the usage line here instead.

From alexmrqt/micropython-sgp30 at 45ad46b. Files: adafruit_sgp30.py (7,011 bytes). package.json

MITrp2 · esp32 · esp8266import mip; mip.install("https://mygekko.si/mip/sgp30")mpremote mip install https://mygekko.si/mip/sgp30
sht31b1e0ddb

SHT30, SHT31 and SHT35 temperature and humidity sensors over I2C

part sht31 · import sht31

Example and notes
import sht31; s = sht31.SHT31(machine.I2C(0), addr=0x44); t, rh = s.get_temp_humi()

get_temp_humi(resolution=R_HIGH, clock_stretch=True, celsius=True) waits 50 ms between the command and the read. The SHT30 and SHT35 share the command set.

  • Readings are not CRC-checked, and only single-shot mode is supported.

From kfricke/micropython-sht31 at b1e0ddb. Files: sht31.py (2,331 bytes). package.json

MITrp2 · esp32 · esp8266import mip; mip.install("https://mygekko.si/mip/sht31")mpremote mip install https://mygekko.si/mip/sht31
tsl2591cc705df

TSL2591 high dynamic range light sensor over I2C

part tsl2591 · import tsl2591

Example and notes
import tsl2591; s = tsl2591.TSL2591(machine.I2C(0)); print(s.lux)

Address 0x29; checks the device id (0x50) and powers on with the light sensor enabled.

  • Needs MicroPython 1.24 or newer (int.from_bytes and to_bytes without byteorder); 1.22 and 1.23 raise TypeError in the constructor.
  • lux is about 9876 times too high at Gain.MAX (the gain ladder tests Gain.HIGH twice).
  • raw_luminosity reads the four data bytes in four separate transactions, so the two channels can come from different integration cycles; lux raises RuntimeError on saturation.

From zyltr/TSL2591 at cc705df. Files: tsl2591.py (9,254 bytes). package.json

MITrp2 · esp32 · esp8266import mip; mip.install("https://mygekko.si/mip/tsl2591")mpremote mip install https://mygekko.si/mip/tsl2591
veml607586d21ff

VEML6075 UVA/UVB light sensor over I2C (raw counts)

part veml6075 · import veml6075mod

Example and notes
from sensor_pack_2.bus_service import I2cAdapter; import veml6075mod; s = veml6075mod.VEML6075(I2cAdapter(machine.I2C(0, freq=400_000))); s.shutdown(False); s.start_measurement(single_meas_mode=False, it_index=1); time.sleep_ms(100); uva, uvb = s.get_uv()

Address 0x10. Returns raw counts; the UV-index formula (Vishay application note 84339) is in the upstream main.py example, not in the package. About 59 KB of source with long docstrings, so the first import is slow.

  • sensor_pack_2 uses @micropython.native: firmware without a native code emitter (some RISC-V builds, such as older ESP32-C3/C6 or RP2350-RISC-V firmware) fails at import with SyntaxError.
  • Needs MicroPython 1.19 or newer (const() with string values).
  • The sensor can start shut down: call shutdown(False) first. get_conversion_cycle_time() keeps the integration time from construction, so call read_settings() after start_measurement() or wait 50 * 2**it_index ms.
  • sensor_pack_2 is shared by the author's other drivers; a package that ships a different sensor_pack_2 into /lib would overwrite this one.
  • Too big to compile in ESP8266 RAM without mpy-cross, so esp8266 is not listed.

From octaprog7/VEML6075 at 86d21ff. Files: veml6075mod.py (15,058 bytes), sensor_pack_2/__init__.py (57 bytes), sensor_pack_2/base_sensor.py (15,913 bytes), sensor_pack_2/bitfield.py (13,582 bytes), sensor_pack_2/bus_service.py (14,511 bytes). package.json

MITrp2 · esp32import mip; mip.install("https://mygekko.si/mip/veml6075")mpremote mip install https://mygekko.si/mip/veml6075

Displays and LEDs9

Displays and LEDs
PackageDrivesLicence, portsInstall on a board, or from a PC
dotstarf4ea122

APA102 (DotStar) addressable LED strips over SPI

part apa102 · import micropython_dotstar

Example and notes
import micropython_dotstar; strip = micropython_dotstar.DotStar(machine.SPI(1, baudrate=4_000_000), 30, brightness=0.2); strip[0] = (255, 0, 0); strip.show()

Called dotstar here because apa102 is a module frozen into the ESP8266 firmware. Pure Python with no imports: pass a machine.SPI or machine.SoftSPI object. Upstream's own package.json installs the file as dotstar.py; this store keeps micropython_dotstar.py, as the upstream README imports it.

  • Reading a pixel back is only correct for the default BGR pixel order.
  • The upstream README builds the bus with SPI(sck=..., mosi=...) and no id, the deprecated software SPI form; use machine.SPI(1, ...) or machine.SoftSPI(...).

From mattytrentini/micropython-dotstar at f4ea122. Files: micropython_dotstar.py (8,962 bytes). package.json

MITrp2 · esp32 · esp8266import mip; mip.install("https://mygekko.si/mip/dotstar")mpremote mip install https://mygekko.si/mip/dotstar
ht16k334.3.0

HT16K33 LED backpacks: 7- and 14-segment displays, 8x8 and bicolour matrices, bar graphs

part ht16k33 · import ht16k33

Example and notes
from ht16k33 import HT16K33Segment; d = HT16K33Segment(machine.I2C(0)); d.set_number(4, 0); d.draw()

Version 4.3.0. Installs the ht16k33 package: HT16K33Segment, HT16K33SegmentBig, HT16K33Segment14, HT16K33SegmentGen, HT16K33Matrix, HT16K33MatrixColour, HT16K33MatrixFeatherWing, HT16K33MatrixMulti and HT16K33Bar. Default address 0x70.

  • ht16k33/__init__.py imports all ten modules, so any import compiles about 95 KB of source: fine on rp2 and esp32, likely MemoryError on an ESP8266 (not listed).
  • ht16k33bar uses f-strings (MicroPython 1.17 or newer).
  • set_angle() with a negative angle falls back to 0 on the matrix classes.

From smittytone/HT16K33-Python at 0060f54. Files: ht16k33/__init__.py (469 bytes), ht16k33/ht16k33.py (4,610 bytes), ht16k33/ht16k33bar.py (4,649 bytes), ht16k33/ht16k33matrix.py (14,037 bytes), ht16k33/ht16k33matrixcolour.py (15,049 bytes), ht16k33/ht16k33matrixfeatherwing.py (11,534 bytes), ht16k33/ht16k33matrixmulti.py (12,614 bytes), ht16k33/ht16k33segment.py (7,960 bytes), ht16k33/ht16k33segment14.py (11,120 bytes), ht16k33/ht16k33segmentbig.py (6,944 bytes), ht16k33/ht16k33segmentgen.py (6,810 bytes). package.json

MITrp2 · esp32import mip; mip.install("https://mygekko.si/mip/ht16k33")mpremote mip install https://mygekko.si/mip/ht16k33
ili934167c5131

ILI9341 240x320 SPI TFT displays (drawing only, no touch)

part ili9341 · import ili9341

Example and notes
import ili9341; d = ili9341.Display(machine.SPI(1, baudrate=40_000_000), cs=machine.Pin(9), dc=machine.Pin(8), rst=machine.Pin(7)); d.draw_text8x8(0, 0, 'Hi', ili9341.color565(255, 255, 255))

Rotation and mirroring, x/y offsets, shapes, sprites, scrolling, and images read from a flash path. draw_text8x8() uses framebuf's built-in font.

  • 38.9 KB in one file: it will not compile in ESP8266 RAM (esp8266 is not listed), and the first import takes a moment on rp2 and esp32; mpy-cross helps.
  • Touch (xpt2046.py) and the font loader (xglcd_font.py and its font files) are not included, so draw_text() needs files from the upstream repository.

From rdagger/micropython-ili9341 at 67c5131. Files: ili9341.py (38,851 bytes). package.json

MITrp2 · esp32import mip; mip.install("https://mygekko.si/mip/ili9341")mpremote mip install https://mygekko.si/mip/ili9341
lcd16027affb0b

HD44780 character LCDs (16x2, 20x4) on a PCF8574 I2C backpack or wired in parallel

part lcd1602_i2c · import machine_i2c_lcd

Example and notes
from machine_i2c_lcd import I2cLcd; lcd = I2cLcd(machine.I2C(0, freq=100_000), 0x27, 2, 16); lcd.putstr('Hello')

machine_i2c_lcd.I2cLcd (PCF8574 backpack) builds on lcd_api.LcdApi. Use address 0x3F on PCF8574A backpacks and I2cLcd(i2c, 0x27, 4, 20) for a 20x4. nodemcu_gpio_lcd.GpioLcd drives a display wired directly in 4-bit or 8-bit mode and, despite its name, is plain machine.Pin code: GpioLcd(rs_pin=Pin(a), enable_pin=Pin(b), d4_pin=Pin(c), d5_pin=Pin(d), d6_pin=Pin(e), d7_pin=Pin(f), num_lines=2, num_columns=16).

From dhylands/python_lcd at 7affb0b. Files: machine_i2c_lcd.py (3,269 bytes), lcd_api.py (7,669 bytes), nodemcu_gpio_lcd.py (5,988 bytes). package.json

MITrp2 · esp32 · esp8266import mip; mip.install("https://mygekko.si/mip/lcd1602")mpremote mip install https://mygekko.si/mip/lcd1602
max721922195dc

MAX7219 8x8 LED matrix modules, chained (FC-16 4-in-1 and similar)

part max7219 · import max7219

Example and notes
import max7219; d = max7219.Matrix8x8(machine.SPI(1, baudrate=10_000_000), machine.Pin(9, machine.Pin.OUT), 4); d.brightness(5); d.text('Hi', 0, 0, 1); d.show()

framebuf drawing (fill, pixel, hline, vline, line, rect, fill_rect, text, scroll, blit) on an internal MONO_HLSB buffer; text() uses framebuf's 8x8 font. The third argument is the number of chained 8x8 modules.

  • 8x8 matrices only: no digit or segment API for the 8-digit 7-segment variant, and no scrolling-text engine like MD_Parola.
  • Module order and orientation depend on the board: some 4-in-1 modules show mirrored or reversed panels.

From mcauser/micropython-max7219 at 22195dc. Files: max7219.py (3,530 bytes). package.json

MITrp2 · esp32 · esp8266import mip; mip.install("https://mygekko.si/mip/max7219")mpremote mip install https://mygekko.si/mip/max7219
pcd8544791d423

PCD8544 (Nokia 5110) 84x48 monochrome LCD over SPI

part pcd8544 · import pcd8544_fb

Example and notes
import pcd8544_fb; lcd = pcd8544_fb.PCD8544_FB(machine.SPI(1, baudrate=2_000_000), cs=machine.Pin(9), dc=machine.Pin(8), rst=machine.Pin(7)); lcd.text('Hi', 0, 0, 1); lcd.show()

pcd8544_fb.PCD8544_FB subclasses framebuf.FrameBuffer and works with Peter Hinch's Writer class. pcd8544.py has the minimal PCD8544 class and a PCD8544_FRAMEBUF wrapper; neither file imports the other.

  • Always pass a reset Pin: the documented rst=None default raises TypeError, because the constructor always calls reset().
  • show() packs the buffer with a 504-argument struct.pack call each time: it works, but it is slow and allocates memory.
  • Unmaintained since 2018.

From mcauser/micropython-pcd8544 at 791d423. Files: pcd8544_fb.py (4,957 bytes), pcd8544.py (5,669 bytes). package.json

MITrp2 · esp32 · esp8266import mip; mip.install("https://mygekko.si/mip/pcd8544")mpremote mip install https://mygekko.si/mip/pcd8544
sh1106fe67423

SH1106 1.3-inch 128x64 OLED over I2C or SPI

part sh1106 · import sh1106

Example and notes
import sh1106; d = sh1106.SH1106_I2C(128, 64, machine.I2C(0, freq=400_000), addr=0x3c); d.text('Hi', 0, 0, 1); d.show()

A framebuf.FrameBuffer subclass that tracks dirty pages for partial updates; call show() after drawing. SH1106_SPI(width, height, spi, dc, res=None, cs=None) for SPI modules. rotate=0/90/180/270, flip(), contrast(), invert() and sleep().

  • ellipse() wraps FrameBuffer.ellipse, which needs MicroPython 1.20 or newer.

From robert-hh/SH1106 at fe67423. Files: sh1106.py (10,394 bytes). package.json

MITrp2 · esp32 · esp8266import mip; mip.install("https://mygekko.si/mip/sh1106")mpremote mip install https://mygekko.si/mip/sh1106
st7789py7265925

ST7789 SPI IPS TFT displays (240x240, 240x320, 135x240, 128x128), pure Python

part st7789 · import st7789py

Example and notes
import st7789py; d = st7789py.ST7789(machine.SPI(1, baudrate=40_000_000), 240, 240, reset=machine.Pin(4, machine.Pin.OUT), dc=machine.Pin(5, machine.Pin.OUT), backlight=machine.Pin(6, machine.Pin.OUT)); d.fill(st7789py.BLUE)

Russ Hughes' pure-Python driver (not his C firmware module st7789, which is why the package is not called st7789). fill, pixel, line, rect, fill_rect, blit_buffer, bitmap, polygon and hardware scrolling, plus color565() and named colours. Other panel sizes need custom_rotations.

  • Uses @micropython.viper and @micropython.native: rp2 and the Xtensa ESP32, S2 and S3 are fine; the RISC-V ESP32-C3 and C6 need a recent MicroPython with the RV32 native emitter.
  • text() needs a bitmap font module and write() a converted TrueType font module from the upstream repository; neither is included.
  • 31 KB of source, too big to compile on an ESP8266, so esp8266 is not listed.
  • Needs MicroPython 1.19 or newer (str-valued const()) and f-strings.

From russhughes/st7789py_mpy at 7265925. Files: st7789py.py (31,173 bytes). package.json

MITrp2 · esp32import mip; mip.install("https://mygekko.si/mip/st7789py")mpremote mip install https://mygekko.si/mip/st7789py
tm16371.3.0

TM1637 4-digit 7-segment display modules

part tm1637 · import tm1637

Example and notes
import tm1637; d = tm1637.TM1637(clk=machine.Pin(2), dio=machine.Pin(3)); d.numbers(12, 34)

Version 1.3.0 (the module's __version__ and the repository's package.json agree). TM1637Decimal for modules with a dot per digit. CLK and DIO are bit-banged on any GPIO.

  • The ACK bit is never read, so a wiring fault shows as a blank display rather than an exception.

From mcauser/micropython-tm1637 at cc9ecc6. Files: tm1637.py (7,943 bytes). package.json

MITrp2 · esp32 · esp8266import mip; mip.install("https://mygekko.si/mip/tm1637")mpremote mip install https://mygekko.si/mip/tm1637

Motors and actuators8

Motors and actuators
PackageDrivesLicence, portsInstall on a board, or from a PC
l298n1.0.0

L298N dual H-bridge: two DC motors, direction and PWM speed

part l298n · import l298n

Example and notes
from l298n import L298N; m = L298N(ena=10, in1=11, in2=12, enb=13, in3=14, in4=15); m.a.speed(60)

Channels .a and .b take speed -100 to 100, stop() to coast and brake(); PWM at 1 kHz by default. Pull the ENA/ENB jumpers so the PWM pins set the speed. Gekko's own helper. Lines 1-21 of the file are its MIT licence, also served as LICENSE.

  • Not yet run on a board: tested under CPython against simulated machine and time modules.

From Gekko helper, MIT. Files: l298n.py (5,264 bytes). package.json

MITrp2 · esp32import mip; mip.install("https://mygekko.si/mip/l298n")mpremote mip install https://mygekko.si/mip/l298n
pca96850fea273

PCA9685 16-channel PWM and servo boards, and the Adafruit Motor Shield V2

parts pca9685, adafruit_motor_shield_v2 · import pca9685

Example and notes
from pca9685_servo import Servos; s = Servos(machine.I2C(0), address=0x40); s.position(0, degrees=90)

pca9685.PCA9685 is the core. pca9685_servo.Servos (upstream servo.py, renamed here so it cannot replace Gekko's servo helper) defaults to address 0x40, 50 Hz, 600-2400 us and 180 degrees. motor.DCMotors and stepper.Steppers default to address 0x60 with the Adafruit Motor Shield V2 channel map: motor.DCMotors(machine.I2C(0), address=0x60).speed(0, 2000).

  • Upstream is archived (last commit 2018), so no fixes will come.
  • duty() read-back is wrong for fully-off and fully-on channels (4096 for off, 0 for on); setting a duty is fine. DCMotors.speed() read-back inherits this.
  • Upstream documentation says 'import servo'; in this store the module is pca9685_servo.
  • motor.py and stepper.py install under those generic names in /lib; another module with either name would collide with them.

From adafruit/micropython-adafruit-pca9685 at 0fea273. Files: pca9685.py (1,893 bytes), motor.py (1,262 bytes), stepper.py (6,320 bytes), pca9685_servo.py (1,177 bytes). package.json

MITrp2 · esp32 · esp8266import mip; mip.install("https://mygekko.si/mip/pca9685")mpremote mip install https://mygekko.si/mip/pca9685
relay1.0.0

Relay modules: single relays and 2, 4 or 8-channel boards

part relay_module · import relay

Example and notes
from relay import Relay; pump = Relay(15); pump.on()

active_low=True by default. The OFF level is set before the pin becomes an output, so the relay does not click at boot. RelayBank drives several channels. Gekko's own helper. Lines 1-21 of the file are its MIT licence, also served as LICENSE.

  • Not yet run on a board: tested under CPython against simulated machine and time modules.

From Gekko helper, MIT. Files: relay.py (3,832 bytes). package.json

MITrp2 · esp32import mip; mip.install("https://mygekko.si/mip/relay")mpremote mip install https://mygekko.si/mip/relay
servo1.0.0

Hobby servos (SG90, MG90S, MG996R) on one PWM pin

part sg90 · import servo

Example and notes
from servo import Servo; s = Servo(15); s.angle(90)

500-2500 us pulses at 50 Hz by default; no pulse is sent until angle() is called. off() stops the pulses and speed() drives continuous-rotation servos. Power the servo from its own 5 V supply. Gekko's own helper. Lines 1-21 of the file are its MIT licence, also served as LICENSE.

  • Not yet run on a board: tested under CPython against simulated machine and time modules.

From Gekko helper, MIT. Files: servo.py (4,820 bytes). package.json

MITrp2 · esp32import mip; mip.install("https://mygekko.si/mip/servo")mpremote mip install https://mygekko.si/mip/servo
solenoid1.0.0

Solenoids switched by a logic-level MOSFET, with an on-time guard

part solenoid · import solenoid

Example and notes
from solenoid import Solenoid; lock = Solenoid(15); lock.pulse(2000)

pulse(ms) is capped at max_on_ms (10 s by default) and always ends with the solenoid off, even on Ctrl-C. An optional PWM hold duty follows the initial kick. Gekko's own helper. Lines 1-21 of the file are its MIT licence, also served as LICENSE.

  • Not yet run on a board: tested under CPython against simulated machine and time modules.

From Gekko helper, MIT. Files: solenoid.py (4,178 bytes). package.json

MITrp2 · esp32import mip; mip.install("https://mygekko.si/mip/solenoid")mpremote mip install https://mygekko.si/mip/solenoid
stepper_4phase1.0.0

28BYJ-48 stepper on a ULN2003 board, or any 4-phase unipolar stepper

part uln2003 · import stepper_4phase

Example and notes
from stepper_4phase import Stepper4Phase; m = Stepper4Phase(2, 3, 4, 5); m.step(4096)

Half-step, full-step and wave sequences with deadline timing that never rushes to catch up after a stall; turn() and release(). Nominally 4096 half-steps per turn (the real 63.684:1 gearbox gives about 4075.8). Gekko's own helper. Lines 1-21 of the file are its MIT licence, also served as LICENSE.

  • Not yet run on a board: tested under CPython against simulated machine and time modules.

From Gekko helper, MIT. Files: stepper_4phase.py (4,816 bytes). package.json

MITrp2 · esp32import mip; mip.install("https://mygekko.si/mip/stepper_4phase")mpremote mip install https://mygekko.si/mip/stepper_4phase
stepper_stepdir1.0.0

STEP/DIR stepper drivers (DRV8825, A4988 and other StepStick carriers)

part drv8825 · import stepper_stepdir

Example and notes
from stepper_stepdir import StepperStepDir; m = StepperStepDir(step=2, dir=3, en=4); m.turn(360)

Keeps the STEP and DIR timing the DRV8825 and A4988 need; enable() and disable(); microstep() sets M0-M2 when they are wired. No acceleration. Gekko's own helper. Lines 1-21 of the file are its MIT licence, also served as LICENSE.

  • Not yet run on a board: tested under CPython against simulated machine and time modules.

From Gekko helper, MIT. Files: stepper_stepdir.py (6,348 bytes). package.json

MITrp2 · esp32import mip; mip.install("https://mygekko.si/mip/stepper_stepdir")mpremote mip install https://mygekko.si/mip/stepper_stepdir
tb6612fng1.0.0

TB6612FNG dual MOSFET motor driver: two DC motors

part tb6612fng · import tb6612fng

Example and notes
from tb6612fng import TB6612FNG; m = TB6612FNG(pwma=10, ain1=11, ain2=12, pwmb=13, bin1=14, bin2=15, stby=16); m.a.speed(60)

Same API as l298n, following Toshiba's truth table. STBY goes HIGH only after every input is off; without a STBY pin, standby() coasts instead. PWM at 20 kHz by default. Gekko's own helper. Lines 1-21 of the file are its MIT licence, also served as LICENSE.

  • Not yet run on a board: tested under CPython against simulated machine and time modules.

From Gekko helper, MIT. Files: tb6612fng.py (6,037 bytes). package.json

MITrp2 · esp32import mip; mip.install("https://mygekko.si/mip/tb6612fng")mpremote mip install https://mygekko.si/mip/tb6612fng

Modules and input9

Modules and input
PackageDrivesLicence, portsInstall on a board, or from a PC
ads1x158981f67

ADS1115, ADS1015, ADS1113 and ADS1114 analog-to-digital converters over I2C

part ads1115 · import ads1x15

Example and notes
from ads1x15 import ADS1115; adc = ADS1115(machine.I2C(0), address=0x48, gain=1); raw = adc.read(4, 0); volts = adc.raw_to_v(raw)

gain is an index (0 = +/-6.144 V, 1 = +/-4.096 V, 2 = +/-2.048 V and so on). read(rate=4, channel1=0, channel2=None) returns a signed raw count, and raw_to_v() converts it. Continuous and ALERT modes are supported too.

  • alert_start(latched=True) writes only the latch and one-conversion bits because of an operator precedence bug, so rate, gain, mode and channel fall back to the chip defaults; latched=False works.

From robert-hh/ads1x15 at 8981f67. Files: ads1x15.py (9,909 bytes). package.json

MITrp2 · esp32 · esp8266import mip; mip.install("https://mygekko.si/mip/ads1x15")mpremote mip install https://mygekko.si/mip/ads1x15
dfplayerca8b5b2

DFPlayer Mini MP3 player module over UART

part dfplayer-mini · import dfplayer

Example and notes
from dfplayer import DFPlayer; df = DFPlayer(uart_id=0, tx_pin_id=0, rx_pin_id=1); df.volume(20); df.play(1, 1)

9600 baud. play(folder, file), stop(), volume(0-30), volume_up() and volume_down(), reset(), is_playing(), get_volume() and get_files_in_folder(). Installs as the package dfplayer/.

  • Checksum bug in send_cmd(): frames whose bytes add up to 384 or more get a wrong checksum (for example play(folder, file) with folder + file >= 108), and the module may reject them.
  • The constructor first opens the UART on the port's default pins. On a classic ESP32 avoid UART 1 (its default pins are flash pins on many modules) and use UART 2.
  • is_playing(), get_volume() and get_files_in_folder() call UART.flush(), which needs MicroPython 1.20 or newer.
  • esp8266 is not listed: its UART1 only transmits, so queries time out.

From redoxcode/micropython-dfplayer at ca8b5b2. Files: dfplayer/__init__.py (2,557 bytes). package.json

MITrp2 · esp32import mip; mip.install("https://mygekko.si/mip/dfplayer")mpremote mip install https://mygekko.si/mip/dfplayer
ds32316c4b362

DS3231 precision real-time clock (ZS-042 module) over I2C

part ds3231 · import ds3231_gen

Example and notes
from ds3231_gen import DS3231; d = DS3231(machine.I2C(0)); print(d.get_time(), d.temperature())

get_time() and set_time() use time.localtime() tuples (set_time() with no argument copies the board's clock); alarm1 and alarm2 repeat from EVERY_SECOND to EVERY_MONTH; temperature() reads the chip's sensor. Only this file is taken from Peter Hinch's samples repository. The AT24C32 EEPROM on the ZS-042 board is not covered.

  • Importing it creates a module-level machine.RTC() and prints a warning if the port has none.
  • DS3231(i2c) raises RuntimeError if 0x68 does not answer a bus scan.
  • Uses f-strings (MicroPython 1.17 or newer).

From peterhinch/micropython-samples at 6c4b362. Files: ds3231_gen.py (4,902 bytes). package.json

MITrp2 · esp32 · esp8266import mip; mip.install("https://mygekko.si/mip/ds3231")mpremote mip install https://mygekko.si/mip/ds3231
matrix_keypad1.0.0

Matrix keypads (4x4, 3x4 and other sizes) scanned from GPIOs

part keypad_4x4 · import matrix_keypad

Example and notes
from matrix_keypad import MatrixKeypad; kp = MatrixKeypad(rows=(2, 3, 4, 5), cols=(6, 7, 8, 9)); print(kp.get_key())

Rows are open-drain outputs pulled LOW one at a time and columns are pull-up inputs; 20 ms debounce. get_key() reports each press once and pressed() returns every key held. Gekko's own helper. Lines 1-21 of the file are its MIT licence, also served as LICENSE.

  • Not yet run on a board: tested under CPython against simulated machine and time modules.

From Gekko helper, MIT. Files: matrix_keypad.py (5,081 bytes). package.json

MITrp2 · esp32import mip; mip.install("https://mygekko.si/mip/matrix_keypad")mpremote mip install https://mygekko.si/mip/matrix_keypad
mfrc5223d52d16

MFRC522 (RC522) 13.56 MHz RFID reader over SPI

part mfrc522 · import mfrc522

Example and notes
from mfrc522 import MFRC522; r = MFRC522(spi_id=0, sck=18, mosi=19, miso=16, cs=17, rst=20); stat, bits = r.request(r.REQIDL)  # stat == r.OK when a card is in the field

Stefan Wendler's driver as extended by Daniel Perron (Pico support, 7- and 10-byte UIDs, NTAG). On rp2 it uses hardware SPI(spi_id, ...). The file has CRLF line endings and is served byte-for-byte.

  • On esp32 and esp8266 it builds the legacy software SPI (SPI with no id): it works at a fixed 100 kHz, ignores spi_id and baudrate, and prints a deprecation warning every time.
  • IsNTAG() checks the wrong byte, so NTAG216 tags are never detected (NTAG213 and 215 are).
  • A missing card costs the full 2000-poll timeout in _tocard(): slow, not wrong.

From danjperron/micropython-mfrc522 at 3d52d16. Files: mfrc522.py (14,944 bytes). package.json

MITrp2 · esp32 · esp8266import mip; mip.install("https://mygekko.si/mip/mfrc522")mpremote mip install https://mygekko.si/mip/mfrc522
micropygpsf6c2b76

NMEA sentence parser for UART GPS modules (u-blox NEO-6M and others)

part neo-6m · import micropyGPS

Example and notes
from micropyGPS import MicropyGPS; gps = MicropyGPS(); uart = machine.UART(0, 9600); [gps.update(chr(b)) for b in (uart.read() or b'')]; print(gps.latitude, gps.longitude)

A pure parser with no machine import: feed it every byte read from the UART. Parses RMC, GGA, VTG, GSA, GSV and GLL sentences from GP, GL and GN talkers.

  • 29.5 KB of source: compiling it on an ESP8266 probably runs out of heap (esp8266 is not listed; use a precompiled .mpy there).
  • GA, GB and BD-only sentences are ignored; the NEO-6M sends GP, so it is fine.
  • gpgsa() and gpgsv() can raise IndexError out of update() on a CRC-valid but truncated sentence.

From inmcm/micropyGPS at f6c2b76. Files: micropyGPS.py (29,515 bytes). package.json

MITrp2 · esp32import mip; mip.install("https://mygekko.si/mip/micropygps")mpremote mip install https://mygekko.si/mip/micropygps
pn532a5d8189

PN532 NFC/RFID reader over SPI (Mifare Classic, NTAG2xx)

part pn532 · import NFC_PN532

Example and notes
import NFC_PN532 as nfc; pn = nfc.PN532(machine.SPI(0, baudrate=1_000_000), machine.Pin(17, machine.Pin.OUT)); pn.SAM_configuration(); uid = pn.read_passive_target(timeout=500)

Single file with no local imports. Set the PN532 board's mode switches to SPI. The constructor waits about 2 s for the chip to wake; an optional reset= Pin pulses RSTPDN. The driver bit-reverses bytes itself, so keep the SPI bus at its default MSB-first mode 0. Supports Mifare Classic authenticate and read, and NTAG2xx write.

  • SPI only: no I2C or HSU (UART) transport.
  • ntag2xx_read_block() raises TypeError when a read fails, and ntag2xx_write_block() and mifare_classic_authenticate_block() fail the same way when the PN532 times out (they index a None response).
  • 15.8 KB of source: compiling it on an ESP8266 may run out of RAM; precompile it with mpy-cross there.

From Carglglz/NFC_PN532_SPI at a5d8189. Files: NFC_PN532.py (15,788 bytes). package.json

MITrp2 · esp32 · esp8266import mip; mip.install("https://mygekko.si/mip/pn532")mpremote mip install https://mygekko.si/mip/pn532
rf433ffb12a1

433 MHz remote controls: record a remote's codes, then replay them

no part record · import tx

Example and notes
from rx import RX; r = RX(machine.Pin(17, machine.Pin.IN)); r('on'); r.save('remote.json')  # later: from tx import TX; TX(machine.Pin(16, machine.Pin.OUT), 'remote.json')('on')

Peter Hinch's record-and-replay library: capture each button once with rx.RX and save the pulse trains to JSON, then replay them with tx.TX. The ESP32 transmits with esp32.RMT, the Pico with PIO. There is no Gekko part record for the 433 MHz modules.

  • Not an RCSwitch replacement: there is no send(code, bits) API, only record and replay.
  • Installs two generic top-level packages, tx/ and rx/, which can clash with a project's own tx.py or rx.py.
  • esp8266 is not supported.
  • On the Pico, TX takes PIO 0 state machine 0 and the PIO0 IRQ, which clashes with other PIO0 users such as hx711_pio with its default state_machine=0.
  • The receiver module's output is 5 V: level-shift it for 3.3 V boards.

From peterhinch/micropython_remote at ffb12a1. Files: tx/__init__.py (4,464 bytes), tx/get_pin.py (729 bytes), tx/rp2_rmt.py (3,259 bytes), rx/__init__.py (4,270 bytes), rx/get_pin.py (623 bytes). package.json

MITrp2 · esp32import mip; mip.install("https://mygekko.si/mip/rf433")mpremote mip install https://mygekko.si/mip/rf433
rotaryb4c8ce5

Rotary encoders (KY-040 and similar), interrupt-driven

part ky-040 · import rotary

Example and notes
from rotary_irq_rp2 import RotaryIRQ; r = RotaryIRQ(pin_num_clk=16, pin_num_dt=17, min_val=0, max_val=100, range_mode=RotaryIRQ.RANGE_BOUNDED); print(r.value())

rotary.py is the core; import the port file: rotary_irq_rp2 on a Pico, rotary_irq_esp on an ESP32 or ESP8266. The Pyboard file (rotary_irq_pyb.py) is not included.

  • Exceptions raised by listeners are swallowed inside the pin IRQ handler.
  • On an ESP8266, GPIO16 has no IRQ and is rejected.

From miketeachman/micropython-rotary at b4c8ce5. Files: rotary.py (5,408 bytes), rotary_irq_rp2.py (1,826 bytes), rotary_irq_esp.py (2,457 bytes). package.json

MITrp2 · esp32 · esp8266import mip; mip.install("https://mygekko.si/mip/rotary")mpremote mip install https://mygekko.si/mip/rotary
03Not hosted

Listed, but not hosted

Only drivers whose licence allows redistribution are hosted: MIT, BSD-2-Clause, BSD-3-Clause, Apache-2.0 and ISC. GPL, D-FSL, unlicensed and unclear drivers are listed under not_hosted with their upstream github: install strings and are never copied to the server. These install straight from their upstream repositories instead.

Drivers that are not hosted
DriverWhy it is not hostedLicenceInstall from upstream
vl53l0xpart vl53l0x

VL53L0X laser time-of-flight distance sensor

Licence unclear. The BSD-3-Clause LICENSE was added in 2026, but about 500 of the file's 512 non-trivial lines are verbatim from uceeatz/VL53L0X, which has no licence; the new grant can only cover the later changes.

A Gekko helper ported from Adafruit_CircuitPython_VL53L0X (MIT), keeping its notice.

import vl53l0x; tof = vl53l0x.VL53L0X(machine.I2C(0)); mm = tof.ping()

BSD-3-Clause (unclear)import mip; mip.install("github:kevinmcaleer/vl53l0x/vl53l0x.py", version="d71ce30b0efaa4e45a771049056d8c9fdc2755ac")mpremote mip install github:kevinmcaleer/vl53l0x/vl53l0x.py@d71ce30b0efaa4e45a771049056d8c9fdc2755ac
fusionno part record

Madgwick sensor fusion (heading, pitch, roll) over any IMU's readings

Licence unclear. The repository is MIT, but update() and update_nomag() transliterate x-io's MadgwickAHRS.cs line by line, and that code was published without a licence (x-io's site defaulted to the GPL), so the MIT grant cannot be relied on for the filter.

Port x-io's newer Fusion library (github.com/xioTechnologies/Fusion, MIT) as a Gekko helper, keeping x-io's notice.

from fusion import Fusion; f = Fusion(); f.update_nomag(accel_xyz, gyro_dps_xyz); print(f.heading, f.pitch, f.roll)

MIT (unclear)import mip; mip.install("github:micropython-IMU/micropython-fusion/fusion.py", version="43748e9cc277ed7d17445025f48b774e2cc2288e")mpremote mip install github:micropython-IMU/micropython-fusion/fusion.py@43748e9cc277ed7d17445025f48b774e2cc2288eimport mip; mip.install("github:micropython-IMU/micropython-fusion/deltat.py", version="43748e9cc277ed7d17445025f48b774e2cc2288e")mpremote mip install github:micropython-IMU/micropython-fusion/deltat.py@43748e9cc277ed7d17445025f48b774e2cc2288e
epaperpart epaper_213

Waveshare 2.13-inch e-paper (V4, SSD1680) on a Pico

GPL-3.0 is copyleft; the store only redistributes MIT, BSD, Apache-2.0 and ISC drivers.

peterhinch/micropython-nano-gui drivers/epaper/pico_epaper_213_v4.py (MIT, needs drivers/boolpalette.py) could be resolved and hosted instead.

The file name has '-' and '.', so save it under an importable name (epd_2in13_v4.py, for example); its pins are hard-coded for the Pico.

GPL-3.0import mip; mip.install("github:waveshareteam/Pico_ePaper_Code/python/Pico_ePaper-2.13_V4.py")mpremote mip install github:waveshareteam/Pico_ePaper_Code/python/Pico_ePaper-2.13_V4.py
apds9960part apds9960

APDS-9960 proximity and light sensor (no gestures)

GPL-3.0 is copyleft; the store only redistributes MIT, BSD, Apache-2.0 and ISC drivers.

s = apds9960LITE.APDS9960LITE(machine.I2C(0)); s.prox.enableSensor(); s.prox.proximityLevel

GPL-3.0import mip; mip.install("github:rlangoy/uPy_APDS9960/uPy_APDS9960/apds9960LITE.py")mpremote mip install github:rlangoy/uPy_APDS9960/uPy_APDS9960/apds9960LITE.py
as608part as608

AS608 / ZhianTec optical fingerprint sensors over UART

D-FSL (German Free Software License) is copyleft; the store only redistributes MIT, BSD, Apache-2.0 and ISC drivers.

PyFingerprint(machine.UART(1, 57600, tx=machine.Pin(4), rx=machine.Pin(5))).verifyPassword() # tested by its author on an R503; the AS608 shares the command set but is unverified

D-FSL-1.0import mip; mip.install("github:chrisb2/micropython-fingerprint/pyfingerprint.py")mpremote mip install github:chrisb2/micropython-fingerprint/pyfingerprint.py