IoT
WLAN
MQTT
FiPy
Pysense 2.0 X
MicroPython
Webhooks
Discord
Datacake
Date of publish: 2022-07-04
Author: Magnusson Millqvist, Hamlet (hm222vx)
Inquiries:
This tutorial presents a solution for notifying the user when they have forgotten to retrieve freshly heated coffee/tea (or any other heated beverage really) before it goes cold again. By only utilising a temperature sensor, programmable micro-controller, connection to the web, and an online database with ability to push webhooks!
This project was done as part of the course Applied internet of things at Linnaeus University, Sweden. All provided imagery, text, and code posted here is available free of use under a slightly modified MIT license provided further down. You are basically free to do whatever you want with any information found in this tutorial as long as you include a copy of the copyright and a mention of where you got it from! Just a thank you to 'Magnusson Millqvist' for providing the code for (this or that) is just fine by me.
This project should take no more than a few hours to set up. Creating the circuit and running the device is not the time-lengthy part. What takes the most time is setting up the webhooks and test-running everything.
This project tackles one the simple problems of an average computer programmer, forgetting your newly heated coffee (or other hot beverage)!
You see, dear reader, I have a tendency of forgetting that I've made coffee, continuing my work while letting the one beverage I enjoy the most cool down to lukewarm temperature. When entering the course in Applied internet of things and being asked to provide a solution to something, it dawned on me that this was the perfect opportunity to attempt solving my problem!
After some thinking and planing in my head I decided that I could easily build a solution with only the temperature sensor MCP9700
, which is one of the many provided sensor at the electrokit bundle available for the course. My plan was simple, by measuring the temperature at short intervals, I could easily determine the state my coffee machine is currently in. By determining my its states as either Cold
, Heating up
, Hot
, or Cooling down
and using simple logic triggering events on state changes, combined with the internal CPU clock, I could determine if my coffee has been standing hot for a prolonged period of time.
I decided that I would be notified of my forgetfulness via Discord, which is a chatting application I almost always have open. This could be solved either by making a completely new Discord bot, or by utilising webhooks. Due to the much easier nature of webhooks, I opted for the second one!
This project will hopefully display the ability to upgrade already existing devices to "smart devices" without the need of replacing them with smart equivalent.
I will take into account the realistic cost of this project, comparing it to that of replacing the old machine completely. While not throwing away old stuff is climate friendly and feels nice, it shouldn't cost you your pets, home, and one of your kidneys.
Part | Description | Price |
---|---|---|
FiPy (with headers) | Microcontroller | €35 - €50 |
Pysense 2.0 X | Expansion board | €40 - €50 |
Breadboard | Heavily simplifies the wiring process | €6 |
Micro USB cable | Power source | Comes with most exp. boards |
MCP9700 | Temperature Sensor | <€2 |
Breadboard wire | Power transmission medium | €4 (bundle) |
Any 3.3V temperature sensor should be capable of replacing the MCP9700. Just make sure that the mathematical formula used to calculate your temperature in the code is replaced with what your sensor's documentation says.
You could also go for most 5V sensors, but that would require additional changes to the wiring.
The FiPy is one of the more expensive microcontroller for it's built in LoRA- and other additional features. The ESP32, which also has WLAN integrated, should suffice for this specific project and has a pricetag of just €18 at some resellers, with programming board with similar prices.
Observe that the code in this project may not work due to differences in naming conventions of MicroPython between FiPy and ESP32!
Node.JS is a requirement for the development environment. Make sure to download one of the releases and installing it by following the installer step by step.
If you encounter issues with Node.JS not being found by your IDE, make sure that Node.JS is added to your PATH. How the path works varies between operative systems and I've made a brief tutorial on adding Node.JS for those unsure how to.
Make sure you have Node.JS before continuing to the next step! It sucks to be stuck for an hour or two just because you didn't read this!
There are several options for what IDE you can use. The three top contenders I know of are Thonny, VSCode and its Pymakr extention, or Atom and its Pymakr extention. I tested out all three of them and found that Atom was the most user friendly in my opinion. I'm more of a VSCode user as it's my primary editor, but the extention had both terrible reviews and honestly took a bit too much work to get running. Thonny was completely find to work with, but since Atom is very similar to VSCode and its got other extentions available I would recommend it over Thonny.
Atom announced that it has been discontinued in favour of VSCode, but, I would still recommend using Atom's implementation of Pymakr (for now) as it's a lot more stable and easier to use.
Just keep in mind that Atom has stopped receiving security updates.
The workflow in Atom Pymakr is extremely simple. You first create an empty directory anywhere on your computer. Open the folder with the Atom text editor. Add a file called main.py
in this folder, this will be the file that is run after booting. If you need to do anything during booting, add another file called boot.py
and have that code there.
Connect your microcontroller (connected to your expansion board!) and Atom should detect it automatically. This will open the RESP interface, allowing direct input through a terminal. You can test that the device is listening and ready by writing something with the following command: print("something")
. If it outputs "something" then the device is ready to go!
There's a handy GUI button that allows you to install your project into the microcontroller and rebooting it, but pressing Control + Alt + S is way faster. Wait for the flashing (that's what the project upload/installationis called) to complete and it will boot without you needing to confirm anything.
Make sure 3.3V, GROUND, and 5V are not connected to each other when the device is powered!
To be extra sure, disconnect all power form the device first, then set up the circuitry. Then, once you're ready to power it up, double-check, and then triple-check to make sure it's connected correctly! Then power the device.
The following picture shows the circuitry of the device. I've followed a simple standard for wire colouring and I recommend you doing the same! Blue is power (-), Red is ground (+), and Yellow is for all interconnected parts and signals. The power from the 3.3V rail go into the MCP9700 where the "magic happens" (I'm not going to go into depth how it works). The power that leaves through the out-pin is then the resulting signal that the MCP9700 outputs (see Image 1). That signal is then returned into the microcontroller pin, in my case P13
(see image 2 & 3). No more than 11 wires were needed to connect everything together.
Image 1: Hand-drawn pinout map of the MCP9700 sensor.
Image 2: Fritzing schematics of the device and circuits.
Image 3: Picture of the actual device.
For any sensor, you should always read how it works, from either a respected source or the device documentation itself!
Make sure that you are using the correct formula for the sensor you've chosen or you will get the wrong results.
The MCP9700 measures the room temperature by allowing a higher voltage through the output pin when warmer. The sensor is calibrated to 500 mV (millivolts) at 0°C (32°F in fake units) and has an accuracy of ±4°C. We are mostly interested in the data sheet section ADC (Analog to Digital Conversion) which tells us that each 10 mV above 500 is approximately 1°C, giving us the following formula:
: Measured pin voltage (mV)
: Actual temperature (°C)
: Estimated temperature (°C)
is measured to 870 mV
The temperature is between 33°C and 41°C but can be estimated to an average of 37°C.
I chose to use Datacake as my online platform. It was very simple to implement and did not require any programming skills, so mostly anyone can use it. The only negative aspect is that a maximum of 500 data points can be uploaded per day on the free version. I could have used Pybytes as you get access to it when buying a FiPy. I simply found Datacake to be sufficient and easy to use. I made sure to test out so that Datacake was capable of handling webhooks and tested sending a notification to my Discord webhook that I created, and everything worked as I wanted.
Before deciding on whether you want to use webhooks or not for Discord (if you're even going to use Discord), take a look at Intro to Webhooks by Discord themselves which explain in short what you can, and cannot do with webhooks.
If you are also planning on making a Discord webhook, I strongly advise going to the Discord developer pages and look at the API as I did!
For quickly assembling the basic message structure, I also recommend Discohook which helps you make the basic JSON message structure. Then use the above link to add additional functionality. I found this later on in development which would've been extremely handy earlier!
Every 5 seconds, the function updateSensorData
is called, reading the current temperature and determining the current machine status through some nested decision making. The sensor data is then printed to the REPL console.
A second function, doNotificationLogic
, determines if the machine status has changed. Basically, if the machine status has changed (e.g., COLD
-> HEATING UP
), then the publishing to Datacake is performed. Data is also sent to Datacake every 15 minutes even if no change has occured.
The microcontroller also keeps track of the previously published values. If a value has not changed, then it will not be published again. E.g., STATUS
will not be published unless it actually changes, same with TIME
and SEND_NOTIFICATION
. This both saves data, and help with Datacake, since it has a limited amount of publishes it supports per day.
The following table shows all variables published over MQTT to Datacake, and gives a short description of what each variable is for.
Variable | Datatype | Description |
---|---|---|
TEMPERATURE |
FLOAT |
The last recorded temperature. |
STATUS |
STRING |
The current coffee machine status. COLD , HOT , HEATING UP , COOLING DOWN |
TIME |
INT |
Seconds since the coffee machine status became HOT . If the status is instead COLD , it's reset to 0 . |
SEND_NOTIFICATION |
BOOLEAN |
If true , sends notification on Discord. Does not keep sending notifications, so it must first be set to false before being able to send a new notification. |
The microcontroller performes a quite simple setup sequence. It enables the WLAN (WiFi connectivity), connects to my local router, then finally sets up a connection over MQTT to Datacake.
While I find most of the code interesting (being the programming nerd with a degree in Informatics), I believe most of it isn't that interesting for you. For those who are actually interested in the full source code you can go to my
Here's the code pieces for reading the temperature. The maths are based on the ones presented in Reading the analog signal of MCP9700.
The following is what sends the MQTT information to Datacake.
Since the project is an upgrade of an already existing home appliance, there's little reason to make it battery dependent. There are power cords and electricity everywhere so just use that right? In other words, the project do not consider electrical usage on the same level as an IoT device disconnected from the power net. For connection to internet, WiFi is a very obvious choice for a home appliance. The WiFi covers my entire apartment, and the WiFi is barely used by more than a few devices, so there's little competition over the wireless connectivity. The WiFi is also a very stable solution. Finally, Bluetooth, which would also similar to WiFi for the above reasons, does have the problem that it needs another intermediate device that receives the Bluetooth signal, and this device must connect to the internet anyway, so why not skip that step and just connect this device to the internet directly?
The following is the visual presentation of the smart coffee machine. It contains history of temperature for both the last day and the last hour. It also shows the current status, the current temperature and the time since it became hot (or 0 if not hot). The data is stored for a week so if I wish to check on data prior to the current day I could look at the history tab for the device variables. Reasoning for using Datacakes own database is simple, it is already well connected with the device triggers as explained in Online Platform (Datacake).
Image 4: Data visualisation of the smart coffee machine.
Datacake allows setting up triggers, called "Rules", that can happend when certain criteria is met. Possible actions include sending emails and pushing webhooks. Image 4 shows how my webhook is set up.
Image 5: Rule implementation for sending Discord notification. API keys and user ID are redacted.
This rule is based on the stored variables that are sent from the micocontroller via MQTT
which can be seen on the following picture. Datacake calls all stored variables "fields". The SEND_NOTIFICATION
field is what was shown as trigger in the above rule.
The table under Image 5 shows exactly what each variable does.
Image 6: Saved fields on Datacake
And here's my home made smart coffee machine…
Ok, I'll be frank. It looks like something made by a terrorist in a film. But it does work! No, not as a bomb you stupid. It actually measures the temperature, decides the coffee machine's status and performes notification pushes to Discord, informing me whenever I've forgotten my amazing drink. For the future, I'm considering making some delicate dissection of my other coffee machine in an attempt at modifying it directly instead of having a secondary device attached to it.
Now, let's discuss money - No, not the type you give me, I'm not selling you anything! It would be interesting to know if is would be better to buy an already existing smart coffee machine or if bying an ESP32 or similar and attaching it would be cheaper.
So, googling "smart coffee machine" we get between €90 - €200 for the average user and over 400€ for the super advanced barista things. We're probably interested in the most simplest of styles, so I'm going in favour of the low price and say €100!
Bysing a set of wires ~€4, a breadboard ~€6, an ESP32 ~€10-€14 and an MCP9700 ~€2 comes to €26. A starter kit on Amazon is around €26 as well, this one for example.
In short, YES, if you have the time and patience, upgrading your already existing coffee machine is cheaper than buying a completely new coffee machine. But if you do not wish for the work associated, buying a basic smart coffee machine is completely doable too!
Image 7: The smart, but ugly smart coffee machine.
Copyright © 2022 Hamlet Magnusson Millqvist
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. Any material used must be presented together with a reference to either the publication source (https://hackmd.io/@hm222vx/SmartCoffeeMachine) , code source (https://github.com/hamletmillqvist/iot-fipy-my-smart-coffee-device), or the author (Magnusson Millqvist, Hamlet).
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.