Go Down

Topic: SleepyTimer, an IMU-based sleep monitor (Read 1 time) previous topic - next topic


I'm a terrible sleeper - always have been.  Not sure what it is, perhaps mild apnoea, but I never seem to wake up refreshed.  So, when a co-worker showed me a sleep monitoring tool on her smartphone a few months ago I thought "Arduino Project!".   You leave the phone under your pillow at night and it uses the built-in IMU to sense movement and produce a graph and stats about your sleep patterns. Not sure exactly how it works, and I didn't find out (where's the fun in that?).

SleepyTimer was my project-a-month (http://www.flickr.com/photos/funnypolynomial/collections/72157629491971107/) for May:

SleepyTimer - Assembling by funnypolynomial, on Flickr

SleepyTimer - Interior by funnypolynomial, on Flickr

A tiny 3-axis accelerometer board sits in a small case at the end of a ribbon cable.  It goes under my pillow.

SleepyTimer - Bedside by funnypolynomial, on Flickr

It's connected to the main unit in a cheap plastic container (oh joy, tons of space!) with the Arduino, a graphics LCD, a DS1307 RTC, buttons etc.

The graphics  LCD is this ST792-based one: http://www.mindkits.co.nz/store/led-lcds/128x64-graphic-lcd ("QC12864").  I could not for the life of me get it to work with the serial interface (grounding PSB always seemed to reset everything).  Parallel did work but pin-use resentment kicked in.  Dropping down to 4-bit parallel still requires 7 precious Arduino pins and, just as important because I wanted the LCD to be a separate module, 7 connections (plus Gnd and VCC!).  So I eventually got the LCD working with just 3 Arduino pins by driving it with a 74HC595.  Four of the 595's outputs are data, two are control (SCLK & CS) and one is used to drive the backlight (one output is unused).

SleepyTimer - LCD Driver by funnypolynomial, on Flickr

When in sleep-monitor mode all three IMU axes are sampled regularly and the values are added to independent rolling averages.  Motion is detected when a new reading spikes more than a threshold amount from the rolling average.  The monitoring session is binned in to 120 6-minute periods.  The motion spikes are averaged within each bin.  Motion within a bin is considered "wakefulness".  The bins, along with some header information (date, start and end time etc), are recorded as a rolling list of 8x 128-byte "pages" in EEPROM.

A simple menu system driven by two buttons lets me navigate through settings etc and view a monitoring session (i.e. a "night's sleep") .  I display the movement as a bar graph with some simple stats: the Total time asleep (the number of bins with no movement) and the Max period of uninterrupted sleep (I have yet to see more than an hour).  The graphing is done in bands.  Rather than allocate enough RAM for the entire image I create an 8-pixel high band and repeatedly render the the graph into it, and send the bands to the LCD.  The banding also fits well with printing.

SleepyTimer - Graphs by funnypolynomial, on Flickr

From day one I had the idea of producing a hard-copy of a night's session.  I found a relatively cheap thermal-transfer printer online (an NCR Receipt Printer, $NZ31) and hooked it up.  I quickly found that the Arduino couldn't drive the RS232 levels appropriately.  I invested in a couple of "level shifter" boards but none of them worked.  In the end I had to create my own with a MAX232 and a few caps.

So now the sensor unit rests under my pillow and the main box on my bedside table (and the printer on the floor beside it).  It's configured to auto-start and auto-end at times based on weekdays vs weekends  (but starting and stopping can be overridden via the green and red buttons).  It is confirmed, I am a terrible sleeper.  I have a smartphone now too, but given how much the battery life sucks, I won't be looking for that app.

There are more photos and details on flickr:http://www.flickr.com/photos/funnypolynomial/sets/72157630783955130/
The sketch is available from my site:http://www.funnypolynomial.com/software/arduino/sleepy.html
// TODO: sig


Actually, technically I guess it's an accelerometer rather than an IMU (inertial measurement unit).
// TODO: sig

Go Up