Badger 2350 Hardware Integration

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

You say
Install this skill Read the source first Free Written by johnlindquist · unverified publisher
Context cost
3k tokensestimated from the bundle, loaded when it triggers
Bundle
1 file · 11.9 kBtext throughout, nothing executable
Licence
free to use
Last change
no release on file
Servers it uses
Noneruns standalone

What it does

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.

Installed, it changes the agent in these ways.

What this skill changes about the agent is not written down here yet. The listing was collected from its source, and the description is in its own SKILL.md.

Output format

Produces one artefact, exactly shaped.

The skill itself

This is the whole product. A skill is instructions the model reads, so there is nothing behind the listing you cannot see first — the front matter loads with every session, and the body below it loads when the skill triggers.

SKILL.md11.9 kB · 528 lines
--- name: badger-hardware description: 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. ---
6# Badger 2350 Hardware Integration
7
8Interface with GPIO pins, sensors, and external hardware on the Badger 2350 badge using I2C, SPI, and digital I/O.
9
10## GPIO Basics
11
12### Pin Configuration
13
14```python
15from machine import Pin
16
17# Configure pin as output (LED, relay, etc.)
18led = Pin(25, Pin.OUT)
19led.value(1) # Turn on (HIGH)
20led.value(0) # Turn off (LOW)
21led.toggle() # Toggle state
22
23# Configure pin as input (button, switch, etc.)
24button = Pin(15, Pin.IN, Pin.PULL_UP)
25if button.value() == 0: # Button pressed (pulled to ground)
26 print("Button pressed!")
27
28# Configure pin as input with pull-down
29sensor = Pin(16, Pin.IN, Pin.PULL_DOWN)
30```
31
32### PWM (Pulse Width Modulation)
33
34```python
35from machine import Pin, PWM
36
37# Control LED brightness or servo motor
38pwm = PWM(Pin(25))
39pwm.freq(1000) # Set frequency to 1kHz
40
41# Set duty cycle (0-65535, where 65535 is 100%)
42pwm.duty_u16(32768) # 50% brightness
43pwm.duty_u16(16384) # 25% brightness
44pwm.duty_u16(65535) # 100% brightness
45
46# Cleanup
47pwm.deinit()
48```
49
50### Interrupts
51
52```python
53from machine import Pin
54
55button = Pin(15, Pin.IN, Pin.PULL_UP)
56
57def button_callback(pin):
58 print(f"Button pressed! Pin: {pin}")
59
60# Trigger on falling edge (button press)
61button.irq(trigger=Pin.IRQ_FALLING, handler=button_callback)
62
63# Trigger on rising edge (button release)
64button.irq(trigger=Pin.IRQ_RISING, handler=button_callback)
65
66# Trigger on both edges
67button.irq(trigger=Pin.IRQ_RISING | Pin.IRQ_FALLING, handler=button_callback)
68```
69
70## I2C Communication
71
72### I2C Setup
73
74```python
75from machine import I2C, Pin
76
77# Initialize I2C (QWIIC connector uses specific pins)
78i2c = I2C(0, scl=Pin(5), sda=Pin(4), freq=400000)
79
80# Scan for connected devices
81devices = i2c.scan()
82print(f"Found {len(devices)} I2C devices:")
83for device in devices:
84 print(f" Address: 0x{device:02x}")
85```
86
87### Reading from I2C Device
88
89```python
90# Read data from I2C device
91address = 0x48 # Example: Temperature sensor
92data = i2c.readfrom(address, 2) # Read 2 bytes
93print(f"Raw data: {data}")
94
95# Read from specific register
96register = 0x00
97i2c.writeto(address, bytes([register])) # Select register
98data = i2c.readfrom(address, 2) # Read data
99```
100
101### Writing to I2C Device
102
103```python
104# Write single byte
105address = 0x48
106data = bytes([0x01, 0xA0])
107i2c.writeto(address, data)
108
109# Write to specific register
110register = 0x01
111value = 0xFF
112i2c.writeto(address, bytes([register, value]))
113```
114
115## Common I2C Sensors
116
117### BME280 (Temperature, Humidity, Pressure)
118
119```python
120from machine import I2C, Pin
121import time
122
123class BME280:
124 def __init__(self, i2c, address=0x76):
125 self.i2c = i2c
126 self.address = address
127
128 def read_temp(self):
129 # Read temperature register
130 data = self.i2c.readfrom_mem(self.address, 0xFA, 3)
131 temp_raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4)
132 # Apply calibration (simplified)
133 temp_c = temp_raw / 100.0
134 return temp_c
135
136 def read_humidity(self):
137 # Read humidity register
138 data = self.i2c.readfrom_mem(self.address, 0xFD, 2)
139 hum_raw = (data[0] << 8) | data[1]
140 humidity = hum_raw / 1024.0
141 return humidity
142
143# Usage
144i2c = I2C(0, scl=Pin(5), sda=Pin(4), freq=400000)
145sensor = BME280(i2c)
146
147temp = sensor.read_temp()
148humidity = sensor.read_humidity()
149print(f"Temp: {temp:.1f}°C, Humidity: {humidity:.1f}%")
150```
151
152### APDS9960 (Gesture, Proximity, Color Sensor)
153
154```python
155class APDS9960:
156 def __init__(self, i2c, address=0x39):
157 self.i2c = i2c
158 self.address = address
159 self._init_sensor()
160
161 def _init_sensor(self):
162 # Enable device
163 self.i2c.writeto_mem(self.address, 0x80, bytes([0x01]))
164 # Enable gesture mode
165 self.i2c.writeto_mem(self.address, 0x93, bytes([0x01]))
166
167 def read_gesture(self):
168 # Read gesture FIFO
169 fifo_level = self.i2c.readfrom_mem(self.address, 0xAE, 1)[0]
170 if fifo_level > 0:
171 data = self.i2c.readfrom_mem(self.address, 0xFC, 4)
172 # Process gesture data
173 return self._detect_gesture(data)
174 return None
175
176 def _detect_gesture(self, data):
177 # Simplified gesture detection
178 if data[0] > data[2]:
179 return "UP"
180 elif data[0] < data[2]:
181 return "DOWN"
182 elif data[1] > data[3]:
183 return "LEFT"
184 else:
185 return "RIGHT"
186
187# Usage
188i2c = I2C(0, scl=Pin(5), sda=Pin(4), freq=400000)
189gesture_sensor = APDS9960(i2c)
190
191gesture = gesture_sensor.read_gesture()
192if gesture:
193 print(f"Gesture detected: {gesture}")
194```
195
196### VL53L0X (Time-of-Flight Distance Sensor)
197
198```python
199class VL53L0X:
200 def __init__(self, i2c, address=0x29):
201 self.i2c = i2c
202 self.address = address
203
204 def read_distance(self):
205 # Start measurement
206 self.i2c.writeto_mem(self.address, 0x00, bytes([0x01]))
207
208 # Wait for measurement
209 time.sleep(0.05)
210
211 # Read distance (mm)
212 data = self.i2c.readfrom_mem(self.address, 0x14, 2)
213 distance = (data[0] << 8) | data[1]
214 return distance
215
216# Usage
217i2c = I2C(0, scl=Pin(5), sda=Pin(4), freq=400000)
218tof = VL53L0X(i2c)
219
220distance = tof.read_distance()
221print(f"Distance: {distance}mm")
222```
223
224## SPI Communication
225
226### SPI Setup
227
228```python
229from machine import SPI, Pin
230
231# Initialize SPI
232spi = SPI(0, baudrate=1000000, polarity=0, phase=0,
233 sck=Pin(2), mosi=Pin(3), miso=Pin(4))
234
235# Chip select pin
236cs = Pin(5, Pin.OUT)
237cs.value(1) # Deselect initially
238
239# Read/write data
240cs.value(0) # Select device
241spi.write(bytes([0x01, 0x02, 0x03])) # Write data
242data = spi.read(3) # Read 3 bytes
243cs.value(1) # Deselect device
244
245print(f"Received: {data}")
246```
247
248### SD Card Reader (SPI)
249
250```python
251from machine import SPI, Pin
252import sdcard
253import os
254
255# Initialize SPI and SD card
256spi = SPI(0, baudrate=1000000, sck=Pin(2), mosi=Pin(3), miso=Pin(4))
257cs = Pin(5, Pin.OUT)
258
259sd = sdcard.SDCard(spi, cs)
260
261# Mount SD card
262os.mount(sd, '/sd')
263
264# Write file
265with open('/sd/data.txt', 'w') as f:
266 f.write('Hello from Badger!')
267
268# Read file
269with open('/sd/data.txt', 'r') as f:
270 print(f.read())
271
272# Unmount
273os.umount('/sd')
274```
275
276## Analog Input (ADC)
277
278```python
279from machine import ADC, Pin
280
281# Initialize ADC on GPIO pin
282adc = ADC(Pin(26))
283
284# Read raw value (0-65535 for 16-bit ADC)
285raw_value = adc.read_u16()
286print(f"Raw ADC: {raw_value}")
287
288# Convert to voltage (assuming 3.3V reference)
289voltage = (raw_value / 65535) * 3.3
290print(f"Voltage: {voltage:.2f}V")
291
292# Example: Read potentiometer
293while True:
294 value = adc.read_u16()
295 percentage = (value / 65535) * 100
296 print(f"Pot: {percentage:.1f}%")
297 time.sleep(0.1)
298```
299
300## NeoPixel (WS2812B) LEDs
301
302```python
303from machine import Pin
304import neopixel
305import time
306
307# Initialize NeoPixel strip (8 LEDs on pin 25)
308num_leds = 8
309np = neopixel.NeoPixel(Pin(25), num_leds)
310
311# Set individual LED color (R, G, B)
312np[0] = (255, 0, 0) # Red
313np[1] = (0, 255, 0) # Green
314np[2] = (0, 0, 255) # Blue
315np[3] = (255, 255, 0) # Yellow
316np.write() # Update LEDs
317
318# Rainbow effect
319def rainbow_cycle(wait):
320 for j in range(255):
321 for i in range(num_leds):
322 pixel_index = (i * 256 // num_leds) + j
323 np[i] = wheel(pixel_index & 255)
324 np.write()
325 time.sleep(wait)
326
327def wheel(pos):
328 """Generate rainbow colors across 0-255 positions"""
329 if pos < 85:
330 return (pos * 3, 255 - pos * 3, 0)
331 elif pos < 170:
332 pos -= 85
333 return (255 - pos * 3, 0, pos * 3)
334 else:
335 pos -= 170
336 return (0, pos * 3, 255 - pos * 3)
337
338rainbow_cycle(0.001)
339```
340
341## Servo Motor Control
342
343```python
344from machine import Pin, PWM
345import time
346
347class Servo:
348 def __init__(self, pin):
349 self.pwm = PWM(Pin(pin))
350 self.pwm.freq(50) # 50Hz for servo
351
352 def angle(self, degrees):
353 """Set servo angle (0-180 degrees)"""
354 # Convert angle to duty cycle
355 # 0° = 1ms (3.2% duty)
356 # 90° = 1.5ms (7.5% duty)
357 # 180° = 2ms (10% duty)
358 min_duty = 1638 # 2.5% of 65535
359 max_duty = 8192 # 12.5% of 65535
360 duty = int(min_duty + (degrees / 180) * (max_duty - min_duty))
361 self.pwm.duty_u16(duty)
362
363 def deinit(self):
364 self.pwm.deinit()
365
366# Usage
367servo = Servo(25)
368
369# Sweep servo
370for angle in range(0, 181, 10):
371 servo.angle(angle)
372 time.sleep(0.1)
373
374servo.deinit()
375```
376
377## Relay Control
378
379```python
380from machine import Pin
381import time
382
383class Relay:
384 def __init__(self, pin):
385 self.pin = Pin(pin, Pin.OUT)
386 self.off()
387
388 def on(self):
389 self.pin.value(1)
390
391 def off(self):
392 self.pin.value(0)
393
394 def toggle(self):
395 self.pin.toggle()
396
397# Usage
398relay = Relay(25)
399
400relay.on()
401time.sleep(2)
402relay.off()
403
404# Pulse relay
405for i in range(5):
406 relay.toggle()
407 time.sleep(0.5)
408```
409
410## Integration with Badge Display
411
412### Display Sensor Data
413
414```python
415import badger2040
416from machine import I2C, Pin
417import time
418
419badge = badger2040.Badger2040()
420i2c = I2C(0, scl=Pin(5), sda=Pin(4), freq=400000)
421
422def display_sensor_data():
423 # Read sensor (example)
424 temp = read_temperature() # Your sensor function
425 humidity = read_humidity()
426
427 badge.set_pen(15)
428 badge.clear()
429 badge.set_pen(0)
430
431 badge.text("Sensor Monitor", 10, 10, scale=2)
432 badge.text(f"Temp: {temp:.1f}C", 10, 40, scale=2)
433 badge.text(f"Humidity: {humidity:.1f}%", 10, 70, scale=2)
434
435 badge.update()
436
437while True:
438 display_sensor_data()
439 time.sleep(1)
440```
441
442### Interactive Hardware Control
443
444```python
445import badger2040
446from machine import Pin
447import time
448
449badge = badger2040.Badger2040()
450led = Pin(25, Pin.OUT)
451led_state = False
452
453def draw_ui():
454 badge.set_pen(15)
455 badge.clear()
456 badge.set_pen(0)
457
458 badge.text("LED Control", 10, 10, scale=2)
459
460 status = "ON" if led_state else "OFF"
461 badge.text(f"Status: {status}", 10, 50, scale=2)
462
463 badge.text("A: Toggle", 10, 100, scale=1)
464
465 badge.update()
466
467while True:
468 draw_ui()
469
470 if badge.pressed(badger2040.BUTTON_A):
471 led_state = not led_state
472 led.value(1 if led_state else 0)
473 time.sleep(0.2) # Debounce
474```
475
476## Power Management for Hardware
477
478```python
479from machine import Pin
480import machine
481
482# Power control for external hardware
483power_pin = Pin(23, Pin.OUT)
484
485def power_on():
486 power_pin.value(1)
487
488def power_off():
489 power_pin.value(0)
490
491# Use with sleep modes
492power_on()
493# ... do work with sensor ...
494power_off()
495machine.lightsleep(5000) # Sleep 5 seconds
496```
497
498## Troubleshooting
499
500**I2C device not detected**: Check wiring, verify device address, ensure pull-up resistors are present
501
502**GPIO not working**: Verify pin is not used by internal badge functions, check if pin is input/output capable
503
504**SPI communication fails**: Check clock polarity and phase, verify baudrate is within device specs
505
506**PWM not smooth**: Increase PWM frequency, ensure duty cycle calculations are correct
507
508**Sensor readings unstable**: Add delays between readings, use averaging, check power supply stability
509
510## Hardware Safety
511
512- **Never exceed 3.3V** on GPIO pins
513- Use level shifters for 5V devices
514- Add current-limiting resistors for LEDs
515- Use flyback diodes with motors and relays
516- Keep I2C wires short (< 20cm) or use bus extenders
517- Use proper power supply for high-current devices
518
519## Pinout Reference
520
521Common Badger 2350 pins available for external hardware:
522- GPIO 0-22: General purpose I/O
523- GPIO 26-28: ADC capable (analog input)
524- I2C QWIIC: SCL (Pin 5), SDA (Pin 4)
525- SPI: SCK, MOSI, MISO (check documentation)
526
527Refer to official Badger 2350 pinout diagram for complete details.
528
In the file
SKILL.md1,515 words
Files1
Licence
Why you can read it

Nothing in a skill executes. The client loads the text and the model follows it, so a skill can be audited the way a runbook is — by reading it.

What it costs in context

Skills are not billed by the call. They are paid for in context: every token the instructions occupy is a token your code, your diff and your conversation cannot use. Here is what this one takes and when it takes it.

≈70
always loaded
The name and description, so the model knows the skill exists and when to reach for it.
2,905
on trigger
The instruction body, read only when the skill fires.
1.5%
of a 200k window
Ten skills this size would take about 15% of the window before you open a file.
050k100k150k200k context window

3k tokens, estimated from the bundle at four bytes to the token, held for the rest of the session once it triggers. Middling. Fine to keep on in a project where you use it weekly, worth unloading in one where you never do.

Servers bill, skills cost

A server charges by the month. A skill charges once per session, in context, and then keeps charging it for as long as the session lives.

Before and after

The same question, put to the same model twice: once as it comes, and once with these instructions loaded.

No worked example has been published for this skill yet.

Adoption
Installsnone yet
Ratingno reviews yet

The procedure it runs

The procedure has not been published here. It is in the skill’s own SKILL.md, which its author has not sent to the marketplace yet.

Prose, not code

These steps are written for a model to follow, not executed by a runtime. It can still be told to skip one, and it will say so when it does.

Servers it uses

None. This skill calls no MCP servers at all.

Everything it needs is in the instructions, so it works in a project with nothing connected — the model reads the file and changes how it works with what it can already reach.

It writes no files and reaches no network. All it changes is how the model reasons and writes.

What it asks for
Writes filesno
Network accessno

Read from the allowed-tools line of this skill’s own SKILL.md. A skill grants no permissions of its own — it can only ask for tools your client already has.

What it will not do

Every skill is narrow, and the useful ones say where they stop. These are the jobs this one is the wrong tool for.

What this skill is not for has not been published here. Nothing is implied by that: it is a section the author has not filled in.

What is in the bundle

1 file, 11.9 kB on disk. A bundle is text throughout: the instructions the model reads, plus the templates it fills in.

  • SKILL.md11.9 kB
What is not in it

No dependencies and nothing executable: a skill is text the agent reads, so the bundle is 1 file you can review in full before installing.

Install

Installing copies the bundle into your project. Nothing runs at install time — the files sit on disk until the model reads them.

# Badger 2350 Hardware Integration · 3k tokens when loaded npx mcprush@latest skill add johnlindquist/badger-2350-hardware-integration

Writes to .claude/skills/badger-2350-hardware-integration/ in the current project. Add --global to put it in your home directory instead, for every project.

Which clients pick it up on their own

A skill is a folder of text. A client with a skills folder reads it without being told; everywhere else the same text works, it is just handed to the model rather than found.

Claude Code.claude/skills/
Claude Desktop
ChatGPT
Cursor.cursor/skills/
VS Code.github/skills/
Codex CLI.agents/skills/
Gemini CLI.gemini/skills/
Grok.grok/skills/
Zed.agents/skills/
Windsurf.windsurf/skills/
Agent SDK.claude/skills/
HTTP / API
This release
Versionnot versioned
Publishedno release date on file
PriceFree
Referencejohnlindquist/badger-2350-hardware-integration

Versions

Its author publishes no version number, so there is nothing here to pin to: what you install is the folder as it stands today. Instructions change more often than APIs do — a skill can be rewritten entirely without anything it depends on moving.

v
  • No earlier releases have been published to the marketplace.
Pinning

Nothing to pin to: this skill carries no version number of its own. What you install is what the folder holds on the day you install it.

Reviews

no reviews yet · no installs yet

Nobody has reviewed this skill yet. The rating is the mean of the reviews written here, so there is none until somebody writes the first.

Who can post

Only accounts that have had the skill installed for fourteen days, so a review is written after living with it rather than after reading it. Publishers may reply once.

Who wrote it

JO
johnlindquist

Publishes on mcprush.

0 servers listed1 skill listednot claimed
Profile
Publisher
Servers0
Claim this skill