Troubleshooting Guide
One of the most common issues is when an LED doesn't light up as expected when connected to the Raspberry Pi.
# 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}")
Buttons may register false presses or miss actual presses due to electrical noise or improper pull-up/pull-down configuration.
Button(pin, pull_up=True).Button(pin, pull_up=True, bounce_time=0.2).# 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")
Understanding how breadboards are internally connected is crucial for troubleshooting circuit issues.
These errors occur when Python can't find a required library or module.
ModuleNotFoundError: No module named 'gpiozero'ImportError: No module named 'Phidget22'ImportError: cannot import name 'Button' from 'gpiozero'sudo apt updatesudo pip3 install <package_name>sudo apt install python3-<library>sudo pip3 install Phidget22python --versionpython3 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
These errors occur when your Python program doesn't have permission to access hardware or create files.
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'sudo python3 your_program.pysudo usermod -a -G gpio,i2c,spi,input pils -la data.csvchmod 666 data.csv# 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
Problems with the camera module often relate to hardware connection, interfaces being disabled, or library conflicts.
PiCameraError: Camera is not enabledPiCameraError: Camera is already in useImportError: No module named 'picamera2'sudo raspi-config → Interface Options → Camera → Enablesudo rebootsudo apt install python3-picamerasudo apt install python3-picamera2# 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()
PIR motion sensors can sometimes trigger falsely or fail to detect motion when expected.
# 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")
The DS18B20 temperature sensor uses the 1-Wire protocol, which can be tricky to set up correctly.
sudo raspi-config → Interface Options → 1-Wire → Enabledtoverlay=w1-gpiols /sys/bus/w1/devices/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")
Photoresistor modules need proper calibration to accurately detect light vs. dark conditions.
# 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")
Random resets, freezes, or the appearance of a rainbow square in the corner of the screen often indicate power issues.
vcgencmd get_throttled# 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
Solar panel power monitoring can be challenging due to variable light conditions and analog signal processing.
sudo raspi-config → Interface Options → SPI → Enable# 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()
Indentation is critical in Python as it defines code blocks. Inconsistent indentation is a common source of errors.
IndentationError: unexpected indentIndentationError: expected an indented blockIndentationError: unindent does not match any outer indentation levelpip install autopep8autopep8 --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})")
Programs that never exit or become unresponsive are often caught in infinite loops or blocking operations.
# 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...")
CSV data logging is common for sensor projects, but can encounter various file handling and formatting issues.
file.flush()with blocks for proper file managementYYYY-MM-DD HH:MM:SS) for compatibility# 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}")