Back to skills
SkillHub ClubShip Full StackFull Stack

hardware

Read and control I2C and SPI peripherals on Sipeed boards (LicheeRV Nano, MaixCAM, NanoKVM).

Packaged view

This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.

Stars
25,427
Hot score
99
Updated
March 20, 2026
Overall rating
C4.0
Composite score
4.0
Best-practice grade
B84.0

Install command

npx @skill-hub/cli install sipeed-picoclaw-hardware

Repository

sipeed/picoclaw

Skill path: workspace/skills/hardware

Read and control I2C and SPI peripherals on Sipeed boards (LicheeRV Nano, MaixCAM, NanoKVM).

Open repository

Best for

Primary workflow: Ship Full Stack.

Technical facets: Full Stack.

Target audience: everyone.

License: Unknown.

Original source

Catalog source: SkillHub Club.

Repository owner: sipeed.

This is still a mirrored public skill entry. Review the repository before installing into production workflows.

What it helps with

  • Install hardware into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
  • Review https://github.com/sipeed/picoclaw before adding hardware to shared team environments
  • Use hardware for development workflows

Works across

Claude CodeCodex CLIGemini CLIOpenCode

Favorites: 0.

Sub-skills: 0.

Aggregator: No.

Original source / Raw SKILL.md

---
name: hardware
description: Read and control I2C and SPI peripherals on Sipeed boards (LicheeRV Nano, MaixCAM, NanoKVM).
homepage: https://wiki.sipeed.com/hardware/en/lichee/RV_Nano/1_intro.html
metadata: {"nanobot":{"emoji":"πŸ”§","requires":{"tools":["i2c","spi"]}}}
---

# Hardware (I2C / SPI)

Use the `i2c` and `spi` tools to interact with sensors, displays, and other peripherals connected to the board.

## Quick Start

```
# 1. Find available buses
i2c detect

# 2. Scan for connected devices
i2c scan  (bus: "1")

# 3. Read from a sensor (e.g. AHT20 temperature/humidity)
i2c read  (bus: "1", address: 0x38, register: 0xAC, length: 6)

# 4. SPI devices
spi list
spi read  (device: "2.0", length: 4)
```

## Before You Start β€” Pinmux Setup

Most I2C/SPI pins are shared with WiFi on Sipeed boards. You must configure pinmux before use.

See `references/board-pinout.md` for board-specific commands.

**Common steps:**
1. Stop WiFi if using shared pins: `/etc/init.d/S30wifi stop`
2. Load i2c-dev module: `modprobe i2c-dev`
3. Configure pinmux with `devmem` (board-specific)
4. Verify with `i2c detect` and `i2c scan`

## Safety

- **Write operations** require `confirm: true` β€” always confirm with the user first
- I2C addresses are validated to 7-bit range (0x03-0x77)
- SPI modes are validated (0-3 only)
- Maximum per-transaction: 256 bytes (I2C), 4096 bytes (SPI)

## Common Devices

See `references/common-devices.md` for register maps and usage of popular sensors:
AHT20, BME280, SSD1306 OLED, MPU6050 IMU, DS3231 RTC, INA219 power monitor, PCA9685 PWM, and more.

## Troubleshooting

| Problem | Solution |
|---------|----------|
| No I2C buses found | `modprobe i2c-dev` and check device tree |
| Permission denied | Run as root or add user to `i2c` group |
| No devices on scan | Check wiring, pull-up resistors (4.7k typical), and pinmux |
| Bus number changed | I2C adapter numbers can shift between boots; use `i2c detect` to find current assignment |
| WiFi stopped working | I2C-1/SPI-2 share pins with WiFi SDIO; can't use both simultaneously |
| `devmem` not found | Download separately or use `busybox devmem` |
| SPI transfer returns all zeros | Check MISO wiring and device power |
| SPI transfer returns all 0xFF | Device not responding; check CS pin and clock polarity (mode) |


---

## Referenced Files

> The following files are referenced in this skill and included for context.

### references/board-pinout.md

```markdown
# Board Pinout & Pinmux Reference

## LicheeRV Nano (SG2002)

### I2C Buses

| Bus | Pins | Notes |
|-----|------|-------|
| I2C-1 | P18 (SCL), P21 (SDA) | **Shared with WiFi SDIO** β€” must stop WiFi first |
| I2C-3 | Available on header | Check device tree for pin assignment |
| I2C-5 | Software (BitBang) | Slower but no pin conflicts |

### SPI Buses

| Bus | Pins | Notes |
|-----|------|-------|
| SPI-2 | P18 (CS), P21 (MISO), P22 (MOSI), P23 (SCK) | **Shared with WiFi** β€” must stop WiFi first |
| SPI-4 | Software (BitBang) | Slower but no pin conflicts |

### Setup Steps for I2C-1

```bash
# 1. Stop WiFi (shares pins with I2C-1)
/etc/init.d/S30wifi stop

# 2. Configure pinmux for I2C-1
devmem 0x030010D0 b 0x2   # P18 β†’ I2C1_SCL
devmem 0x030010DC b 0x2   # P21 β†’ I2C1_SDA

# 3. Load i2c-dev module
modprobe i2c-dev

# 4. Verify
ls /dev/i2c-*
```

### Setup Steps for SPI-2

```bash
# 1. Stop WiFi (shares pins with SPI-2)
/etc/init.d/S30wifi stop

# 2. Configure pinmux for SPI-2
devmem 0x030010D0 b 0x1   # P18 β†’ SPI2_CS
devmem 0x030010DC b 0x1   # P21 β†’ SPI2_MISO
devmem 0x030010E0 b 0x1   # P22 β†’ SPI2_MOSI
devmem 0x030010E4 b 0x1   # P23 β†’ SPI2_SCK

# 3. Verify
ls /dev/spidev*
```

### Max Tested SPI Speed
- SPI-2 hardware: tested up to **93 MHz**
- `spidev_test` is pre-installed on the official image for loopback testing

---

## MaixCAM

### I2C Buses

| Bus | Pins | Notes |
|-----|------|-------|
| I2C-1 | Overlaps with WiFi | Not recommended |
| I2C-3 | Overlaps with WiFi | Not recommended |
| I2C-5 | A15 (SCL), A27 (SDA) | **Recommended** β€” software I2C, no conflicts |

### Setup Steps for I2C-5

```bash
# Configure pins using pinmap utility
# (MaixCAM uses a pinmap tool instead of devmem)
# Refer to: https://wiki.sipeed.com/hardware/en/maixcam/gpio.html

# Load i2c-dev
modprobe i2c-dev

# Verify
ls /dev/i2c-*
```

---

## MaixCAM2

### I2C Buses

| Bus | Pins | Notes |
|-----|------|-------|
| I2C-6 | A1 (SCL), A0 (SDA) | Available on header |
| I2C-7 | Available | Check device tree |

### Setup Steps

```bash
# Configure pinmap for I2C-6
# A1 β†’ I2C6_SCL, A0 β†’ I2C6_SDA
# Refer to MaixCAM2 documentation for pinmap commands

modprobe i2c-dev
ls /dev/i2c-*
```

---

## NanoKVM

Uses the same SG2002 SoC as LicheeRV Nano. GPIO and I2C access follows the same pinmux procedure. Refer to the LicheeRV Nano section above.

Check NanoKVM-specific pin headers for available I2C/SPI lines:
- https://wiki.sipeed.com/hardware/en/kvm/NanoKVM/introduction.html

---

## Common Issues

### devmem not found
The `devmem` utility may not be in the default image. Options:
- Use `busybox devmem` if busybox is installed
- Download devmem from the Sipeed package repository
- Cross-compile from source (single C file)

### Dynamic bus numbering
I2C adapter numbers can change between boots depending on driver load order. Always use `i2c detect` to find current bus assignments rather than hardcoding bus numbers.

### Permissions
`/dev/i2c-*` and `/dev/spidev*` typically require root access. Options:
- Run picoclaw as root
- Add user to `i2c` and `spi` groups
- Create udev rules: `SUBSYSTEM=="i2c-dev", MODE="0666"`

```

### references/common-devices.md

```markdown
# Common I2C/SPI Device Reference

## I2C Devices

### AHT20 β€” Temperature & Humidity
- **Address:** 0x38
- **Init:** Write `[0xBE, 0x08, 0x00]` then wait 10ms
- **Measure:** Write `[0xAC, 0x33, 0x00]`, wait 80ms, read 6 bytes
- **Parse:** Status=byte[0], Humidity=(byte[1]<<12|byte[2]<<4|byte[3]>>4)/2^20*100, Temp=(byte[3]&0x0F<<16|byte[4]<<8|byte[5])/2^20*200-50
- **Notes:** No register addressing β€” write command bytes directly (omit `register` param)

### BME280 / BMP280 β€” Temperature, Humidity, Pressure
- **Address:** 0x76 or 0x77 (SDO pin selects)
- **Chip ID register:** 0xD0 β†’ BMP280=0x58, BME280=0x60
- **Data registers:** 0xF7-0xFE (pressure, temperature, humidity)
- **Config:** Write 0xF2 (humidity oversampling), 0xF4 (temp/press oversampling + mode), 0xF5 (standby, filter)
- **Forced measurement:** Write `[0x25]` to register 0xF4, wait 40ms, read 8 bytes from 0xF7
- **Calibration:** Read 26 bytes from 0x88 and 7 bytes from 0xE1 for compensation formulas
- **Also available via SPI** (mode 0 or 3)

### SSD1306 β€” 128x64 OLED Display
- **Address:** 0x3C (or 0x3D if SA0 high)
- **Command prefix:** 0x00 (write to register 0x00)
- **Data prefix:** 0x40 (write to register 0x40)
- **Init sequence:** `[0xAE, 0xD5, 0x80, 0xA8, 0x3F, 0xD3, 0x00, 0x40, 0x8D, 0x14, 0x20, 0x00, 0xA1, 0xC8, 0xDA, 0x12, 0x81, 0xCF, 0xD9, 0xF1, 0xDB, 0x40, 0xA4, 0xA6, 0xAF]`
- **Display on:** 0xAF, **Display off:** 0xAE
- **Also available via SPI** (faster, recommended for animations)

### MPU6050 β€” 6-axis Accelerometer + Gyroscope
- **Address:** 0x68 (or 0x69 if AD0 high)
- **WHO_AM_I:** Register 0x75 β†’ should return 0x68
- **Wake up:** Write `[0x00]` to register 0x6B (clear sleep bit)
- **Read accel:** 6 bytes from register 0x3B (XH,XL,YH,YL,ZH,ZL) β€” signed 16-bit, default Β±2g
- **Read gyro:** 6 bytes from register 0x43 β€” signed 16-bit, default Β±250Β°/s
- **Read temp:** 2 bytes from register 0x41 β€” TempΒ°C = value/340 + 36.53

### DS3231 β€” Real-Time Clock
- **Address:** 0x68
- **Read time:** 7 bytes from register 0x00 (seconds, minutes, hours, day, date, month, year) β€” BCD encoded
- **Set time:** Write 7 BCD bytes to register 0x00
- **Temperature:** 2 bytes from register 0x11 (signed, 0.25Β°C resolution)
- **Status:** Register 0x0F β€” bit 2 = busy, bit 0 = alarm 1 flag

### INA219 β€” Current & Power Monitor
- **Address:** 0x40-0x4F (A0,A1 pin selectable)
- **Config:** Register 0x00 β€” set voltage range, gain, ADC resolution
- **Shunt voltage:** Register 0x01 (signed 16-bit, LSB=10Β΅V)
- **Bus voltage:** Register 0x02 (bits 15:3, LSB=4mV)
- **Power:** Register 0x03 (after calibration)
- **Current:** Register 0x04 (after calibration)
- **Calibration:** Register 0x05 β€” set based on shunt resistor value

### PCA9685 β€” 16-Channel PWM / Servo Controller
- **Address:** 0x40-0x7F (A0-A5 selectable, default 0x40)
- **Mode 1:** Register 0x00 β€” bit 4=sleep, bit 5=auto-increment
- **Set PWM freq:** Sleep β†’ write prescale to 0xFE β†’ wake. Prescale = round(25MHz / (4096 Γ— freq)) - 1
- **Channel N on/off:** Registers 0x06+4*N to 0x09+4*N (ON_L, ON_H, OFF_L, OFF_H)
- **Servo 0Β°-180Β°:** ON=0, OFF=150-600 (at 50Hz). Typical: 0Β°=150, 90Β°=375, 180Β°=600

### AT24C256 β€” 256Kbit EEPROM
- **Address:** 0x50-0x57 (A0-A2 selectable)
- **Read:** Write 2-byte address (high, low), then read N bytes
- **Write:** Write 2-byte address + up to 64 bytes (page write), wait 5ms for write cycle
- **Page size:** 64 bytes. Writes that cross page boundary wrap around.

## SPI Devices

### MCP3008 β€” 8-Channel 10-bit ADC
- **Interface:** SPI mode 0, max 3.6 MHz @ 5V
- **Read channel N:** Send `[0x01, (0x80 | N<<4), 0x00]`, result in last 10 bits of bytes 1-2
- **Formula:** value = ((byte[1] & 0x03) << 8) | byte[2]
- **Voltage:** value Γ— Vref / 1024

### W25Q128 β€” 128Mbit SPI Flash
- **Interface:** SPI mode 0 or 3, up to 104 MHz
- **Read ID:** Send `[0x9F, 0, 0, 0]` β†’ manufacturer + device ID
- **Read data:** Send `[0x03, addr_high, addr_mid, addr_low]` + N zero bytes
- **Status:** Send `[0x05, 0]` β†’ bit 0 = BUSY

```