Raspberry Pi baby monitor
In this second of a multi-part post I will show how I added some lights to my Raspberry Pi baby monitor (using a RPi 3). The IR leds are not visible to humans, so it will not wake up the sleeping monster. I will also look at some of the software solutions for streaming audio/video over my network. Spoiler alert, in the end I have opted for the Fruitnanny system that Dmitry Ivanov developed.
Hardware, part 2
To be able to follow this guide, the hardware and associated installation from part 1 of this series (Raspberry Pi baby monitor – Hardware, part 1), is neither really advanced nor a requirement. The scripts I use are tailored to the hardware in part 1 and this part (i.e. you have a RPi, RPi Camera and BrightPi, however if you just want a smart RPi lamp this might help some too).
List of components
What you need (except the Raspberry Pi 3B with PiNOIR v2 camera):
- BrightPi kit (board with pre-soldered components + the leds and pin connector)
- Soldering iron and solder wire
Optional parts
- A sturdy holder for the board
- Sticky putty (brilliantly called “elephants bugger” in Denmark), which is good for holding LEDs in place while soldering
Soldering the LEDs
The BrightPi comes as a partial kit. There are two types of LEDs that need to be soldered on to the board, IR and visible light. Along with the LEDs there is also a connector that need to be soldered, if you want to use cables with connectors, and not solder the cables directly to the board. There are nice instructions at the Pi-supply site (https://learn.pi-supply.com/make/bright-pi-quickstart-faq/). I followed those and must admit that I am pretty happy with the results shown in the picture below.

Connect and mount the LEDs
Now we are ready to mount the LEDs to our set up. First I tested the LEDs though, just connecting the cables to the correct GPIO pins of the Pi. After this boot it up, and test the LEDs with the i2cset
command (after enabling I2C in sudo raspi-config
Interfacing Options>>I2C).
Soldered and connected. The visible light LEDs are working. The IR LEDs are working too!
There are cool 3D print mounts for the BrightPi (e.g. https://www.thingiverse.com/thing:2784985), and the PiMoroni camera holder supports it (ugly though). Since I do not have a 3D printer (yet!) I opted for a LEGO mounting solution. I was already using a Raspberry Pi LEGO case, so I thought, if I get some nice pieces that fit and make it possible to direct the lamp that would be awesome. Another option might be to drill holes in the case to connect the screws of the BrightPi board to the camera board directly. Anyway, this is my current solution.
Now that is it, ready to flash the lights.
Temperature sensors
I also wanted to add some environmental sensors to monitor the baby room, because why not, this is a learning experience. So I bought the dirt-cheap but not great accuracy sensor DHT11. Hooked it up with wires according to specs and just let it hang outside the case for now.
Software
During the past year I tested several solutions to streaming video over my local network, and to the outside through VPN. The main solutions I tested were:
- The RaspiCam interface.
- The UV4L project WebRTC and MJPEG streamer
- Simple VLC stream
- Python Flask app
- Python rpicam script
- Dmitry Ivanov’s FruitNanny (GStreamer, Janus, NodeJS)
After testing all these solutions I opted for the polished “FruitNanny” baby monitor, by Dmitry Ivanov (https://ivadim.github.io/2017-08-21-fruitnanny/). Its is perhaps a bit complex, a lot of software pieces need to fit. I cannot seem to access it from the outside through my VPN though, so a minus on that one. However I managed to set things up pretty quick using the guide on a fresh Raspbian install. Below are some comments on all the options.
Comments on (some of) the software
RaspiCam interface. (link)
I tested this through the DietPi distribution. Very easy to install and low usage. The landing page starts streaming directly, you can run scripts from the interface (i.e. toggle light). Full screen is possible. However, no audio, or audio noise meter.
UV4L project. (link)
Also tested through the DietPi dist. THe UV4L is an advanced project, with loads of functionality (such as running meeting rooms etc). The project has two way audio and video in the form of a native WebRTC client, in my use case it was one way. You just “call” the RPi and get audio + video. It was tricky to get the right parameters to see anything in the dark (gain, shutter speed etc), since I couldn’t trigger the lights manually. Also it was pretty unreliable, parameters would reset on reboot, slow and most importantly has some huge ugly text written all over (thus not really ‘open’ software). I read somewhere you can email someone to get a code to remove the text, but I decided to just give up on UV4L.
Python flask app. (link)
Very cool and interesting code by Miguel Grinberg, but how to tie in audio is not obvious, and probably expensive resource wise.
While some of the problems I ran into could be solved fairly easy, such as creating a background script that would turn on the LEDs for the UV4L solution, it was just too cumbersome. I would have a script take a photo to check if it’s too dark and then turn on the lights etc, but then the camera stream could not have been triggered before this. So in the end I went with the FruitNanny project. However there where a few things to fix because they were different in my setup, namely the LEDs and how I like my play/pause button.
Fix: Controlling the LEDs
For controlling the baby monitor’s LEDs there are basically two options. CLI/Bash script control through i2cset
or Python script with the BrightPi library. I ended up with the Python BrightPi library, and a script to replace the existing light.py file as follows.
#!/usr/bin/python # file: /opt/fruitnanny/bin/light.py import sys from brightpi import * # get cli argument par = sys.argv[1] # define convenience variables LED_ALL = (1, 2, 3, 4, 5, 6, 7, 8) LED_IR = LED_ALL[4:8] ON = 1 OFF = 0 # now check the cli argument and do what is asked if par == 'on': # turn on the IR LEDs, but first reset them bpi = BrightPi() bpi.reset() bpi.set_led_on_off(LED_IR, ON) # gain can be 0 to 15 bpi.set_gain(13) elif par == 'off': bpi = BrightPi() bpi.set_led_on_off(LED_ALL, OFF) elif par == 'status': # here we are asking for the BrightPi status # so we use get_led_on_off method bpi = BrightPi() all = bpi.get_led_on_off(LED_ALL) # all now has the status of the LEDs # thus adding them all will show if any of them are on # but if all LEDs are off, 0+0...+0 = 0 if reduce( lambda x,y: x+y, all)>0: print(1) else: print(0)
This can now be run to check the status and turn on/off the IR LEDs of the BrightPi. For example ./light.py on
should turn the IR LEDs on (make sure you chmod +x light.py
as well).
Now since the app previously used the Bash script light.sh
we need to change this in the light.js
file located in /opt/fruitnanny/server/routes/
. So open the file for editing, and change every bin/light.sh status/on/off
line to bin/light.py status/on/off
, simple.
Fix: the play/pause button
While the baby monitor setup by Dmitry Ivanov is super sleek, the play/pause button always got me confused. When paused it shows the pause button and the play button when playing. While I do see the logic and convenience in this, I feel I want a more YouTube-like experience, where the play button shows when it is paused and vice versa.
If you are like me you need to edit two files /opt/fruitnanny/views/index.ejs
and /opt/fruitnanny/public/project/js/video-player.js
and change every fa-play
to fa-pause
and every fa-pause
to fa-play
. You can probably do it with some cool sed
command combo. The ‘fa’ stands for Font Awesome (https://fontawesome.com), just a font that has a lot of nice icons.
Things left to do (or: Wishlist)
There are a few things I want to do
- Light diffuser, the light is very spot-like. Would like to light the full image as evenly as possible.
- Wall holder, put the contraption in a more stationary location.
If I end up with new things, tweaks, I will post the updates here.
Hello !
Thanks for the explanations.
Can you precise for beginners how nd where to install the brightpi library ?
Thanks
Hi, thanks! Well, the install instructions for BrightPi is here: https://github.com/PiSupply/Bright-Pi
Basically, run
curl -sSL https://pisupp.ly/brightpicode | bash
in a terminal and it will be installed in your active Python environment.Regards,
Magnus
Hi, I also played around with a Pi Zero + NOIR Cam + Bright PI as a baby monitor. Do you have any insights about intensity of the IR leds? I’m just a bit hesitant to expose my kid to IR light over many hours without knowing if this could be potentially dangerous. Did you thought about that?
Hi, I apologize for my late reply. You can calculate the irradiance at the cornea and retina from the datasheet of the leds.
The datasheet on the LiteOn HSDL-4261 IR LEDs which there are 8 of on the BrightPi says the radiant (on-axis) intensity (I_e) at max is 180 mW/Sr. To get the irradiance (E_e) we have to calculate it at a certain distance from the light source. If we assume you place it like 1 m away, you get an irradiance of 0.180/(1^2) = 0.18 W/m2, times 8 we have 1.44 W/m2 instead. The limit for exposure to the cornia is 100 W/m2.
For the retina the calculation is a bit more tricky, but after some checks and using default values for the eyes lens opening angle etc, I get values that are below the limits but calculated at like 20 cm distance. So it would be fine putting the BrightPi at least 1 meter away from the baby.
We bought a Tapo C200, and I put it on its own network (VLAN) without internet access. It has IR LEDs too, and it is marketed as a baby monitor. One possible improvement to the BrightPi is mounting a diffuser since the LEDs do not do alot of diffusion of the light, this might make the image better and also spread the radiation over a larger area, thus lowering the irradiation.
Check datasheet for the LiteOn IR led used in BrightPi, medium post on IR Illumination and eye safety, and lastly OSRAM document on eye safety and lamp applications