---
# System prepended metadata

title: Smart litterbox

---

# Smart litterbox
A project by Hugo Blomqvist (hb223az) for the course 1DT305 Introduction to Applied IoT!

A visual system for making litterbox cleaning easier and expanding knowledge of IoT!


## Background
The idea for this project started after I moved in with my partner and her cat. Having never had a cat before, I didn't realize how much of a mess they could make around their litterbox. Every day we check and clean out his litterbox, eventhough it sometimes probably wouldn't be needed. To make it clearer if the litterbox needs cleaning I decided to make the litterbox smart. 

By making it smart, I mean making it able to count cat visitations since last cleaning and visualize if it is in need of cleanup by the means of LED and a simple statistcal dashboard! The dashboard will also allow me to see at which times the litterbox is used the most and plan the robot vacuum to clean at appropiate times.

In the future I want to expand upon this by automatically sending out the robot vacuum, create a proper dashboard, use weight sensors to measure presence and if filling of sand is needed!

![](https://i.imgur.com/2vX8NaK.png)
*A picture of the mess maker himself*

### Objectives
* Visualize litterbox usage
* Help track cleaning
* Learn hos a PIR sensor work
* Learn how to send data over wifi
* Provide a base for future expansions

Initialy I had ever greater ambitions for this project but due to lack of time I've unfortunatly had to simplify the project.

With all the hardware in hand, and my code downloaded the approximate time to completion would be 2-4 hours, depending on your skill level.

### Future plans
The cat drops a lot of fur around it, which is one of the reasons we got ourselves a robotic vacuum which helps keep the floors clean. While it have done wonders with its daily cleanup I would like it target clean around the litterbox whenever the cat's businesses are concluded, as he tends to drag some litter sand out every time he leavs the box. For this I would need a smart home hub that can intergrate with the vacuum, which I have yet to aquire.
* Change the vacuum automation from timer to detection of litterbox usage
* 3D-print a custom casing for the electronics
* Make a better looking dashboard (perhaps on [Ubidots](https://ubidots.com/)?)
* Add a weight sensor to help track sand level and more accurate presence

## BOM
For this project, a small device capable of internet connection is needed. For this I've chosen the Pycom LoPy4. To detect a presence inside the litterbox a PIR sensor is used. The ones I've used were bought on [**Electrokit**](https://www.electrokit.com/). To indicate the usage of the litterbox 3 leds of different colors are used and to toggle cleaning a switch. It may be cheaper to source the needed parts by them self instead of going with the bundle as I did.

| What  | Why | Where | Price | Comments  |
| ----- | --- | ----- | ----- | --------- |
| LoPy4 bundle | Act as core | [Electrokit](https://www.electrokit.com/produkt/lnu-1dt305-tillampad-iot-lopy4-and-sensors-bundle/) | ~950 SEK | Contains many modules as well as everything needed to get started with IoT. Only the Pycom device, the expansionboard, jumperwires, breadboard and LEDs are used from this package |
| Switch | To toggle cleaning | [Electrokit](https://www.electrokit.com/produkt/vagomkopplare-1-pol-on-off-svart-i-o/) | ~25 SEK | Used to toggle cleaning mode |
| PIR sensor   | Detect presence | [Electrokit](https://www.electrokit.com/produkt/pir-rorelsedetektor-hc-sr501/) | ~50 SEK  | Used to sence whenever the cat is present. Could be replaced by similar trigger, such as a Sonic sensor, vibration sensor etc. |


## Computer setup
### IDE
For this project I have decided to work in [**Visual Studios Code**](https://code.visualstudio.com/) but any similar IDE should also work. I chose this because it is open source, free and offers many plugins and extensions and support for many languages. I also already had it installed from a previous project I did. Follow the link above and simply download and install it for your platform.

To use VSC with the lopy4, the PyMakr plugin is needed. It can be downloaded from through the IDE's built in plugin browser. To use it we also need [**Node.js**](https://nodejs.org/en/), which is a dependancy for PyMakr. It is downloaded through the link above as an installer.

After making sure these are installed, we can move on to installing PyMaker!

### Installing PyMakr
To install PyMaker, start by starting VSC. After that, follow the steps bellow!
![](https://i.imgur.com/8Xn74uv.png)
1. Press the Extension button
2. Enter PyMakr in searchfield
3. Press the blue install button found on the plugin
4. When the installation is done, press the Reload button which has replaced the install button to activate the plugin


### Flashing firmware
When you first get the parts, you need to update the firmware! For that, I recommend following the official guide found [**here**](https://docs.pycom.io/updatefirmware/expansionboard/). It will guide you through the entire process of updating the expansionboard. Updating the lopy4 will be done after we have configured pybytes, as we need a token it to properly link the device later.

#### Configuring pybytes
For this project, the pybytes platform is utilised for the dashboard. In order to configure pybytes I recommend reading through the official guide found [**here**](https://docs.pycom.io/pybytes/gettingstarted/).
* Start by making an account at [**Pybytes**](https://pybytes.pycom.io/)
* After signing up, it is recommended that you you start by adding your WIFI network by going to the settings tab. 
* After that, you can configure your device and give it a name.
* When you enter the device, go to **Provisioning** and select **OFFLINE FIRMWARE UPDATER**
* There you can generate an activation token needed when you flash the lopy4.
![](https://i.imgur.com/ZiW7PKE.png)


##### Flashing the lopy4
Download the [**Pycom firmware updater**](https://docs.pycom.io/updatefirmware/device/) and run it. When you reach the step seen in the figure below, make sure you select the "*Force update Pybytes registration*" checkbox.
![](https://i.imgur.com/aaYKVyO.png)
Moving forward will then show this screen where you need to enter the Pybytes activation token we aquired earlier!

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

---

### The code
To get the code onto the board we simply need to plug it in with the USB-cable and press the upload button found at the bottom of the console in VSC. The full code can be found on pastebin [**here**](https://pastebin.com/vM1Ji0SQ). To upload the code to the lopy4, press the upload button at the bottom of the VSC window: 
![](https://i.imgur.com/UUwtPd7.png)

Sometimes I had troubles flashing it, which led me to needing to hold the Safe boot button on the expansionboard and pressing the restart button on the lopy4. This would boot it in safe mode, indicated by orange light. Then you simply hit the upload button again and it should work.
![](https://i.imgur.com/sI6P3dX.png)
*The safe boot button*

The code is quite simple on its own and uses a while-loop that calls a function that checks the state of the sensor and switch and act accordingly.

```python=37
## Function for checking the state of triggers. 
def check_state(cleaningmode=False, presence=False):
    if clean_button() == 0:
        cleaningmode = True
    if pir() == 0:
        presence = True
    return (cleaningmode, presence)
```

```python=65
## Main loop
while True:
    if check_state() == (False, True):
        print("Presence detected, litterbox occupied")
        visits_since_start += 1
        visits_since_cleanup += 1
        red_led.value(1)
        while pir() == 0:
            time.sleep(safe_time) # A small stop that allows the sensor to retrigger if he is still there
        red_led.value(0)
        print("Presence gone, litterbox available")
        update_stats(visits_since_start, visits_since_cleanup, nr_of_cleanups)
        
    elif (check_state() == (True, False)) or (check_state() == (True, True)):
        startclean()
        while cleaning == True:
            if check_state() == (False, False):
                print("Cleaning mode disengaged")
                cleaned()
            elif check_state() == (False, True):
                print("Cleaning mode disengaging with cooldown")
                while pir() == 0:
                    time.sleep(safe_time)
                print("Cleaning mode disengaged")
                cleaned()
            else:
                time.sleep(5)
        update_stats(visits_since_start, visits_since_cleanup, nr_of_cleanups)
    time.sleep(2)
```

It uses a few variables to track the stats shown here:
``` python=17
## Starting values for variables
visits_since_start = 0
visits_since_cleanup = 0
nr_of_cleanups = 0
cleaning = False
```

#### Sending data to pybytes
To set up the dashboard, I'll be using the pybytes cloud services. Pybytes offers free storage for data for up to 1 MB of data. It can then be rolled over, saved locally or simply increased for a fee. It can also be pushed to other platforms through their APIs. It also allows you to set up a simple dashboard. Following the pybytes configuration done above, data can simply be set to be sent to pybytes with this simple line of code:
``` python
pybytes.send_signal(channel, data) # how you send data to pybytes
```
When you go to the pybytes page, on the device page under **SIGNALS** you can define these channels as seen in the picture below. ![](https://i.imgur.com/zyHgpNt.png)
Pressing the button **DEFINE NEW SIGNAL** will open up this box where you can enter an ID (1) for the signal, a name (2) and the unit (3) you want for it.
![](https://i.imgur.com/CsI4Q0m.png)

To send the data to pybytes you simply set the channel to the same ID you configured on pybytes. I my case, I made it so that data is sent every time the function "update_stats() is called". I call the function every time the litterbox is cleaned and every time the cat leaves it. Since that won't happen so often, I'm not to concerned about bandwitdh. The function also prints out in the console, but that is mostly for me to see when debugging. Lastly it light's a yellow LED if the litterbox has been used 4 times without cleaning.
```python=23
## Function for updating the stats on pybytes.
def update_stats(start=0,current=0,cleanups=0):
    pybytes.send_signal(1, start)
    pybytes.send_signal(2, current)
    pybytes.send_signal(3, cleanups)
    print("Updating stats")
    print("Litterbox has been used %d times since start" % (start))
    print("Litterbox has been used %d times since cleanup" % (current))
    print("Litterbox has been cleaned %d times since start" % (cleanups))
    if current > 3:
        yellow_led.value(1)
    else:
        yellow_led.value(0)
```
![](https://i.imgur.com/DFVvtSz.png)

As you can see on my pybytes page, I have set up channels 1-3 for this, Where the first one is the amount of times the litterbox has been used since start, second how many times since last cleanup and third how many times it has been cleaned since start.

## Assembly
With the code uploaded to the board we can begin to put it all together!
### Wiring
The breadboard isn't really needed if the ground wires are connected together. The easiest way would probably be to solder the cathods of the LEDs together and then only run one ground wire. The PIR-sensor could be connected directly to VIN and the ground wire connected to the same as the LEDs. What you see below is what I went for. This might change in the future when I 3D-print a case and expand upon the system with more functions.
![](https://i.imgur.com/YJGvbwt.png)
*Wiring overview*


For debuging purposes, the PIR can be replaced with a button going between ground and P20 That can be held in to simulate a presence. This allowed me to test the code itself without waiting for my cat to assist me by triggering the sensor. In my testing I also used a similar button for the cleaning. This can be seen in the picture below: ![](https://i.imgur.com/yiFuZek.png)
*Debugging setup*


### Mounting to litterbox
As this is a temporary setup while I make a case and evaluate the function, it is simply mounted with tape to the lid of the litterbox as shown below. I did however print a small fixture for the PIR so that it would sit at an angle. The file I printed can be found on [thingiverse](https://www.thingiverse.com/thing:291270). I did however need to cut out a part of the back for the wires. 
![](https://i.imgur.com/GRw7iya.png)
*The inside of the lid*
![](https://i.imgur.com/OdsE2yA.jpg)
*The top of the lid*

## Results
Overall I am pleased with the result as it has earned me a lot of experience and ideas for further improvements around the house. I also learned how to send data over WIFI, which I indend to make more sure of later on! As for the execution of the project, it could have gone better but sadly dividing my time between family, friends, work, this project as well as other courses has been hard.

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

As you can see from the picture above, a case is really needed! Right now the electronics sit exposed which might make the cat play with it or expose it to water! Seeing as the towels are mounted right behind it, this is a likely case and once I have collected enough data to make sure it works as intended I will remove it and rework it!

The dashboard will also require some more work to be useful, as seen in the next picture. The graphs are not so clear and doesn't really help much. I also lack enough data to show anything useful, as I havn't been able to run it for long. When I get the time to finish up on ubidots I will try to make a new dashboard.
![](https://i.imgur.com/76Z8vXG.png)

### Future improvements
For now, the usage of a PIR-sensor has proven difficult, both because of the device calibration it self and also because of the unviliingness of my cat to assist! If the litterbox has a cat door, I would instead fit it with either a magnet and hall effect sensor or vibration sensor to trigger the presence. An alternative might be to put one on a string infront of the entrance so that it gets bumped when entering/leaving.