Wake Up with a Natural Sunrise Simulation
This project is dedicated to building a programmable light-based Sunrise Alarm Clock where full spectrum LED simulates natural sunlight by utilizing the PIC32 microcontroller and LED Driver.
This article discusses the design and construction of a programmable light-based alarm clock. The clock uses a full spectrum LED to wake you up using your body’s natural response to sunlight. Rather than jarring you awake with an annoying alarm, a sunrise alarm clock slowly turns on a light in your room over a configurable schedule to simulate a natural sunrise that allows your body to naturally wake up. If you are still asleep at the end of the sunrise cycle a backup audio alarm will play to wake you up. For the busy professional person or student, the sunrise alarm clock can mean waking up peacefully for a job or class.
This sunrise alarm clock (Figure 1) adheres to several design requirements. It required a full spectrum LED to mimic sunlight. This was intended to not only create a pleasing light but also help combat Seasonal Affective Disorder on those dark winter mornings. The LED also required analog dimming, which prevents the annoying flicker that is characteristic of most PWM methods. It also required an alternate mode where the user could utilize the light as a normal light source outside of the sunrise alarm function of the clock. This mode would allow the user to utilize the system as a “night light” if they wake up in the middle of the night, or simply to enable using the full spectrum LED as a traditional light source in the room.
The system also needed a backup audio alarm in case the sunrise wasn’t enough to wake you. A simple piezo buzzer fits this requirement perfectly. It is very annoying and is sure to wake even the heaviest of sleepers. A physical user interface with buttons and a screen was also required. An LCD screen displays the time and displays the menus for the alarm, and a three-button interface with a rotary encoder provides all the user input and feedback needed to run the alarm clock as a standalone device.
In addition to functioning as a standalone device, one additional requirement is that the alarm clock should have an option for remote control of the system. This way users can set an alarm from the comfort of their bed. Connecting to a phone app via a Bluetooth connection enables this remote control operation for the system.
One final requirement is that the alarm clock should remember the alarm, and keep track of time, even if it loses power (such as by being unplugged, or through a power outage). An RTC chip and EEPROM for alarm storage with onboard battery backup solve both issues.
Figure 2 shows a high-level block diagram of the system. At the heart is a microcontroller, which is the brain of the system and interacts with the different “modules.” For this project, a PIC32 was used but any microcontrollers could serve the same function. Each module in the block diagram represents a standalone system that can be tested either alone or with the adjacent modules. This provided the framework for a structured testing approach where each module could be first tested to ensure it worked appropriately in isolation, and then connected to the adjacent modules to make sure the connections and interactions between modules worked as specified. The schematics of the sunrise alarm clock are shown in Figure 3.
One unique thing that was implemented in the system was hardware-based input debouncing using an analog low-pass filter. This makes the software side of the system a lot easier to run since the inputs to the system are clean and it wouldn’t require additional state machines or delays to debounce the switches. However, this comes at the cost of some additional hardware complexity. It requires additional components and filtering, and if the hardware debounce isn’t made carefully, it could cause some bounces on rare occasions that would need to be debounced in software. Since software-based debouncing is one of the most common methods, hardware-based debounce was pursued as an engineering exercise to see if it could fully replace a software debounce.
The hardware for this project can be subdivided into several submodules. There is the UART Bluetooth interface, the I2C devices, the LED systems and alarms, and the physical user interface.
Bluetooth: Communicating with an app on a phone required the integration of a Bluetooth module into the system. For this project, a generic HM10 Bluetooth module clone (image) was used. These modules make Bluetooth connection very easy by acting as a simple serial passthrough. The microcontroller sends serial data to the Bluetooth module via UART, and then the HM10 module forwards the serial data to any connected devices via Bluetooth. Any connected device can also send data back to the HM10, which is then passed on to the microcontroller via UART. The HM10 module does all the heavy lifting of managing Bluetooth connections. Since the HM10 supports Bluetooth Low Energy (BLE) connections, most modern smartphones can connect to this module.
I2C: This alarm clock utilizes two peripheral devices which connect to the microcontroller via I2C. The DS3231 is a high-precision Real-Time Clock (RTC) chip with temperature compensation. It can be connected to a battery backup and can keep track of time with an accuracy down to 4ppm, which equates to less than half a second drift per day. Using this device, the current time is always known, and the system can continue to keep track of the time even when the alarm clock is unplugged thanks to a backup lithium coin cell.
The second device the AT24C32 is a 32Kb EEPROM chip and it is often integrated into the same PCB as the DS3231 on commercial breakout boards making it a convenient choice for this system. This connects to the same I2C line as the RTC chip and allows the system settings and alarms to be stored and reloaded in the event power is lost to the system. In combination with the RTC, this allows the system to recover from a power loss without losing the current time and recovering the current alarm state and settings, so a temporary power outage doesn’t cause you to miss your alarm.
LED and Alarm System: There were two primary design goals of the LED system of this alarm clock. The first was to use a full spectrum LED to simulate natural sunlight (Figure 4), and the second was to implement analog dimming to avoid that annoying PWM flicker. The Seoul Semiconductor SunLike line of LEDs contains phosphors that combined with a violet LED can replicate the sun’s spectrum very closely compared to traditional LEDs. The hope is that this replication of sunlight will wake up your body more easily and help with Seasonal Affective Disorder (SAD) during the dark winter months. The Sunlike LED used for this alarm clock was the daylight white, 5000K, LED that runs at 25W for plenty of light output.
Driving an LED as large as this isn’t as simple as running your typical 12V LED strips. This COB LED has a typical forward voltage of 36V so we need a fairly beefy power supply to get it working. The ODLC-45 from Meanwell is designed to easily drive this LED from mains power and has a built-in analog dimming functionality taking a 10V PWM input signal. The duty cycle of the PWM signal determines the current that the LED runs at as can be seen in Figure 5.
In addition to a driver, this large LED requires a heatsink to be able to dissipate that 25W of power. A simple Sunon LED heatsink with an integrated 12v fan was used and kept the LED nice and cool.
For the audio alarm, a simple piezo buzzer is used. It is more than loud enough and the tone is annoying enough to get anybody to wake up from sleep if they have failed to get woken up by the gentle sunrise.
User Interface: The user interface consists of the display and the controls. The display used was a 240×320 pixel TFT LCD with a 2.8” screen size. The controls consisted of two momentary switch buttons and a rotary encoder/button combination. A picture of the original UI concept is shown in Figure 6.
The hardware debounce is achieved through an RC filter combined with a Schmitt trigger. The RC filter smooths over the bounces and outputs a smooth curve. This classic RC charging curve is then fed into a Schmitt trigger which creates a very sharp cutoff and outputs a clean on/off digital signal which is connected to the external interrupt pins for the input signal.
The rotary encoder uses quadrature encoding (Figure 7). When the rotary encoder is turned, two pulses are emitted, each on a separate channel. If the rotary encoder is turning clockwise, the pulse on channel A leads the one on channel B. If it is turning counterclockwise the pulse on channel B leads the one on channel A. By noting which signal is detected first the direction of rotation can be determined.
The program on the microcontroller that controls the alarm clock is broken into multiple threads (Figure 8), which all run on the same processor using a round-robin scheduler. To achieve this, the proto-threads library, created by Adam Dunkels, was used, which provides a lightweight threading framework for embedded systems. Some of the threads run continuously while others wait for a flag to change or only run while the alarm clock is in a specific state. The control thread is the main hub, managing the state of the system and activating or receiving info from other threads as needed. In addition to the threads, each of the user interface buttons has an associated Interrupt Service Routine (ISR) that is used to toggle flags to indicate that a button has been pressed to the rest of the program.
Control Thread: This thread controls the state of the system and every flag that doesn’t directly involve the hitting of a button or movement of the rotary encoder. (These flags are set in the button ISRs). The control thread is essentially a finite state machine that changes the state based on the buttons that have been pressed or when certain times such as alarm times occur. An implementation of a finite state machine fits the requirements here very well. The various number of states that the alarm can be in is known, and it provides a good framework for mapping the interfaces to the underlying states. The buttons can have different behavior depending on the current state of the control thread: for example, when the TFT is displaying the default clock screen, the rotary encoder button has the effect of toggling night light mode, but when the TFT is displaying the setting’s screen, the rotary encoder button instead has the effect of entering a setting to change it.
Night Light Thread: This thread controls the night light mode of the alarm clock and only runs if night light mode is enabled. Night light mode lets you use the LED as a light source without needing to set an alarm. When running, this thread manages the dimming level of the LED and turns the LED on and off.
Sunrise Thread: If the alarm clock is in sunrise mode, this thread manages the pulse-width modulated (PWM) signal to the sunrise LED driver. The duty cycle of this signal is determined by the ratio of Ts/Ls with Ts being the time in seconds since the sunrise started and Ls being the length in seconds of the full sunrise. This has the effect of increasing the intensity of the LED linearly from zero to its maximum as time progresses from the start of the sunrise to the alarm time.
Audio Alarm Thread: If the alarm audio setting is enabled and the alarm is currently activated, this thread toggles the pin that controls the audio output every 500 milliseconds to produce a beeping that will wake the user up if the sunrise has failed to do so.
Update Time Thread: This thread runs every 100 milliseconds. It first calls a function that queries the RTC module for the current time. Then, if the returned time is different from the currently displayed time, it updates the TFT display. If an alarm is enabled the thread checks for a match between the current time, the sunrise start time, and the alarm time. If either of the latter two matches the former, then the flags for starting the sunrise or starting the alarm sound are set depending on what alarm settings have been enabled.
BT Serial Thread: The BT serial thread only activates when a serial command is received. Its job is to parse the command and perform any operations if required. There are currently 6 commands that it recognizes:
- Toggling the TFT Backlight
- Toggling the alarm enable
- Set alarm to the received data
- Send out current alarm data
- Set the night light brightness level
- Toggle the Night Light Mode
With these commands, the associated phone app can control the alarm clock remotely via serial communication.
Interrupt Service Routines: The interrupt service routines (ISRs) for the buttons were very simple. All they did was set two global flags and clear the interrupt. First, they set the flag for their associated button, and then they set the flag for a general input change which activates the control thread.
The ISRs for the rotation of the rotary encoder were a bit more complex due to the quadrature decoding. They need to first check the flag for the other rotary encoder channel to see if the interrupt for the other channel was triggered first. If it was, then the ISR knew the direction of rotation and saved it. If it did not see that the other channel was triggered, it would simply set the flag for its channel and clear the interrupt.
One additional check needs to happen though. It can occasionally happen that the inputs are misread if the rotary encoder is spun too quickly, and one of the pulses gets missed. When this happens suddenly the program thinks the encoder is spinning in the other direction since it thinks the other channel arrived first. This effect can be mitigated by making the ISR check how long it has been since the last interrupt, and if it is greater than the timeout, 100ms in this case, it simply resets both rotary encoder flags to ensure the correct direction is read on the next pulse.
Main Program: The purpose of the main function is simply to set up all the input and output pins, activate the serial and I2C channels, and initialize the threads. After that, the protothread scheduler manages the threads.
The phone app (Figure 9) was programmed using MIT App Inventor. This allowed rapid development of the basic functionality required. The phone app is a graphic user interface wrapper for the serial commands that can be sent to the Bluetooth module and processed by the serial thread on the microcontroller:
- Toggling the TFT Backlight
- Toggling the alarm enable
- Set alarm to chosen settings
- Get the current alarm data
- Set the night light level
- Toggle the Night Light
RESULTS OF THE DESIGN
Our alarm clock system works very well. The user interface functions exactly as intended, and the buttons are effectively debounced. The phone app works well, you can lay in bed and change the alarm settings as desired. A cardboard box enclosure was used for simplicity and to reduce cost. The LED heatsink stays cool and only gets slightly warm when the LED is powered on at full power for extended periods.
Despite the hardware debounce being very effective overall, there were still some issues with bouncing switch contacts in the rotary encoder. The issue related to smoothing is caused by the RC circuit and the speed at which you turn the rotary encoder. The faster you spin the encoder the faster the response time you need to register the inputs correctly. It became a balancing act between having a low enough RC value to have a quick response but high enough to prevent bouncing.
The values that ended up in the final version were good for the normal use speed of the rotary encoder, but once the rotary encoder is spun a little too fast, it has a chance of missing one of the pulses and starts registering in the wrong direction. This is fixed by simply stopping and starting again in the direction. This is enough time for the timeout in the ISR routine to reset the quadrature decoding. Functionally, this is not an issue during day-to-day use of the alarm clock.
This design and the final product met all of the required needs of the sunrise alarm clock specifications. The goal was to create an alarm clock that emulated the rising of the sun to wake up the user, and the project achieves that. It is easy to use, the phone app works seamlessly, and this alarm clock is likely to be used for a long time going into the future.
Some of the issues related to the rotary encoder could be resolved with a different encoding method. The rotary encoder used in this project ended up being a quadrature encoder but other encodings also exist. A grey code encoder likely would have served the purposes of this project better. Each time the encoder reaches a decent, only one of the channels flips its bit. Compared to the quadrature, this allows for long times between changing values, which is very well suited for the hardware debouncing method. Any future revisions of this alarm clock will likely utilize a grey code rotary encoder.
Overall this project turned out to be a success and while the end product might be missing a feature or two compared to commercial options, it still functions well and has other features, such as a full spectrum LED, that are missing in the commercial space at the moment. It has functioned excellently and is in use daily.
 Amptek, Inc., “XRF Instrumentation – Introduction to spectrometer”
 Cremat Inc., “Femtojoule Detection”,
 F. J. Ramírez, “X-Ray Spectroscopy with PIN diodes,” September 2006,
 Giuseppe Bertuccio, US Patent 5,347,231
PUBLISHED IN CIRCUIT CELLAR MAGAZINE • JULY 2022 #384 – Get a PDF of the issueSponsor this Article
Jonathan Pfeifer has a B.S. in Electrical and Computer Engineering from Cornell University. He currently works on environmental chemical sensor development for oceanographic measurements at MIT in pursuit of a doctoral degree. In his spare time, he likes to build useful and helpful gadgets using his electrical engineering skills and share them with others.