In our previous blog posts we have discussed how illumy works from the customer’s perspective. We’ve covered how the red light simulates a sunset and the blue light simulates a sunrise. We have covered some of the science and research that shows that blue light exposure in the morning can be more effective than a cup of coffee (if you missed it: click here for a good starting point). Our How-to videos demonstrate how to use our newest sleep mask (on YouTube). What about the insides of the device? How can illumy be programmed by sound and keep track of the time and alarm as well as the sunrise and sunset settings? In this article I will try to give some insight into how the illumy tone decode circuit and software works from a technical point of view.
The sleep mask is programmed when it receives a series of audible tones or beeps from a device. The device creating the tones can be a smartphone, tablet, iPod, PC, Mac or laptop. We chose this approach because it is almost universal. The eye mask can be programmed from almost any device with an Android or iOS App or our web based programmer at  (AND Blackberry 10 through the Amazon App store - My Z30 was integral in the design of this product because of its excellent sound reproduction). Why did we decide to use a smartphone or computer to program the mask? So that it didn’t look like this:
Our early concepts included buttons and a display to set the time. Yeah…it didn’t work out the way we were hoping. It was huge, heavy and expensive. Luckily we had another approach to try.
So how does this work? – Electronics:
Illumy contains a small microprocessor, a microphone and an audio amplifier. The microphone and amplifier are tuned to respond to low volume audio tones in the lower end of the audible range. The audio signal is received by the microphone, is amplified and then passed to the microcontroller. The microcontroller contains a module called a comparator. All a comparator does is – wait for it – compares two inputs and changes from a 1 to a 0 depending on whether one input is higher or lower than the other. Why is this important? A sound wave is a signal that oscillates from a minimum to a maximum strength. It crosses the middle point between the max and min many times a second. For a pure tone, you can count how many times the sound wave crosses the middle per second and determine the frequency (what tone it is). Once you can differentiate between different tones, you can send information to the device. This is exactly how we program illumy – we send different tones or sound waves to represent each setting or piece of information we wish to transfer to it. It is a little trickier than that, as we found out during development (I know, all the electronics engineers out there are saying “this is obvious”…agreed. Sometimes I just need to see if in a real life situation before I it sinks in). It turns out that background noise and instability in electronics causes all sorts of trouble. We dealt with a lot of this by tuning the amplifier gain and using a technique called hysteresis. Hysteresis boils down to ignoring small changes in the signal. If your comparator sees a 1 because signal A is higher than signal B, normally the comparator would immediately change to 0 if signal A changed to be even a little bit lower than signal B. Hysteresis keeps the comparator at 1 until signal A is much lower than signal B. This means that if A is bouncing up and down slightly (maybe due to external sound or some source of electronic noise), the comparator will not change value until we are sure that the signal has changed. Here is a basic hysteresis circuit:
How sure do we have to be?
That comes from the values you choose for your hysteresis circuit. It took us some time to get it right but trial and error can be your friend sometimes. Especially when your circuit looks like this:
In practice, hysteresis makes the software much simpler. Since a real audio signal usually has all sorts of noise, we need to ignore the noise. Here is an example from our breadboard that shows how noisy the audio signal can be – the comparator would trip so many times that our measurements would be difficult to understand (especially with an 8 or 16 bit MCU). The yellow signal is audio and the red signal is the comparator with hysteresis. Note how the yellow audio signal is a thick line – this is the signal jumping up and down at many times the tone frequency.
To set up the comparator, we have to choose resistor values that will ignore any change that has the same magnitude as the noise. We can improve the filtering in software but this hardware solution gives us a very reliable frequency measurement to begin with. The next image should give us a good idea of how the hysteresis cleans up the signal for us.
Note how the comparator (in red) does not change state until the audio signal has gone past the audio zero point. The effect is that the noise on the audio signal (the small, fast jumps up and down) don’t trigger a change of state in the comparator when the audio signal is close to zero. I marked the transitions with red vertical lines and you can see how this lags behind the audio slightly. Mission accomplished.
Basic software approach:
In principle, the software for the tone decoder is simple. You need a few elements:
- A timer
- Memory to save information to
- A strategy to ensure you lock onto the tones correctly
To measure an audio or tone frequency accurately, you will want to use a timer that is several times faster than the period of the audio wave. If you want to differentiate between a variety of different tones that are close together, you need a timer that is much faster. Detecting tones around 400 Hz requires a timer operating at at least 800 Hz which means the timer has to expire every 1.25 ms. We used about 50 times this speed to be able to discern each of the 12 tones we wished to detect. Although this sounds fast, with a 16 MHz processor, it is actually pretty slow. The general idea to measure one wave length assuming you have an audio input into the mic is like this:
- Start the timer
- Wait for the comparator to change state
- Reset the timer
- Wait for the comparator to change state again
- Record the time
- Wait for the comparator to change state once more
- Record the time
You can now add the two values together to get the audio wavelength. Converting a wavelength to frequency is easy f = 1/T (f is frequency, T is the period/wavelength). Now you have a basic tone decoder.
Multiple tones for data transfer:
If you want to decode multiple tones you can save each tone that you detect in an array. One issue that will arise is that you will likely detect the same tone over and over again. This will fill up your array very quickly. This is where the strategy is important. You will want to discard any consecutive readings that are the same. By discard I mean you can compare the current tone to the previous one and if they are the same, don’t save it in the array. You will need to find a way to demark between tones but I’ll leave that to you to figure out (hint: You can do this with timing (more difficult) or you can use specific tones as separators). This should be fairly easy to implement on an Arduino but I used a PIC from Microchip. The first decoder was developed on a tiny 8 pin unit but later prototypes use a 28 pin device.