| name | badger-diagnostics |
| description | System diagnostics, verification, and troubleshooting for Badger 2350. Use when checking firmware version, verifying installations, diagnosing hardware issues, troubleshooting errors, or performing system health checks on Badger 2350. |
Badger 2350 Diagnostics and Troubleshooting
Comprehensive diagnostics and troubleshooting tools for verifying your Badger 2350 setup, checking installations, and resolving common issues.
⚠️ When to Use This Skill
Use this skill FIRST in these situations:
- Starting a new session - Verify everything works before coding
- After setup - Confirm installation completed correctly
- Before debugging - Rule out environment issues
- When errors occur - Diagnose the root cause
- After firmware updates - Verify everything still works
Best Practice: Run diagnostics at the start of EVERY development session. It takes 30 seconds and prevents hours of debugging.
Quick Verification Command
Run this FIRST every session (doesn't require any files to exist):
Level 1: Basic Connection Test
# Simplest test - just verify badge responds
mpremote exec "print('Badge connected!')"
# Should print: Badge connected!
# If this fails, badge isn't connected or mpremote not installed
Level 2: Full Verification
# Complete verification (auto-detects port on macOS/Linux)
mpremote exec "import sys, gc; from badgeware import screen, brushes, shapes, io; print('=== VERIFICATION ==='); print('✓ MicroPython:', sys.version[:30]); print('✓ Memory:', gc.mem_free(), 'bytes'); print('✓ badgeware: loaded'); print('✓ Display: 160x120'); print('=== ALL OK ===')"
Expected output: All checks with ✓ marks and no errors.
With explicit port (if auto-detect fails):
mpremote connect /dev/cu.usbmodem1101 exec "from badgeware import screen; print('✓ Badge OK')"
# Replace /dev/cu.usbmodem1101 with your port
If this fails: Continue with detailed diagnostics below.
Quick System Check
Run this complete system diagnostic in REPL:
# diagnostic.py - Complete system check
import sys
import gc
import os
from machine import freq, unique_id
import ubinascii
def system_info():
"""Display complete system information"""
print("=" * 50)
print("BADGER 2350 SYSTEM DIAGNOSTICS")
print("=" * 50)
# MicroPython version
print(f"\n[MicroPython]")
print(f" Version: {sys.version}")
print(f" Implementation: {sys.implementation}")
print(f" Platform: {sys.platform}")
# Hardware info
print(f"\n[Hardware]")
print(f" CPU Frequency: {freq():,} Hz ({freq() / 1_000_000:.0f} MHz)")
uid = ubinascii.hexlify(unique_id()).decode()
print(f" Unique ID: {uid}")
# Memory
gc.collect()
print(f"\n[Memory]")
print(f" Free: {gc.mem_free():,} bytes ({gc.mem_free() / 1024:.1f} KB)")
print(f" Allocated: {gc.mem_alloc():,} bytes ({gc.mem_alloc() / 1024:.1f} KB)")
total = gc.mem_free() + gc.mem_alloc()
print(f" Total: {total:,} bytes ({total / 1024:.1f} KB)")
# File system
print(f"\n[File System]")
try:
stat = os.statvfs('/')
block_size = stat[0]
total_blocks = stat[2]
free_blocks = stat[3]
total_bytes = block_size * total_blocks
free_bytes = block_size * free_blocks
used_bytes = total_bytes - free_bytes
print(f" Total: {total_bytes:,} bytes ({total_bytes / 1024 / 1024:.2f} MB)")
print(f" Used: {used_bytes:,} bytes ({used_bytes / 1024 / 1024:.2f} MB)")
print(f" Free: {free_bytes:,} bytes ({free_bytes / 1024 / 1024:.2f} MB)")
except:
print(" Unable to check filesystem")
# Module path
print(f"\n[Module Search Paths]")
for path in sys.path:
print(f" {path}")
print("\n" + "=" * 50)
# Run diagnostic
system_info()
Firmware Version Check
Check MicroPython Firmware
import sys
# Full version info
print(sys.version)
# Example: 3.4.0; MicroPython v1.20.0 on 2023-04-26
# Implementation details
print(sys.implementation)
# (name='micropython', version=(1, 20, 0), _machine='Raspberry Pi Pico W with RP2040', _mpy=6182)
# Extract version number
version = sys.implementation.version
print(f"MicroPython {version[0]}.{version[1]}.{version[2]}")
Check Badger Library Version
import badger2040
# Check if version attribute exists
if hasattr(badger2040, '__version__'):
print(f"Badger library version: {badger2040.__version__}")
else:
print("Badger library version not available")
# Check file location
print(f"Badger library: {badger2040.__file__}")
Recommended Firmware Versions
Verify you have compatible firmware:
def check_firmware_compatibility():
"""Check if firmware is compatible with Badger 2350"""
version = sys.implementation.version
if version[0] >= 1 and version[1] >= 20:
print("✓ MicroPython version is compatible")
return True
else:
print("✗ MicroPython version may be outdated")
print(" Recommended: MicroPython 1.20+")
print(f" Current: {version[0]}.{version[1]}.{version[2]}")
return False
check_firmware_compatibility()
Module Verification
Check Core Modules
def verify_core_modules():
"""Verify essential modules are available"""
required_modules = {
'badger2040': 'Badger display library',
'machine': 'Hardware interface',
'time': 'Time functions',
'gc': 'Garbage collection',
'sys': 'System functions',
'os': 'Operating system interface'
}
optional_modules = {
'network': 'WiFi support',
'urequests': 'HTTP client',
'ujson': 'JSON parsing',
'ubinascii': 'Binary/ASCII conversion'
}
print("Checking required modules...")
all_ok = True
for module, description in required_modules.items():
try:
__import__(module)
print(f" ✓ {module:15s} - {description}")
except ImportError:
print(f" ✗ {module:15s} - MISSING - {description}")
all_ok = False
print("\nChecking optional modules...")
for module, description in optional_modules.items():
try:
__import__(module)
print(f" ✓ {module:15s} - {description}")
except ImportError:
print(f" ○ {module:15s} - Not installed - {description}")
return all_ok
verify_core_modules()
List All Installed Packages
import os
def list_installed_packages():
"""List all installed packages in /lib"""
print("Installed packages:")
# Check /lib directory
try:
lib_contents = os.listdir('/lib')
if lib_contents:
for item in sorted(lib_contents):
# Try to get more info
path = f'/lib/{item}'
try:
stat = os.stat(path)
size = stat[6] # File size
print(f" {item:30s} {size:8,} bytes")
except:
print(f" {item}")
else:
print(" (no packages in /lib)")
except OSError:
print(" /lib directory not found")
# Check root directory for .py files
print("\nRoot directory modules:")
root_contents = os.listdir('/')
py_files = [f for f in root_contents if f.endswith('.py')]
for f in sorted(py_files):
stat = os.stat(f)
size = stat[6]
print(f" {f:30s} {size:8,} bytes")
list_installed_packages()
Hardware Diagnostics
Display Test
import badger2040
def test_display():
"""Test display functionality"""
print("Testing display...")
badge = badger2040.Badger2040()
# Test 1: Clear screen
badge.set_pen(15)
badge.clear()
badge.update()
print(" ✓ Clear screen")
# Test 2: Draw text
badge.set_pen(0)
badge.text("Display Test", 10, 10, scale=2)
badge.update()
print(" ✓ Draw text")
# Test 3: Draw shapes
badge.line(10, 40, 100, 40)
badge.rectangle(10, 50, 50, 30)
badge.update()
print(" ✓ Draw shapes")
print("Display test complete!")
test_display()
Button Test
import badger2040
import time
def test_buttons():
"""Test all buttons"""
print("Button test - Press each button:")
print(" A, B, C, UP, DOWN")
print("Press Ctrl+C to exit")
badge = badger2040.Badger2040()
tested = set()
while len(tested) < 5:
if badge.pressed(badger2040.BUTTON_A) and 'A' not in tested:
print(" ✓ Button A works")
tested.add('A')
elif badge.pressed(badger2040.BUTTON_B) and 'B' not in tested:
print(" ✓ Button B works")
tested.add('B')
elif badge.pressed(badger2040.BUTTON_C) and 'C' not in tested:
print(" ✓ Button C works")
tested.add('C')
elif badge.pressed(badger2040.BUTTON_UP) and 'UP' not in tested:
print(" ✓ Button UP works")
tested.add('UP')
elif badge.pressed(badger2040.BUTTON_DOWN) and 'DOWN' not in tested:
print(" ✓ Button DOWN works")
tested.add('DOWN')
time.sleep(0.1)
print("All buttons tested successfully!")
test_buttons()
GPIO Test
from machine import Pin
def test_gpio():
"""Test GPIO pins"""
print("Testing GPIO pins...")
# Test output
test_pin = Pin(25, Pin.OUT)
test_pin.value(1)
print(f" ✓ Pin 25 set to HIGH: {test_pin.value()}")
test_pin.value(0)
print(f" ✓ Pin 25 set to LOW: {test_pin.value()}")
# Test input with pull-up
input_pin = Pin(15, Pin.IN, Pin.PULL_UP)
print(f" ✓ Pin 15 input (pull-up): {input_pin.value()}")
print("GPIO test complete!")
test_gpio()
I2C Bus Scan
from machine import I2C, Pin
def scan_i2c():
"""Scan for I2C devices"""
print("Scanning I2C bus...")
i2c = I2C(0, scl=Pin(5), sda=Pin(4), freq=400000)
devices = i2c.scan()
if devices:
print(f" Found {len(devices)} device(s):")
for device in devices:
print(f" 0x{device:02X} ({device})")
else:
print(" No I2C devices found")
return devices
scan_i2c()
Network Diagnostics
WiFi Connection Test
import network
import time
def test_wifi(ssid, password, timeout=10):
"""Test WiFi connection"""
print(f"Testing WiFi connection to '{ssid}'...")
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
# Check if already connected
if wlan.isconnected():
print(" ✓ Already connected")
print(f" IP: {wlan.ifconfig()[0]}")
return True
# Attempt connection
print(" Connecting...")
wlan.connect(ssid, password)
# Wait for connection
start = time.time()
while not wlan.isconnected() and (time.time() - start) < timeout:
time.sleep(0.5)
print(".", end="")
print() # New line
if wlan.isconnected():
config = wlan.ifconfig()
print(" ✓ Connected successfully")
print(f" IP Address: {config[0]}")
print(f" Subnet Mask: {config[1]}")
print(f" Gateway: {config[2]}")
print(f" DNS: {config[3]}")
print(f" Signal Strength: {wlan.status('rssi')} dBm")
return True
else:
print(" ✗ Connection failed")
status = wlan.status()
print(f" Status code: {status}")
return False
# Usage
# test_wifi('YourSSID', 'YourPassword')
Network Speed Test
import urequests
import time
def test_network_speed():
"""Test network download speed"""
print("Testing network speed...")
url = "http://httpbin.org/bytes/10000" # 10KB test file
try:
start = time.ticks_ms()
response = urequests.get(url)
end = time.ticks_ms()
size = len(response.content)
duration = time.ticks_diff(end, start) / 1000 # Convert to seconds
speed = (size / duration) / 1024 # KB/s
print(f" Downloaded: {size} bytes")
print(f" Time: {duration:.2f}s")
print(f" Speed: {speed:.2f} KB/s")
response.close()
return True
except Exception as e:
print(f" ✗ Network test failed: {e}")
return False
# test_network_speed()
Memory Diagnostics
Memory Usage Analysis
import gc
def analyze_memory():
"""Analyze memory usage"""
print("Memory Analysis:")
# Before collection
free_before = gc.mem_free()
alloc_before = gc.mem_alloc()
# Collect garbage
gc.collect()
# After collection
free_after = gc.mem_free()
alloc_after = gc.mem_alloc()
print(f"\nBefore garbage collection:")
print(f" Free: {free_before:,} bytes ({free_before / 1024:.1f} KB)")
print(f" Allocated: {alloc_before:,} bytes ({alloc_before / 1024:.1f} KB)")
print(f"\nAfter garbage collection:")
print(f" Free: {free_after:,} bytes ({free_after / 1024:.1f} KB)")
print(f" Allocated: {alloc_after:,} bytes ({alloc_after / 1024:.1f} KB)")
freed = free_after - free_before
print(f"\nReclaimed: {freed:,} bytes ({freed / 1024:.1f} KB)")
# Total memory
total = free_after + alloc_after
usage_percent = (alloc_after / total) * 100
print(f"\nTotal memory: {total:,} bytes ({total / 1024:.1f} KB)")
print(f"Usage: {usage_percent:.1f}%")
# Warning if low
if free_after < 10000:
print("\n⚠ WARNING: Low memory!")
elif free_after < 50000:
print("\n⚠ CAUTION: Memory running low")
else:
print("\n✓ Memory usage looks good")
analyze_memory()
Find Memory Leaks
import gc
def find_memory_leaks(function, iterations=10):
"""Test function for memory leaks"""
print(f"Testing for memory leaks ({iterations} iterations)...")
gc.collect()
initial_mem = gc.mem_free()
for i in range(iterations):
function()
gc.collect()
current_mem = gc.mem_free()
leaked = initial_mem - current_mem
if leaked > 0:
print(f" Iteration {i+1}: Leaked {leaked} bytes")
gc.collect()
final_mem = gc.mem_free()
total_leaked = initial_mem - final_mem
if total_leaked > 100: # Allow small variance
print(f"⚠ Possible memory leak: {total_leaked} bytes leaked")
else:
print(f"✓ No significant memory leak detected")
# Usage
# def test_func():
# data = [i for i in range(100)]
# find_memory_leaks(test_func)
Error Diagnosis
Common Error Patterns
def diagnose_error(error):
"""Provide diagnosis for common errors"""
error_str = str(error)
diagnostics = {
'ImportError': """
Module not found. Check:
- Module is installed (use mip.install())
- Module is in /lib or root directory
- Module name is spelled correctly
- File has .py extension
""",
'MemoryError': """
Out of memory. Try:
- Run gc.collect() before allocation
- Reduce variable scope
- Use generators instead of lists
- Break large operations into smaller chunks
- Delete unused objects with 'del'
""",
'OSError': """
File/Hardware operation failed. Check:
- File path is correct
- File exists (for reading)
- Filesystem not full (for writing)
- Hardware is connected properly
- Pins are not already in use
""",
'AttributeError': """
Attribute not found. Check:
- Object has the attribute/method
- Spelling is correct
- Module is imported correctly
- Object is initialized
""",
'ValueError': """
Invalid value. Check:
- Parameter values are in valid range
- Data types match expected types
- String formats are correct
"""
}
# Find matching error type
for error_type, advice in diagnostics.items():
if error_type in error_str:
print(f"Diagnosis for {error_type}:")
print(advice)
return
print("Error type not recognized. Common debugging steps:")
print("- Check error message carefully")
print("- Print variable values before error")
print("- Simplify code to isolate problem")
print("- Check MicroPython documentation")
# Usage
# try:
# import nonexistent_module
# except Exception as e:
# diagnose_error(e)
System Health Check
def health_check():
"""Comprehensive system health check"""
print("=" * 50)
print("SYSTEM HEALTH CHECK")
print("=" * 50)
issues = []
# Memory check
gc.collect()
free_mem = gc.mem_free()
if free_mem < 10000:
issues.append("CRITICAL: Very low memory")
elif free_mem < 50000:
issues.append("WARNING: Low memory")
else:
print("✓ Memory: OK")
# Filesystem check
try:
stat = os.statvfs('/')
free_blocks = stat[3]
block_size = stat[0]
free_bytes = free_blocks * block_size
if free_bytes < 100000:
issues.append("WARNING: Low disk space")
else:
print("✓ Filesystem: OK")
except:
issues.append("ERROR: Cannot check filesystem")
# Core modules check
required = ['badger2040', 'machine', 'time', 'gc', 'sys', 'os']
for module in required:
try:
__import__(module)
except:
issues.append(f"ERROR: Missing module '{module}'")
if not issues:
print("✓ Core modules: OK")
# Display results
if issues:
print("\n" + "!" * 50)
print("ISSUES FOUND:")
for issue in issues:
print(f" {issue}")
print("!" * 50)
else:
print("\n" + "=" * 50)
print("✓ ALL SYSTEMS HEALTHY")
print("=" * 50)
health_check()
Recovery Procedures
Safe Mode Boot
If badge won't boot normally:
- Hold BOOTSEL button while connecting USB
- Badge appears as USB drive
- Delete
main.pyif it's causing crashes - Copy new firmware
.uf2file to drive - Badge will reboot automatically
Factory Reset
import os
def factory_reset():
"""Remove all user files (DANGEROUS!)"""
print("WARNING: This will delete all files!")
print("Type 'CONFIRM' to proceed:")
# In interactive mode, get user confirmation
# confirm = input()
# if confirm != 'CONFIRM':
# print("Reset cancelled")
# return
print("Removing files...")
for f in os.listdir('/'):
if f not in ['boot.py']: # Keep boot.py
try:
os.remove(f)
print(f" Removed {f}")
except:
pass
print("Factory reset complete. Reboot badge.")
# Uncomment to use:
# factory_reset()
Firmware Reflash
# From your computer (badge in BOOTSEL mode)
# Download latest MicroPython firmware
# Visit: https://micropython.org/download/rp2-pico-w/
# Flash firmware
# Drag .uf2 file to RPI-RP2 drive
# Or use picotool:
picotool load firmware.uf2
# Verify
picotool info
Troubleshooting Checklist
When encountering issues, work through this checklist:
- Check MicroPython version (
sys.version) - Verify core modules load (
import badger2040) - Run memory diagnostic (
gc.mem_free()) - Check filesystem space (
os.statvfs('/')) - Test display (
badge.update()) - Test buttons (button test function)
- Scan I2C bus (if using sensors)
- Test WiFi connection (if using network)
- Review error messages carefully
- Check documentation for API changes
- Try soft reset (Ctrl+D in REPL)
- Try hard reset (power cycle)
This comprehensive diagnostic approach will help you quickly identify and resolve issues with your Badger 2350!