/*
ESP32 IoT Project with MQTT
- publishes data from 2 DHT22 sensors and an ultrasonic sensor
- controls 3 LEDs (orange, pink, blue) via MQTT subscription
- uses EMQX broker for MQTT communication
- designed for wokwi web/wokwi for vscode
- work best on wokwi for vscode
created by: bhagaskara rafael w/ ♥
*/
#include <Arduino.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
#include <ArduinoJson.h>
// pin definitions
const int TRIG_PIN = 18;
const int ECHO_PIN = 19;
const int DHT1_PIN = 32;
const int DHT2_PIN = 33;
const int LED_ORANGE = 25;
const int LED_PINK = 26;
const int LED_BLUE = 27;
// wifi settings
const char *WIFI_SSID = "Wokwi-GUEST";
const char *WIFI_PASSWORD = "";
// mqtt settings
const char *MQTT_BROKER = "broker.hivemq.com";
const int MQTT_PORT = 1883;
const char *MQTT_CLIENT_ID = "glitchhunters";
const char *MQTT_USER = "";
const char *MQTT_PASSWORD = "";
const char *MQTT_TOPIC_SENSOR = "/glitchhunters/bhagaskara/data_sensor";
const char *MQTT_TOPIC_LED = "/glitchhunters/bhagaskara/aktuasi_led";
// initialize objects
DHT dht1(DHT1_PIN, DHT22);
DHT dht2(DHT2_PIN, DHT22);
WiFiClient espClient;
PubSubClient client(espClient);
// store previous sensor data
String prevData = "";
void setupWiFi()
{
Serial.print("connecting to wifi");
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED)
{
Serial.print(".");
delay(100);
}
Serial.println(" connected!");
}
float measureDistance()
{
// trigger the ultrasonic pulse
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
// measure the return pulse
float duration = pulseIn(ECHO_PIN, HIGH);
return duration / 58.0; // convert to centimeters
}
void handleMqttMessage(char *topic, byte *payload, unsigned int length)
{
// create a buffer for the payload
char message[length + 1];
memcpy(message, payload, length);
message[length] = '\0';
Serial.printf("got message on %s: %s\n", topic, message);
// parse json message
StaticJsonDocument<200> doc;
DeserializationError error = deserializeJson(doc, message);
if (!error)
{
// update led states
if (doc.containsKey("orange"))
{
digitalWrite(LED_ORANGE, doc["orange"].as<int>());
}
if (doc.containsKey("pink"))
{
digitalWrite(LED_PINK, doc["pink"].as<int>());
}
if (doc.containsKey("blue"))
{
digitalWrite(LED_BLUE, doc["blue"].as<int>());
}
}
else
{
Serial.println("couldn't process the message");
}
}
void reconnectMqtt()
{
while (!client.connected())
{
Serial.print("connecting to mqtt broker...");
if (client.connect(MQTT_CLIENT_ID, MQTT_USER, MQTT_PASSWORD))
{
Serial.println(" connected!");
client.subscribe(MQTT_TOPIC_LED);
}
else
{
Serial.print(" failed, rc=");
Serial.print(client.state());
Serial.println(" retrying in 5 seconds");
delay(5000);
}
}
}
void setup()
{
// initialize serial and pins
Serial.begin(115200);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
pinMode(LED_ORANGE, OUTPUT);
pinMode(LED_PINK, OUTPUT);
pinMode(LED_BLUE, OUTPUT);
// start sensors
dht1.begin();
dht2.begin();
// setup wifi and mqtt
setupWiFi();
client.setServer(MQTT_BROKER, MQTT_PORT);
client.setCallback(handleMqttMessage);
}
void loop()
{
// ensure mqtt connection
if (!client.connected())
{
reconnectMqtt();
}
client.loop();
// read sensor data
float temp1 = dht1.readTemperature();
float humidity1 = dht1.readHumidity();
float temp2 = dht2.readTemperature();
float humidity2 = dht2.readHumidity();
float distance = measureDistance();
// create json message
StaticJsonDocument<200> doc;
doc["temp1"] = temp1;
doc["humidity1"] = humidity1;
doc["temp2"] = temp2;
doc["humidity2"] = humidity2;
doc["distance"] = distance;
String message;
serializeJson(doc, message);
// publish if data changed
if (message != prevData)
{
Serial.printf("publishing: %s\n", message.c_str());
client.publish(MQTT_TOPIC_SENSOR, message.c_str());
prevData = message;
}
delay(1000);
}