Claude-skill-registry badger-hardware
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.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/badger-hardware" ~/.claude/skills/majiayu000-claude-skill-registry-badger-hardware && rm -rf "$T"
skills/data/badger-hardware/SKILL.mdBadger 2350 Hardware Integration
Interface with GPIO pins, sensors, and external hardware on the Badger 2350 badge using I2C, SPI, and digital I/O.
GPIO Basics
Pin Configuration
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)
PWM (Pulse Width Modulation)
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()
Interrupts
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)
I2C Communication
I2C Setup
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}")
Reading from I2C Device
# 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
Writing to I2C Device
# 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]))
Common I2C Sensors
BME280 (Temperature, Humidity, Pressure)
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}%")
APDS9960 (Gesture, Proximity, Color Sensor)
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}")
VL53L0X (Time-of-Flight Distance Sensor)
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")
SPI Communication
SPI Setup
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}")
SD Card Reader (SPI)
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')
Analog Input (ADC)
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)
NeoPixel (WS2812B) LEDs
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)
Servo Motor Control
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()
Relay Control
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)
Integration with Badge Display
Display Sensor Data
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)
Interactive Hardware Control
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
Power Management for Hardware
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
Troubleshooting
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
Hardware Safety
- Never exceed 3.3V on GPIO pins
- Use level shifters for 5V devices
- Add current-limiting resistors for LEDs
- Use flyback diodes with motors and relays
- Keep I2C wires short (< 20cm) or use bus extenders
- Use proper power supply for high-current devices
Pinout Reference
Common Badger 2350 pins available for external hardware:
- GPIO 0-22: General purpose I/O
- GPIO 26-28: ADC capable (analog input)
- I2C QWIIC: SCL (Pin 5), SDA (Pin 4)
- SPI: SCK, MOSI, MISO (check documentation)
Refer to official Badger 2350 pinout diagram for complete details.