Skip to main content

more options

Our final project


Elevator Pitch / 1-second Description

“An adaptive alarm clock that chooses the optimal time to wake up the user using an accelerometer that detects his/her body movements.”


The goal of our final project was to create an alarm clock that is able to detect your sleep patterns and wake you up at the optimal time, i.e. when you are in the lighter phases of sleep. Our goals for this project were broken up into several progressive milestones. The milestones are listed as follows:

Sleep Analyzer

Since the main goal of our project is to analyze one's sleeping pattern, we considered many different sensors in order to detect this. We decided upon using an accelerometer in order to collect body motion data during the course of one's sleep. Using accelerometer output, we hypothesize that one's body motion during deeper sleep is less than during lighter sleep. We found that the accelerometer works in detecting body motion during sleep and our resulting data is presented in the rest of this document.

Adaptive Alarm Clock

After accomplishing the goal of obtaining sleep movement, we wanted to make use of this data in the form of an alarm clock to achieve the best wake-up time. Parsing the sleep movement data proved to be harder than expected. We came up with an algorithm that actively tracks and predicts the wake-up time. The algorithm for this wake-up time is described in detail later in this report.

Readback Mode

Finally, we needed a way to test and demo our alarm clock. We saved sleep movement data to an SD card and we were able to analyze this on a computer using Matlab. We then built in a readback mode, which runs the alarm clock at 100 times the speed and reads back accelerometer output from the SD card, simulating a night's worth of sleep.

High Level Design

A high-level diagram of the hardware componenets of our alarm clock


The reason we chose this project was to build an alarm clock that could improve one's sleep by simply picking a good time to wake up. Optimally, this would reduce the number of times one would hit the snooze button and one would wake up refreshed after a good night's sleep. We also thought it would be interesting to analyze one's movement during sleep.

Background Math

Very little background math is needed to understand our project. The alarm clock keeps track of time internally using military time (24 hours). We make use of simple mathematical concepts like averaging and counting in our algorithm.

Logical Structure

The logical structure of our program is to sample A/D conversions from the accelerometer and write those samples to the SD card. We also have to keep track of and display the time. We also had to set up an interface so that user could set an alarm time and turn off the alarm.

Our program was structured with multiple tasks with separate timers. There was a single timer 0 overflow ISR that interrupted every millisecond in order to keep track of time and set off task timers. The tasks in our program consisted of taking A/D conversions from the accelerometer, write read values to the SD card, update the LED display, check for button presses, and set off the buzzer. These tasks are fully described later in the software section.

Hardware/Software Tradeoffs

We used 4511 series BCD-to-7-segment decoders to greatly simplify the programming of the LED displays. Without them, we would have to drive the LEDs in the 7-segment displays individually and that could take up many MCU port pins. In order to minimize the number of pins used for the LED display, we connected the corresponding bits of the input to the decoders together. Since the decoder for each digit had a latch, we simply enabled the latch of the digit to update its value in the updateLEDdisplay function. Refer to the Hardware and Software sections for further discussion of design tradeoffs.

Relationship of Design to available IEEE and other standards.

We followed the standards according to the SD Association for using the SD card in MMC mode using SPI for communication. The FatFs library that we are using is a Windows compatible FAT file system. The RS232 standard was used for serial communication.

Existing patents, copyrights, and trademarks

There has been a lot of existing and related work in this field. We looked at several products on the market that offer the same functionality as our alarm clock. The closest product was an iPhone app called Sleep Cycle that makes use of the iPhone accelerometer to produce a graph describing one's different sleep phases throughout the night. It makes use of this data to wake up the user. Other products include WakeMate, Axbo, and Zeo. They make use of a variety of sensors that are attached to one's body to detect movement, pulse, and even brainwaves. A full listing of these products is listed in our references section in the appendix.

There exist several patents in this area that describe similar ideas but to our knowledge we have not been able to find a patent that is remarkedly similar to ours. The following is a description of several patents that we found to be similar to our idea. We found a patent for an adaptive alarm system that uses a motion sensor or video camera to track a person's movement and to determine whether or not to adjust alarm clock signals accordingly. There has also been work in determine one's sleep phase using the heart rate and pulse. Such a system is described in this patent. Finally, there have been models proposed that use a system similar to ours that uses a general sensor and a signal processing unit that analyzes the output from this sensor.


ECE 4760 Custom PCB Board

We used the ECE 4760 Custom PCB board to create a board for our microcontroller. The full details about this board can be found on the ECE 476 webpage. Our final board included a Max233CP for serial communication and an RS232 connector. The board included an LED which we used to indicate whether or not the program was writing to the alarm clock. We powered our board using a 9VDC wall wart.

The PCB layout and picture of the custom board taken from the ECE 476 website.


Using this resource that we found online, we were able to determine which type of accelerometer to use. We tried out a few accelerometers with varying parameters. We found that the parameter that affected our performance the most was maximum swing. The accelerometer that we used was a Freescale MMA1260D. It is a Low G Accelerometer. It is a one-axis accelerometer with a maximum swing of +1.5g. We also tried 2-axis and higher maximum swing accelerometers. We found that the higher maximum swing accelerometers did not fit our needs since a person's motion in bed is a relatively low-G activity. There were 2 key reasons for why we did not use a 2-axis device (or adding another one-axis device to acheive the same functionality). The first reason was that we found that the extra axis did not provide much more extra information, and simply reinforced the single axis device's data. Secondly, it was also a design decision not to complicate our design by adding another accelerometer axis.

Freescale MMA1260D accelerometer that we used

SD card

We used an off-the-shelf SD card for storing and reading back data. We used SPI to commmunicate the SD card with the microcontroller. The main challenge in doing this was stepping down the voltage from 5V to 3.3V. For this we used a 3.3V voltage regulator to step down the voltage.

Schematics of the circuit for the SD card

A picture of the circuit for the SD card


We looked at a variety of alarm devices. Primarily, we needed to find an audible wake-up device. We looked at a variety of buzzers and their rated dB. Using a dB scale we found online for common sounds, we were able to find a buzzer of appropriate loudness. Secondly, we needed to look at the rated voltage of the buzzer. Most buzzers we looked at had a range of voltages corresponding to dB ranges. Using the dB scale, we aimed to find a buzzer around 100 dB and with a large enough voltage range so that we could vary the buzzer loudness (for ramping up buzzer loudness, so as to not jar the sleeping user). The buzzer we found had a voltage range of 3V to 28V and 90 dB sound level at 12 V. These characteristics allowed us to have flexibility in how we implemented the buzzer.

The buzzer we ultimately decided to use

Buttons and Switches

The buttons we used were buttons we found in 476 lab. They were connected to the microcontroller using port pins with pull-up resistors on. We debounced all buttons since the user needs the accuracy to set the clock and alarm time (i.e. we don't want the user to accidently increment the hours twice instead of meaning to do it once). The two switches we used we also found in the 476 lab. We connected one of the leads from the switch to Vcc, the other end to GND, and the middle one to the input pin. Each button was individually debounced. We used a debounce state machine based on the debounce state machine from Lab 2.

The debounce state machine used for debouncing individual buttons.

The buttons and switches that we have used

LED Display

The LED display shows the time and alarm time. There is also an LED indicator for showing whether or not the time is in AM or PM. The LED is lit for AM.

The LED display was set up to minimize the number of Mega644 pins we would have to dedicate to the display. If we were to display each 7-segment display separately we would need to dedicated 1 port per display. This is unfeasible since we needed the other ports for other functionality. Thus we used 4 BCD-to-7-segment decoders to drive all 4 7-segment displays using one port. Each BCD-to-7-segment decoder has a latch that holds the digit on each display, so we can update each display separately. The details of how we updated these displays in software is described later in the Software section

One LED decoder. There are four total, one for each 7-segment display

The circuit for 4 7-segment displays

The circuit for driving 4 7-segment displays with 4 decoders

The actual LED 7-segment display

When we were testing the alarm clock time display, we used a whiteboard with the BCD-to-7-segment decoders plugged in via SIP machine pins. We did this first before we soldered a board that interfaced the actual LED digit displays to Port C of the Mega644. This agreed with our approach of testing each module of the clock system independently before integrating modules. Hence, the 4 decoders are connected to a circuit board with SIP pins in the final design.

Power supply

We found that 4 7-segment displays drew too much current from the microcontroller (in fact it blew out the power regulator on our prototype board). In order to supply more power to the LED display, we added an additional power supply whose sole purpose was to supply power to the LED display. We used a 12VDC wall wart that had an output current of 1A. However, since our LED displays needed 5VDC we needed to step down the voltage from 12VDC to 5VDC. To do this we needed to create a circuit.

The circuit used for stepping down the voltage from 12VDC to 5VDC.

We found that 4 7-segment displays drew too much current from the microcontroller (in fact it blew out the power regulator on our prototype board). The current draw of each segment's LED of a 7-segment display is approximately (5 V - 3.7 V)/(75 ohm) = 17.3 mA ~ 20 mA. 7 segments on each of the 4 digits displays means the time display can draw up to 560 mA. In order to supply more power to the LED display, we added an additional power supply whose sole purpose was to supply power to the LED display. This was a way to ensure through hardware that the LED display did not damage the microcontroller board and its power connection. We used a 12VDC wall wart that had an output current of 1A. However, since our LED displays needed 5VDC we needed to step down the voltage from 12VDC to ~5VDC. To do this we created a DC-DC converter using a NPN BJT (TIP31) as shown below.

"Things we tried that didn't work"

We described in the previous Accelerometer and Buzzer sections in Hardware accelerometers and buzzers that we considered but ultimately did not use. Additionally, we tried PWM mode for the buzzer output, but found that the buzzer, itself, pulsed when 5V was applied to it, so we decided not to use PWM output. We also wanted to implement a wider range of output voltages to the buzzer (from 3V to 12V) using a control similar to the motor control in Lab 4. However, we found that we were out of time and resources in our budget to do such a control. In addition, the buzzer was loud enough at 5V that it was not necessary to try using PWM to increase the voltage applied to it. We tried using the LCD display offered in the ECE 4760 lab, but we did not use it in our final project, opting instead to use the LED displays. The reasons for this were lack of brightness on the LCD display as well as slower refresh rates.



In the main function, we run a series of tasks that were run at different periodic times. These tasks and their periods are listed in the following table:

Task Period
writeSDcard 250 ms
takeADmeasurement 250 ms
updateLEDdisplay 250 ms
buttonStateMachine 50 ms
setOffBuzzer 250 ms

There were three main parts of the software design that handled different portions of our project. The first main part was keeping track of time and interfacing with the clock buttons in order to set the time, alarm time, arming the alarm, and setting the alarm off. The second main part was interfacing the accelerometer and SD card with the microcontroller. Finally, the last main part of the code was the wake-up algorithm (i.e. how the clock determined the time to set off the alarm given the user given alarm time). The tasks/functions are grouped into these three main parts and are described below.

Clock functions

These clock functions handle all of the logic behind the clock and its buttons. Although the focal point of our project is having an adaptive alarm clock, we still do need to have the traditional clock and alarm features. The clock has millisecond precision; it is updated every millisecond in the ISR. We set up timer 0 to trigger an overflow interrupt every millisecond using a clock period of ~4 microseconds and counting 256 timer 0 clock ticks. On each interrupt we update the millisecond counter and subsequently increment the seconds, minutes, and hours if necessary. We also time each of the task timers in the ISR.

Readback Mode

Readback mode speeds up the clock by 8 times. For every 1 ms, 125 ms elasp. The speeding up of time is performed as follows. There is a function replayTask that is called every 2 ms, which is timed by the ISR. The replayTask records the previous reading, reads a measurement from the SD card in the special measure.txt file. It then performs an algorithm step on this reading value. Time is then incremented by 250 ms (simulating 4 samples per second).

There were several challenges in implementing readback mode. Since we are running the clock at a significantly faster rate, it was challenging to run all of our tasks in time. The most computationally significant function is the algorithm_step function. In order to conserve computational power, we turned off all button control. So besides updating the LED display and running the algorithm, we also run the function to check the buzzer.

Program mode can be turned on by enabling the compiler flag READBACK in the header file.

LED Display

The LED display is interfaced with Port C with the lowest 4 bits assigned the 4-bit input signal that the BCD-to-7-segment decoder needs to display the digits 0-9. Turning all lower 4 bits low, turns off the 7-segment display. By setting the lower 4-bits to the corresponding digit in binary will cause the 7-segment display to light up that digit; the decoder handles the encoding/decoding of these bits.

Since the decoders featured an output latch on the 7-segment signals, we can update each digit of the display by simply activating the corresponding latch enable. In the function that updates the LED display, we cycle through each LED display updating it to the correct value. The upper 4-bits of the output from Port C select which digit to display. The latch enable signals for the lowest to the highest digits of the time display are assigned to pins 4 to 7 of Port C. Hence, the I/O port that is connected to the LED display is assigned combinations of these two 4-bit signals in order to update each digit. The encoding of which display to enable is encoded in the table below (the lower 4 bits are the digit to be display):

Encoded bits Display
0x7x Second Hours Digit
0xbx First Hours Digit
0xdx Second Minutes Digit
0xex First Minutes Digit

For example, to display the digit 1 on the second hours display we would simply say: PORTC = 0x70 | 0x01. The upper four bits select the display and the lower four bits display the digit.


The accelerometer is connected to the microcontroller through the A/D converter. It is connected through pin A.0. We are running this using 10-bit digital values for greater precision. There are 4 A/D conversions per second and each conversion is collected and stored on the SD card. The code was based on the ADC example from Lab 3. The key change we made was changing the accelerometer conversion values from 8-bits to 10-bits.

SD card


The SD card interfaces with the microcontroller through the SPI interface. It is the only SPI device that we used. In order to interface with the SD card, we made use of the FatFS library as well as code from a previous year's project*. The FatFS is an upper-level module that sits on top of a layer that handles the MMC interface.

* See GPS Logger with Wireless Trigger

The files we used from the FatFS library were: diskio.h, ff.c, ff.h, and integer.h. We also used the modified mmc.h file from *. This file was originally take from the sample project for use with MMC cards on the FatFS page.

Implementing FatFs driver

The API for the SD card is listed online at the FatFs homepage. The FatFs library is broken up into two layers. The upper layer contains the functions for using FAT volumes. The lower layer is a disk I/O layer. This is not part of the FatFs module and needs to be provided by the implementer of the FatFs library. Luckily, there was a provided FatFs example run on Atmel microcontrollers and there was a previous project that made use of this library. Thus, we included the previous year's file mmc.c in our FatFs folder. The one function that we needed to implement ourselves was the get_fattime function, which is required only for writing to SD cards. Since our program is a clock, we naturally have the time. Since our clock does not keep track of the month, day, and year, we use bogus values when setting these values. From the FatFs specification, the return value for get_fattime is a DWORD in the following format:

The return value: DWORD
Bits 31:25 - Year from 1980 (0..127)
Bits 24:21 - Month (1..12)
Bits 20:16 - Day in month (1..31)
Bits 15:11 - Hour (0..23)
Bits 10:5 - Minute (0.59)
Bits 4:0 - Second / 2 (0..29)

Using FatFs

When the alarm clock starts up, we need to initialize the SD card and mount the file system on the card. The disk initialization is done through the function call disk_initialization. We then have to mount the file system through the function f_mount. Throughout our program we used the functions f_open, f_write, and f_read to open, write, and read files. The use of these functions is documented in the FatFs documentation and we looked at examples provided by FatFs as well as the previous year's project.

Computer support

The primary reason for using FatFs was the ability to read back data written to the SD card on a computer. Using an SD card reader, we plugged the SD card into our computers and we were able to read,write, and copy files from the SD card. We were able to read back the SD card on both Windows and Macintosh computers.

Wake-up Algorithm

The algorithm for setting the wake-up time made use of the accumulated sleep data through the night. The user inputs an alarm time, which is the latest possible time that the user would want to be woken up by. The algorithm figures out a wake-up time based on these inputs.

The Algorithm

Given a list of output values from the A/D converter taken from the acceleromter, we take the derivative of this data. We take the derivative in order to normalize the data. The derivative was computed as taking the difference between the current data point and the previous data point. E.g. data'[i] = data[i] - data[i-1]. Now, we analyze over the derivative of the data. For the entire data set, the algorithm parititions this into intervals. The length of time of these intervals is specified by the parameter INTERVAL_WINDOW. Then we look at each of these intervals separately. We keep track of the number of derivative points that have exceeded another parameter, MOVE_MAGNITUDE. Next, we keep track of all of the intervals that have exceeded another parameter NUM_MOVEMENTS. Then, we compute the average time difference between the intervals that have exceeded NUM_MOVEMENTS. We use this average time difference to compute the predicted wake-up time. We need one more parameter which is the length of time before the alarm time that the user is allowed to be woken up. We chose this time to be 30 mins. So, the algorithm needs to pick a wake-up time between 30 mins before the alarm time and the alarm time.

A high-level diagram of the algorithm that determines the wake-up time.

The algorithm is implemented in the function algorithm_step. This function is called every time an ADC conversion is made from the accelerometer. It relies on several state variables listed below:

  • sampleCounter - counter of number of samples in the interval
  • numMovements - number of movements in this interval
  • movementPeriod - average movement period (the unit is intervals)
  • numMoveSamples - number of intervals that have exceeded the NUM_MOVEMENTS threshold
  • numIntervals - the number of intervals that have elasped
  • lastInterval - the last interval that had NUM_MOVEMENTS threshold

These variables are reset by the function algorithm_reset when the alarm is disarmed and armed again, marking a new sleep period for analysis.

The algorithm partitions the data points into intervals (red lines). It then counts the number of times, in each interval, that the maximum movement magnitude is exceeded (green line). Using this information, it calculates the period between intervals with movements that have exceeded the parameter NUM_MOVEMENTS. It then calculates the next several expected movement interval. If an expected movement interval appears in the alarm window, then it sets this time to be the wake-up time. If an expected movement interval does not appear in the alarm window, then it simply sets the wake-up time to be the alarm time.

"Things we tried that didn't work"

Improvements can definitely be made to our wake-up algorithm. In the current algorithm, there are only two levels of magnitude of movement that is measures. We would like to try out varying different levels and see the relation in sleep for magnitude of movement. Though, we were also partially constrained by the resolution of the accelerometer. We also had to make a tradeoff in the "smoothing" factor in discretizing movements into intervals.


Speed of Execution

The alarm clock runs in real-time. There is no delay in calculating the wake-up time. There is no flicker in displaying the clock time on the LEDs. We added a readback mode that speeds up time by 8 times. We ran into some difficulties in trying to speed up readback too fast in updating the LED display (digit flickers as it is updated) and calculating the wake-up time. The readback mode has little bearing on the actual functionality of the project, however. It was created for demo purposes in reading back a night's worth of sleep, and it also demonstrates that we can read sleep data from the SD card with the Mega644 alone.


Accuracy of the clock

The accuracy of the clock is dictated by the accuracy of our board's crystal, the 16 MHz crystal supplied by the 476 lab. By looking at the data sheet, we found its frequency deviation to be 50 ppm. Since this deviation directly translates to time deviations, we expect at most 50 ppm deviation in time. This implies that our clock's time would deviate by at most ~1500 seconds (or 25 minutes) in one year since one year has about 31.5 million seconds. This is acceptable since the actual deviation should be much lower as long as we use an accurate crystal.

The wakeup times

We now look at the wakeup times. We include 3 sets of sleep movement data in our report. The times have been normalized to all start at time 0. The duration of sleep is variable across the three nights. The data is presented and explained below.

Sleep Data Set 1

This graph shows the digital value after an ADC conversion from the accelerometer as a function of time. As we can see, there are clear movements throughout the night above the noise margin

This graph show an approximate derivative of the digital value after an ADC conversion from the accelerometer as a function of time. The approximate derivative is calculated by subtracting the current ADC reading from the previous reading. Doing this serves to normalize our accelerometer output values.

This graph shows the number of movements that have exceeded the parameter MAX_MOVEMENTS in an interval. The x-axis represents each interval in time. In this graph there are about 2 or 3 peaks in movements that have exceeded this threshold. Each of these occurs at around the 3 hour mark, the 5 hour mark, and the 6 and a half hour mark.

This graph shows the output from the wake-up algorithm. It shows the wake-up time as a function of time. This graph shows the different predicted wake-up times throughout the night. We defined an "alarm window", which is 30 minutes before the start of an alarm in order to determine a wake-up time. The start of the alarm window is represented by the green vertical line and the end of the alarm window is represented by the red vertical line. For clarity's sake, we zeroed the wake-up time when the algorithm hasn't produced a wake-up time that has changed. The red wake-up times represent times that the alarm clock should sound the alarm, since the predicted wake-up time corresponds with the current time. In this case, the earlier wake-up time was 6:34AM.

The other two sets of sleep data are included in the appendix

We had no objective measure of accuracy. The output of our alarm clock matched the expected outcome from our Matlab Analayzer. However, we do not know if this produces the "correct" result, since being awoken at the right time is somewhat arbitrary. We can, however, conclude that our alarm clock sets off the alarm when it expects or detects a significant level of movement. Our interpretation of our results would be biased since there is the psychological element in which we either believe or disbelieve our results. In order to test this further, we would have to run extensive blind trials in which the user is unaware of the functionality of the alarm clock. However, due to time constraints we were unable to do this.

Subjectively speaking, choosing a wake-up time that is earlier than the alarm time seems like we were missing out on sleep. Also, due to a variety of causes, we were always tired so being woken up early did not seem to be like an advanatge.


To ensure safety, no device is ever attached to the human body. The accelerometer was placed under the bed sheets and was small enough to be unintrusive. It is meant to be put in the corner of the bed where the user will not come into contact with it and where it can still detect body movements. The buzzer sound level is at a safe dB and pitch so that it won't cause harm to one's ears from a bedside table.


We incorporated no wireless/RF that would interfere with other people's designs and projects. However, we did set off our buzzer in lab several times, which may have annoyed some people.


We based our interface on the typical digital alarm clock. That being said, the typical digital alarm clock is not a very user friendly interface (only being able to increment in hours and minutes). If we had additional time and resources we would have liked to improve this aspect of the project, perhaps by adding an LCD display and keypad. Additionally, our interface for pulling sleep data out of the alarm clock could be improved. It requires users to load the SD card into a computer in order to be able to view this data. We do, however, provide a Python script for parsing the sleep logs pulled from the SD card. We also provide the Matlab Analyzer for analyzing one's sleep data on Matlab. We could increase the usability of this interface by providing an application that automatically loads the data from the SD card and analyzes it.


The results of our alarm clock matched our expectations but we were a bit disappointed. We were able to somewhat accuarately predict periodic motion during sleep. However, it seemed that sleep movement did not correlate as strongly with deep sleep as we had hoped (at least for us). In order to truly determine the effectiveness of our project we would have to test it on a wide variety of people, not just two sleep deprived college students. If we had more time to work on the project, we would simplify the hardware, so that we do not have so many wires by having a better layout on our solder boards. We would probably want to include a better user interface and perhaps a GUI on the computer end to view the data pulled from the alarm clock. With more time and room in our budget, we probably could have added different wake-up signals in addition to the buzzer. We think features such as a button that triggers the clock to "speak" the time and date would be cool improvements if we had more time. We were satisfied with how our alarm clock came out, especially with the ability to save sleep data to an SD card. Part of what we learned from this project is the difficulty in integrating systems. Each of the modules worked well independently when we were initially building them, but when we put modules together, unexpected outcomes, such as the blown voltage regulator on the Mega644 board, occurred that hindered us from getting the entire system working easily. We used code from Jeff Melville's project in the part of our program that read and wrote data from the SD card. One of the toughest parts was coming up with a satisfactory algorithm for analyzing the data from the accelerometer. Implementing the algorithm in Matlab allowed us to try out several versions and fine-tune parameters before settling on a final design. We also found it challenging to keep the accelerometer on the bed.

Ethical Considerations

We considered ethics when we were designing and building our project. We made the adaptive alarm clock safe and easy to use. Although most of the clock is intended to sit on a bedside table or surface, the accelerometer was placed on the bed. Everything else that was part of the alarm clock was put inside a box in order to appear more like an alarm clock and prevent the user from tampering with the circuitry inside. Our alarm clock is designed with the user's health in mind since it is meant to wake up the user so that he/she is less tired from a good nightÕs sleep. We understand the limits of our project and that the wakeup algorithm does not guarantee waking up the user at his/her preferred time. In addition, we know that the buzzer may not be the preferred alarm of the user. We simply wanted to demonstrate an alarm clock that incorporated the sleep analysis algorithm and operated on the principle of less body movement during lighter phases of sleep. In this way, our project may not be the most desirable alarm clock to every user, but it is an alarm clock with a clear guiding principle in its design and operation. We tried to represent our project as accurately as possible and to not misrepresent its features in our specifications. This report details the features of the alarm clock to the best of our ability.

Intellectual Property and Legal Considerations

The prototype board that we used for the Mega644 and the initial test code for it was designed by ECE 4760 Professor Bruce Land. The code we used for uart and LCD interfaces when we were testing our project was provided as part of prior ECE 4760 labs. The FatFs file system library was used in accordance with its license. The FatFs library is distributed using a BSD-style license. A description from the FatFs website is as follows:

Because FatFs is for embedded projects, the conditions for redistributions in binary form, such as embedded code, hex file and binary library, are not specified to increase its usability. The documentation of the distributions need not include about FatFs and its license document, and it may also. Of course FatFs is compatible with the projects under GNU GPL. When redistribute it with any modification, the license can also be changed to GNU GPL or BSD license.

Regardless of the license requirements, it is mandated by the ECE 4760 project requirements that all of our source code be available online. In addition to the FatFs library we used a modified file from the FatFs sample application for microcontrollers. The modified file is from a previous year's project and their source code is freely available online. The SD memory cards are covered by multiple patents owned by the SD Association. Some features, such as DRM and encryption, require licensing royalty fees, but since we set up the SD card as an MMC card over an SPI interface, we did not use features that required royalty fees. All other code and circuitry was original. There may be a patent opportunity for this device, but we do not intend on patenting our design since there are several, already established products that use similar wakeup techniques.


We would like to acknowledge Freescale, Texas Instruments, and Molex for providing samples of the accelerometer, BCD-to-7-segment decoders, and SD card socket respectively. We would like to thank Bruce Land for all of the help he provided us throughout this project. We would also like to thank all of the TAs for keeping the lab open and for all of their helpful hints. In particular we would like to thank our TA Jeff Melville, as well as the TAs Tim Sams and Yuchen Zhang for their additional help. Finally we would like to thank non-staff persons. Special thanks to Rob Miceli (rjm73) for his out-of-lab hints and to William Gallagher (wag4) for his help with machining some key parts.




Related Products

Parts List

-- -- -- -- -- $67.62
Atmel Mega644 1 476 Lab $8.00 $8.00
40-pin DIP socket for 644 1 476 Lab $0.50 $0.50
Custom PC Board 1 476 Lab $4.00 $4.00
Wall Wart 1 $2.85 $2.85
Header Socket/plug 16 476 Lab $0.05 $0.80
Max233CPP 1 476 Lab $7.00 $7.00
RS232 connector 1 476 Lab $1.00 $1.00
Header Socket/plug 14 476 Lab $0.05 $0.70
SD socket 1 Molex sample $0.00 $0.00
SD card 1 Previously owned $0.00 $0.00
Large Solder Board 1 476 Lab $2.50 $2.50
Small Solder Board 1 476 Lab $1.00 $1.00
3.3V Voltage Regulator TI TPS7233 1 TI Sample $0.00 $0.00
8-pin DIP socket for TPS7233 1 476 Lab $0.50 $0.50
Accelerometer Freescale MMA1260D 1 Sample $0.00 $0.00
1" 7-Segment Display SC10-21SRWA 4 Mouser Electronics $2.52 $10.08
4511 LED drivers CD4511 4 TI sample $0.00 $0.00
SOIC/ST203 Carriers 4 476 Lab $1.00 $4.00
Header Socket/plug 32 476 Lab $0.05 $1.60
Header Socket/plug 32 476 Lab $0.05 $1.60
Bread board 1 476 Lab $6.00 $6.00
Large Solder Board 1 476 Lab $2.50 $2.50
Large Solder Board 1 476 Lab $2.50 $2.50
Power Supply 1 476 Lab $5.00 $5.00
Button 3 476 Lab $0.00 $0.00
Switch 2 476 Lab $0.00 $0.00
Buzzer 1 Radio Shack $5.49 $5.49
Shoe Box 1 Previous Owned $0.00 $0.00

Program Listing

The following is a list of included files in our source code and a brief description of each file. There is also a README included in the zipped file that contains this information.

Program for Mega644

  • alarm_clock.c is the main program.
  • alarm_clock.h is the header file for the main program. It contains all of the constant definitions, variable declarations, and method signatures. It is organized by tasks.
  • fatfs is the folder that contains the fatfs library and the required files for interfacing the SD card with the FAT file system.
  • uart.c, uart.h are the serial communication files.


  • acctest2.c - A program to test that the accelerometer outputs correctly
  • sdacc.c - A program to test that the accelerometer output can be written to the SD card
  • clock.c - A program that tested the clock functionality, buttons and switches


  • is the Python script for parsing the sleeplog.txt files that the microcontroller writes to the SD card. It exports a data file that is used the the Matlab Analyzer.
  • process3.m is the Matlab Analyzer that reads in the data file into a matrix and plots the resulting sleep data.

Breakdown of Work


got accelerometer working, wrote SD card code, wrote basic clock mode, data collection, wrote wake-up algorithm, wrote Matlab simulator, wrote wake-up algorithm for SD card, soldered prototype board, soldered SD card board, wrote lab report, tested the alarm clock


soldered and tested other accelerometers, got LED display working with decoder chips, soldered SD card socket, designed SD card circuit, got basic clock functionality working with alarm setting, buzzer selection and getting the buzzer working, wrote lab report, tested the alarm clock, soldered LED display circuit

Additional Data sets

Sleep Data Set 2

Raw accelerometer output versus time

Normalized accelerometer output versus time

Number of movements in intervals over time

The predicted wake-up times over time. We can that this wake-up time was rather late in the alarm window period.

Sleep Data Set 3

Raw accelerometer output versus time

Normalized accelerometer output versus time

Number of movements in intervals over time

The predicted wake-up times over time.

Code Documentation

The following is a documentation of each of the functions in our program.

SD card functions


In our timer 0 overflow ISR, we include a portion of code that calls the function disk_timerproc() every 10ms. This is necessary for the SD card to know how long it has been waiting for a response for the card and allows it to determine timeout.

DWORD get_fattime(void)

This function is required for writing to the SD card. The FatFS library requires a function that passes it the time. Since we don't keep track of the month, date, and year, we simply pass bogus values to the this function. However, the main functionality of writing to the SD card still works.

void init_fs(void)

This function serves to initializes the SD card and then mounts the filesystem on the card. It needs to be called before any writes/reads are made to the disk.

void openSleepLog(void)

This function sets the global FIL (file) pointer that points to the current sleep log. This function creates the next sequential sleep log and sets the FIL pointer. There is a limit of 1000 files.

void closeSleepLog(void)

This function properly closes the sleep file on the filesystem

void printFRcode(FRESULT fResult)

This function was used for simply for debugging and error reporting. We wanted an automated way of mapping file result codes (returned from FatFS functions) to readable human messages. This function simply prints out the return message to stdout.

void writeSDcard(void)

This function writes the A/D reading to the SD card. It makes use of the FatFS functions to write to the SD card.

Wake-up Algorithm

void algorithm_step(void)

This function is called whenever a new A/D measurement is made. It uses the variables prev_reading and reading. It makes use of several state variables.

  • sampleCounter - counter of number of samples in the interval
  • numMovements - number of movements in this interval
  • movementPeriod - average movement period (the unit is intervals)
  • numMoveSamples - number of intervals that have exceeded the NUM_MOVEMENTS threshold
  • numIntervals - the number of intervals that have elasped
  • lastInterval - the last interval that had NUM_MOVEMENTS threshold

This is the implemenation of the algorithm described above.

void algorithm_reset(void)

This function resets the algorithm state variables. It is called when the alarm is disarmed and the armed, marking the new period for analysis.


void takeADmeasurement(void)

This function reads the A/D conversion and stores the reading. Then it calls the algorithm_step on this reading. Finally, it starts a new conversion.

Clock Functions


In the ISR, there is a millisecond counter that keeps track of the number of milliseconds that have elasped counting up to 1000. Once 1000 is reached, the seconds counter is incremented by one. Once 60 is reached on the seconds counter, the minutes counter is incremeted by one. Once 60 is reached on the minutes counter, the hours counter is incremented by one. Once 24 is reached on the hours counter, all counters are reset. Time is kept in military time internally. The ISR also handles the PWM for setting off the buzzer.

void updateLEDdisplay(void)

This function sets each of the 7-segment LED displays and sets the AM/PM LED.

void setOffBuzzer(void)

This function sets the buzzer flag high so that the buzzer will go off.

void handleButtonFlags(void)

This function handles all of the logic behind the buttons. It sets the clock or alarm mode and it increments the appropriate hours and minutes counter.

void handleSnoozeFlags(void)

This function checks to see if the snooze button has been pushed. If it has, it pushes back the wakeup time by the snooze amount.

Contact Information

Michael Chow

Rajesh Atluri

Arecibo at Dusk
Libe Cafe