Project Schrodinger is a device that uses increasingly rude reminders to tell me to clean my cat's litter box. Litter box uses are detected using an ultrasonic sensor, and a night vision camera takes a picture of the litter box to let the me know how dirty it is (a delay is used to protect feline privacy). I developed the LitterBox Android app, which can be used to monitor litter box usage and configure settings for the device.
Physical componentsThe electronics of the project consist of a Raspberry Pi 3B, an ultrasonic sensor connected using a breadboard, and a night vision camera. I got the circuit for the ultrasonic sensor from this article.
I used the RPi.GPIO Python library to read data from the ultrasonic sensor. This involves sending out high frequency sound from one side of the sensor, and then recording the amount of time until the sound echoes back to determine the distance to an object.
def distance():
GPIO.output(GPIO_TRIGGER, True)
time.sleep(0.00001)
GPIO.output(GPIO_TRIGGER, False)
StartTime = time.time()
StopTime = time.time()
while GPIO.input(GPIO_ECHO) == 0:
StartTime = time.time()
while GPIO.input(GPIO_ECHO) == 1:
StopTime = time.time()
TimeElapsed = StopTime - StartTime
distance = (TimeElapsed * 34300) / 2
return distance
To use the camera, I first had to enable it in the raspi-config settings. I am using a legacy version of the Raspberry Pi OS (Raspbian Buster) in order to support this particular camera, as the camera software has changed in recent releases. I'm using the PiCamera Python library to take pictures within the monitoring script. The images are saved with a name corresponding to the date and time at which they were taken so they can be accessed later (more on the software in the second section).
def take_picture(dt_string):
camera = PiCamera()
camera.capture("./images/" + dt_string + ".png")
camera.close()
The electronics are protected from potential contaminants by a cardboard enclosure. This is the first version of the case, which was made from several pieces of cardboard hot glued together:
This case wasn't very sturdy, so I decided to make a new version by folding up one piece of cardboard. I found that the best way to make the folds is to cut halfway through the cardboard and add hot glue to make the folds keep their shape.
The device is positioned so that the ultrasonic sensor creates a line that the cat must cross to enter the litter box, which allows for reliable detection, since the ultrasonic sensor makes accurate distance measurements to objects directly in front of it. The enclosure holds the camera at a downward angle so that it is looking at the litter box from where the device is positioned (it may have been more convenient to get a longer ribbon cable instead).
Yes, the litter box is in a bathtub. Don't question it.
After assembling the hardware and testing the sensor and camera, the next step was to start working on the details of the code running on the Raspberry Pi. I wrote all code for the device in Python, as I found it to be the most convenient for this use case. I did most of my coding on other devices and transferred the code using Git by connecting to the Pi through SSH.
The first step was to make sure the sensor could reliably detect litter box uses without setting off false alarms. The monitoring script polls the sensor each second and compares the measurement to a distance threshold value. I designed the script so that the sensor has to be triggered a certain number of times within a certain time interval in order to register a single litter box use, which prevents the occasional inaccurate sensor measurement from setting off the device. The device then waits 10 minutes before being able to register another litter box use to prevent counting the same one multiple times.
My original plan for the project was to have the device just send text messages to remind me to clean the litter box, which I accomplished using the Twilio API. (I had some free API credits from the GitHub student developer pack). However, a slight drawback here is that you still get a "Twilio trial account" message added to the beginning of your message, but this was fine for my prototype.
The first small roadblock was the fact that Twilio only accepts images as URLs, which required creating a simple flask server (also written in Python) running on the Pi to send the images to Twilio. To make the server accessible to the internet, you could use a service like ngrok, which provides a public URL that corresponds to a server running on localhost. However, the free version of ngrok changes the URL every time the server is started, which isn't ideal. Instead, I set up port forwarding on my home router, which makes the Pi server publicly accessible so that it can be used by Twilio.
The first version of the project would always start sending messages after three litter box uses, sending a harsher reminder with each additional litter box use:
Instead of adding a button to reset the device, I decided to have the user text "Clean" to reset the counter, which also pauses the sensor for a few minutes to prevent it from being triggered while cleaning. Reading incoming messages through Twilio required adding another endpoint to the flask server and supplying the URL in the Twilio console.
After finishing the essential features, I decided it would be cool to track stats about when the litter box was used and how often it was cleaned to give the user a sense of how good of a cat owner they are. To do this, I set up an SQLite database that records the dates and times of all uses and cleanings. The user can get stats by texting "Stats" to the device. I also added a feature where the owner can text "Name [cat name]" to receive messages that are personalized to the cat's name.
After adding these features through text messaging, I decided that it would be more convenient to monitor the device through a mobile app. I already had a flask server and database set up, so on the device/server side I just had to add a few API endpoints to fetch litter box data.
The app allows the cat owner to view a history of all litter box uses and cleanings along with pictures of the litter box. The app includes the same cleaning feature from the SMS system, which pauses the sensor for cleaning and resets the counter. It also provides the same stats from the text messaging system, including uses since the last cleaning, average uses before cleaning, and average uses per day, in a more convenient format. The app lets the owner configure settings, including the cat name, phone number, sensor distance threshold, and reminder settings all in one place.
The system still sends reminders through text messages, and all text message features continue to work as alternatives to the app, but a possible future improvement could be to send push notifications through the app instead, or allow the user to choose between text messaging and push notifications.
In summary, the final structure of the project looks something like this, with two python scripts on the backend side (one for sensor monitoring and one for the server) along with Twilio and the LitterBox app for interacting with the user:
For the final product, I set up cron (a linux utility that automatically runs commands) on the raspberry Pi to run the monitoring script and server at startup, so all I have to do is plug in the device and everything should start working. Because the project now runs off of a database, losing power will not erase the counter or any other information. The mobile app currently requires the device to be running to display data, but another possible improvement would be to cache data from the API.
Video demo
Source code
All code for the project is available in the two linked GitHub repos (LitterBox is the repo for all code running on the pi and LitterBoxApp contains the source for the Android app).
Comments
Please log in or sign up to comment.