Tuesday, July 9, 2013

Sidetracked: Using the light sensor on the Raspberry Pi - Talking Alarm Clock

One thing that came with my RasPi kit was the light sensor. Getting it to work was easy enough using this great tutorial on adafruit

After playing with the sensor with the example script, and figuring out the rc range of values that indicate that the light is on or off in my home office, I added some logic to print "THE LIGHT IS ON" and "THE LIGHT IS OFF".

OK that's good to know, but what else can I do with that information? Hmmmm. I know!

I decided to make a simple "alarm clock" in python which takes a time as an input on the command line, poll the current time every second, and trigger an alarm once the set time is reached. An alarm requires sound, and since we are building a robot, I thought I would play around with some text-to-speech software for the Raspberry Pi and use that as the voice to wake someone up (and we will use it for other things robot-related down the road)

After playing with a couple text to speech apps, I found that the best one for the Pi is espeak. One of the many things I like about espeak is its tun-ability (pitch/dialect/speed/etc..). One problem I found with running espeak on the Pi is that the words would slow down towards the end of long sentences (like TRON getting derezzed in the grid). I'm not sure if that is due to a CPU/memory resource issue with the Pi and sound driver, but I found a workaround for the slowdown by using an option in espeak which allows output to a wav file. The wav file sounds fine and has no lag, so my talking alarm clock will generate a wav file on the fly (with a random name) and play it with little or no noticeable delay.

I used the built in aplay  for playing the wav files. Aplay is part of the alsa sound driver tools on the Pi.

Where does the light sensor come into all of this? Oh yeah. The alarm clock won't shut up until you get up and turn on the light. Once the light sensor detects that the light is on, the alarm clock will deactivate. This will be great for getting my son out of bed when the school year starts back up in the fall!

Since I am delving into object oriented development, I made the following classes:

  • LightSensor
  • Voice
  • AlarmClock
The AlarmClock has-a voice and has-a light sensor and does all of the time keeping and triggering of the alarm.

An AlarmClock object can be enabled by calling the function AlarmClock.enable_alarm_<st|int>()

Usage: <executable> HH:MM
  • HH:     00-23"
  • MM:    00-59"
Here is an example of the LightSensor class:

class LightSensor(object):

        def __init__(self):
                self.rc_pin = LIGHT_SENSOR

        def rc_time(self):
                reading = 0
                GPIO.setup(self.rc_pin, GPIO.OUT)
                GPIO.output(self.rc_pin, GPIO.LOW)
                GPIO.setup(self.rc_pin, GPIO.IN)
                # This takes about 1 millisecond per loop cycle
                while (GPIO.input(self.rc_pin) == GPIO.LOW):
                        reading += 1

                return reading

        def light_is_on(self):
                reading = self.rc_time()
                if reading > 400: #value when light is off
                        return False
                        return True

light_is_on() returns True if the light is on, False if it is off.

My Voice class has two main methods that can be called by a program:
  • say(<string>) - say the string that is passed to it
  • say_cl(<command line string>) - say the output of the cl command passed to it. In my case, I used the classic UNIX program "fortune"
Code for everything would be messy to paste here, so you can get all of my alarm clock code on github: https://github.com/bugbiteme/alarmclock

The README file should tell you all you need to know to get it up and running!


  1. How are you connection the sensors?

    1. Please look at this tutorial: