Raspberry Pi & Phidgets Workshop

Troubleshooting Guide

Quick Navigation

Hardware Connection Issues

LED Not Lighting Up
Components: LED, Resistor, GPIO

One of the most common issues is when an LED doesn't light up as expected when connected to the Raspberry Pi.

Possible Causes:

  • LED is connected backward (incorrect polarity)
  • Using wrong GPIO pin number in code
  • Resistor value too high (limiting current too much)
  • Bad connection on breadboard
  • Missing ground connection

Step-by-Step Solution:

  1. Check LED orientation: The longer leg (anode) should connect to the resistor, and the shorter leg (cathode) to ground.
  2. Verify GPIO pin number in code matches your physical connection.
  3. Make sure you're using a 220Ω resistor (red-red-brown) and not a higher value.
  4. Test the LED directly with a 3V battery (with resistor) to ensure it works.
  5. Ensure all connections are firm on the breadboard.
  6. Double-check your ground connection is secure.
# Correct LED setup
from gpiozero import LED
from time import sleep

led = LED(17)  # Ensure this matches your wiring

# Test with a simple blink
led.on()
sleep(1)
led.off()
sleep(1)

# If the above doesn't work, try this to check the GPIO state:
print(f"LED is_lit: {led.is_lit}")
print(f"LED pin: {led.pin}")
Success Check: When properly connected, the LED should light up when the GPIO pin is set to HIGH (3.3V) and turn off when set to LOW (0V).
Official Raspberry Pi GPIO Documentation
Inconsistent Button Behavior
Components: Button, GPIO, Pull-up resistor

Buttons may register false presses or miss actual presses due to electrical noise or improper pull-up/pull-down configuration.

Possible Causes:

  • Missing pull-up or pull-down resistor
  • Electromagnetic interference (noisy circuit)
  • Button "bounce" (rapid on/off oscillations)
  • Loose connections
  • Incorrect GPIO pin mode

Step-by-Step Solution:

  1. Always use a pull-up resistor with buttons (10kΩ is standard).
  2. In gpiozero, enable internal pull-up with Button(pin, pull_up=True).
  3. Add debounce time: Button(pin, pull_up=True, bounce_time=0.2).
  4. Ensure button is firmly seated on the breadboard.
  5. Keep button wires short and away from power sources.
# Proper button setup with debounce
from gpiozero import Button
from time import sleep

# Use internal pull-up and debounce
button = Button(4, pull_up=True, bounce_time=0.2)  

# Test button with a simple function
def button_pressed():
    print("Button was pressed!")

# Assign callback function
button.when_pressed = button_pressed

# Keep program running
try:
    while True:
        sleep(0.1)
except KeyboardInterrupt:
    print("Program stopped")
Success Check: The button should trigger exactly once per press, without false triggers, and consistently detect all presses.
GPIO Zero Button Documentation
Breadboard Connection Issues
Components: Breadboard, Jumper Wires

Understanding how breadboards are internally connected is crucial for troubleshooting circuit issues.

Common Misunderstandings:

  • Rows are connected horizontally (except at the center gap)
  • Power rails (+ and -) run vertically along the edges
  • Center gap separates each row into two independent sections
  • Old or worn breadboards can have unreliable connections

Step-by-Step Checks:

  1. Ensure components span the center gap correctly.
  2. Check that wire colors match conventional usage (red for power, black for ground, etc.).
  3. Press wires and component legs firmly into the breadboard.
  4. Test connections with a multimeter if available.
  5. Use a new breadboard if persistent issues occur.
Pro Tip: Take a photo of your circuit before disassembling for troubleshooting. This makes it easier to recreate the original setup if needed.
Comprehensive Breadboard Guide

Software & Library Problems

ModuleNotFoundError or ImportError
Python Libraries & Dependencies

These errors occur when Python can't find a required library or module.

Example Errors:

  • ModuleNotFoundError: No module named 'gpiozero'
  • ImportError: No module named 'Phidget22'
  • ImportError: cannot import name 'Button' from 'gpiozero'

Step-by-Step Solution:

  1. Update your package repository: sudo apt update
  2. Install the missing package: sudo pip3 install <package_name>
  3. For official Raspberry Pi libraries: sudo apt install python3-<library>
  4. For Phidget22: sudo pip3 install Phidget22
  5. Verify Python version (should be Python 3): python --version
  6. Make sure to use python3 when running your script, not just python
# Common installation commands
sudo apt update
sudo apt upgrade

# GPIO libraries
sudo apt install python3-gpiozero  

# Phidget libraries
sudo pip3 install Phidget22

# SPI interface (for ADC)
sudo apt install python3-spidev

# Camera interface
sudo apt install python3-picamera2

# GUI libraries
sudo pip3 install guizero

# Check installed packages
pip3 list | grep gpio
pip3 list | grep Phidget
Success Check: After installation, the import error should be resolved. Test with a simple import statement: python3 -c "import gpiozero; print('Import successful!')"
GPIO Zero Installation Guide
Permission Denied Errors
System Permissions & Access

These errors occur when your Python program doesn't have permission to access hardware or create files.

Example Errors:

  • PermissionError: [Errno 13] Permission denied: '/dev/gpiomem'
  • PermissionError: [Errno 13] Permission denied: '/dev/spidev0.0'
  • PermissionError: [Errno 13] Permission denied: '/dev/i2c-1'
  • PermissionError: [Errno 13] Permission denied: 'data.csv'

Step-by-Step Solution:

  1. Run the program with sudo: sudo python3 your_program.py
  2. Add your user to required groups:
    sudo usermod -a -G gpio,i2c,spi,input pi
  3. For file permissions, check ownership: ls -la data.csv
  4. Change file permissions if needed: chmod 666 data.csv
  5. Log out and log back in after changing group membership
# Add user to all hardware access groups
sudo usermod -a -G gpio,i2c,spi,input,video pi

# Check if you belong to these groups
groups

# Set permissions for a specific directory
sudo chmod -R 775 /path/to/your/project

# Create a log directory with write permissions
mkdir -p ~/logs
chmod 777 ~/logs
Pro Tip: Instead of always using sudo (which can create files owned by root), add your user to the appropriate groups and log out/in for the changes to take effect.
Raspberry Pi OS Permissions Documentation
Camera Module Configuration Issues
Raspberry Pi Camera Setup

Problems with the camera module often relate to hardware connection, interfaces being disabled, or library conflicts.

Common Camera Errors:

  • PiCameraError: Camera is not enabled
  • PiCameraError: Camera is already in use
  • ImportError: No module named 'picamera2'
  • Black or corrupted images

Step-by-Step Solution:

  1. Enable camera interface: sudo raspi-config → Interface Options → Camera → Enable
  2. Reboot after enabling: sudo reboot
  3. Check ribbon cable connection (blue side faces away from Ethernet port)
  4. Install the correct library:
    • For legacy camera: sudo apt install python3-picamera
    • For new library: sudo apt install python3-picamera2
  5. Make sure you're not running multiple camera programs simultaneously
# Test camera with Picamera2
from picamera2 import Picamera2
import time

# Initialize camera
picam2 = Picamera2()
camera_config = picam2.create_preview_configuration()
picam2.configure(camera_config)
picam2.start()

# Give camera time to adjust
time.sleep(2)

# Capture a test image
picam2.capture_file("test_photo.jpg")
print("Photo captured. Check test_photo.jpg")

# Clean up
picam2.stop()
Success Check: A properly configured camera will capture an image when the test code runs. Check for the test_photo.jpg file.
Official Raspberry Pi Camera Documentation

Sensor Calibration & Testing

PIR Motion Sensor False Triggers
Components: PIR Motion Sensor

PIR motion sensors can sometimes trigger falsely or fail to detect motion when expected.

Common PIR Issues:

  • False triggers (detecting motion when none occurs)
  • Missing motion events (not detecting when movement happens)
  • Constant triggering even with no movement
  • Inconsistent range or field of view

Step-by-Step Solution:

  1. Allow the PIR sensor to calibrate after power-up (30-60 seconds)
  2. Adjust sensitivity with the potentiometer (usually marked 'Sx')
  3. Adjust trigger duration with the second potentiometer (usually marked 'Tx')
  4. Keep PIR away from heat sources (including the Raspberry Pi itself)
  5. Ensure stable power supply (PIR sensors are sensitive to voltage fluctuations)
  6. Add delay between readings in code to prevent rapid retriggering
# Reliable PIR setup with calibration time
from gpiozero import MotionSensor
import time

# Create PIR sensor object with longer queue_len for stability
pir = MotionSensor(4, queue_len=5, sample_rate=10)

print("PIR sensor warming up...")
# Allow sensor to calibrate (essential!)
time.sleep(60)  
print("Ready! Sensor calibrated.")

try:
    while True:
        if pir.motion_detected:
            print("Motion detected!")
            # Prevent rapid re-triggering
            time.sleep(2)  
        time.sleep(0.1)
except KeyboardInterrupt:
    print("Program stopped")
Pro Tip: For testing, create a simple LED indicator that lights up when motion is detected to visualize the sensor's triggering behavior.
GPIO Zero MotionSensor Documentation
DS18B20 Temperature Sensor Issues
Components: DS18B20 Temperature Sensor

The DS18B20 temperature sensor uses the 1-Wire protocol, which can be tricky to set up correctly.

Common Temperature Sensor Issues:

  • Sensor not detected (no device files in /sys/bus/w1/devices/)
  • Reading shows 85°C (default value when sensor fails)
  • Inconsistent or inaccurate readings
  • CRC errors in raw readings

Step-by-Step Solution:

  1. Verify 1-Wire is enabled: sudo raspi-config → Interface Options → 1-Wire → Enable
  2. Add to /boot/config.txt: dtoverlay=w1-gpio
  3. Check proper wiring: Red/VDD→3.3V, Black/GND→Ground, Yellow/DQ→GPIO4
  4. Ensure 4.7kΩ pull-up resistor is connected between DQ and VDD
  5. Check device detection: ls /sys/bus/w1/devices/
  6. Install w1thermsensor library: sudo pip3 install w1thermsensor
# Reliable DS18B20 temperature reading
from w1thermsensor import W1ThermSensor, Sensor
import time

try:
    # Attempt to find and read from DS18B20 sensor
    sensor = W1ThermSensor(Sensor.DS18B20)
    
    # Read temperature and convert to Fahrenheit
    celsius = sensor.get_temperature()
    fahrenheit = celsius * 9/5 + 32
    
    print(f"Temperature: {celsius:.2f}°C / {fahrenheit:.2f}°F")
    
except Exception as e:
    print(f"Error: {e}")
    print("\nTroubleshooting steps:")
    print("1. Check if 1-Wire is enabled in raspi-config")
    print("2. Verify the pull-up resistor (4.7kΩ) is connected")
    print("3. Check sensor wiring (VDD→3.3V, GND→Ground, DQ→GPIO4)")
    print("4. Run: ls /sys/bus/w1/devices/ to check if sensor is detected")
Success Check: A properly connected DS18B20 will show up in /sys/bus/w1/devices/ with a name like 28-xxxxxxxxxxxx and will give temperature readings between -55°C and +125°C.
W1ThermSensor Library Documentation
Photoresistor Module Calibration
Components: Photoresistor/Light Sensor Module

Photoresistor modules need proper calibration to accurately detect light vs. dark conditions.

Common Light Sensor Issues:

  • Inconsistent triggering at different light levels
  • Always reporting light or always reporting dark
  • Rapid switching between states in moderate light
  • Digital output not switching as expected

Step-by-Step Solution:

  1. Adjust the potentiometer on the module to set the light threshold
  2. Test in actual usage conditions (not just at your desk)
  3. Add hysteresis in software to prevent rapid switching
  4. Keep sensor facing the light source you want to detect
  5. Shield from unwanted light sources
  6. For analog readings, use an ADC (e.g., MCP3008) for better sensitivity
# Light sensor with hysteresis to prevent rapid switching
from gpiozero import DigitalInputDevice, LED
import time

# Set up components
light_sensor = DigitalInputDevice(4)
led = LED(17)

# Track last state to implement hysteresis
last_state = None
state_count = 0  # Count of consecutive same readings
THRESHOLD = 5  # Number of readings needed to change state

print("Light sensor active...")

try:
    while True:
        current_reading = light_sensor.value
        
        # If reading is same as last reading, increment counter
        if current_reading == last_state:
            state_count += 1
        else:
            state_count = 0
            
        # Only change LED state if we get consistent readings
        if state_count >= THRESHOLD:
            if current_reading:  # Light detected
                led.off()
                print("Bright environment - LED OFF")
            else:  # Dark detected
                led.on()
                print("Dark environment - LED ON")
                
        last_state = current_reading
        time.sleep(0.1)
        
except KeyboardInterrupt:
    print("Program stopped")
Pro Tip: For projects that need to work in variable lighting conditions, implement adaptive calibration that adjusts thresholds based on ambient light.
Raspberry Pi Light Sensor Tutorial

Power & Performance Issues

Raspberry Pi Resetting or Freezing
Power Supply Issues

Random resets, freezes, or the appearance of a rainbow square in the corner of the screen often indicate power issues.

Common Power Problems:

  • Under-voltage warnings (rainbow square icon)
  • Random reboots during high CPU or GPIO usage
  • Unstable behavior when multiple components are connected
  • SD card corruption due to improper shutdowns

Step-by-Step Solution:

  1. Use a high-quality power supply (official Raspberry Pi supply recommended)
  2. Ensure power supply provides at least 5V/2.5A for Raspberry Pi 3B+ or 5V/3A for Raspberry Pi 4
  3. Use a short, high-quality USB cable (poor cables cause voltage drop)
  4. For high-power components (motors, multiple sensors), use a separate power supply
  5. Check for power warnings: vcgencmd get_throttled
  6. For battery-powered projects, ensure sufficient capacity and regulate voltage
# Check for power issues
vcgencmd get_throttled

# If return value is 0x0, power is good.
# If return value is 0x50000, under-voltage detected.

# Check CPU temperature (heat can also cause instability)
vcgencmd measure_temp

# Check voltage levels
vcgencmd measure_volts core
Pro Tip: For portable projects, use a quality power bank with at least 2.4A output capability per port, and test it fully before relying on it for demonstrations.
Raspberry Pi Power Requirements Documentation
Solar Panel Power Generation Issues
Components: Solar Panel, ADC, Voltage Divider

Solar panel power monitoring can be challenging due to variable light conditions and analog signal processing.

Common Solar Monitoring Issues:

  • No voltage reading from the solar panel
  • Inconsistent or erratic readings
  • ADC0834 communication errors
  • Voltage readings not matching actual voltage
  • SPI interface errors

Step-by-Step Solution:

  1. Enable SPI interface: sudo raspi-config → Interface Options → SPI → Enable
  2. Verify ADC0834 wiring:
    • CS → GPIO8 (CE0)
    • CLK → GPIO11 (SCLK)
    • DO → GPIO9 (MISO)
    • DI → GPIO10 (MOSI)
  3. Verify voltage divider (10kΩ + 1kΩ resistor) is correctly wired
  4. Check solar panel orientation toward light source
  5. Test with a voltmeter to verify actual voltage output
  6. Adjust scaling factor in code based on actual vs. measured voltage
# Testing ADC0834 and solar panel
import spidev
import time

# Set up SPI for ADC0834
spi = spidev.SpiDev()
spi.open(0, 0)  # Bus 0, Device 0
spi.max_speed_hz = 1000000  # 1MHz

def read_adc0834(channel):
    """Read from ADC0834 channel (0-3)"""
    # Start bit (1), Single-ended mode (1), Channel select
    cmd = 0b10000000 | (channel << 4)
    # Send command and receive data
    reply_bytes = spi.xfer2([cmd, 0, 0])
    # Extract value from reply
    value = reply_bytes[2]
    return value

def convert_to_voltage(adc_value):
    """Convert ADC reading to actual voltage"""
    # ADC0834 is 8-bit (0-255), reference is 3.3V
    # For 10kΩ + 1kΩ voltage divider (10kΩ to solar, 1kΩ to ground)
    # Divider divides by 11:1, so multiply by 11
    voltage = adc_value * 3.3 / 255.0 * 11.0
    return voltage

try:
    print("Testing ADC and Solar Panel...")
    print("Press Ctrl+C to exit")
    print("\nADC\tVoltage")
    print("---\t-------")
    
    while True:
        # Read ADC channel 0
        adc_value = read_adc0834(0)
        # Convert to voltage
        voltage = convert_to_voltage(adc_value)
        # Display values
        print(f"{adc_value}\t{voltage:.2f}V")
        time.sleep(1)
        
except KeyboardInterrupt:
    print("\nTest completed.")
    spi.close()
Pro Tip: Solar panels produce varying voltage depending on light level. Test in various lighting conditions to establish expected voltage ranges for your environment.
ADC Usage Guide for Raspberry Pi

Python Code Debugging

Indentation Errors in Python
Python Syntax

Indentation is critical in Python as it defines code blocks. Inconsistent indentation is a common source of errors.

Common Indentation Errors:

  • IndentationError: unexpected indent
  • IndentationError: expected an indented block
  • IndentationError: unindent does not match any outer indentation level
  • Mixing tabs and spaces (extremely common error)

Step-by-Step Solution:

  1. Use a text editor with Python syntax highlighting
  2. Configure your editor to show whitespace characters
  3. Use either spaces or tabs consistently (4 spaces per level is standard)
  4. Use a code formatter like autopep8: pip install autopep8
  5. Check editor settings to ensure it uses spaces (not tabs)
  6. For existing code, try: autopep8 --in-place your_script.py
# Example of proper indentation
def calculate_temperature(sensor_reading):
    """Convert sensor reading to temperature."""
    # First level of indentation (4 spaces)
    voltage = sensor_reading * 3.3 / 1023
    temperature = voltage * 100
    
    # Conditional block with second level indentation
    if temperature > 50:
        # Second level (8 spaces total)
        print("Warning: High temperature detected!")
        return temperature, "HIGH"
    elif temperature < 0:
        print("Warning: Below freezing!")
        return temperature, "LOW"
    else:
        return temperature, "NORMAL"
        
# Main program (back to no indentation)
reading = 512
temp, status = calculate_temperature(reading)
print(f"Temperature: {temp}°C ({status})")
Pro Tip: Use an integrated development environment (IDE) like Thonny (pre-installed on Raspberry Pi) that automatically handles indentation and provides visual cues for indentation errors.
Python PEP 8 Indentation Guidelines
Infinite Loops and Program Hangs
Python Logic

Programs that never exit or become unresponsive are often caught in infinite loops or blocking operations.

Common Loop Issues:

  • Missing exit conditions in while loops
  • Blocking calls that never return (waiting indefinitely)
  • Forgetting to update loop variables
  • Resource exhaustion (memory leaks)

Step-by-Step Solution:

  1. Always include an exit condition in while loops
  2. Implement timeout mechanisms for waiting operations
  3. Add debug print statements to track program flow
  4. Include KeyboardInterrupt handling (try/except) to allow clean exit with Ctrl+C
  5. For hardware-dependent code, add "safety valve" conditions
  6. If a program hangs, press Ctrl+C to attempt to exit
# Safe waiting for sensor with timeout
from gpiozero import MotionSensor
import time

# Motion sensor setup
pir = MotionSensor(4)

def wait_for_motion_with_timeout(timeout_seconds=60):
    """Wait for motion with timeout to prevent infinite waiting."""
    print(f"Waiting for motion (timeout: {timeout_seconds}s)...")
    
    start_time = time.time()
    
    while True:
        # Check if motion detected
        if pir.motion_detected:
            return True
            
        # Check if timeout has elapsed
        if time.time() - start_time > timeout_seconds:
            print("Timeout reached waiting for motion.")
            return False
            
        # Small sleep to prevent CPU overuse
        time.sleep(0.1)

# Main program with clean exit
try:
    # Set a reasonable timeout
    motion_detected = wait_for_motion_with_timeout(30)
    
    if motion_detected:
        print("Motion detected! Taking action...")
    else:
        print("No motion detected within timeout period.")
        
    print("Program completed normally.")
    
except KeyboardInterrupt:
    print("\nProgram stopped by user.")
    
finally:
    # Cleanup code that always runs, even after errors
    print("Cleaning up resources...")
Pro Tip: For graphical applications using guizero or other event-based frameworks, avoid infinite loops in the main thread. Use event callbacks or scheduled functions instead.
Python While Loop Best Practices
CSV Data Logging Issues
File I/O & Data Handling

CSV data logging is common for sensor projects, but can encounter various file handling and formatting issues.

Common CSV Issues:

  • File permission errors
  • CSV file corruption when program exits abruptly
  • Data not appearing until program ends (buffering)
  • Incorrect formatting or delimiter issues
  • Time/date formatting problems

Step-by-Step Solution:

  1. Use the csv module for reliable CSV handling
  2. Flush the file after each write with file.flush()
  3. Use with blocks for proper file management
  4. Include error handling for file operations
  5. Create log directories if they don't exist
  6. Use ISO format for dates (YYYY-MM-DD HH:MM:SS) for compatibility
  7. Don't rely on non-ASCII characters in filenames
# Robust CSV data logging
import csv
import os
import time
from datetime import datetime

# Create log directory if it doesn't exist
log_dir = "sensor_logs"
if not os.path.exists(log_dir):
    os.makedirs(log_dir)

# Generate a timestamp-based filename
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"{log_dir}/temperature_log_{timestamp}.csv"

try:
    # Open file in context manager for automatic handling
    with open(filename, 'w', newline='') as csvfile:
        # Create CSV writer
        writer = csv.writer(csvfile)
        
        # Write header row
        writer.writerow(['Timestamp', 'Temperature (C)', 'Status'])
        
        # Simulate data collection
        for i in range(10):
            # Get current time
            current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            
            # Simulate temperature reading
            temperature = 20 + (i * 0.5)
            
            # Determine status
            if temperature > 22:
                status = "HIGH"
            else:
                status = "NORMAL"
                
            # Write data row
            writer.writerow([current_time, f"{temperature:.2f}", status])
            
            # Flush to ensure data is written immediately
            csvfile.flush()
            
            print(f"Logged: {current_time}, {temperature:.2f}°C, {status}")
            
            # Simulate delay between readings
            time.sleep(1)
            
    print(f"Data logging complete. File saved as: {filename}")
    
except Exception as e:
    print(f"Error writing to CSV file: {e}")
    
except KeyboardInterrupt:
    print("\nLogging stopped by user.")
    print(f"Partial data saved to: {filename}")
Pro Tip: For projects that run for extended periods, implement log rotation (creating new files after a certain size or time) to prevent excessively large files and potential data loss.
Python CSV Module Documentation