---
# System prepended metadata

title: 'A bearable, yet effective morning alarm'

---




# A bearable, yet effective morning alarm








###### by: David Johansson, dj222nd

For this course, I’m making a version of Donald Duck’s alarm clock we all see every Christmas at 15:00. A temperature sensor and a light sensor control two blinds. Two electric beds get wifi communication and are controlled both from the phone and an abort button on the other side of the room, together with the existing wired remote.

Well over 100 hours to learn and another 100 hours to make.





## Objective

I choose to add the temperature sensor to be sure that when I buy a new expensive TV in the future is going to have some longevity to it, because right now I burn my hands on the back of it the days I forget to protect my current one, and that can’t be good. The temperature sensor will act as a failsafe for letting the TV overheat from the sun and set one of the blinds to fully cover the window on a hot summer day. For the rest of the project, I chose to make mornings fun and bearable, and a great way to deal with the most significant side effect of insomnia; sleeping over the next day. The goal is to try to do something for all five senses, both by waking up from the deepest sleep possible, and the first hour of the day.

#### The alarm scene
* Before the alarm, the blinds are going to slowly go up as a way to notify that it is almost time to wake up. The first thing that happens when the alarm goes off is a chosen song starts playing on the TV at a low volume and the bed adjusts a little. A few minutes later, it switches to a horrible morning alarm playlist on Spotify at an increasing volume. The bed goes up and down to increasingly uncomfortable levels, first in sync, then out of sync. The blinds go up and down to leave the choice open to get out of bed and turn the alarm off while the room isn’t painfully bright.

#### The morning scene
* A light sensor measures the lux in the room and adjusts the blinds accordingly in the mornings to not shock the eyes the first hour of the day. The TV switches to another playlist with really good music playing at a lower volume. The bed goes into being fully adjusted to take away the option to get back into bed again.

#### The day scene
* The bed adjusts to an incompatible seated position for using the tv later, the tv turns off and the blinds go fully up to let light in. This is the default.

The worst thing for the eyes in the mornings is an undefused bright lamp from a single source. So after this is all set up and ready to be built upon, the single lamp on the roof is going to be replaced by 17 meters of LED strips around the room. This is going to work with the light sensor to make up the difference when the sun isn’t shining in on early mornings or most of the winter season. Speaking of which, at a later date, before winter, an electric radiator with wifi compatibility is going to set the temperature from a good sleeping temperature at 18-20 C, to something that makes you want to through away the quilt, around 25 C. When that is said and done it should be a piece of cake to add more scenes for the room like a night scene and a cinema scene.

I've always wanted to learn to make my own automation and thought I needed to study a whole program to know what I'm doing. To own a product and say, “wouldn’t it be better to automate this, maybe even control it from my phone”. This is a great opportunity to choose a platform that I like and really dig deep into learning it for future projects, and begin with the most important part. These are the other things I'm going to do but can’t make everything in time for this course:

* A few moisture sensors in the garden to keep track of watering and send a reminder if it's too low for too long.
* An automatic chicken pen door to close and open depending on sunset and sunrise data at my location and Sea level height. Also controlled the Home Assistant app to manually open and close it.
* Kitchen counter LED lights to turn on with a presence detector and the brightness increases gradually depending on the hour of the day. Turn off slowly without presence detection for a few minutes so as to not leave one suddenly in the dark, if still.

Almost all of it can be summarized under the name IoT. There are so many subjects this project covers that I’ll be able to try out and learn what I like doing for future studies and eventually customize my own degree.


## Material


| Product | Cost | Amount | Short description |
| ------- | ---- | ------ | ----------------- |
| [ODROID N2 Plus](https://en.odroid.se/products/odroid-n2-plus-n2-med-4gbyte-ram) | 1 499 SEK | 1 st | computer to host the platform |
| [64 GB eMMC](https://r-pi.se/products/64gb-emmc-android-module-for-odroid-n2-and-n2) | 686 SEK | 1 st | memory for computer |
| [Adapter 12V/2A](https://r-pi.se/products/12a-2a-power-supply-eu-plug?pr_prod_strat=copurchase&pr_rec_id=f76bea5c2&pr_rec_pid=4000125255768&pr_ref_pid=4756635123800&pr_seq=uniform) | 186 SEK | 1 st | powersupply for computer |
| [FYRTUR blinds](https://www.ikea.com/se/sv/p/fyrtur-moerklaeggande-rullgardin-smart-tradloes-batteridriven-gra-90408170/) | 3 190 SEK | 2 st | [blinds controlled with Zigbee](https://zigbee.blakadder.com/Ikea_E1757.html) |
| [CC2531 Zigbee Adapter](https://sizable.se/P.3FHCK/CC2531-Zigbee-Adapter) | 97 SEK | 1 st | [Zigbee adapter for computer](https://zigbee.blakadder.com/CC2531.html) |
| [Okimat 3H4/6](https://www.yumpu.com/de/document/read/5317165/okimat-3h4-3h6-einbauanleitung-fur-den-hersteller-des-okin) | 1 800 SEK | 2 st | simple electric adjustable bed |
| [Step-Down Adj 20A](https://sizable.se/P.Z8RD7/Step-Down-Adj-20A) | 278 SEK | 2 st | electric regulator and filter |
| [I2C BH1750 FVI](https://sizable.se/P.5BWJP/Digital-I2C-ljussensor-BH1750FVI) | 29 SEK | 1 st | digital light sensor |
| [Abort button](https://www.eldirekt.se/varumarken/malmbergs/komplett-nodstopp-ip44) | 229 SEK | 1 st | abort button that has to be reset |
| [L298N Dual H-Bridge Controller](https://www.amazon.co.uk/dp/B09TJZ953V/ref=pe_27063361_487055811_TE_dp_1) | 111 SEK | 2 st | [relays that can control voltage direction of two outputs separatly](https://microcontrollerslab.com/l298n-dc-motor-driver-module-esp32-tutorial/) |
| [ESP32 Dev](https://www.amazon.co.uk/dp/B09FJZQDVW/ref=pe_27063361_487055811_TE_dp_2) | 245 SEK | 3 st | generic ESP32 |
| [Digital multimeter](https://www.biltema.se/en-se/tools/measuring-tools/measuring-instruments/multimeters/digital-multimeter-2000018521) | 120 SEK | 1 st | something to check voltages and current |


## Computer setup

To work with an ESP32, you have to install [a driver](https://www.silabs.com/documents/public/software/CP210x_Windows_Drivers.zip) for the computer to communicate between the two. The ESP32 has to be flashed with the [latest firmware](https://micropython.org/download/esp32/) on [this site](https://nabucasa.github.io/esp-web-flasher/). From now on, the boot button on the ESP32 has to be pressed the whole time from connecting, to finish. Choose the COM port with the same name as the driver that was installed earlier when connecting to the site; USB to UART Bridge. Erase the old firmware, type in an offset of 1000, and upload the new firmware. This takes a few minutes and has to be repeated on all three ESP32.

Install [Node.js](https://nodejs.org/en/) and then [Atom](https://atom.io/), with the pymakr plugin, the first IDE. I wanted to try a second IDE and installed the latest [Python](https://www.python.org/downloads/) together with [VSCode](https://code.visualstudio.com/download). Visual Studio Code has way more features and options, a very useful tool for debugging the code with native highlighting of obvious errors in real-time as Python and Micropython are visually the same languages. While VSCode has extensions to get the features, I would need to only use that program. But for actually discussing the code with others and getting feedback, it is much more useful to have a common familiar IDE. No further effort was put into researching how to add the features I need that Atom has natively with the pymakr plugin into VSCode for this reason. The third IDE that was looked into is an add-on that comes with my chosen platform, called [ESPHome](https://esphome.io/guides/getting_started_hassio.html), an open-source project by [Nabu Casa](https://www.nabucasa.com/). It has two very useful features; one is that the code is easily updated over wifi and the second is that it is written in the same language as the platform and they work together YAML. That means that writing the ESP32 works exactly the same as writing in new features on the platform that is going to host every piece of automation in the household. It is a language that I’m going to have to want to learn eventually, but together with the reason stated above and wanting to try out Python, it was discarded. 

The Odroid N2+ also needs to be flashed to [install](https://www.home-assistant.io/installation/odroid) the hub that is going to host every platform that is going to be used later, locally on Home Assistant. In my case, the eMMC came with an Android installation complete wish we need to get rid of. Install [BalenaEtcher](https://www.balena.io/etcher/) and run as administrator. Etcher wants to access the device either via USB directly into the computer or a [Network Attached Storage](https://en.wikipedia.org/wiki/Network-attached_storage), NAS. To do that, attach the eMMC and flip the onboard switch to boot from that. Connect it to a USB keyboard, a monitor through HDMI, a network cable, and lastly, the power cable. As soon as something shows up on the monitor, press enter to stay in BIOS. If you don’t do it fast enough, the operating system already installed on the eMMC is going to start. If nothing showed up before the operating system started, you have to switch to another monitor. Choose the option ‘Exit to shell’ and here we are going to write two commands to make it into a NAS. 
 
 ```= 
ls /dev/mmc*
ums /dev/mmcblk0
```

The keyboard and monitor aren’t needed anymore. Back on the computer, [select “Flash from URL” in Etcher](https://www.home-assistant.io/images/installation/etcher1.png) and paste the [specific Github URL for the device](https://www.home-assistant.io/installation/) you want to install Home Assistant on. Select the device and wait a few minutes for Etcher to flash and install. Your Home Assistant can be accessed in any browser on any computer connected to the same network with the URL: http://homeassistant.local:8123. Or any phone with the app installed. Create an account and update to the latest version. To access it from outside of the local network you set up a [reverse proxy and a DNS](https://youtu.be/AK5E2T5tWyM?t=153) and use the new URL then.

## Putting everything together

After [simulating he existing PCB in the bed](https://tinyurl.com/2y2zsbfj), we see that it can be split into three parts shown as their own breadboard on the diagram. One is the AC/DC converter, the second is the failsafe part to stop the motors from pushing the piston too far in either direction and breaking the case. This was all originally tied together through the remote and was the only means of controlling the bed. These three parts can be broken down to simply output and input and leave them working as is, as this is a working product powered by electronic logic with no computer or software. 

![](https://i.imgur.com/XWZJlvl.png)

The [AD/DC converter](https://www.allaboutcircuits.com/uploads/articles/example_ac_dc_converter_circuit.jpg) outputs are accessed by soldering some cables on pins sticking out on the back on either side of the blue capacitor. But bigger cables than that can be soldered on the remote below. These cables are going to handle at least twice the current. The multimeter measured over 30 Volt and 0.5 amps. These outputs are going to be routed through an [H-bright relay](https://youtu.be/I7IFsQ4tQU8?t=91) instead. This voltage is way too high to actually power the [L298N](https://youtu.be/I7IFsQ4tQU8?t=200), and we still need to power the ESP32 somehow. So an [external regulator](https://sizable.se/P.Z8RD7/Step-Down-Adj-20A) is introduced in parallel that can handle these voltages down to 5V, while also working as a filter. 

The remote doesn’t need ground anymore when the ESP32 has internal pulldown resistors, so we only care about one output for each of the four buttons and an input. Up and down for both legs and back. These can be seen soldered in the picture below. 

Now for the fun part with ten cables attached to it. It is a failsafe for two separate motors, so we only have to look at one to understand the other. The piston that the motor's power has a button for being fully out and one for being fully in. These [limit switch buttons reroute the current](https://realpars.com/wp-content/uploads/2020/10/Microswitch-Circuit-Example-1.gif) through the diodes, which means the current can only go one way instead of both ways. Wich in turns means the motor can only go in one direction; trying to go the other way does nothing. This is a feature that is essential and might be expanded upon to let the ESP32 know the bed is at its maximum and minimum position. The cables marked with 1 and 3 go to one motor while 4 and 6 go to the other, but the inputs that were directly connected to the remote are 1, 2 and 4, 5. One for each button on the remote. These are the cables that we’re going to connect to the outputs on the [dual H-bridge relay](https://1ohm.in/wp-content/uploads/2021/07/L298N-Motor-Driver-Controller-module-Dual-H-Bridge-Motor-Driver-1.jpg). 

![](https://i.imgur.com/UQvSHD1.jpg)

The ESP32s for the beds are powered by the step-down regulator at 5 volts. The remote needs four pins with pull-down resistors for the remote buttons and sends 3.3 volts to check if the current goes through. Two pins that support PWM signals go to the dual H-bridge and control the speed of the motors in turn. Four other output pins that can be set to high or low control the direction.

For the other ESP32, it is powered by a USB cable. The temperature sensor is then in turn powered by a 3,3 volts pin while the digital temperature sensor is powered by a 5 volts pin. The temperature sensor communicates through a pin with analog-to-digital compatibility. The light sensor communicates with I2C, through the scl and sda pins. The abort button works just like any other button and is connected to 3,3 volts and a pin with an integrated pulldown resistor.

The only electrical calculations needed really, are when setting up the step down adjuster to a voltage and amp that both the H-bridge and ESP32 can handle. This is done using the digital multimeter and [Ohm’s law](https://www.calculator.net/ohms-law-calculator.html). 

## Platform

In general, a local server is great for speed, stability, and privacy, but none of that had much say in my choice. Home Assistant is famous for the extremely wide range of compatible devices that it supports natively and the customizability it offers home automation. As it is an open source and written entirely in a language that is easy to learn and straight forward. Anyone can contribute on both front end and back end and share a registry for anyone to install and build futher appon. A dashboard that can work and look however you see fit and is designed to work on anything with access to a browser. That means that is is actually a challange to find a product that can’t be controlled with Home Assistant if the product has any communication protocal. It can be assumed that someone already has written an integration already, and if not, it isn’t a hastle to do so myself.

Companies that caters to make their products exclusive for their own services, like a specific app that or hub that isn’t ever going to get used for anything but for one specific purpose, and usually it’s missing features and can’t work together with another different service. Every common wireless comunication protocal already has a really cheap USB stick for recieving, transmitting, and interpreting that information. In my case, [Ikea smart blinds](https://zigbee.blakadder.com/Ikea_E1757.html) use [Zigbee as a wireless protocal](https://en.wikipedia.org/wiki/Zigbee) and the only advertized way to fully make use of the features their products offer, is to buy more of their products that can only be used for their products, and then use their own app for that specific purpose. Instead, the USB stick instead cost me 97 SEK and gives way more control over any Zigbee network. 

As I want to make custom made IoT and have it controlled over the phone in a design that i made myself, with alot of specific features that also works reliably with other products. I’ve chosen to selfhost everything and then later integrate google assistant voice control, even though it can only understand that you name a specific device half of the time, it’s still a cool feature to have. 

| Logo | Name | Use |
| ---- | ---- | --- |
| ![](https://upload.wikimedia.org/wikipedia/commons/thumb/9/9a/Visual_Studio_Code_1.35_icon.svg/2048px-Visual_Studio_Code_1.35_icon.svg.png) | [VSCode](https://github.com/hassio-addons/addon-vscode) | To access, search and edit any piece of code on the Home Assistant and a terminal for commands such as installing HACS. With this platform I will edit the code for the dashboard, and the attributes of the devices. |
| ![](https://external-preview.redd.it/dNAR1JQ8WZ2NL4Nzcx5t38L0Suq3IzAq2YyxGdEzEwY.jpg?auto=webp&s=4a612e74ca4bd4299a7d0cd40ea4181fcdea1c7a) | [Home Assistant Community Store](https://github.com/hacs) | Download, install and update community-made integrations, front-end and back-end. Such as an expanded library of Node-RED integrations. |
| ![](https://projects.eclipse.org/sites/default/files/mosquitto-200px.png) | [Eclipse Mosquitto MQTT broker](https://github.com/home-assistant/addons/tree/master/mosquitto) | Message broker that implements the MQTT protocol for lightweight communication. Can easily send and recieve information as strings over the local wifi between different devises by setting up topics for specific purposes. |
| ![](https://raw.githubusercontent.com/Koenkk/zigbee2mqtt/master/images/logo.png) | [Zigbee2MQTT](https://github.com/Koenkk/zigbee2mqtt) | Allows the use of Zigbee devices without the vendor's bridge or gateway. Full control over the Zigbee network and allows devices to update the firmware. [Makes every command communicate through MQTT topics](https://www.zigbee2mqtt.io/devices/E1757.html#exposes) for easy triggers in Node-RED. |
| ![](https://nodered.org/about/resources/media/node-red-icon.png) | [Node-RED](https://github.com/hassio-addons/addon-node-red) | Visual-based programming that is going to handle most of the automation instead of using Home Assistants' own UI-based or YAML code-based programming. This gives a better overview and is easier to work with for the more advanced automations.  |
| ![](https://www.pngitem.com/pimgs/m/255-2551990_influxdb-logo-png-transparent-png.png) | [InfluxDB](https://github.com/hassio-addons/addon-influxdb) | Scalable time-based data storage. Easy to send and access data with Node-RED nodes. Fun to try a TIG-stack and have this as a long time data storage to see how my habits change over time. |
| ![](https://seeklogo.com//images/G/grafana-logo-15BA0AFA8A-seeklogo.com.png) | [Grafana](https://github.com/hassio-addons/addon-grafana) | Data visualization of the stored data on InfluxDB, it’s always fun to see the collected data in a good-looking graph to get a true overview and make new automation decisions based on that. |

## The code



| Library | Author | Description |
| ------- | ------ | ----------- |
| [button_test.py](https://gist.github.com/jedie/8564e62b0b8349ff9051d7c5a1312ed7) | [jedie](https://gist.github.com/jedie) | Debounce signal for button presses |
| [bh1750.py](https://github.com/PinkInk/upylib/blob/master/bh1750/bh1750/__init__.py) | [PinkInk](https://github.com/PinkInk) | [Digital light sensor](https://github.com/PinkInk/upylib/tree/master/bh1750) i2c, scl, sda |
| [simple.py](https://github.com/micropython/micropython-lib/blob/master/micropython/umqtt.simple/umqtt/simple.py) | [MicroPython](https://github.com/micropython) | [Both publishing and subscribing to MQTT topics](https://github.com/micropython/micropython-lib/tree/master/micropython/umqtt.simple) |
| [dcmotor.py](https://www.robotique.tech/wp-content/uploads/2022/05/dcmotor.py) | [robotique](https://www.robotique.tech/tutoriel/commander-un-moteur-par-la-carte-esp32-et-le-module-l298n/) | dual H-bridge direction and speed |




 ```phyton= 
# Import libraries
import config
import network
from simple import MQTTClient

# MQTT Setup
client = MQTTClient(config.MQTT_broker,
                    user=config.MQTT_user,
                    password=config.MQTT_password,
                    port=config.MQTT_port)

leg_target = None   # Setup a global variables for the mqtt topic payloads here
back_target = None  # as they are used later in the code aswell as in this function.

def sub_cb(topic, msg):                    # Define subscribe callback function.
    global leg_target                       # Access the variable from outside the function
    if topic.decode() == 'leg_target':      # Decode topic and execute the payload.
        leg_target = int(msg.decode())      # Change to global variable to the mqtt payload.
        print('leg_target :', leg_target)   # Print in terminal to confirm it's working.
    global back_target                      # Access the variable from outside the function
    if topic.decode() == 'back_target':     # Decode topic and execute the payload.
        back_target = int(msg.decode())     # Change to global variable to the mqtt payload.
        print('back_target :', back_target) # Print in terminal to confirm it's working.

client.set_callback(sub_cb)
client.connect()
print('connected to MQTT broker')   # Print in terminal to confirm it's working.
client.subscribe('leg_target')      # Subrcribe to mqtt topics sent from node-red to
client.subscribe('back_target')     # update the global variables on the ESP32 code.
```
Import, and connect to MicroPython's own MQTT library, subscribe to the topics. The code looks about the same on the other ESP32, but it is the sleep cycle time that is updated with MQTT topics instead.





```phyton= 
    def goal(self, target, speed):
        self.target = target
        self.speed = speed

        if self.target != None:
            if self.target > self.current_pos:
                self.up()
                self.update(True)

            if self.target < self.current_pos:
                self.down()
                self.update(True)

            if self.target == self.current_pos:
                self.stop()
                self.target = None
                self.update(True)
```
A goal function written in the dcmotor class library, this is where the MQTT topic payloads are executed until either the update function has updated the current position to the target position or until one of the physical buttons on the remote is pressed, as that sets the target position to none. The up, down and stop functions update the relevant pins connected to the H-Bridgde, and are also called upon with the physical button presses.

## Transmitting the data / connectivity

Power consumption isn’t a problem as it is powered directly by a power outlet. But to keep overheating and unnecessary wastage to a minimum for environmental and cost reasons, some precautions have been taken were it can be. The circuit with the abort button changes between two different sleep timings depending on the scene that is set. It measures and sends data every 5 minutes if it doesn’t expect the lux data and the button to have a use. While that data is useful, it sets the sleep cycle to every 5 seconds. All that data is sent and received through MQTT topics to easily categorize the data packages in Node-RED. [As the Zigbee devices are converted back and forth to MQTT topics in the Zigbee2MQTT add-on with these commands.](https://www.zigbee2mqtt.io/devices/E1757.html#exposes)

![](https://i.imgur.com/jFguMQB.png)

There was some dabbling in UDP protocols, but as the project grew and there was a lot of different protocals that was going to be used back and forth. So as the Zigbee2MQTT already used MQTT topics, they seemed easier to work with once they are set up, and fewer types of nodes to debug in Node-RED, it was the logical choice. With MQTT the devieces aren't timing sensative compared to some other protocals, the broker handles that. 

![](https://i.imgur.com/uOZZIQO.png)

All the devices have a static placement in the house and are just a few meters away from the nearest WIFI mesh router, while the Home Assistant is connected with a ethernet cable. The MQTT packages is only sent through the local network to the ODroid with Home Assistant and it works as a gateway that can be accessed through my phone from outside the network with a DNS server and a reverse proxy. 

## Presenting the data

The two choices i wanted to work with is Home Assistents own dashboard for the data i expect to daily for the last few days and something bigger to gather more data over an extended period of time, TIG-stack. Both dashboards are accessible from the phone, but home assistants is integrated into every other functionality around the house. The data is stored for a year and both have access InfluxDB. 

![](https://i.imgur.com/7c6rh59.png)

This is the Lux data from the light sensor over 24 hours in Grafana. The smaller gaps in light intensity in the room go down drastically when the clouds or trees cover the sun and are next to none when the blinds were down from 22:00 to 13:00.The data on this graph is received in five-second intervals, as it is set to when the data is expected to be of use. The payload on the MQTT lux topic triggers a switch if it is outside the set perimeters, then perceives to open or close the blinds for three seconds and wait for the new values.

## Finalizing the design

I have the code written for the temperature sensor as well, and it was working. But i most likely set the pins in the wrong way when i connected the button, the light sensor and the temperature sensor into the same ESP32, and i only noticed once the smell of melted breadboard started. As I’m later going to upgrade with a few better sensors that have humidity as well and have them in different rooms around the house, I can order a new sensor once the things I have are set up and working properly.

The debounce effect on button-presses is something that wasn’t expected and is the reason I have not yet assembled everything together yet. There are two solutions to this, one is having a capacitor between each button to smoothen out the electricity, the other is not taking the first half a second of pressing the button into account when checking if it is in a pressed state or a released state. The latter has been in the works for the last few weeks now, and I’m about to give up and buy those capasitors.


{%youtube Q7fnPZwrWlU%}