---
# System prepended metadata

title: 'Coffee & Climate: A Raspberry Pi Pico WH Sensing System'

---


# Coffee & Climate: A Raspberry Pi Pico WH Sensing System

Elias Svensson - es277fn

In this project, I have built a multifunctional IoT system using a Raspberry Pi Pico WH that monitors environmental conditions and interacts with the user. The system includes two main parts: a humidity and temperature sensor placed near plants to monitor their environment, and a separate temperature sensor for a coffee mug. The mug sensor can be toggled on or off via a button, with its temperature range indicated by an RGB LED, and a piezo buzzer alerting when the optimal temperature is reached. A status LED blinks periodically to show the system is active. All three sensor values (ambient temperature, humidity, and coffee mug temperature) are sent via MQTT over Wi-Fi to the Adafruit IO broker. An Adafruit IO dashboard is used to display the latest values and visualize historical data through graphs for the past day.

This project should take around 3-7 hours to complete depending on previous experience with microcontrollers, circuitry, and programming.


## Objective

I chose this project because I was curious about how the environment around my plants changes throughout the day, particularly in terms of temperature and humidity. At the same time, I often drink coffee in the morning and find it either too hot to enjoy right away or forget about it until it’s gone cold. I wanted a simple way to be alerted when the coffee reaches the ideal drinking temperature. Additionally, I was interested in experimenting with multiple types of sensors and integrating them into a single system.

This setup can provide useful insights into the daily environmental conditions near my plants and how quickly my coffee cools under different circumstances, helping me better understand and respond to both over time. Additionally, it provides a great opportunity to familiarize oneself with IoT.

## Material
[Start Kit]: https://www.electrokit.com/lnu-starter
[Sensor Kit]: https://www.electrokit.com/sensor-kit-25-moduler

Below is a table of the components I used. Included is also the sensor kits they are part of ([Start Kit] - 349 SEK, [Sensor Kit] - 299 SEK) in case you prefer to buy this instead of the individual components:

| Component | Kit | Individual Link | Individual Price |
| --- | -------- | -------- | -------- |
| Raspberry Pi Pico WH | [Start Kit] | [Electrokit](https://www.electrokit.com/raspberry-pi-pico-wh) | 99 SEK |
| DHT11 | [Start Kit] | [Electrokit](https://www.electrokit.com/temp/fuktsensor-dht11) | 39 SEK |
| Red LED | [Start Kit] | [Electrokit](https://www.electrokit.com/led-5mm-rod-diffus-1500mcd) | 10 SEK (for two) |
| Passive Piezo Buzzer | [Sensor Kit] | [Electrokit](https://www.electrokit.com/piezohogtalare-passiv) | 29 SEK |
| RGB LED | [Sensor Kit] | [Electrokit](https://www.electrokit.com/led-modul-rgb-smd) | 23 SEK |
| Button | [Sensor Kit] | [Electrokit](https://www.electrokit.com/tryckknapp-momentan) | 19 SEK |
| DS18B20 Temperature Sensor | [Sensor Kit] | [Electrokit](https://www.electrokit.com/temperatursensor-ds18b20) | 42 SEK |

Additionally, a breadboard, three $330 \Omega$ resistors, some jumper wires and a USB-A to micro USB cable are needed. These are found in the [Start Kit], or can be purchased separately.

I also used a small box I had lying around and some tape to make a holding structure for the coffee monitoring system (as you will see in the project result pictures), though this is not really necessary.

### Raspberry Pi Pico WH

![PICO-WH-HERO](https://hackmd.io/_uploads/SyFqFbHSxx.jpg)

The Raspberry Pi Pico WH is a compact microcontroller board that includes built-in Wi-Fi, enabling wireless communication. It is powered and programmed via a micro-USB port, which allows code to be uploaded directly from a computer. The board features a range of pins with different functions: some provide power or ground, while others serve as GPIO (General Purpose Input/Output) pins used to connect and control external electronic components.

### DHT11

![41016231](https://hackmd.io/_uploads/BJmit-SBee.jpg)

A temperature and humidity sensor.

### Passive Piezo Buzzer

![41db_41015713-2](https://hackmd.io/_uploads/HyInKWSHxe.jpg)

A buzzer that can play frequencies from $1.5$Hz - $2.5$ kHz.

### RGB LED

![41015716](https://hackmd.io/_uploads/SkoCFZHHge.jpg)

An LED module that can display different colors by controlling the red, green, and blue intensities individually.

### Button

![41015723](https://hackmd.io/_uploads/ByYkq-rHxl.jpg)

A push button which signals if it is pressed down or not.

### DS18B20 Temperature Sensor

![41015731](https://hackmd.io/_uploads/Byul9bBHge.jpg)

Measures temperature. This component has a wider working temperature window and a greater accuracy than the DHT11 temperature sensor.


## Computer setup

I chose to use the [Thonny](https://thonny.org/) IDE for this project. The Raspberry Pi Pico WH runs MicroPython firmware, which allows for easy scripting and interaction. Code is uploaded directly from my personal computer to the Pico WH via a USB-A to micro-USB cable.

Setting up the environment is straightforward: simply install [Thonny](https://thonny.org/) on your computer, connect Pico WH using the USB cable, then open Thonny and navigate to Tools $\rightarrow$ Options $\rightarrow$ Interpreter. From there, select "MicroPython (Raspberry Pi Pico)" as the interpreter. Once configured, you can write and run code on the Pico WH directly from the Thonny interface. 

To make a program run without starting it directly from your computer, simply name the code file "main.py" and it will execute whenever your Pico WH is powered on.

## Putting everything together

![Untitled](https://hackmd.io/_uploads/rkVZcZrBll.jpg)

This is a figure of the circuitry created with [WokWi](https://wokwi.com/). There are however some caveats here:

- In the [Sensor Kit] manual, they recommend the following resistance for the modules in the RGB LED to prevent burnout:
    - Red: $180\Omega$
    - Green: $100\Omega$
    - Blue: $100\Omega$

However, I did not have access to these, so I tried with the $330\Omega$ resistors you see in the figure, and it works well.
- The DHT11 sensor is not available in WokWi, hence the DHT22 is used in its place (it has one more leg than the DHT11, but simply ignore the rightmost leg).
- The RGB LED looks slightly different to the real one. The legs in the figure correspond to (from left to right) red, ground, green, blue.
- The real push button has only three legs. I thus chose the legs in the figure signify:
    - Top right leg - Signal
    - Top left leg - Power
    - Bottom left leg - Ground
- You can see what pins the different components correspond to further down, where they are defined in the code.

The setup in terms of its looks and the improvised holding structure for the coffee monitoring system (which you will see in the final pictures) makes this lean towards a development setup. But besides this, I don't see any issues besides tidying up the wires and making a case for the setup in order to make it more "commercially friendly".


## Platform
I chose to use Adafruit IO for both the MQTT broker and the dashboard. The free tier is well-suited for this project, offering up to 30 messages per minute and 30 days of data retention -- more than sufficient for monitoring a few sensors. However, for scaling up this project to applications involving more sensors or higher data frequency, it may be necessary to consider a paid plan or explore self-hosted MQTT solutions.

The Adafruit IO dashboard is easy to set up and use, making it ideal for quick prototyping and basic visualization. That said, it offers limited customization options. For more advanced features or a more polished and flexible user interface, alternative platforms may be worth considering. More information on using this dashboard is given in the "Presenting the data" section.

## The code
This project contains several components, and the codebase is too extensive to go through it all in detail (The complete code has been uploaded to https://github.com/Eliassve/IoT_Project). In this section, I’ll walk through the core logic and explain the ideas behind the main parts of the implementation.

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

The script begins by importing the necessary libraries and functions. Notably, send_mqtt_message -- a function defined in a separate file -- handles communication with the MQTT broker. This function will be discussed in the next section.

Following the imports, the hardware components are initialized by assigning them to their respective GPIO pins.

The program runs continuously in a while loop, executing every 5 seconds. A "heartbeat" LED (referred to as the process-alive LED) indicates that the program is running by blinking once every 15 cycles (i.e., every 75 seconds).

The loop handles two primary tasks:
- Ambient temperature and humidity measurement
- Coffee temperature monitoring (only active when enabled)

Ambient temperature and humidity are measured every five minutes. This is managed by checking the current time and ensuring that a measurement hasn’t already been taken in the current minute. When it’s time, the ambient_measurement() function is called, which reads values from a DHT11 sensor and sends the results to the appropriate MQTT feeds.

![AMB_msmt](https://hackmd.io/_uploads/HJ3m5-BHxg.png)

The coffee temperature logic is more involved. A push-button is used as a toggle switch to activate or deactivate coffee monitoring. This is handled using a binary flag that flips its state on each button press.

When monitoring is active, the coffee temperature is measured on each 5-second cycle using the measure_coffee_temp() function.

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

The temperature reading is sent to an MQTT feed, and based on the current value, the RGB LED indicates the coffee's heat level:

$T > 44$°C $\rightarrow$ Red LED active

$45$°C $> T > 42$°C $\rightarrow$ Green LED active

$43$°C $> T$ $\rightarrow$ Blue LED active

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

To prevent false "coffee ready" signals during the transient warm-up period of the mug and sensor, a historical trend analysis is used:
- A temperature_history array stores the 12 most recent readings.
- The average of the first 6 readings is compared to the average of the last 6.
- If the temperature is within the optimal window ($T \in [42,45]$°C) and is decreasing over time (indicated by the historical trend), the coffee is considered “ready”.

This approach filters out transient conditions where the temperature might briefly pass through the optimal range during warm-up but isn’t actually stable.

To avoid repeatedly triggering the "ready" indication when the temperature hovers near the threshold, a boolean flag ensures that the alert is only played once per cup of coffee. The toggle button must be turned off and back on again to reset this state.

When the coffee is ready, a buzzer plays a short tune (you can implement this by finding the tune notes, what frequencies they correspond to, and the note durations). Alternatively, a simple buzz is enough to alert the user.

## Transmitting the data / connectivity
As described in the previous section, ambient measurement data is collected and sent every 5 minutes, while coffee temperature is monitored and sent every 5 seconds -- but only when coffee monitoring mode is enabled.

The Raspberry Pi Pico W connects to WiFi using the following function:

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

Here, "ssid" refers to your WiFi network name, and "password" is your network password.

Data is transmitted via the Adafruit MQTT broker using the function below:

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

In this function, you also need to specify your Adafruit username and IO key. The function sends the provided "message" to the selected "feed" on Adafruit IO. Note: With the free Adafruit plan, you're limited to 30 messages per minute, so keep this in mind when designing your data frequency.

## Presenting the data

I'm using the Adafruit IO Dashboard, which is very straightforward to set up -- just create a new dashboard, add the desired blocks (e.g., gauges, charts, or indicators), and link each block to the appropriate feed.

Below is a screenshot of my current dashboard, captured shortly after making a fresh cup of coffee. You can clearly see the initial transient period in the coffee temperature data, which underscores the need for the historical trend analysis described earlier.

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


With Adafruit's free plan, data is retained on their servers for up to 30 days.

## Finalizing the design
Here are some photos of the final setup, both on its own and in its intended location:

![IMG_9097-min](https://hackmd.io/_uploads/H1199ZrBxl.jpg)
![IMG_9098-min](https://hackmd.io/_uploads/Bk15cWHSxe.jpg)
![IMG_9099-min](https://hackmd.io/_uploads/H1J55WHHeg.jpg)
![IMG_9100-min](https://hackmd.io/_uploads/BJJc5bBSex.jpg)
![IMG_9101-min](https://hackmd.io/_uploads/B1k55WrSxg.jpg)

To keep the coffee temperature sensor and push button in place, I used a box and some tape. This isn’t strictly necessary, but it makes setup easier and keeps the sensor reliably positioned close to the mug.

![IMG_9102-min-min](https://hackmd.io/_uploads/SkQT5WSrgl.jpg)

Here’s the system in action -- with my coffee mug (don’t ask how I ended up with transparent coffee! 😆).

Potential improvements and future additions include:
- Upgrade the ambient temperature sensor: The DHT11’s low temperature resolution results in a blocky-looking temperature graph, as it mostly toggles between 24°C and 25°C. A higher-resolution sensor would improve the granularity of ambient data.
- Improve coffee temperature accuracy: Replacing the current sensor with one that can be submerged in the coffee would give a more accurate reading of the actual coffee temperature (rather than the mug's surface temperature). It would also improve thermal contact, reducing the warm-up time and shortening the transient period.
- Use a physical switch instead of a push button: While the push button toggle works fine via software, a physical switch would simplify both the code and the user interface.
- Explore self-hosting: Hosting my own MQTT broker and dashboard could eliminate limitations on message frequency and data retention, and allow more customization than Adafruit IO offers.

Lessons Learned and Challenges Encountered:
- Adafruit message rate limit: I initially didn’t realize the free Adafruit IO plan only allows 30 messages per minute, which caused my program to crash unexpectedly. Once I discovered the limit, I implemented error handling using a try block and reduced the message rate to stay within bounds.
- Poor sensor placement: At first, I tried placing the coffee temperature sensor directly above the coffee rather than in contact with the mug. This led to a much longer transient period, reduced sensitivity to cooling, and overall less reliable data. Mounting the sensor directly against the mug dramatically improved performance.
- High thermal mass mug: My first mug was quite thick, meaning it had a high thermal mass and absorbed a lot of the coffee’s heat before reaching thermal equilibrium. This often caused the coffee to already be cooling past the optimal window before the sensor caught up. Switching to a thinner mug helped reduce this heat loss and significantly shortened the transient period.
- False "ready" signals during warm-up: Even with better mug contact, I still experienced premature “coffee ready” alerts as the sensor temperature passed through the target range during warm-up. To solve this, I implemented a temperature history analysis -- comparing the trend of recent measurements -- to ensure the temperature is falling (i.e., stabilizing) before triggering the alert.