Showing posts with label sleep. Show all posts
Showing posts with label sleep. Show all posts

2009-03-23

Planning to build own cellphone based sleeptracker project

I'm using Sleeptracker, but I need something to get better data that it provides, and have more flexible work modes.
There are many interesting projects with custom devices based on micro-controllers. I used to solder small electronic devices in past, but now I'm maybe too lazy and just looking for some pragmatic device, that looks and works good. It's fun to make design of own device but there are many ready small computing platforms with suitable features.
I'm thinking about cellphone, or maybe smart-phone, with built in accelerometers and available free software development tools for developers. It needs to have accelerometers and API to get acceleration data from it.

That kind of device has nice features:
  • it's programmable so you can put any features you think about
  • compact size, good for wrist attachment (ok maybe little too big, but make some trade off)
  • built in battery with quite long operating time and possibility of charging
  • possibility to use other input devices to get data like camera to get light level, or microphone to catch noises
  • builtin gprs or wifi to send data to server
  • of course its still cellphone

The biggest problem may be lack of API to needed devices. New devices are more open than in those in past, but some vendors still don't expose access to internal services.

2008-06-16

Analysing SleepTracker data for R.E.M. phases

I'm collecting sleep data from my Sleeptracker watch for above 3 months. It's a good time to check what is interesting in there. My goal is to check pattern of my sleep R.E.M. phases.

First, I get my sleep data in csv format stored on www.sleeptracker.net site. Then using simple python script I've converted all night/time data into relative values. Now I have all SleepTracker movement occurrence time saved in "hours after going sleep".

After looking at initial data I was a little bit disappointed. I have not seen clean gaps for non R.E.M phases. Picture was so cluttered. There were many possible reasons. I've choosen one - sometimes I go sleep at different time, but sleep patterns may be anchored to usual hours.

I decided to make more preprocessing to move out "outstanding" data. I removed data instances with non standard "going to bed" times, movements it the first hour of sleep and some made some minor tweakings. When I viewed data again the picture was much clearer.



I rerun data clustering software using standard kmeans method and get some results:

Cluster 1
Mean/Mode: 0.8458
Std Devs: 0.2783

Cluster 2
Mean/Mode: 1.5433
Std Devs: 0.2069

Cluster 3
Mean/Mode: 2.6117
Std Devs: 0.2857

Cluster 4
Mean/Mode: 3.6685
Std Devs: 0.236

Cluster 5
Mean/Mode: 4.8086
Std Devs: 0.2848

Cluster 6
Mean/Mode: 5.9405
Std Devs: 0.4276


That means that probably REM phases occurs about 0.85, 1.5, 2.6, 3.6, 4.8 and 5.9 hours after falling asleep. Common value found in literature is about 1.5 hour between R.E.M. phases.
Bigger standard deviation in later vs earlier phases reflects longer R.E.M. phases at each cycle, what is also found in sleep research. First cycle must be treated in special way - the sleep pattern is different sudden after falling asleep.
The last one can be also less reliable because of standard waking time after about 6 hours.

I decided to pick R.E.M. time values by my self using "smoothed" histogram of sleep data. Local modalities are clearly visible on picture.


Now middle of phase values seems like: 0.8, 1.6 , 2.3 , 2.8, 3.4 , 4 , 4.9. Comparing these results with those from automatic clustering method it seems that "k means" method joined 2 close groups together.
I assume that manually picked results are better.

Time for conclusion.

To get more reliable results I need more data and regular sleep :) . SleepTracker is quite effective by using simple accelerometer movement detection method. Unfortunately many movement events aren't recorded (for example the subtle ones or when the arm is blocked under the pillow). I will try to catch more good data and check results again.

2008-04-07

Sleeptracker - gadget for sleep optimizers



In last month I get new gadget- Sleeptracker Pro alarm watch.
Short description how it works from original website:


SLEEPTRACKER® continuously monitors signals from your body that indicate whether you are asleep or awake. Because you wear SLEEPTRACKER® on your wrist like a watch, its internal sensors can detect even the most subtle physical signals from your body. SLEEPTRACKER® finds your best waking moments, so that waking up has never been easier.


Manufacturer created positive buzz amongst community. I have read so many positive reviews that even price tag (about 180$ in US for Pro model) doesn't stopped me out of buying it.

Some remarks about alarm clock features:
- clock with date on quite big display
- one alarm time
- sound and/or vibration alarm (sound and vibration may be too silent for very hard sleepers!)
- back light is nice
- can be worn as casual watch, but can be too bulky for some people

Because it's not normal alarm clock there are additional outcomes:
1) It wakes you in the moment (within set time window) you are better prepared to wake up, so you feel better
It generally "feels" true or it's hard to say without comparing statistics with and without Sleeptracker

2) It is shortening your sleeping time by about 15-30 minutes (it depends on sleep schedule) without negative consequences.
It's strong dependable on sleeping schedule and works best for unoptimized sleep with waking time in the middle of sleep cycle. On the other way every day sleep patterns may vary a little so monitoring device it's catching actual cycles. For me alarm clock sets up between 0 and 40 minutes before usual waking time.

3) It records R.E.M. activity during night, so data can be collected and analyzed to improve sleep habits.
Sleep data can be reviewed on watch or Sleeptracker Pro has USB port to transfer data to computer.




There are important rules I figured out that should be considered before buying that stuff:
- Sleeptracker will not work for you if you don't have enough sleep or have heavy sleep disorders
- alarm sound is silent so get enough of sleep to be ready top wake up in the morning
- it did not worked for my polyphasic sleep schedule (look at get enough sleep point)
- watch is worn on wrist, so if you place your arm under pillow or in other position that could block arm movement, Sleeptracker won't record R.E.M. phase due to lack of movements
- it may won't work for people who don't move their arms at during R.E.M. cycle (it's hard to check but it's possible)
- have I told that you should get enough sleep?

Sleeptracker Pro package contains USB cable, printed manual and little CD with software for windows. Interesting solution is used for connecting USB cable to watch. Cable ends with clip that have 3 springing pins matching connector on the backside of watch. I didn't mentioned the watch is waterproof!.

Sleeptracker software is used for transfer sleep data from watch and tracking that data with a day events like drinking coffee or alcohol, sleeping light and temperature conditions etc. I tried to run that software under WINE on Linux, but USB data transfer did not work.

So I tried to find another solution. I found the PERL script to get data from USB cable on sleeptracker forum. I found two version of script with bugs or unimplemented features so I integrated both to get one better. Instead of desktop software it can store data as text or xml files. The next nice feature of script is export to web version of Sleeptracker software at http://www.sleeptracker.net/. I'm still collecting data so later I report my findings.


Below is mentioned PERL script:

#!/usr/bin/perl -w

# This program downloads records from your Sleeptracker Pro
# and displays them as text, xml, or csv
#
# Sleeptracker and Sleeptracker Pro are trademarks of
#
# Innovative Sleep Solutions
# 2870 Peachtree Road #140
# Atlanta, GA 30305
#
# This program is NOT developed or supported by Innovative Sleep Solutions
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# You can purchase your Sleeptracker or Sleeptracker Pro from:
#
# http://www.sleeptracker.com
# http://www.sleeptracker.de
# http://www.sleeptracker.fr
# ... and some other stores
#

# Chagelog:
# --------------
# 09.12.2007: fixed bug in xml output tag
# 10.12.2007: fixed wrong cecksum calculation
# 11.12.2007: added browser output
# 13.12.2007: fixed seconds from DataA
# 14.12.2007: fixex wrong eff.alarm time, when no alert in window
#
#
#


use Device::SerialPort;
use Time::Local;
use strict;


my $browser="firefox"; # which browser to call
my $uploadURL="http://www.sleeptracker.net/import.php"; # which upload URL to call

my $numArgs = $#ARGV + 1;
my $ttyPath="";
my $format="browser"; #set default

if($numArgs > 1){
$format=$ARGV[0];
$ttyPath=$ARGV[1];
} elsif ($numArgs == 1){
$ttyPath=$ARGV[0];
} else {
help();
exit 1;
}

if (not -w $ttyPath) {
print STDERR "Can't access Sleeptracker at device '$ttyPath'\n";
exit 1;
}

print STDERR "Reading Sleeptracker data from $ttyPath\n\n";

my $serial = Device::SerialPort->new("$ttyPath");
$serial->baudrate(2400);
$serial->databits(8);
$serial->purge_all();
$serial->rts_active(0);
$serial->dtr_active(1);
# Send request
$serial->write("V");
# Wait one second
select(undef, undef, undef, 1);
# Read response
my($count, $data) = $serial->read(250); # goog for more than 70 awake moments

if($count<15){
print STDERR "Error while reading from Sleeptracker!\nWatch showing DATA screen?\n";
exit 1;
}

my @stBytes=();
my $cnt=0;
my $crc=0;
foreach my $byu (split (//, $data)) {
$cnt++;
# for debug
#printf "%03d: %02x = %d \n",$cnt,ord($byu),ord($byu);
push @stBytes,ord($byu);
if($cnt>1 && $cnt<$count-1){
$crc+=ord($byu);
}
}
#printf "%x=%d\n\n",$crc,$crc;
$crc=$crc%256;

# compare checksum
if($crc!=$stBytes[$count-2]){
print STDERR "Checksum Error while reading. $crc!=$stBytes[$count-2]";
exit 1;
}


# calculations and data formating

my $pos=1;

my (undef,undef,undef,$mday,$mon,$year,undef,undef,undef)=localtime();
my $jahr=$year+1900;
my $monat=$mon+1;
my $tag=$mday;

my $stTag=$stBytes[$pos+1];
my $stMonat=$stBytes[$pos+0];
my $stJahr=$jahr;

if($stMonat>$monat || ($stMonat==$monat && $stTag>$tag) ){
$stJahr=$jahr-1;
}

my $datum = sprintf "%02d.%02d.%4d",$stTag,$stMonat,$stJahr;
$pos+=2;

#$unknown=$stBytes[$pos];
$pos+=1;

my $window = sprintf "%2d",$stBytes[$pos];
$pos+=1;

my $toBed= sprintf "%02d:%02d",$stBytes[$pos+0],$stBytes[$pos+1];
my $toBedTS = timelocal(0,$stBytes[$pos+1],$stBytes[$pos],$tag,$monat-1,$jahr);
$pos+=2;

my $alarm =sprintf "%02d:%02d",$stBytes[$pos],$stBytes[$pos+1];
my $alarmTS=timelocal(0,$stBytes[$pos+1],$stBytes[$pos],$tag,$monat-1,$jahr);
$pos+=2;

my $cntData=$stBytes[$pos];
$pos+=1;

my @almostAwake=();
my @almostAwakePst=();

my $lastAwake=$toBedTS;
my $thisAwake=$lastAwake;
my $alltimes="";
for(my $i=0;$i<$cntData;$i++){
my $aaw=sprintf "%02d:%02d:%02d", $stBytes[$pos+($i*3)+0],$stBytes[$pos+($i*3)+1],$stBytes[$pos+($i*3)+2];
my $aawShort=sprintf "%02d:%02d", $stBytes[$pos+($i*3)+0],$stBytes[$pos+($i*3)+1];
$alltimes.=$aawShort.",";
push @almostAwake,$aaw;
$thisAwake = timelocal($stBytes[$pos+($i*3)+2],$stBytes[$pos+($i*3)+1],$stBytes[$pos+($i*3)+0],$tag,$monat-1,$jahr);
if($thisAwake<$lastAwake){
$thisAwake+=(24*60*60); # day has changed
}
my $slept=sprintf "%d",($thisAwake-$lastAwake)/60;
$lastAwake=$thisAwake;
push @almostAwakePst, $slept; #period sleeping time in sec
}
$pos+=($cntData*3);

if($thisAwake<$toBedTS){
$thisAwake+=(24*60*60); # day has changed
}

my $getUp=$almostAwake[@almostAwake-1];

# when the last awake moment was outside the window, the alert goes off at alarm time
if($lastAwake<$alarmTS-$window){
$getUp="$alarm:00";
}

my $dataAVal=($stBytes[$pos+1]*0xff)+$stBytes[$pos];
my $dataASec=$dataAVal%60;
#my $dataA=sprintf "%d:%2d",(($dataAVal-$dataASec)/60),$dataASec ;
#my $dataACalc=sprintf "%d:%2d",(($thisAwake-$toBedTS)/$cntData)/60,(($thisAwake-$toBedTS)/$cntData)%60;
my $dataA=sprintf "%d:%02d",(($dataAVal-$dataASec)/60),$dataASec ;
my $dataACalc=sprintf "%d:%02d",(($thisAwake-$toBedTS)/$cntData)/60,(($thisAwake-$toBedTS)/$cntData)%60;


# output Browser
if($format eq "browser"){
my $URLParam=sprintf "a=%s&w=%s&t=%s&dt=%s&da=%s",$alarm,$window,$toBed,$alltimes,$dataA;
my $callFirefox=sprintf "%s \"%s?%s\" &",$browser,$uploadURL,$URLParam;
print "\n";
print $callFirefox;
print "\n";
my $ret=system($callFirefox);
}

# output Text
if($format eq "text"){
print "Date: $datum\n";
print "To Bed: $toBed\n";
print "Alarm Time: $alarm\n";
printf "Effective Alarm Time: %s\n",$getUp;
print "Window: $window min\n";
print "Data A (Clock): $dataA min\n";
print "Data A (Calculated): $dataACalc min\n\n";

print "Awake moments ($cntData): \n";

my $aawCnt=0;
foreach my $awm (@almostAwake) {
printf " Data %2d: %s (slept: %3d min)\n",$aawCnt+1,$awm,$almostAwakePst[$aawCnt];
$aawCnt++;
}
print "\n";
}

# output CSV
if($format eq "csv"){
printf "%s;%s;%s;%s;%s;%s;%s;%s",$datum,$toBed,$alarm,$getUp,$window,$dataA,$dataACalc,$cntData;
my $aawCnt=0;
foreach my $awm (@almostAwake) {
printf ";%s",$awm;
$aawCnt++;
}
print ";\n";
}

# output XML
if($format eq "xml"){
print "\n";
print " $toBed\n";
print " $alarm\n";
printf " %s\n",$getUp;
print " $window\n";
print " $dataA\n";
print " \n";

my $aawCnt=0;
foreach my $awm (@almostAwake) {
printf " %s\n",$aawCnt+1,$awm,$almostAwakePst[$aawCnt];
$aawCnt++;
}
print "
\n";
print "
\n";
}



sub help {
print STDERR "Usage: sleeptracker [format] device\n";
print STDERR "format: browser(default), text, csv, xml\n";
}