A Breathing Light Controlled by a Raspberry Pi




About: I have a background in chemistry, molecular biology and immunology and I am working in the field of in vitro diagnostics and life sciences. I like the concept of citizen science, and my intension is to simp...

The "Breathing Exercise Light" described here is a simple and relatively inexpensive pulsing light that may support you in your breathing execises and help you to keep a constant breathing rhythm. It might also be used e.g. as a soothing night light for children. In the current stage it is more a working prototype.

You may also use it as an inexpensive and simple to build example for "physical computing" with a Raspberry Pi, e.g. to be used as a educational project on the beginners level, Here you have analog (rotary potentiometer) and digital inputs (push button) as well as digital (LED) and PWM output (LED chains), and the effects of changes are directly visible.

The light runs through repetitive circles consisting of four phases: a green (upper) to red (lower) transition, a red-only phase, a red-to-green transition and a green-only phase. The length of these phases are defined by constants which can be modified by potentiometers. The process can be started, paused, resumed and stopped by pressing push buttons. LEDs are indicating the current phase.

It is based on the “Firefly Light” example by Pimoroni (see here). Similar to the “Firefly Light” it requires a Raspberry Pi (Zero), the Pimoroni Explorer pHAT (or HAT) and two IKEA SÄRDAL LED light chains. The later are connected to the two PMW/motor ports of the pHAT. Instead of using a jar, I have placed the LEDs in an IKEA picture frame.

I have been trying to optimize the original “firefly light” python script a bit, implementing an optional sinus function for the brightness/ pulse width changes and have introduced two “hold” phases between the dimming phases. While modifying the parameters to find a light pattern that feels more comfortable, I found that the device can helpful to support a very clearly defined, regular breathing pattern. Thus, some of you may find this “Breathing Light” helpful for meditation or training purposes.

As the Explorer pHAT has four digital and four analog inputs, it is very easy to regulate up to four different parameters using slide or rotary potentiometers, and to introduce start/restart/stop functions for the lights using push buttons. This will allow you to use the device and optimize the parameters to your needs without a monitor has to be attached to the Pi.

In addition the Explorer pHAT comes with four digital out-ports, which allow to add LEDs or buzzers, plus two 5V and two Ground ports and two PWM out ports for motors or similar devices. Please make sure you are using the correct resistors to reduce the voltage for your LEDs.

Pimoroni's Explorer pHAT python library makes it extremely simple to control all these I/O ports.

In this instructable versions of the device with 0, 2 and 4 potentiometers and buttons are described. Pick the one that fits your needs.

To run the device autonomously, one could use either a power pack, or the combination of a Pimoroni LiPo shim and a LiPo battery, as described for the "Firefly Light".


Updated versions
Dec. 28, 2018: 'four potentiometers and four push buttons' version added.
Dec. 30: code for 4-poti version and fritzing images added.


Step 1: Materials Used / Required

- Raspberry Pi Zero (4.80 GBP at Pimoroni, UK), and a micro SD card (>= 8 GB) w/ Raspian

- Pimoroni Explorer pHAT (10 GBP at Pimoroni, UK). Optional: a single row header, jumper cables

- IKEA SÄRDAL LED chain lights w/ 12 LEDs (2 x, 3.99 € each at IKEA Germany), or any similar 3-5V LED chain.

- IKEA RIBBA picture frame (13 x 18 cm, 2.49 € at IKEA Germany).

- A piece of PU foam (2 x 18 x 13.5 cm), to hold the LEDs. Alternatively styro foam might be used.

- A piece of opaque plastic (18 x 13.5 cm), acting as diffusor.

- Two sheets of colored transparent paper (9 x 13.5 cm each). I used red and green.

- A piece of thin, highly opaque plastic sheet (18 x 13.5 cm), acting as the outer screen. I used a thin white polycarbonate sheet.

Optional, for the tunable version:

To adjust ramping timing and plateau duration, or alternatively other parameters like brightness.
- 10, 20 or 50 kOhm potentiometers (up to four, I used two 10 kOhm respectively four 50 Ohm).

As start/stop/pause/resume buttons:
- Push buttons (up to four, I used four or two)

As indicators for the phases of the circle:
- Colored LEDs and the necessary resistors (will depend on the characteristics of the LEDs you will use).

  1. about 140 Ohm for 5.2 -> 2,2 V (yellow, orange, red; some green LEDs),
  2. about 100 Ohm for 5.3 -> 3.3 V (some green; blue, white LEDs)

- Jumper cables and a breadboard

Optional, for a battery-driven version:

  • 5V Micro-USB power pack, or
  • Pimoroni Zero LiPo shim and a LiPo battery

Step 2: Lazout and Assembly

Assemble the Explorer pHAT as described by the manufacturer. I have added a single row female header for the simplified connection of jumper cables to the pHATs I/O ports. Set up your Pi and install the Pimoroni library for the Explorer HAT/pHAT, as described by Pimoroni. Turn off the Pi and attach the pHAT onto the Pi.

Remove the battery packs from the LED chains by cutting the wires and tin the end of the wires. Cut two 2x male jumper cables at the middle, tin the end of the wires. Solder the jumper cables to the LED chains, and isolate the soldering points using either adhesive tape or shrink tubing. Before soldering, check which of the wires have to be connected to plus or ground ports, and mark them accordingly. I used jumper wires with different colors.

Cut the foam to hold the LEDs, the diffusor and screen sheets to the appropriate size. On the LED holding plate mark the positions where the LEDs shall be placed and punch 3-5 mm holes into the foam. Then insert the 24 LEDs at the given positions. Place the colored papers and diffusor plates on the LED plate (see images), them place the frame above the pack. Fix the foam layers in the frame, e.g. using adhesive tape. Attach the LED strip cables to the “motor” ports of the Explorer pHAT.

For the tunable version place potentiometers, push buttons, control LEDs (and/or buzzers) and resistors on the breadboard and connect them with the corresponding ports at the Explorer pHAT.

Start your Pi and install the required libraries, as described on the Pimoroni website, then run the provided Python 3 script. If one of the LED chains is not working it might be connected in the wrong direction. Then you may either the change the plus/minus connections on the pHAT or make a change in the program, e.g. change “eh.motor.one.backwards()” to “ … forwards()”.

Attached you find scripts with fixed settings you can change within the program and an example where you can modify some of the settings with potentiometers, and start and stop the light cycle using push buttons.

It should not be too difficult to adjust the scripts fit to your own layout of the “breathing light”.

Step 3: The Python Scripts

Pimoroni's Python library for the Explorer HAT/pHAT makes it extremely simple to adress the components attached to the HATs' I/O ports. Two examples: "eh.two.motor.backwards(80)" drives the device attached to the PWM/motor port 2 with 80% maximum intensity in backwards direction, "eh.output.three.flash()" makes a LED connected to output port number three flash until it is stopped.

I have generated a few variations of the light, basically adding increasing levels of control by adding up to four push buttons and potentiometers.
Attached you find a Python program called "Breathing light fixed lin cosin.py" where all four parameter settings have to be modified within the program. In addition a version called "Breathing light var lin cosin.py" where the length of the two dimming phases can be adjusted using two potentiometers and the most elaborated version "Breathing light var lin cosin3.py" for the four potentiometer & push button version. The programs are written in Python 3.

In all cases the cycling process can be evoked and stopped using two push buttons, in the four button version you also can interrupt and restart the process. In addition four (colored) LEDs can be connected to the digital output ports, indicating the specific phases.

A cycle of the device consists of four phases:

- the "inhale" phase, where the upper LEDs are dimmed low and the lower LEDs increase intensity

- the "hold your breath" phase, where the upper LEDs are turned off and the lower LEDs are set to maximum

- the "exhale" phase, where the lower LEDs are dimmed low and the upper LEDs increase intensity

- the "stay exhaled" phase, where the lower LEDs are turned off and the upper LEDs light on maximum.

The length of all four phases are defined by a individual numeric parameter, which might either fixed in the program and/or might be adjusted using a potentiometer.

A fifth parameter defines the maximum intensity. It allows you to set the maximum brightness of the LEDs, which could be handy if you want to use it as a nightlight. In addition it may allow you improve the dimming process, as I have the impression that it is hard to see a difference between 80 and 100% intensity.

I was adding an optional (co-)sinus function for the increase/decrease of brightness, as it gives a smoother connection between the phases. Feel free to try other functions. E.g. you may eliminate the breaks and use two different (complex) sinus functions for both LED chains and adjust frequency and amplitude by potentiometers.

# The "breathing" lamp: two button & two potentiometer version
# a modification of the firefly example for the Pimoroni Explorer pHAT
# here: sinoid increase/decrease of motor/PWM values
# for linear function unmute linear and mute cosin function
# This version "var" does read analog inputs, overrides predefined settings
# reads digital input, buttons to start and stop

to start upon switching on the Pi you may use Cron:
Cron is a Unix program that is used to schedule jobs, and it has a convenient @reboot function that allows you to run a script whenever your Pi boots.
Open a terminal, and type crontab -e to edit your crontab. Scroll all the way to the bottom of the file, past all of the lines that begin #, and add the following line (assuming your code is at /home/pi/firefly.py):
@reboot sudo python /home/pi/filename.py &
Close and save your crontab (if you're using nano then press control-x, y and enter to exit and save).
import time
import explorerhat as eh
import math

constant values
xmax = 316 
step = 5   # step width, e.g. 315/5 gives 63 steps/cycle
start_button = 0 # this defines the state of a push button connected to input port no 1
stop_button = 0 # this defines the state of a push button connected to input port no 3
pause_1 = 0.02 # sets lenght of breaks within steps in "inhale" phase, thereby ramping rate and duration
pause_2 = 0.04 # sets "exhale" ramping rate
pause_3 = 1.5 # break between inhale and exhale phases (keep inhaled)
pause_4 = 1.2 # break at the end of the exhale phase (keep exhaled)

max_intens = 0.9 # maximum intensity/brightness
max_intens_100= 100*max_intens # the same in %
# May allow to optimize "breathing" impression of LEDs and reduce flickering.<br>
l_cosin=[]   # list with cosinus derived values (100 >= x >=0)
l_lin=[]    # list with linear values (100 >= x >=0)

# generate cosinus function list
for i in range (0, 316, 3):   # 315 is close to Pi*100, 105 steps
    # print (i)
    n_cosin = [(((math.cos (i/100))+1)/2)*100] #generate value 
    # print (n_cosin)
    l_cosin = l_cosin + n_cosin  #add value to list
# print (l_cosin)    

# generate linear list for i in range (100,-1, -1): # count down from 100 to zero n_lin=[i] l_lin=l_lin + n_lin # print (l_lin) # shows a boring list print () print ("""To start the light cycles, press the "Start" Button (Input One)""") print () print ("""To stop the light, press and hold the "Stop" Button (Input Three)""") print ()
# wait until Start Button gets pressed while (start_button==0): start_button=eh.input.one.read() # read button number one eh.output.one.blink() # blink LED number one time.sleep(0.5) # read twice a second #run lights while (stop_button==0): # read analog inputs ONE and TWO, define settings set_1=eh.analog.one.read() # defines red-> green ramping rate pause_1=set_1*0.02 # values will range between 0 and 0.13 sec/step print ("set_1:", set_1," -> pause _1:" ,pause_1) set_2=eh.analog.two.read() # defines green -> red ramping rate pause_2=set_2*0.02 # values will range between 0 and 0.13 sec/step print ("set_2:", set_2," -> pause _2:" ,pause_2) # "inhalation" phase eh.output.one.on() # may drive an LED or beeper ''' for x in range (len(l_lin)): fx=max_intens*l_lin [x] # linear curve eh.motor.one.backwards(fx) eh.motor.two.backwards(max_intens_100-fx) time.sleep(pause_1) eh.output.one.off() ''' for x in range (len(l_cosin)): fx=max_intens*l_cosin [x] # linear curve eh.motor.one.backwards(fx) eh.motor.two.backwards(max_intens_100-fx) time.sleep(pause_1) eh.output.one.off() #check if Stop Button is pressed stop_button=eh.input.three.read()<br> # "Keep your breath" pause at the end of the inhalation phase eh.output.two.on() # turn on LED two eh.motor.one.backwards(0) eh.motor.two.backwards(max_intens_100) time.sleep(pause_3) eh.output.two.off() #check if Stop Button is pressed stop_button=eh.input.three.read()<br> # "exhale" phase eh.output.three.on() # turn on LED three ''' for x in range (len(l_lin)): fx=max_intens*l_lin [x] # linear curve eh.motor.one.backwards(max_intens_100-fx) eh.motor.two.backwards(fx) time.sleep(pause_2) ''' for x in range (len(l_cosin)): fx=max_intens*l_cosin [x] # linear curve eh.motor.one.backwards(max_intens_100-fx) eh.motor.two.backwards(fx) time.sleep(pause_2) eh.output.three.off() #check if Stop Button is pressed stop_button=eh.input.three.read()<br> # pause between "exhale" and "inhale" phases eh.output.four.on() eh.motor.one.backwards(max_intens_100) eh.motor.two.backwards(0) time.sleep(pause_4) eh.output.four.off() #check if Stop Button is pressed stop_button=eh.input.three.read()
# shutdown, turn of all output ports eh.motor.one.stop() eh.motor.two.stop() eh.output.one.off() eh.output.two.off() eh.output.three.off() eh.output.four.off() print () print ("Bye bye")

If you want to use the light as a stand-alone device, e.g. as sleeping or wake-up light, you may add a mobile power source to the Pi and have the program starting after booting and use "Cron" to switch it on or off at given times. How to use "Cron" has described in vast detail elsewhere.

Step 4: Video Examples

In this step you will find a number of videos showing the light under normal (i.e. all values > 0, #1) and extreme conditions, as all values set to zero (#2), ramping only (#3 & #4) , and no ramping (#5 & #6).

Step 5: Some Remarks

Please apologize any wrong terms, typos and errors. I am neither a native speaker of English, nor do I have elaborated knowledge in electrics, electronics or programing. Which actually means that I am trying to write an English instructable about things where I hardly know the correct terms in my own language.

Thus any hints, corrections or ideas for improvement are welcome.




    • Woodworking Contest

      Woodworking Contest
    • Colors of the Rainbow Contest

      Colors of the Rainbow Contest
    • Gardening Contest

      Gardening Contest

    2 Discussions