1. Recap: MQTT Protocol Fundamentals
Before connecting the ESP32 to any cloud service, it's essential to remember the core building blocks of the MQTT protocol, since almost every IoT cloud platform (ThingSpeak, Adafruit IO, AWS IoT, etc.) is built around the same publish/subscribe model.
Figure 1 — Basic MQTT publish/subscribe flow between a device and a broker.
To use any MQTT-based service, you always need the following pieces of information:
- MQTT Broker address (server hostname)
- Username
- Password / API Key
- Topic name (usually username/feeds/feedname)
2. Introducing Adafruit IO
While ThingSpeak is a common choice for logging sensor data, this guide introduces an alternative cloud platform called Adafruit IO — a managed IoT service operated by Adafruit Industries (based in New York) that makes it extremely easy to build visual dashboards for IoT projects.
| Free Plan Feature | Limit |
|---|---|
| Number of accounts / dashboards | Free personal use allowed |
| Data rate | 1 data point every 2 seconds |
| Data storage | 30 days of history |
| Feeds | Up to 10 feeds on free tier |
| Automation | Basic "Actions" supported |
The platform can be accessed at io.adafruit.com and is suitable for both personal experimentation and light professional use.
3. Creating Your Adafruit IO Account
Follow these steps in order to create a free account:
- Open your browser and go to io.adafruit.com
- Click "Get Started for Free"
- Enter your First Name
- Enter your Last Name
- Choose a Username
- Choose a Password
- Submit the form to create your account
- Sign in with your new credentials
4. Creating Feeds
In Adafruit IO terminology, a Feed is equivalent to a "field" in ThingSpeak — it represents a single stream of data (for example, one sensor reading or one control value). For this project, three feeds are required:
Steps to create each feed
- Go to the "Feeds" section
- Click "New Feed"
- Type the feed name: temperature
- (Optional) Add a description
- Click "Create"
- Repeat the same steps for the feed: humidity
- Repeat the same steps for the feed: relay
5. Creating the Dashboard
A Dashboard in Adafruit IO is the visual interface where feed data is displayed and controlled in real time.
- Go to the "Dashboards" section
- Click "New Dashboard"
- Name the dashboard: ESP32 IoT Project
- (Optional) Add a description
- Click "Create"
- Open the newly created dashboard
At this point the dashboard is a blank canvas, ready for visualization blocks to be added.
6. Adding Visualization Blocks
Adafruit IO provides several block types: Gauge, Toggle, Slider, Line Chart, Stream, Text, Number, Color Picker, Icon, and more. This project uses four specific blocks.
6.1 Gauge Block — Temperature
- Click "Create New Block"
- Select block type: Gauge
- Connect it to feed: temperature
- Set title: Room Temperature
- Set minimum value: 0
- Set maximum value: 60
- Set low range: 0 to 20 (shown in blue)
- Set normal range: 21 to 34 (shown in green)
- Set high range: 35 and above (shown in red)
- Select a thermometer icon
- Click "Create Block"
Figure 2 — Gauge block with low (blue), normal (green), and high (red) color zones.
6.2 Gauge Block — Humidity
- Click "Create New Block"
- Select block type: Gauge
- Connect it to feed: humidity
- Set title: Humidity
- Set unit label: %
- Click "Create Block"
6.3 Toggle Block — Relay / Lamp Control
- Click "Create New Block"
- Select block type: Toggle
- Connect it to feed: relay
- Set title: Lamp
- Click "Create Block"
6.4 Line Chart Block — Temperature History
- Click "Create New Block"
- Select block type: Line Chart
- Connect it to feed: temperature
- Set title: Temperature Trend
- Click "Create Block"
Once all four blocks are created, use "Edit Layout" to resize and rearrange them so the dashboard looks clean and readable — this step is purely cosmetic and fully customizable.
7. Example ESP32 Code (Adafruit IO via MQTT)
The following sketch demonstrates the generic MQTT connection pattern described earlier: the ESP32 publishes temperature and humidity readings, while subscribing to the relay feed to control a lamp. This structure is not limited to Adafruit IO — the same pattern applies to virtually any MQTT broker.
#include <WiFi.h>
#include <Adafruit_MQTT.h>
#include <Adafruit_MQTT_Client.h>
#include <DHT.h>
#define WLAN_SSID "YOUR_WIFI_SSID"
#define WLAN_PASS "YOUR_WIFI_PASSWORD"
#define AIO_SERVER "io.adafruit.com"
#define AIO_SERVERPORT 1883
#define AIO_USERNAME "YOUR_ADAFRUIT_IO_USERNAME"
#define AIO_KEY "YOUR_ADAFRUIT_IO_KEY"
#define DHTPIN 4
#define DHTTYPE DHT22
#define RELAYPIN 5
DHT dht(DHTPIN, DHTTYPE);
WiFiClient client;
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
Adafruit_MQTT_Publish temperatureFeed = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/temperature");
Adafruit_MQTT_Publish humidityFeed = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/humidity");
Adafruit_MQTT_Subscribe relayFeed = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/relay");
void setup() {
Serial.begin(115200);
dht.begin();
pinMode(RELAYPIN, OUTPUT);
WiFi.begin(WLAN_SSID, WLAN_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("WiFi connected");
mqtt.subscribe(&relayFeed);
}
void MQTT_connect() {
if (mqtt.connected()) return;
Serial.println("Connecting to MQTT...");
while (mqtt.connect() != 0) {
delay(2000);
}
Serial.println("MQTT connected");
}
void loop() {
MQTT_connect();
Adafruit_MQTT_Subscribe *subscription;
while ((subscription = mqtt.readSubscription(1000))) {
if (subscription == &relayFeed) {
int relayState = atoi((char *)relayFeed.lastread);
digitalWrite(RELAYPIN, relayState);
Serial.print("Relay set to: ");
Serial.println(relayState);
}
}
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
temperatureFeed.publish(temperature);
humidityFeed.publish(humidity);
Serial.print("Temperature: ");
Serial.println(temperature);
Serial.print("Humidity: ");
Serial.println(humidity);
delay(5000);
}
8. What's Next?
At this stage, the Adafruit IO account, feeds, and dashboard are fully configured, and the ESP32 sketch is ready to connect. The next step — covered separately — is wiring the DHT sensor and relay module to the ESP32 and verifying that live data flows correctly from the device to the cloud dashboard and back.
Figure 3 — Complete system: sensor → ESP32 → cloud dashboard → relay actuation.