---
# System prepended metadata

title: Tutorial on how to build a doorbell and knock notifier
tags: [IoT]

---

# Tutorial on how to build a doorbell and knock notifier

### This tutorial provides the steps needed to build a system for notifying someone when someone is knocking on your door or the doorbell is used.
* Use sensors to get information when someone is knocking or pushing a button
* Send data via WiFi to a broker and notify the user
* Visualize the data on said broker

### Aproximate time to build: 8 hours


Author: Andreas Backman (ab226pi)


## Objective

The objective of the project is to make a system for your door to notify the user by sending a notification via WiFi when someone is knocking or ringing the doorbell. 

My thought regarding the device is mostly to be used by people who can't hear that great or not at all, by for example sending this notification to the persons phone, smart watch but can also be configured to for example flimmer the lights. This since my father has bad hearing. He already has a system for him to hear when the doorbell is used by him hearing it with his hearing aids, but that is not used when someone is knocking.

But the device can also be usefull for someone at their computer using a headset and in that case the notification can also be sent to for example discord, which is perfect when said user is playing games.


## Materials



|IoT Device|Cost|Description|Suplier|
|----------|----|-------------|-----|
|[Rasperry Pi Pico WH](https://www.electrokit.com/produkt/raspberry-pi-pico-wh/)<img src="https://www.electrokit.com/cache/ba/700x700-product_41019_41019114_PICO-WH-HERO.jpg" alt="Raspberry Pi Pico WH">|109.00SEK|Microcontroller with built in WiFi that uses a RP2040 CPU an ARM Cortex-M0+ with 133MHz, 256kB of RAM, a 2MB on-board QSPI Flash and a CYW43439 wireless chip. The device make use of IEEE 802.11 b/g/n wireless LAN. It comes with its 40 pins pre-soldered and of these 40 pins it has 30 GPIO pins|Electrokit|
|[Breadboard](https://www.electrokit.com/produkt/kopplingsdack-840-anslutningar/)<img src="https://www.electrokit.com/upload/product/10160/10160840/10160840.jpg" alt="Breadboard">|69.00SEK|A high quality breadboard which makes use of its 840 connectors to connect the microcontroller to sensors without the need for soldering. Whichs makes it easy to replace, remove or add new sensors if needed.|Electrokit|
|[Jumper Wires](https://www.electrokit.com/produkt/labbsladd-40-pin-30cm-hona-hane/)<img src="https://www.electrokit.com/cache/b9/700x700-product_41012_41012686_41012686.jpg" alt="Jumper Wires">|49.00SEK|Lab cable with connectors in both ends (male-to-female) which is used together with the breadboard to connect each sensor to the microcontroller|Electrokit|
|[Knocking sensor](https://www.electrokit.com/produkt/knacksensor/)<img src="https://www.electrokit.com/upload/product/41015/41015735/41015735.jpg" alt="Knocking sensor">|39.00SEK|Microcontroller with built in WiFi that uses a RP2040 CPU and has 30 GPIO pins|Electrokit|
|[Push button](https://www.electrokit.com/produkt/tryckknapp-momentan/)<img src="https://www.electrokit.com/upload/product/41015/41015723/41015723.jpg" alt="Push button">|19.00SEK|Sensor with a push button which will have a low output when pressed and switch back to high when button is released|Electrokit|
|[Micro USB cable](https://www.electrokit.com/produkt/usb-kabel-a-hane-micro-b-5p-hane-1m/)<img src="https://www.electrokit.com/cache/ad/700x700-quick_54_1f_9382_41009860.png" alt="Micro USB cable">|39.00SEK|USB-to-Micro USB used for powering and sending data to the microcontroller|Electrokit|


## Computer setup

The first step in the setup is to install an IDE, which is used to write our
code. Two of the IDEs that can be used is Thonny and Visual Studio Code (VSC).
I will go over how VSC is installed and setup since that was my IDE of choice. 

First head over to the VSC download page located [here](https://code.visualstudio.com/download). I am using Windows as an operating system which is straight forward. Simply download and run the installer and follow the instructions during installation.



Installing MicroPython on your Pico WH:
In order to install the MicroPython firmware, you may start by visiting this [link](https://https://micropython.org/download/rp2-pico-w/) where you simply download the latest version. Don't worry, if you are using another microcontroller you can look for this [here](https://micropython.org/download/) instead. :wink:

To then flash your Pico WH, you hold down the BOOTSEL button when plugging your USB cable. This will then make your device show up as a drive in which you can drag your firmware onto the device. This will flash your device and make it disappear from your drives and the device is now ready for use.


We will then install the MicroPython extension **Pymakr (NOT Pymakr - Preview version)**
This is done via the extensions tab. After installing Pymakr, a new tab is added to your activity bar. 
![](https://hackmd.io/_uploads/ryEwuibK2.png)



Testing out our Pico WH:
Connect your Pico WH to your computer and click on said Pymaker tab. Then click on the connect icon. Followed by the start terminal icon.
![](https://hackmd.io/_uploads/SkRhPobKh.png)![](https://hackmd.io/_uploads/rycpvsWKh.png)




This will then open your REPL terminal, where you may try toggeling the light on your Pico WH by entering this code.
![LED](https://hackmd.io/_uploads/SJGzvs-Yh.png)


Let us now create our first program!
Head back to the Pymakr extension tab and click on Create project. Select your path and save. Chose your project name and select an empty template.
Go to the explorer tab where you will find a file called boot.py and one called main.py. Let us skip right to the main.py file.

This is as it sounds, the main file of the program.
Let us write a short program to see how this will be uploaded to our device and executed.
```
from machine import Pin
led_pin = Pin("LED", Pin.OUT) # Declares variable for led pin

# Function to blink the onboard LED
def blink_led(frequency = 0.5, num_blinks = 3): # Frequency in sec, number of blinks
    for _ in range(num_blinks):
        led_pin.on()
        time.sleep(frequency)
        led_pin.off()
        time.sleep(frequency)

while True:
    blink_led()
```
This program will declare a function that will turn the on-board led on and of every 0.5 seconds three times.
To upload this to our Pico WH, we first save the project, and head over to the Pymakr extension. 

Here we click on the three dots and stop the script and then sync the project to the device. We then go back to the three dots and hard reset the device. This should then automatically run the program on the device and the led should start to blink. 
![](https://hackmd.io/_uploads/rJco2iZt3.png)


## Putting everything together

**Make sure to disconnect your device from the computor before doing anything else**

### Connecting the Pico W and sensors:

![](https://hackmd.io/_uploads/By9N1abFn.png)

![](https://hackmd.io/_uploads/Hy7oR3ZF2.png)

By looking at the following images we can see that I have made the choice to connect the knock sensor to GP14 and the push button to GP15. Note that this is the pin number used when writing the code later on.
The power is connected via the 3v3 pin at pin number 36 and ground at pin number 38. Since we are using two sensors we utilize the bus strips to connect these. Since both of these sensors has a built in resistor, no resistor is connected to the breadboard. 
Make sure that the sensors are connected. An easy way to do this in this case is to look for the S and the - on the sensors. S is where you connect the green cable and - is used for ground.


## Platform

I chose to use Adafruit for my platform since it offers a free version of the platform which give me enough for this project. It is also easy to use as it requires litle to no programming knowledge. Since I don't plan on upscaling my project, I will keep using Adafruit as a host. I never got to try out another platform, since I found Adafruit so easy to use.


## The code

For this project, four documents were used. 
The boot.py file is used for connecting to WiFi. This due to that the boot.py file will run automatically when the device is running. The mqtt.py file is then used for connectivity and the keys.py file is used to store more sensitive data such as the WiFi and Adafruit login information. 

The main.py file how ever is where the functionality of the sensors is created, where we connect to Adafruit and where we publish the messages to Adafruit. These are all straight forward stuff, so I will first go over the how we notice when a knock is made or when the button is pushed.

```
# Function for sensors being used
def sensor_callback(pin):
    global publish_message
    # Restrict publishing rate to one message every 3 seconds
    MIN_PUBLISH_INTERVAL = 5 # seconds
    global last_publish_time
    current_time = time.time()
    # Making sure that messages only will be published once every third second
    if current_time - last_publish_time >= MIN_PUBLISH_INTERVAL:
        if pin == button_pin: # if button is pressed
            publish_message = "Someone rang your doorbell!"
        elif pin == knock_pin: # if knock is made
            publish_message = "Someone knocked on your door!"
        else:
            return
        
        # Calls function to publish the message
        send_notification()
        
        # Reset publish time
        last_publish_time = current_time
```
Here we create a callback function which will set an interval of how often a sensor can be activated. It does this using the time library, and checking the current time, the last time something was published against a constant made for setting the publish interval. Using statements we then check if the argument is a knock made or a button pushed and update the next message sent accordingly. To then call the function that publish the message.
To then trigger the function when a sensor is used, we make use of the following code that simply interupts the button_pin object when the button is pressed, and instead calls the sensor_callback function. It does this by noticing when the pin transitions from a high to low voltage.


Let's now look at the boot.py file which will connect us to WiFi.
```
import network
import keys

# Create WLAN interface and activate it
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
# Check if connected already before trying to connect
if not wlan.isconnected():
    print("Connecting to WiFi...")
    # Connect using SSID and password
    wlan.connect(keys.ssid, keys.password)
    
    # Wait until connection is established
    while not wlan.isconnected():
        pass
print("Connected to WiFi: ", wlan.ifconfig()) # Prints IP config
```
Here we create and activate a WLAN interface which we then connect to using our SSID and password which we stored in the keys.py file. It can be wise to first check if we are connected before connecting to avoid any errors.

Other than the SSID and password stored in keys.ph we also set up all needed variables to connect to our MQTT broker Adafruit. This includes the clientID, the brokers domain name or IP, the brokers port, and your username and password to the broker. I also specify the publish path to the broker in the keys.py file.

The connection and actual publish is then made in the main.py file
```
# Function to send notifications to Adafruit IO
def send_notification():
    # Connect to Adafruit IO MQTT broker
    client = MQTTClient(keys.clientID, keys.mqttBroker, keys.adafruit_port, keys.adafruitUsername, keys.adafruitPassword)
    client.connect()

    # Publish message to Adafruit IO feed
    global publish_message
    client.publish(keys.publish_topic, publish_message)

    # Disconnect from MQTT broker
    client.disconnect()
```


## Transmitting the data / connectivity

The data is transfered to the internet using a WiFi connection by utalizing the built in WiFi capabilities of the Pico WH microcontroller. The choice for using WiFi is based on its reliable and fast data transmission and since the device most commonly will be located in your home, I don't see the need for a LoRaWAN connection.

The data is sent via messages being published to the broker Adafruit using the MQTT (Message Queuing Telemetry Transport) protocol which is a protocol well suited for IoT programs since it is light weight and offers an easy way to publish our messages.

The code for establishing the WiFi connection and sending MQTT messages is implemented in the main.py file. The boot.py file is used to connect to WiFi by configuring the WLAN interface with the provided SSID and password. Once the connection is established, the main.py file handles the sensor inputs and publishes messages to the MQTT broker.

The data is sent about every 4 seconds. This is done by implementing a delay in the main.py files sensor_callback() function which prevents spamming of the publishing of messages. Both to not overwhelm the broker but maybe more importantly the user.

To send data to Discord we will need to access a webhook which can be done by simply heading to Discord, creating a new server, clicking the cog wheel on the text channel, selecting integration and from there you create a webhook.
If this webhook is then used in a reactive action in Adafruit IO where one specifies what should happen. 


## Presenting the data

Sadly the dashboard part of this project is not that exciting due to it is made to publish data, not recieve it from the MQTT broker. Due to this I have chosen to visualize the sensors being used in my dashboard. 
On Adafruits free version has a data saving rate of 30 per minute which seems to work fine for my project. The data is then saved for 30 days, which is perfectly fine for the usage.
![](https://hackmd.io/_uploads/SJtB2efKn.png)

Regarding Discord I have made use of a webhook to notify the user via text through discord. The webhook tags the user which makes the user get notified when someone is at the door.
![](https://hackmd.io/_uploads/H1263xGFn.png)


## Finalizing the design

The final result of the project works as first intended. But if I had the chance to start over, I would have worked on a better solution regarding both the physical aspect of the project such as a battery, a better knock sensor  and a better way of holding the microcontroller and the sensors together. But also the implementation of the code. I would have for example wanted to implement a way to turn the program of digitaly using my brokers dashboard.
Sadly I felt that I ran out of time by changing projects midway to then needing to go back to this one. All in all I feel like it has been a really fun and learnable experience.

Final pictures of the project: (I apologize in advance for the chaos :joy:
![](https://hackmd.io/_uploads/SyELv-fY3.png)
![](https://hackmd.io/_uploads/ryTUvZMF3.png)

















