Hardware integration for Badger 2350 including GPIO, I2C sensors, SPI devices, and electronic components. Use when connecting external hardware, working with sensors, controlling LEDs, reading buttons, or interfacing with I2C/SPI devices on Badger 2350.
Control GPIO, I2C, and SPI hardware on Badger 2350 for sensors, LEDs, buttons, and motors. Use when connecting external components, reading sensors, or managing electronic I/O.
/plugin marketplace add johnlindquist/badger-2350-plugin/plugin install badger-2350-dev@badger-marketplaceThis skill inherits all available tools. When active, it can use any tool Claude has access to.
Interface with GPIO pins, sensors, and external hardware on the Badger 2350 badge using I2C, SPI, and digital I/O.
from machine import Pin
# Configure pin as output (LED, relay, etc.)
led = Pin(25, Pin.OUT)
led.value(1) # Turn on (HIGH)
led.value(0) # Turn off (LOW)
led.toggle() # Toggle state
# Configure pin as input (button, switch, etc.)
button = Pin(15, Pin.IN, Pin.PULL_UP)
if button.value() == 0: # Button pressed (pulled to ground)
print("Button pressed!")
# Configure pin as input with pull-down
sensor = Pin(16, Pin.IN, Pin.PULL_DOWN)
from machine import Pin, PWM
# Control LED brightness or servo motor
pwm = PWM(Pin(25))
pwm.freq(1000) # Set frequency to 1kHz
# Set duty cycle (0-65535, where 65535 is 100%)
pwm.duty_u16(32768) # 50% brightness
pwm.duty_u16(16384) # 25% brightness
pwm.duty_u16(65535) # 100% brightness
# Cleanup
pwm.deinit()
from machine import Pin
button = Pin(15, Pin.IN, Pin.PULL_UP)
def button_callback(pin):
print(f"Button pressed! Pin: {pin}")
# Trigger on falling edge (button press)
button.irq(trigger=Pin.IRQ_FALLING, handler=button_callback)
# Trigger on rising edge (button release)
button.irq(trigger=Pin.IRQ_RISING, handler=button_callback)
# Trigger on both edges
button.irq(trigger=Pin.IRQ_RISING | Pin.IRQ_FALLING, handler=button_callback)
from machine import I2C, Pin
# Initialize I2C (QWIIC connector uses specific pins)
i2c = I2C(0, scl=Pin(5), sda=Pin(4), freq=400000)
# Scan for connected devices
devices = i2c.scan()
print(f"Found {len(devices)} I2C devices:")
for device in devices:
print(f" Address: 0x{device:02x}")
# Read data from I2C device
address = 0x48 # Example: Temperature sensor
data = i2c.readfrom(address, 2) # Read 2 bytes
print(f"Raw data: {data}")
# Read from specific register
register = 0x00
i2c.writeto(address, bytes([register])) # Select register
data = i2c.readfrom(address, 2) # Read data
# Write single byte
address = 0x48
data = bytes([0x01, 0xA0])
i2c.writeto(address, data)
# Write to specific register
register = 0x01
value = 0xFF
i2c.writeto(address, bytes([register, value]))
from machine import I2C, Pin
import time
class BME280:
def __init__(self, i2c, address=0x76):
self.i2c = i2c
self.address = address
def read_temp(self):
# Read temperature register
data = self.i2c.readfrom_mem(self.address, 0xFA, 3)
temp_raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4)
# Apply calibration (simplified)
temp_c = temp_raw / 100.0
return temp_c
def read_humidity(self):
# Read humidity register
data = self.i2c.readfrom_mem(self.address, 0xFD, 2)
hum_raw = (data[0] << 8) | data[1]
humidity = hum_raw / 1024.0
return humidity
# Usage
i2c = I2C(0, scl=Pin(5), sda=Pin(4), freq=400000)
sensor = BME280(i2c)
temp = sensor.read_temp()
humidity = sensor.read_humidity()
print(f"Temp: {temp:.1f}°C, Humidity: {humidity:.1f}%")
class APDS9960:
def __init__(self, i2c, address=0x39):
self.i2c = i2c
self.address = address
self._init_sensor()
def _init_sensor(self):
# Enable device
self.i2c.writeto_mem(self.address, 0x80, bytes([0x01]))
# Enable gesture mode
self.i2c.writeto_mem(self.address, 0x93, bytes([0x01]))
def read_gesture(self):
# Read gesture FIFO
fifo_level = self.i2c.readfrom_mem(self.address, 0xAE, 1)[0]
if fifo_level > 0:
data = self.i2c.readfrom_mem(self.address, 0xFC, 4)
# Process gesture data
return self._detect_gesture(data)
return None
def _detect_gesture(self, data):
# Simplified gesture detection
if data[0] > data[2]:
return "UP"
elif data[0] < data[2]:
return "DOWN"
elif data[1] > data[3]:
return "LEFT"
else:
return "RIGHT"
# Usage
i2c = I2C(0, scl=Pin(5), sda=Pin(4), freq=400000)
gesture_sensor = APDS9960(i2c)
gesture = gesture_sensor.read_gesture()
if gesture:
print(f"Gesture detected: {gesture}")
class VL53L0X:
def __init__(self, i2c, address=0x29):
self.i2c = i2c
self.address = address
def read_distance(self):
# Start measurement
self.i2c.writeto_mem(self.address, 0x00, bytes([0x01]))
# Wait for measurement
time.sleep(0.05)
# Read distance (mm)
data = self.i2c.readfrom_mem(self.address, 0x14, 2)
distance = (data[0] << 8) | data[1]
return distance
# Usage
i2c = I2C(0, scl=Pin(5), sda=Pin(4), freq=400000)
tof = VL53L0X(i2c)
distance = tof.read_distance()
print(f"Distance: {distance}mm")
from machine import SPI, Pin
# Initialize SPI
spi = SPI(0, baudrate=1000000, polarity=0, phase=0,
sck=Pin(2), mosi=Pin(3), miso=Pin(4))
# Chip select pin
cs = Pin(5, Pin.OUT)
cs.value(1) # Deselect initially
# Read/write data
cs.value(0) # Select device
spi.write(bytes([0x01, 0x02, 0x03])) # Write data
data = spi.read(3) # Read 3 bytes
cs.value(1) # Deselect device
print(f"Received: {data}")
from machine import SPI, Pin
import sdcard
import os
# Initialize SPI and SD card
spi = SPI(0, baudrate=1000000, sck=Pin(2), mosi=Pin(3), miso=Pin(4))
cs = Pin(5, Pin.OUT)
sd = sdcard.SDCard(spi, cs)
# Mount SD card
os.mount(sd, '/sd')
# Write file
with open('/sd/data.txt', 'w') as f:
f.write('Hello from Badger!')
# Read file
with open('/sd/data.txt', 'r') as f:
print(f.read())
# Unmount
os.umount('/sd')
from machine import ADC, Pin
# Initialize ADC on GPIO pin
adc = ADC(Pin(26))
# Read raw value (0-65535 for 16-bit ADC)
raw_value = adc.read_u16()
print(f"Raw ADC: {raw_value}")
# Convert to voltage (assuming 3.3V reference)
voltage = (raw_value / 65535) * 3.3
print(f"Voltage: {voltage:.2f}V")
# Example: Read potentiometer
while True:
value = adc.read_u16()
percentage = (value / 65535) * 100
print(f"Pot: {percentage:.1f}%")
time.sleep(0.1)
from machine import Pin
import neopixel
import time
# Initialize NeoPixel strip (8 LEDs on pin 25)
num_leds = 8
np = neopixel.NeoPixel(Pin(25), num_leds)
# Set individual LED color (R, G, B)
np[0] = (255, 0, 0) # Red
np[1] = (0, 255, 0) # Green
np[2] = (0, 0, 255) # Blue
np[3] = (255, 255, 0) # Yellow
np.write() # Update LEDs
# Rainbow effect
def rainbow_cycle(wait):
for j in range(255):
for i in range(num_leds):
pixel_index = (i * 256 // num_leds) + j
np[i] = wheel(pixel_index & 255)
np.write()
time.sleep(wait)
def wheel(pos):
"""Generate rainbow colors across 0-255 positions"""
if pos < 85:
return (pos * 3, 255 - pos * 3, 0)
elif pos < 170:
pos -= 85
return (255 - pos * 3, 0, pos * 3)
else:
pos -= 170
return (0, pos * 3, 255 - pos * 3)
rainbow_cycle(0.001)
from machine import Pin, PWM
import time
class Servo:
def __init__(self, pin):
self.pwm = PWM(Pin(pin))
self.pwm.freq(50) # 50Hz for servo
def angle(self, degrees):
"""Set servo angle (0-180 degrees)"""
# Convert angle to duty cycle
# 0° = 1ms (3.2% duty)
# 90° = 1.5ms (7.5% duty)
# 180° = 2ms (10% duty)
min_duty = 1638 # 2.5% of 65535
max_duty = 8192 # 12.5% of 65535
duty = int(min_duty + (degrees / 180) * (max_duty - min_duty))
self.pwm.duty_u16(duty)
def deinit(self):
self.pwm.deinit()
# Usage
servo = Servo(25)
# Sweep servo
for angle in range(0, 181, 10):
servo.angle(angle)
time.sleep(0.1)
servo.deinit()
from machine import Pin
import time
class Relay:
def __init__(self, pin):
self.pin = Pin(pin, Pin.OUT)
self.off()
def on(self):
self.pin.value(1)
def off(self):
self.pin.value(0)
def toggle(self):
self.pin.toggle()
# Usage
relay = Relay(25)
relay.on()
time.sleep(2)
relay.off()
# Pulse relay
for i in range(5):
relay.toggle()
time.sleep(0.5)
import badger2040
from machine import I2C, Pin
import time
badge = badger2040.Badger2040()
i2c = I2C(0, scl=Pin(5), sda=Pin(4), freq=400000)
def display_sensor_data():
# Read sensor (example)
temp = read_temperature() # Your sensor function
humidity = read_humidity()
badge.set_pen(15)
badge.clear()
badge.set_pen(0)
badge.text("Sensor Monitor", 10, 10, scale=2)
badge.text(f"Temp: {temp:.1f}C", 10, 40, scale=2)
badge.text(f"Humidity: {humidity:.1f}%", 10, 70, scale=2)
badge.update()
while True:
display_sensor_data()
time.sleep(1)
import badger2040
from machine import Pin
import time
badge = badger2040.Badger2040()
led = Pin(25, Pin.OUT)
led_state = False
def draw_ui():
badge.set_pen(15)
badge.clear()
badge.set_pen(0)
badge.text("LED Control", 10, 10, scale=2)
status = "ON" if led_state else "OFF"
badge.text(f"Status: {status}", 10, 50, scale=2)
badge.text("A: Toggle", 10, 100, scale=1)
badge.update()
while True:
draw_ui()
if badge.pressed(badger2040.BUTTON_A):
led_state = not led_state
led.value(1 if led_state else 0)
time.sleep(0.2) # Debounce
from machine import Pin
import machine
# Power control for external hardware
power_pin = Pin(23, Pin.OUT)
def power_on():
power_pin.value(1)
def power_off():
power_pin.value(0)
# Use with sleep modes
power_on()
# ... do work with sensor ...
power_off()
machine.lightsleep(5000) # Sleep 5 seconds
I2C device not detected: Check wiring, verify device address, ensure pull-up resistors are present
GPIO not working: Verify pin is not used by internal badge functions, check if pin is input/output capable
SPI communication fails: Check clock polarity and phase, verify baudrate is within device specs
PWM not smooth: Increase PWM frequency, ensure duty cycle calculations are correct
Sensor readings unstable: Add delays between readings, use averaging, check power supply stability
Common Badger 2350 pins available for external hardware:
Refer to official Badger 2350 pinout diagram for complete details.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.