A Breathing Light, Controlled by a Raspbery 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 could also be used e.g. as a soothing night light for children.

In the current stage, it is hardly more than a working prototype. But you may also see it as an inexpensive and simple to build example for "physical computing" with a Raspberry Pi, and it might be used as a educational project on the beginners level.

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 turnable 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. Please make sure you are using the correct resistors to reduce the voltage for the LEDs.

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

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".

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:
- 10 kOhm potentiometers (up to four, I used two). To adjust ramping times, or other parameters like brightness.
As start/stop/… buttons:
- Push buttons (up to four, I used 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: Assembly

Assemble the Explorer pHAT as described by the manufacturer. I have added a single row 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.

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. And a version called "Breathing light var lin cosin.py" where the length of the two dimming phases can be adjusted using two potentiometers. In both cases the cycling process can be evoked and stopped using two push buttons. In addition four (colored) LEDs can be connected to the output ports, indicating the specific phases. Both programs are written in Python 3.

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 lenght 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 might give 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.

<p># The "breathing" lamp:<br># 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).
"""
<br>import time
import explorerhat as eh
import math
<br># constant values
#sinus
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
<br>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)
<br>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)
<br># 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)    
<br># 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 ()
<br># 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()
<br># 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: 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.

H

Make it Glow Contest 2018

This is an entry in the
Make it Glow Contest 2018

Share

    Recommendations

    • First Time Author

      First Time Author
    • Toys Contest

      Toys Contest
    • PCB Contest

      PCB Contest

    2 Discussions