Introduction: Children's Sleep Training Clock

About: Former FAA Technician Instructor, Electronics Hobbyist, and maker. Now living in Alaska and enjoying all the wonders of the 49th state.

I needed a clock to help my 4 year old twins learn to sleep in a little longer (I've had enough of having to wake up at 5:30 in the morning on Saturdays), but they can't read time yet. After browsing through a few items on a very popular shopping site, I thought, "How hard would it be to just make one?!"

So here's what I figured I wanted in this project. It would use some RGB LED's (mostly because I have about fifty of them from another project) to display three different colors. Red would mean go back to sleep, it's too early to wake up. Yellow would mean that they can get up and play quietly in their room. Green, of course means you can get up. I also wanted to be able to adjust the time, because I would like to sleep in longer on some days (Weekends/Holidays vs Weekdays and such).

Supplies

Raspberry Pi Zero W

Two RGB LED's

Six 220 Ohm resistor's

Files (.stl, python, html) found here

Various little screws, wires, and small parts as needed.

Step 1: 3D Printing

My daughter's really like unicorns, so for this project i remixed Riven02's Unicorn Nightlight, which is a remix of Apachcreation's Unicorn Trophy, which can be found on Thingiverse.com and used under a Creative Commons Non-Commercial license. I modified the unicorn base to fit a power cord for the raspberry pi zero. I happened to have some AMZ3D Red PLA laying around, so the unicorn base and head will be red. I used clear/translucent PLA for the horn. The .stl files and settings I used are:

Unicorn.stl

  • Layer Height: 0.02
  • Wall Thickness: .8
  • Wall Line Count: 2
  • Infill: 15%
  • Infill Pattern: Grid

UnicornBase.stl

  • Layer Height: 0.02
  • Wall Thickness: .8
  • Wall Line Count: 2
  • Infill: 15%
  • Infill Pattern: Grid

Horn.stl

  • Layer Height: 0.02
  • Wall Thickness: 0.8
  • Wall Line Count: 3
  • Infill: 0

          Step 2: The Circuit

          The circuit is pretty easy. I chose six different GPIO pins to control the on/off for the different colors of the RGB. Those pins and the corresponding LED Colors are:

          • Pin 11 to RGB 1 RED
          • Pin 13 to RGB 1 GREEN
          • Pin 15 to RGB 1 BLUE
          • Pin 16 to RGB 2 RED
          • Pin 18 to RGB 2 GREEN
          • Pin 36 to RGB 2 BLUE
          • Pin 39 to Ground

          Each pin is hooked up to the resistor through a 220 ohm current limiting resistor (with the exception of ground of course.) I soldered the resistor in line and covered it up with heat shrink tubing.

          Step 3: Raspberry Pi Preparation

          I wanted to be able to set times for the sleep trainer clock using a web interface. So I needed to set up an Apache and PHP Server on the Raspberry Pi. First thing that you should always do when installing new software on a Raspberry Pi is to make sure it's up to date by typing:

          sudo apt-get update

          After that, we can really get down to business. We'll do that by installing Apache2:

          sudo apt-get install apache2 -y

          this should install the Apache web server. You can test this by using a browser on the Raspberry pi and navigating to:

          <a href="http://localhost/" rel="nofollow">http://localhost/</a>

          or by navigating from another computer's browser to your Raspberry Pi's ip address. To find your ip address type:

          hostname -I

          Doing these will lead to a default Apache Web Server page. This can be changed by replacing index.html located in the /var/www/html/ directory. It can be replaced it with my own index.html file.

          Next we'll set up the Apache web server to be able to run PHP files. Start by typing:

          sudo apt-get install php libapache2-mod-php -y

          you should now be able to place the sleepset.php file in the /var/www/html with the index.html file.

          In order to navigate to this page in your own network, you'll need to set up your Raspberry Pi with a static ip address (or you can just try to figure out the new ip address when your network renew's it now and then). You'll need to edit a couple of files for this to work. You'll need to edit the /etc/dhcpcd.conf file with the following:

          interface wlan0
          
          static ip_address=192.168.1.100/24
          static routers=192.168.1.1
          static domain_name_servers=192.168.1.1

          Replace with your network information. The only thing you'll need to do now is reboot.

          sudo reboot

          The placement of the files from the Google drive link should be as follows:

          • index.html and sleepset.php should be placed in the /var/www/html directory
          • sleepset.txt and sleeptrainer1_1.py should be placed in the /home/pi/pythoncode directory (hint: you'll have to create this directory)

          After placing these files in the correct directory, the rc.local file needs to be modified to run the sleeptrainer1_1.py program at startup. You'll need root-level access to modify the rc.local file, so type:

          sudo nano /etc/rc.local

          In the editor, scroll down, and just before the exit 0 line, add:

          python /home/pi/pythoncode/sleeptrainer1_1.py &

          There are two things to remember here:

          1. Use the absolute filepath so that LINUX doesn't think that the sleeptraner1_1.py file is located in the same directory as rc.local.
          2. Don't forget the ampersand (&) at the end. this will allow LINUX to run this file in the background and continue booting.

          Now, save the file by typing ctrl-x and then y when prompted to save and then ENTER.

          Then type sudo reboot.

          It should be mentioned somewhere in here that (at a minimum) you should change you Raspberry Pi password using the passwd command. If you haven't done this yet, now would be a good time.

          Step 4: The Code

          The following is the code from the sleeptrainer1_1.py file. I used a datetime object to compare times to those read in the sleepset.txt file. The text file is simply two lines, the first for hour, the second for minute. sleeptrainer1_1.py sleeps for one minute between loop iterations to not tie up the processor. The green light was originally coming out way too bright, so I used pulse width modulation to dim it when used with red to make yellow.

          Python code:

          import RPi.GPIO as GPIO
          from datetime import datetime as dt
          import time
          
          GPIO.setmode(GPIO.BOARD)
          GPIO.setwarnings(False)
          
          red1 = 11
          red2 = 16
          green1 = 13
          green2 = 18
          blue1 = 15
          blue2 = 36
          
          GPIO.setup(red1, GPIO.OUT)
          GPIO.setup(red2, GPIO.OUT)
          GPIO.setup(green1, GPIO.OUT)
          GPIO.setup(green2, GPIO.OUT)
          GPIO.setup(blue1, GPIO.OUT)
          GPIO.setup(blue2, GPIO.OUT)
          
          p1 = GPIO.PWM(green1, 100)
          p2 = GPIO.PWM(green2, 100)
          
          def readset():
              setfile = open("/home/pi/pythoncode/sleepset.txt",'r')
              a = setfile.readline()
              b = setfile.readline()
              a = int(a)
              b = int(b)
              return a,b
          
          def ledlight(color):        
              if (color == "red"):
                  GPIO.output(red1, GPIO.HIGH)
                  GPIO.output(red2, GPIO.HIGH)
                  p1.stop()
                  p2.stop()
                  GPIO.output(blue1, GPIO.LOW)
                  GPIO.output(blue2, GPIO.LOW)        
              elif (color == "blue"):
                  GPIO.output(red1, GPIO.LOW)
                  GPIO.output(red2, GPIO.LOW)
                  p1.stop()
                  p2.stop()
                  GPIO.output(blue1, GPIO.HIGH)
                  GPIO.output(blue2, GPIO.HIGH)
              elif (color == "green"):
                  GPIO.output(red1, GPIO.LOW)
                  GPIO.output(red2, GPIO.LOW)
                  p1.start(100)
                  p2.start(100)
                  GPIO.output(blue1, GPIO.LOW)
                  GPIO.output(blue2, GPIO.LOW)
              elif (color == "yellow"):
                  p1.start(60)
                  p2.start(60)
                  GPIO.output(red1, GPIO.HIGH)
                  GPIO.output(red2, GPIO.HIGH)
                  GPIO.output(blue1, GPIO.LOW)
                  GPIO.output(blue2, GPIO.LOW)
              elif (color == "off"):
                  GPIO.output(red1, GPIO.LOW)
                  GPIO.output(red2, GPIO.LOW)
                  GPIO.output(blue1, GPIO.LOW)
                  GPIO.output(blue2, GPIO.LOW)
                  p1.stop()
                  p2.stop()
                  
          
          while True:    
              settime = readset()
              hour,minute = settime
              
          
          if minute == 0:
                  if dt(dt.now().year, dt.now().month, dt.now().day, hour-2) < dt.now() < dt(dt.now().year, dt.now().month, dt.now().day, hour-1, minute+30):
                      ledlight("red")
                  elif dt(dt.now().year, dt.now().month, dt.now().day, hour-1, minute+30) < dt.now() < dt(dt.now().year, dt.now().month, dt.now().day, hour, minute):
                      ledlight("yellow")
                  elif dt(dt.now().year, dt.now().month, dt.now().day, hour, minute) < dt.now() < dt(dt.now().year, dt.now().month, dt.now().day, hour+1, minute):
                      ledlight("green")
                  else:
                      ledlight("off")
              elif dt(dt.now().year, dt.now().month, dt.now().day, hour-2) < dt.now() < dt(dt.now().year, dt.now().month, dt.now().day, hour, minute-30):
                  ledlight("red")
              elif dt(dt.now().year, dt.now().month, dt.now().day, hour, minute-30) < dt.now() < dt(dt.now().year, dt.now().month, dt.now().day, hour, minute):
                  ledlight("yellow")
              elif dt(dt.now().year, dt.now().month, dt.now().day, hour, minute) < dt.now() < dt(dt.now().year, dt.now().month, dt.now().day, hour+1, minute):
                  ledlight("green")
              else:
                  ledlight("off")
          
              time.sleep(60)

          The file index.html is a basic form designed in HTML. It takes the contents of two text boxes and passes them to the sleepset.php file for form handling. The PHP file simply overwrites the sleepset.txt file with updated data.


          Step 5: Putting It All Together

          With the coding finished and all the parts printed, it's time for assembly. I followed these steps for putting it all together:

          1. Drill two small holes sized to the RGB LED's in the Bottom of the horn and place the LEDS in these holes.
          2. Place horn into the hole in the unicorn head and pull it through until it is tight. Use glue from the inside to secure the horn.
          3. Attach the Raspberry Pi Zero W to the inside of the unicorn head. (Using Hot Glue Gun Maybe)
          4. Attach the unicorn head to the unicorn base.
          5. Attach power cord, and attach entire assembly to the wall.
          6. Plug in the clock.

          At this Point I have a functioning Children's Sleep Trainer Clock.

          Step 6: One Year Later ...

          One year later:

          My girls are sleeping in a little longer. We have gotten used to waking up to little kids in our room saying, "Daddy, the light is green." and that is great. Long story short, we only wake up at 5:30 AM on a Saturday when we plan it anymore.

          Things I plan on improving in the future:

          • Maybe adding some sensors or other items like a mic and speakers.
          • Maybe edit the code to work with a speaker to use as an alarm clock as my kids will be starting school soon.
          Colors of the Rainbow Contest

          Participated in the
          Colors of the Rainbow Contest