Algorithm
Back to the main page: PRE2015_3_Groep4
To the input: Input
To the output: Output
to the measurement plan and experiments: Measurement plan and experiments
Explanation MATLAB-scripts
For the processing of data and determining the ideal moment to wake up the user, MATLAB is used. Three scripts were created. The first script, runscript.m, is used for determining when to call the other two scripts and contains all the alarm clock settings. Every four minutes, the second script is called, based on its return value, the user is awakened or MATLAB waits another four minutes and tries again.
The second script calculates when it's time to wake up the user. It starts with importing recorded data and fixing bad samples, then the respiration frequency is calculated. Finally, the script checks whether it's time to wake up the user and returns this as a boolean value.
The third and last script contain the wake-up cycle. From this script, a sound is played with increasing volume and the LED's on the Arduino are controlled.
runscript.m
Runscript.m uses the timer and clock functions to keep track of time passage. When the start delay has passed a while loop is started to check whether it's time to wake the user. If it is, the output function is called.
Clock returns a 1x6 matrix containing the current year, month, day, hour, minute and second, this is multiplied by a 6x1 matrix (times) containing a number of seconds in each of the aforementioned time-units, to create a scalar time in seconds.
The wake-up time, interval and delay are entered using this same format, with preset variables for the number of seconds before the start of this day and the next.
The timer works through two functions, tic and toc. tic starts or resets the timer, toc returns the current value. This timer is reset before calling the complete_script function. If the user needn't be awoken, the while loop restarts and complete_script is called again after 4 minutes have passed, evaluating toc every 5 seconds. if the alarm has not been set when the wake-up interval has almost passed, the alarm is called anyway. This is done just before the wake-up time, so you never wake up too late. Not even a second.
Then, in the end, OutputFunc is called, starting the wake-up cycle.
Complete_script.m
Complete_script.m Calculates when to wake up the user, this is done in three steps: importing data, processing data and applying the wake-up algorithm.
Importing data
It all starts with the import data function, which imports the data from the file as three columns, namely timestamp, audio data and envelope data. The imported data is not perfect, there are some missing lines from the communication with the Arduino. These misprints have to be filtered out, this is done using a while loop nested in a for loop. The outer loop cycles through all(but the first) samples, searching for 'bad' samples.
For each sample the time difference between this sample and its predecessor are calculated if this value is larger than twice the assumed sample time, at least one sample is missing. It is also possible for missing samples to occur at the microsecond-overflow, that results in a sample time of some negative value, greater than -2^16 (about -65k) microseconds. these are filtered out by finding samples with a sample time between -60k and half a sample time. Samples with a time difference of less than -2^16 microseconds are also removed, but this is theoretically impossible. For each of these 'bad' samples, the while loop is started. This loop removes an entire timestamp cycle of 2^16 microseconds, up to the point where the time difference between two consecutive samples is between 0.5 and 2 sample times. From a data analysis point of view this is bad conduct, but since only 0.065 s of samples are removed on a four-minute window, we consider this negligible.
Once we are left with only good, clean data, the microsecond-overflow needs to be corrected. This is done by finding all the samples where the time difference is negative(overflow samples). Then yet another for loop is started, adding 2^16 for every overflow sample that has passed before this sample.
Processing data
In this part of the script, the respiratory frequency is calculated for every 4 minutes 'frame' using a for loop. Firstly, the current frame is extracted from the data. Only the 'envelope' signal (sound volume) is used because our sample frequency is not high enough to measure the sound frequency.
Secondly, a fast fourier transform is applied to the frame. The output of this function is then cropped, removing all frequencies outside of the respiratory frequency range(0.22 - 0.45 Hz). We assume the frequency that is most significantly present is the respiratory frequency of the user, this frequency is stored. Besides the respiratory frequency of each frame, a shifting average of 5 frames (20 minutes) is kept as well.
In the current script, each frame is calculated again every four minutes, because we do not retain data between separate calls of Complete_script.m.
Applying the wake-up algorithm
From our measurements, we got information about respiration during your sleep. Out of this information, we get a global line of your sleep phase throughout the night. Out of this line, we have to determine what's the best moment to wake someone between a given interval. The best moment to wake someone is just after the REM-sleep. So this is the first or second nREM-sleep stage. (see literature, add reference).
In our algorithm, we have developed two methods which can determine at which moment the app should wake you. The first method is looking at the slope of the line. During REM-sleep, the respiration frequency is at its highest. So we can detect the end of the REM-phase with a drop in frequency. Another method is looking at the current frequency relative to the mean frequency of the night. With this method, we can detect a 'good' moment, i.e. when the frequency is below the mean of the past night. But the mean is probably too low, so we have to increase the value with a small factor of the variation.
However, during the REM-sleep, the respiration frequency varies a lot (see literature, add reference), so we need to be sure that a decline, or a value below the mean, is really the end of the REM-sleep and not just a variation during the REM-sleep. This can be done by looking for two consecutive decreasing frames. (two frames is around 8 minutes).
Finally, it's decided to use both criteria's to determine the ideal wake-up moment. So the determination of the wake-up moment is based on the following criteria:
- Slope: if the respiratory frequency decreases, the user is transferring to a deeper sleep stage, indicating a good wake-up time.
- Relative position: if the respiratory frequency is relatively high (above the mean frequency), you are in a shallower sleep stage.
these criteria are checked for a few frames in a row if both criteria are true for all frames and the frame is in the wake-up interval specified by the user, the alarm is activated.
Appendix
Matlab-scripts:
This script has to run; here, the user have to fill in the wake-up time and interval:
This script is a function which will process the gathered data. This function will also calculate out of these data the sleep phase. Finally, there will be checked if there is a good moment to wake-up within the interval.