Skills micropython-skills/sensor
MicroPython sensor reading — DHT11/22, BME280, MPU6050, ADC, ultrasonic HC-SR04, photoresistor, generic I2C sensors.
install
source · Clone the upstream repo
git clone https://github.com/openclaw/skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/openclaw/skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/0x1abin/micropython-skills/skills/sensor" ~/.claude/skills/openclaw-skills-micropython-skills-sensor && rm -rf "$T"
OpenClaw · Install into ~/.openclaw/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/openclaw/skills "$T" && mkdir -p ~/.openclaw/skills && cp -r "$T/skills/0x1abin/micropython-skills/skills/sensor" ~/.openclaw/skills/openclaw-skills-micropython-skills-sensor && rm -rf "$T"
manifest:
skills/0x1abin/micropython-skills/skills/sensor/SKILL.mdsource content
Sensor Reading
Code templates for reading common sensors on MicroPython devices. All sensor reads are Safe tier — execute directly without user confirmation.
Always adapt pin numbers to the target board. When unsure, ask the user which GPIO pins are connected.
DHT11 / DHT22 (Temperature & Humidity)
import dht, json from machine import Pin try: # DHT22 is more accurate; use dht.DHT11 for DHT11 sensor = dht.DHT22(Pin(4)) # Adapt GPIO pin sensor.measure() print("RESULT:" + json.dumps({ "temperature_c": sensor.temperature(), "humidity_pct": sensor.humidity(), })) except Exception as e: print("ERROR:" + str(e))
Notes:
- DHT22 range: -40~80C, 0-100% RH, accuracy +-0.5C
- DHT11 range: 0~50C, 20-80% RH, accuracy +-2C
- Minimum 2s between reads for DHT22, 1s for DHT11
- Needs a 4.7k-10k pull-up resistor on data pin (many modules have this built-in)
BME280 (Temperature, Pressure, Humidity)
I2C sensor, common addresses: 0x76 or 0x77.
from machine import Pin, I2C import json try: i2c = I2C(0, sda=Pin(21), scl=Pin(22), freq=100000) addrs = i2c.scan() bme_addr = 0x76 if 0x76 in addrs else (0x77 if 0x77 in addrs else None) if not bme_addr: print("ERROR:BME280 not found. I2C scan: " + str(["0x{:02x}".format(a) for a in addrs])) raise SystemExit # Read calibration and raw data — simplified using BME280 register map # For production use, recommend uploading a bme280 library via mpremote fs cp # Quick raw read of chip ID to verify: chip_id = i2c.readfrom_mem(bme_addr, 0xD0, 1)[0] if chip_id == 0x60: sensor_type = "BME280" elif chip_id == 0x58: sensor_type = "BMP280 (no humidity)" else: sensor_type = "Unknown (chip_id=0x{:02x})".format(chip_id) print("RESULT:" + json.dumps({ "sensor": sensor_type, "address": "0x{:02x}".format(bme_addr), "note": "Upload bme280.py library for full T/P/H reading: mpremote fs cp bme280.py :", })) except Exception as e: print("ERROR:" + str(e))
With library uploaded (
mpremote mip install bme280 or manual upload):
import bme280, json from machine import Pin, I2C try: i2c = I2C(0, sda=Pin(21), scl=Pin(22)) sensor = bme280.BME280(i2c=i2c) t, p, h = sensor.values # Returns strings like "23.45C", "1013.25hPa", "48.7%" print("RESULT:" + json.dumps({"temperature": t, "pressure": p, "humidity": h})) except Exception as e: print("ERROR:" + str(e))
MPU6050 (Accelerometer + Gyroscope)
I2C address: 0x68 (or 0x69 with AD0 high).
from machine import Pin, I2C import json, struct try: i2c = I2C(0, sda=Pin(21), scl=Pin(22), freq=400000) addr = 0x68 # Wake up MPU6050 (power management register) i2c.writeto_mem(addr, 0x6B, b'\x00') # Read 14 bytes starting at 0x3B (accel + temp + gyro) data = i2c.readfrom_mem(addr, 0x3B, 14) ax, ay, az, temp_raw, gx, gy, gz = struct.unpack(">hhhhhhh", data) # Convert: accel in g (default +-2g range), gyro in deg/s (default +-250) print("RESULT:" + json.dumps({ "accel_g": {"x": ax/16384, "y": ay/16384, "z": az/16384}, "gyro_dps": {"x": gx/131, "y": gy/131, "z": gz/131}, "temp_c": temp_raw/340 + 36.53, })) except Exception as e: print("ERROR:" + str(e))
ADC (Analog-to-Digital Converter)
from machine import ADC, Pin import json try: adc = ADC(Pin(34)) # ESP32 ADC1 pins: 32-39 # ESP32 attenuation settings: # ADC.ATTN_0DB: 0-1.1V (most accurate) # ADC.ATTN_6DB: 0-1.5V # ADC.ATTN_11DB: 0-3.3V (full range) adc.atten(ADC.ATTN_11DB) adc.width(ADC.WIDTH_12BIT) # 0-4095 raw = adc.read() voltage = raw / 4095 * 3.3 # Approximate voltage print("RESULT:" + json.dumps({ "raw": raw, "voltage_v": round(voltage, 3), "attenuation": "11dB (0-3.3V)", })) except Exception as e: print("ERROR:" + str(e))
Notes:
- ESP32 ADC is non-linear; for precision, use calibration lookup or external ADC
- ADC2 pins (GPIO 0,2,4,12-15,25-27) cannot be used while WiFi is active
- RP2040: use
,ADC(26)
,ADC(27)
— 12-bit, 0-3.3V rangeADC(28)
HC-SR04 Ultrasonic Distance
from machine import Pin, time_pulse_us import time, json try: trigger = Pin(5, Pin.OUT) echo = Pin(18, Pin.IN) trigger.value(0) time.sleep_us(2) trigger.value(1) time.sleep_us(10) trigger.value(0) duration = time_pulse_us(echo, 1, 30000) # timeout 30ms (~5m max) if duration < 0: print("ERROR:No echo received (object too far or not connected)") else: distance_cm = duration * 0.0343 / 2 print("RESULT:" + json.dumps({ "distance_cm": round(distance_cm, 1), "duration_us": duration, })) except Exception as e: print("ERROR:" + str(e))
Photoresistor (LDR)
Light level via ADC — brighter light = lower resistance = higher ADC value (with pull-down) or lower (with pull-up voltage divider):
from machine import ADC, Pin import json try: adc = ADC(Pin(34)) adc.atten(ADC.ATTN_11DB) raw = adc.read() # Map to rough percentage (depends on voltage divider circuit) light_pct = round(raw / 4095 * 100, 1) print("RESULT:" + json.dumps({"raw": raw, "light_pct": light_pct})) except Exception as e: print("ERROR:" + str(e))
Generic I2C Sensor Read
Template for reading arbitrary I2C registers:
from machine import Pin, I2C import json try: i2c = I2C(0, sda=Pin(21), scl=Pin(22), freq=100000) addr = 0x48 # Target device address reg = 0x00 # Register to read nbytes = 2 # Number of bytes to read data = i2c.readfrom_mem(addr, reg, nbytes) print("RESULT:" + json.dumps({ "address": "0x{:02x}".format(addr), "register": "0x{:02x}".format(reg), "data_hex": " ".join("0x{:02x}".format(b) for b in data), "data_bytes": list(data), })) except Exception as e: print("ERROR:" + str(e))