Smithery Logo
MCPsSkillsDocsPricing
Login
NewFlame, an assistant that learns and improves. Available onTelegramSlack
    johnlindquist

    badger-hardware

    johnlindquist/badger-hardware
    Productivity
    4

    About

    SKILL.md

    Install

    • Telegram
      Telegram
    • Slack
      Slack
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    • Download skill
    ├─
    ├─
    └─
    Smithery Logo

    Give agents more agency

    Resources

    DocumentationPrivacy PolicySystem Status

    Company

    PricingAboutBlog

    Connect

    © 2026 Smithery. All rights reserved.

    About

    Hardware integration for Badger 2350 including GPIO, I2C sensors, SPI devices, and electronic components...

    SKILL.md

    Badger 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.

    Recommended Servers
    GroundRoute: Web Search for AI Agents across 6 Engines ($10 free credit)
    GroundRoute: Web Search for AI Agents across 6 Engines ($10 free credit)
    DataForB2B
    DataForB2B
    GENESIS ProofRelay MCP Verifier
    GENESIS ProofRelay MCP Verifier
    Repository
    johnlindquist/badger-2350-plugin
    Files