Wikijunior:Raspberry Pi/Raspberry Pi Star Wars Lightsaber

Tutorial by Andy Baker, instructions by Hal Motley

This tutorial is available in the public domain. In this tutorial you will connect a multi-colour LED to the Raspberry Pi to create a lightsaber like in Star Wars.

How lightsabers work

edit
 

For this tutorial, the colour-changing LED represents a kyber crystal. In the Star Wars universe, lightsabers are powered by a kyber crystal which the Jedi attunes to their will using the Force. There are a wide variety of blade colours including:

  • Luke Skywalker – green
  • Obi-Wan Kenobi – blue
  • Mace Windu – purple
  • Rey Skywalker – yellow
  • Ahsoka Tano – white

Sith lords such as Darth Vader, Kylo Ren and Darth Maul have red lightsabers because they dominate the kyber crystals using the Force causing them to bleed.

There is a full list of lightsaber colours here: https://www.bossksbounty.com/films/every-lightsaber-color-in-star-wars

The kit

edit
  • ×4 male-female GPIO jumper cables (also called DuPont cables, preferably of different colours)
  • ×1 breadboard (a small 5×5 breadboard works well, but any size is fine)
  • ×1 68 Ohm (blue grey black gold) resistor
  • ×1 4-pin colour-changing LED

Using a breadboard

edit
 

Breadboards are used to prototype and test electronic components without needing to solder them.

Each hole is identified with a notation system using numbers horizontally across the breadboard and letters vertically down the breadboard.

Connecting the components

edit
 
 

To setup the lightsaber, do the following:

Step 1: Power off your Raspberry Pi by shutting it down.

Step 2: Connect the colour-changing LED to the 4 holes in the top row (A13, A14, A15 and A16). Make sure that the longest pin (the ground) is lined up with the jumper wire to GPIO 39 (GND) so the LED is properly grounded.

Step 3: Connect the 68 Ohm resistor into the breadboard by placing one wire into hole B15 the other into B20 (the last hole of the second row) above the jumper wires.

Step 4: Connect the 4 jumper cables from the GPIO pin 33 (GPIO 13), pin 35 (SPI1 MISO), pin 37 (GPIO 26) and pin 39 (GND) (the last four bottom right pins, assuming the USB and Ethernet ports are to the right) to the bottom left four holes of the breadboard. I recommend trying to use the same coloured jumper wires that match the diagram exactly, though any colour combination can be used.

Step 5: Run each of the Python scripts in order, which are lightsaber.py, ls1.py, ls2.py and ls3.py. Try altering the code and see if you can make your own colour combinations.

Files

edit

lightsaber.pdf

edit

The original PDF for this tutorial is on Wikimedia Commons: Lightsaber.pdf

ls1.py

edit
#!/usr/bin/env python

# Pull in the code libraries that the code will need to use.
from __future__ import division
import RPi.GPIO as GPIO
import time

# Set up the GPIO library to use the numbering of the pin on the board
# i.e. 1 - 40 of the main GPIO connector.
GPIO.setmode(GPIO.BOARD)

# Tell the code the red LED is plugged into pin 35, and that pin 35
# is an output, and set the output to low (i.e. red LED is off)
RED_LED = 35
GPIO.setup(RED_LED, GPIO.OUT)
GPIO.output(RED_LED, GPIO.LOW)

# A new pulse starts every second, and half of that time, the LED is on.
pulse_period = 1
on_fraction = 1/2

# This try and the except below allow the code to stop cleanly by
# capturing the exception from a keyboard ctrl-C. 
try:

  # Store off when the while loop starts.
  start_time = time.time()

  # Start looping around the code forever.  
  while True:

    # Work out what time it is since we started, and from that, the 
    # fraction of the pulse period.
    time.sleep(1/1000)
    clock_time = (time.time() - start_time) % pulse_period

    # For the LEDs, check how far through its fraction of the pulse it 
    # is and turn the LED on if it's less or off if it's more.

    #============================= RED =============================#

    if clock_time < on_fraction * pulse_period:
        GPIO.output(RED_LED, GPIO.HIGH)
    else:
        GPIO.output(RED_LED, GPIO.LOW) 

# The except here needs to do nothing but has to do something; the pass
# statement means do nothing.
except KeyboardInterrupt as e:
  pass

# Finally turn off the LEDs and cleanup the GPIO.  
GPIO.output(RED_LED, GPIO.LOW)
GPIO.cleanup()

ls2.py

edit
#!/usr/bin/env python

# Pull in the code libraries that the code will need to use.
from __future__ import division
import RPi.GPIO as GPIO
import time

# Set up the GPIO library to use the numbering of the pin on the board
# i.e. 1 - 40 of the main GPIO connector.
GPIO.setmode(GPIO.BOARD)

# Tell the code the red LED is plugged into pin 35, and that pin 35
# is an output, and set the output to low (i.e. red LED is off)
RED_LED = 35
GPIO.setup(RED_LED, GPIO.OUT)
GPIO.output(RED_LED, GPIO.LOW)

# Tell the code the green LED is plugged into pin 33, and that pin 33
# is an output, and set the output to low (i.e. green LED is off)
GREEN_LED = 33
GPIO.setup(GREEN_LED, GPIO.OUT)
GPIO.output(GREEN_LED, GPIO.LOW)

# Tell the code the blue LED is plugged into pin 37, and that pin 37
# is an output, and set the output to low (i.e. blue LED is off)
BLUE_LED = 37
GPIO.setup(BLUE_LED, GPIO.OUT)
GPIO.output(BLUE_LED, GPIO.LOW)

# A new pulse starts every second, and half of that time, the LED is on.
pulse_period = 1
on_fraction = 1/2

# This try and the except below allow the code to stop cleanly by
# capturing the exception from a keyboard ctrl-C. 
try:

  # Store off when the while loop starts.
  start_time = time.time()

  # Start looping around the code forever.  
  while True:

    # Work out what time it is since we started, and from that, the 
    # fraction of the pulse period.
    time.sleep(1/1000)
    clock_time = (time.time() - start_time) % pulse_period

    # For the LEDs, check how far through its fraction of the pulse it 
    # is and turn the LED on if it's less or off if it's more.

    #============================= RED =============================#

    if clock_time < on_fraction * pulse_period:
        GPIO.output(RED_LED, GPIO.HIGH)
    else:
        GPIO.output(RED_LED, GPIO.LOW) 

    #============================ GREEN =======-====================#

    if clock_time < on_fraction * pulse_period:
        GPIO.output(GREEN_LED, GPIO.HIGH)
    else:
        GPIO.output(GREEN_LED, GPIO.LOW)

    #============================= BLUE ============================#

    if clock_time < on_fraction * pulse_period:
        GPIO.output(BLUE_LED, GPIO.HIGH)
    else:
        GPIO.output(BLUE_LED, GPIO.LOW)

# The except here needs to do nothing but has to do something; the pass
# statement means do nothing.
except KeyboardInterrupt as e:
  pass

# Finally turn off the LEDs and cleanup the GPIO.  
GPIO.output(RED_LED, GPIO.LOW)
GPIO.output(GREEN_LED, GPIO.LOW)
GPIO.output(BLUE_LED, GPIO.LOW)
GPIO.cleanup()

ls3.py

edit
#!/usr/bin/env python

# Pull in the code libraries that the code will need to use.
from __future__ import division
import RPi.GPIO as GPIO
import time

# Set up the GPIO library to use the numbering of the pin on the board
# i.e. 1 - 40 of the main GPIO connector.
GPIO.setmode(GPIO.BOARD)

# Tell the code the red LED is plugged into pin 35, and that pin 35
# is an output, and set the output to low (i.e. red LED is off)
RED_LED = 35
GPIO.setup(RED_LED, GPIO.OUT)
GPIO.output(RED_LED, GPIO.LOW)

# Tell the code the green LED is plugged into pin 33, and that pin 33
# is an output, and set the output to low (i.e. green LED is off)
GREEN_LED = 33
GPIO.setup(GREEN_LED, GPIO.OUT)
GPIO.output(GREEN_LED, GPIO.LOW)

# Tell the code the blue LED is plugged into pin 37, and that pin 37
# is an output, and set the output to low (i.e. blue LED is off)
BLUE_LED = 37
GPIO.setup(BLUE_LED, GPIO.OUT)
GPIO.output(BLUE_LED, GPIO.LOW)

# Each pulse period is 1 second, and each colour is on for a different
# number of thirds of this time.
pulse_period = 1
red_fraction = 1/3
green_fraction = 2/3
blue_fraction = 3/3

# This try and the except below allow the code to stop cleanly by
# capturing the exception from a keyboard ctrl-C. 
try:

  # Store off when the while loop starts.
  start_time = time.time()

  # Start looping around the code forever.  
  while True:

    # Work out what time it is since we started, and from that, the 
    # fraction of the pulse period.
    time.sleep(1/10)
    clock_time = (time.time() - start_time) % pulse_period

    # For the LEDs, check how far through its fraction of the pulse it 
    # is and turn the LED on if it's less or off if it's more.

    #============================= RED =============================#

    if clock_time < red_fraction * pulse_period:
        GPIO.output(RED_LED, GPIO.HIGH)
    else:
        GPIO.output(RED_LED, GPIO.LOW) 

    #============================ GREEN =======-====================#

    if clock_time < green_fraction * pulse_period:
        GPIO.output(GREEN_LED, GPIO.HIGH)
    else:
        GPIO.output(GREEN_LED, GPIO.LOW)

    #============================= BLUE ============================#

    if clock_time < blue_fraction * pulse_period:
        GPIO.output(BLUE_LED, GPIO.HIGH)
    else:
        GPIO.output(BLUE_LED, GPIO.LOW)

# The except here needs to do nothing but has to do something; the pass
# statement means do nothing.
except KeyboardInterrupt as e:
  pass

# Finally turn off the LEDs and cleanup the GPIO.  
GPIO.output(RED_LED, GPIO.LOW)
GPIO.output(GREEN_LED, GPIO.LOW)
GPIO.output(BLUE_LED, GPIO.LOW)
GPIO.cleanup()

lightsaber.py

edit
#!/usr/bin/env python

# Pull in the code libraries that the code will need to use.
from __future__ import division
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BOARD)

# Tell the code the red LED is plugged into pin 35, and that pin 35
# is an output, and set the output to low (i.e. red LED is off)
RED_LED = 35
GPIO.setup(RED_LED, GPIO.OUT)
GPIO.output(RED_LED, GPIO.LOW)

# Tell the code the green LED is plugged into pin 33, and that pin 33
# is an output, and set the output to low (i.e. green LED is off)
GREEN_LED = 33
GPIO.setup(GREEN_LED, GPIO.OUT)
GPIO.output(GREEN_LED, GPIO.LOW)

# Tell the code the blue LED is plugged into pin 37, and that pin 37
# is an output, and set the output to low (i.e. blue LED is off)
BLUE_LED = 37
GPIO.setup(BLUE_LED, GPIO.OUT)
GPIO.output(BLUE_LED, GPIO.LOW)

# Each pulse period is 1/100 second, and each colour is on for a different
# number amount of time each time round the loop.
pulse_period = 1/100

red_fraction = 1/500
red_on = 0

blue_fraction = 1/300
blue_on = 0

green_fraction = 1/200
green_on = 0

# This try and the except below allow the code to stop cleanly by
# capturing the exception from a keyboard ctrl-C. 
try:

  # Store off when the while loop starts.
  start_time = time.time()

  # Start looping around the code forever.  
  while True:

    # Work out what time it is since we started, and from that, the 
    # fraction of the pulse period.
    time.sleep(1/1000)
    clock_time = (time.time() - start_time) % pulse_period

    # For the LEDs, check how far through its fraction of the pulse it 
    # is and turn the LED on if it's less or off if it's more.
    # In this case, the fraction changes each time round the loop, so
    # the LEDs change their brightness.

    #============================= RED =============================#

    if clock_time < red_on * pulse_period:
        GPIO.output(RED_LED, GPIO.HIGH)
    else:
        GPIO.output(RED_LED, GPIO.LOW) 

    red_on += red_fraction 
    if red_on > 1 or red_on < 0:
        red_fraction = -red_fraction
        red_on += red_fraction

    #============================ GREEN =======-====================#

    if clock_time < green_on * pulse_period:
        GPIO.output(GREEN_LED, GPIO.HIGH)
    else:
        GPIO.output(GREEN_LED, GPIO.LOW)

    green_on += green_fraction
    if green_on > 1 or green_on < 0:
        green_fraction = -green_fraction
        green_on += green_fraction


    #============================= BLUE ============================#

    if clock_time < blue_on * pulse_period:
        GPIO.output(BLUE_LED, GPIO.HIGH)
    else:
        GPIO.output(BLUE_LED, GPIO.LOW)

    blue_on += blue_fraction
    if blue_on > 1 or blue_on < 0:
        blue_fraction = -blue_fraction
        blue_on += blue_fraction

# The except here needs to do nothing but has to do something; the pass
# statement means do nothing.
except KeyboardInterrupt as e:
  pass

# Finally turn off the LEDs and cleanup the GPIO.  
GPIO.output(RED_LED, GPIO.LOW)
GPIO.output(GREEN_LED, GPIO.LOW)
GPIO.output(BLUE_LED, GPIO.LOW)
GPIO.cleanup()