## Tutorial on how to build The Super Cool Binary Alarm Clock This is a tutorial for a project called: **The Super Cool Binary Alarm Clock**. The person who created it is named **Jacob Reinikainen Lindström** and has the student credentials: **jr223ek**. ### Short project overview I have created an internet connected alarm clock, that I just now named **The Super Cool Binary Alarm Clock**, as my final grand project in a course called [Introduction to Applied Internet of Things](https://lnu.se/en/course/introduction-to-applied-internet-of-things/distance-international-summer/) at Linnaeus University. The following text on this page is an attempt to describe how and why I created the amazing product that is **The Super Cool Binary Alarm Clock**. The text I am about to write is hopefully so goddamn well written that it also serves as a tutorial so you can replicate my work and create your own copy of my amazing product **The Super Cool Binary Alarm Clock**. ### ⏳ How much time it might take to do this project This really depends on your previous knowledge and experience. If you have a general understanding of these kinds of things, and have all the necessary components ready, you should be able to follow my instructions and copy my code and be done in **an hour or two**. If you don't know shit, you will probably have to learn a few things along the way and this will add more hours (depending on how shit you are) to the total time you will spend trying to create this project. --- ### Objective I chose to build this device (**The Super Cool Binary Alarm Clock**) because I am terrible at getting out of bed, and saw an opportunity to build an alarm clock that required effort to turn off - therefore making it harder for me to snooze. It's purpose is to look cool with its binary clock and to make me a better morning person. The insights **The Super Cool Binary Alarm Clock** will give is maybe that it will serve as a kind of experiment if an internet-controlled alarm clock actually makes me better at getting out of bed. --- ### Material | Picture | Thing | What is does | Where I bought it | | - | - | - | - | | ![](https://hackmd.io/_uploads/rybu4hZF3.jpg) | Microcontroller - Raspberry Pi Pico W | The central hub. Executes code and sends and receives signals from its inputs and outputs, like connected sensors and WiFi. | [Electrokit](https://https://www.electrokit.com/produkt/start-kit-applied-iot-at-linnaeus-university-2023/) - 399 kr (part of *Applied IoT Start Kit*) | |![](https://hackmd.io/_uploads/H1kxd3-Fn.png)|Breadboard - Solderless breadboard 840 tie-points|Simplifies utilizing the microcontroller's inputs and outputs with e.g. wires and sensors|[Electrokit](https://https://www.electrokit.com/produkt/start-kit-applied-iot-at-linnaeus-university-2023/) - 399 kr (part of *Applied IoT Start Kit*) | |![](https://hackmd.io/_uploads/H1vuX1GY3.png) | 10x jumper wire - female/male | Connecting between breadboard and sensor/LED etc.|[Electrokit](https://https://www.electrokit.com/produkt/start-kit-applied-iot-at-linnaeus-university-2023/) - 399 kr (part of *Applied IoT Start Kit*)| |![](https://hackmd.io/_uploads/r1anZJzF2.png)|14x jumper wire - male/male| Connecting between different places in the breadboard|[Electrokit](https://https://www.electrokit.com/produkt/start-kit-applied-iot-at-linnaeus-university-2023/) - 399 kr (part of *Applied IoT Start Kit*) | |![](https://hackmd.io/_uploads/SyBCk1fK2.png)|5x resistor - 330 ohm |Limits flow of electrical current|[Electrokit](https://https://www.electrokit.com/produkt/start-kit-applied-iot-at-linnaeus-university-2023/) - 399 kr (part of *Applied IoT Start Kit*) | |![](https://hackmd.io/_uploads/S1FsJ1GKh.png)|4x resistor - 1k ohm |Limits flow of electrical current|[Electrokit](https://https://www.electrokit.com/produkt/start-kit-applied-iot-at-linnaeus-university-2023/) - 399 kr (part of *Applied IoT Start Kit*) | |![](https://hackmd.io/_uploads/HydkeJfFn.png)|5x resistor - 10k ohm|Limits flow of electrical current|[Electrokit](https://https://www.electrokit.com/produkt/start-kit-applied-iot-at-linnaeus-university-2023/) - 399 kr (part of *Applied IoT Start Kit*) | |![](https://hackmd.io/_uploads/BJwVWJztn.png)|5x LED - 5mm green diffuse 80mcd|LED with green light|[Electrokit](https://https://www.electrokit.com/produkt/start-kit-applied-iot-at-linnaeus-university-2023/) - 399 kr (part of *Applied IoT Start Kit*)| |![](https://hackmd.io/_uploads/BysXZJMt2.png)|4x LED - 5mm yellow diffuse 1500mcd|LED with yellow light|[Electrokit](https://https://www.electrokit.com/produkt/start-kit-applied-iot-at-linnaeus-university-2023/) - 399 kr (part of *Applied IoT Start Kit*)| |![](https://hackmd.io/_uploads/BJZQ-JfF3.png)|5x LED - 5mm red diffuse 1500mcd|LED with red light|[Electrokit](https://https://www.electrokit.com/produkt/start-kit-applied-iot-at-linnaeus-university-2023/) - 399 kr (part of *Applied IoT Start Kit*)| |![](https://hackmd.io/_uploads/Sknhp0-K3.png)|Piezospeaker - passive|Very simple speaker|[Electrokit](https://https://www.electrokit.com/produkt/start-kit-applied-iot-at-linnaeus-university-2023/) - 299 kr (del av *Sensor kit*)| |![](https://hackmd.io/_uploads/BJiSRC-Yh.png)|LED-module - color shifing|Module with LED light that changes color at random|[Electrokit](https://https://www.electrokit.com/produkt/start-kit-applied-iot-at-linnaeus-university-2023/) - 299 kr (part of *Sensor kit*)| |![](https://hackmd.io/_uploads/rkDYRRZt3.png)|LED-module - RGB|Module with LED light that can be set using RGB|[Electrokit](https://https://www.electrokit.com/produkt/start-kit-applied-iot-at-linnaeus-university-2023/) - 299 kr (part of *Sensor kit*)| |![](https://hackmd.io/_uploads/SkH5pCZth.png)|Push button - key switch module|A simple button that can be pressed|[Electrokit](https://https://www.electrokit.com/produkt/start-kit-applied-iot-at-linnaeus-university-2023/) - 299 kr (part of *Sensor kit*)| |![](https://hackmd.io/_uploads/rkTlEJMK3.png)|USB-kabel A male – micro B male|Cable for connecting Pico to a computer or power|[Electrokit](https://https://www.electrokit.com/produkt/start-kit-applied-iot-at-linnaeus-university-2023/) - 399 kr (part of *Applied IoT Start Kit*)| ||Any computer to write code on|I mostly used an Apple iMac|---| --- ### Computer setup All the programming in this project is made using **MicroPython**. The programming was made in an IDE (integrated development environment - which basically just means a program for writing code aka programming) called **Thonny**. I started out using Visual Studio Code, a very popular IDE for all kinds of programming, but had some annoying issues so I went and tried Thonny. I had heard about Thonny after reading about programming MicroPython for the Raspberry Pi Pico W, and it seemed to be a popular programming of choice. #### Here are some steps that could be useful for getting started programming with MicroPython and Thonny for the Raspberry Pi Pico W: 1. **Download and open Thonny** This should be an easy step. Just go to thonny.org and follow the steps for your operating system. 2. **Add MicroPython firmware to the Pico** To be able to utilize MicroPython, you first have to add MicroPython firmware to it. This is done in a few easy steps. 2.1 - Connect a USB cable to the Pico, but do not connect the other end to a computer, yet! 2.2 - On the Pico, press and hold the button that says BOOTSEL. While you are pressing/holding the button, connect the other end of the USB cable to your computer. 2.3 - In Thonny, on the menu row, choose Run > Configure interpreter. Now a window titled *Thonny options* should appear. Below *Which kind of interpreter should Thonny use for running your code?* click the dropdown and choose *MicroPython (Raspberry Pi Pico)*. 2.4 - Click install on the following pop-up box. 2.5 - Done! 3. **Installing packages** This project uses a few packages that needs to be downloaded. This is done by going to Menu -> Tools -> Manage packages. Download these: **micropython-umqtt.simple** and **picozero**. 4. **Creating, saving and running code on the Pico** You can create python files on the Pico easily in Thonny. The easiest way (according to me) is to first make sure you view your files by selecting Menu -> View -> Files. Then you right-click anywhere in the Pico's file view, and select "New file..." Name it whatever you want and end the filename with `.py`, for example `my-file.py`. When you now press the *Save* icon or press `command + s`, it now directly saves the file onto the Pico. If you now press the *Play* icon to the right of the *Save* icon, Thonny will actually run the code through the Pico! --- ### Putting everything together This project is very much just a test and a project made and within the scope of a basic level university course. The completed setup is in the end just for development and should not in any way be seen as a something that should or could be used in production. #### Circuit diagram ![](https://hackmd.io/_uploads/SyzisWzK3.png) Some notes on the circuit diagram: - **Jumper wires** Wires are represented as lines with circles at each end. No distinction is being made between male/female and male/male wires. Black represent wires that go to ground. Orange represent signal wires. All other colors represent wires that go to LED:s that display the same color as the wire. - **Resistors** Resistors are represented as black wide ovals with white text describing its resistor value. - **Binary clock LEDs** These 14 LED lights are respresented as colored squares. On each LED, one leg is connected to the same line as the resistor and the other is connected to ground. --- ### Platform The platform used for this project is <a href="https://io.adafruit.com">Adafruit IO</a>. It is a beginner-friendly cloud service/platform for managing data to and from IoT devices. It is free to get started, and you can quick and easy create different feeds (used for data transfer) and dashboards (used for example to visualize data or creating a simple UI for sending commands to the device). Adafruit IO was chosen because it was introduced to me before I started this project, and I did not know of any better alternatives to try out. If I were to scale this project in the future, I would look for some other alternative. I would like to have more options to customize user input for example. --- ### The code Code for the full project can be found on my <a href="https://github.com/jazzjacob/iot-binary-alarm-clock">GitHub repository</a>. Below I will show examples from the code relating to **how an alarm is activated**. From the program's point of view, turning on the alarm is a process with a few steps. After the device is connected to the internet and has connection and subscribes to its MQTT client, the program starts running its main loop. On each loop it firsts checks if there are any messages from the MQTT client: ```python= mqtt_client.check_msg() ``` If the `check_msg()` function detects any messages, it will then run this callback function: ```python= def mqtt_subscription_callback(topic, message): #... ``` Simplified, the full callback function looks like this: ```python= def mqtt_subscription_callback(topic, message): if message == RESET_JSON_FILE_COMMAND: # Empty internally saved alarms elif message == TURN_ALRM_OFF_COMMAND: # If alarm is on, turn it off elif is_24_hour_clock(message): # If message is a correctly formatted time # add it list of saved alarms else: # Message is discarded ``` Later in the main program loop, the program checks if an alarm should be activated. The process of checking if an alarm should be activated looks like this: - Check that an alarm isn't already running. - Loop through all the alarms that are saved. - On each iteration, check if the saved alarm is equal to the current time (to the minute). - Also on each iteration, check that the alarm hasn't already been activated (otherwise an alarm that has been turned off within the same minute as it was activated will be turned on again). - If the program passes all these check, the alarm (speaker and LED) will turn on! ```python= # Check if alarm should be turned on if not alarm_is_active: for alarm in saved_alarms.values(): if (alarm == current_time) and not alarm_already_activated(alarm): # Turn on alarm ``` The process of activating the alarm looks like this: ```python= # Turn on alarm alarm_is_active = True play_song() random_LED.value(1) activated_alarms = [] activated_alarms.append(alarm) ``` And it is not much more complicated than that `play_song()` turns on the speaker and plays a song, and `random_LED.value(1)` turns on a LED module that randomly changes color in a fun way. For fun, I <a href="https://github.com/jazzjacob/iot-binary-alarm-clock/blob/main/Songs.py">programmed</a> the melody from <a href="https://www.youtube.com/watch?v=rEeiRXOlWUE">Starmachine2000</a> by Wintergatan as the song the speaker plays. --- ### Transmitting the data / connectivity #### How often the data is sent Data is sent to the device only when the user sends something from the dashboard. Data is sent from the device around every 6 seconds. This could probably be higher number in the future, because there is no actual need for a frequent data transfer in its final form (as I imagine it now). It only sends data to keep contact with the MQTT host. But right now the project is still is in a sort of testing phase, so it helps with debugging to have a relatively frequent data transfer, so that I can see that everything is running as it should. #### Wireless protocol This project uses WiFi because the alarm clock is made for use in my home. #### Transport protocol This project uses MQTT as transport protocol, because it works good for this case and I did not have any reasons to find anything else. --- ### Presenting the data ![](https://hackmd.io/_uploads/HkROc4BF3.png) Here is my dashboard on Adafruit IO. Here we have three inputs and two outputs from the two different feeds. One feed is for sending commands to the device from this dashboard, and the other feed is for the device to send data to the feed. The device sends data around every 6 seconds. As of right now, the main purpose of sending data from the device is just for keeping the connection to the MQTT client alive. In the future, this feed could be tuned to perhaps send data less frequent and with more purpose - perhaps with sending a status update or a list of all the current saved alarms. The *Add alarm* input is a text field that the user (me) can enter a time that will be sent to the device. Because of limitations in Adafruit IO (or my limited knowledge of Adafruit IO) you can enter any type of string in this text field, and it is up to the user to make sure it is formatted correctly. The *Turn off alarm* button sends a command to the feed that the device will interpret and turn off the alarm, if an alarm is active. The *Reset* button sends a command to the feed that the device will interpret as to delete all internally saved alarms. --- ### Finalizing the design Here a few videos showing the device and some features of the result of the project: <iframe width="560" height="315" src="https://www.youtube.com/embed/s3E6KNrXYaw" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe> **Boot up animation, displaying state and clock** A fun little bootup animation using the "clock" LEDs, and then the RGB LED showing different states: - slow blinking blue = loading WiFi - faster blinking green = WiFi connected The current time is displayed with colored LEDs forming a binary clock. Time is displayed in a 24h hh:mm format with each decimal digit being represented in binary. There is also an LED switching on/off each second - a visual tick-tock, you could say. --- <iframe width="560" height="315" src="https://www.youtube.com/embed/9Y_PjpPsgak" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe> **Rebooting** Holding down the button reboots the device. --- <iframe width="560" height="315" src="https://www.youtube.com/embed/rNYSetGeG_I" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe> **Set timer, active timer and turning off alarm** Sending a time to start the alarm from the dashboard. Since the time of the alarm is the current time, the alarms turns on automatically directly after recieving the command from the feed. --- **Other features that were implemented:** - Storing alarms in a json-file on device - Emptying that json-file on command from the dashboard - The alarm clock automatically setting the current time on bootup by using NTP (Network time protocol) --- **What could be improved** The device still is not perfect, I think there are still some bugs in the code related to the network or MQTT connection. I have not had the time to do any real long time testing (>1h). The longest the device have ran and worked is around 5 hours, before the network connection failed and crashed. Worth noting is that the clock functionality in the code is running on a separate thread and has never failed, even when the network connection fails. **Final thoughts** I am very happy with the result of this project. I had a clear vision and managed to create a pretty decent kinda-working version of **The Cool Binary Alarm Clock**. Altough it is probably not very useful as a product in its current state, looking at it instead as prototype makes it a success according to me. It shows promise, and you could just fine tune some details and to make it a fun little device, or you could develop it even further in a multitue of ways. ---