Description
This project demonstrates a wireless electromechanical relay controlled by a virtual toggle switch control on Machinechat’s JEDI Pro dashboard. The wireless relay hardware consists of a ESP32 microcontroller board and a Seeed Grove relay. The ESP32 subscribes to a topic on the MQTT broker running on Machinechat JEDI Pro and changes the Grove relay state depending on the topic value. The MQTT topic subscribed to is the value of a virtual toggle switch control on JEDI Pro’s dashboard. Arduino is used to implement the ESP32 relay application and JEDI Pro is installed and running on a Seeed Odyssey Blue x86 Mini PC running Ubuntu Linux.
Hardware
- Seeed Odyssey Blue x86 Mini PC
Quad Core Celeron J4105 Mini PC with 128GB external SSD - DFRobot Beetle ESP32C3
Beetle ESP32-C ESP32-C3 (version 2) Transceiver; 802.11 a/b/g/n (Wi-Fi, WiFi, WLAN) 2.4GHz Evaluation Board - Seeed Grove Relay
Electromechanical Relay Grove Platform Evaluation Expansion Board
Software
- JEDI Pro
Adaptable software for IoT data collection, visualization, monitoring and data storage that can be integrated into IoT solutions. Capabilities include: collect data from sensors, devices and machines; build intuitive real-time and historical data and system view dashboards; create rules to monitor and respond to data conditions automatically; receive alert notifications by email and SMS. - Arduino
Arduino is an open-source electronics platform based on easy-to-use hardware and software.
Background
Machinechat JEDI Pro is IoT application software that is able to collect data from multiple sources including HTTP, serial, LoRaWAN, MQTT and internal. Collected data can be visualized, stored, acted upon and accessed via the MQTT broker running on JEDI. JEDI MQTT topics include all data coming into JEDI from any source (not just MQTT).
In version 3.1, JEDI introduced an ability to add controls to data dashboards. With a control, a user can input a value via a dashboard graphic which is then saved into a predefined data metric. The resulting data metric can be accessed over the MQTT broker running on JEDI (see Machinechat article Adding Controls to Data Dashboards )
Implementation
The project uses a Beetle ESP32C3 module and a Grove electromechanical relay board to implement a WiFi enabled relay. An Arduino PubSub library is utilized to implement a MQTT client on the ESP32 module. The ESP32 client subscribes to a virtual toggle switch value on JEDI and changes state of the relay (open/closed) dependent on the switch value.
Below schematic and associated BOM can be accessed at Scheme-it project link BeetleESP32relay.
Set up the ESP32 based WiFi relay Arduino application
1 - Set up Arduino on the Beetle ESP32C3 module. See link Beetle ESP32C3 Wiki link
2 - Install libraries needed for application. Add these libraries thru Arduino’s Library Manager:
3 - Code walkthrough (filename: BeetleESP32cMqttRelay1.ino)
Connect to WiFi network, connect to JEDI MQTT broker and parse JSON MQTT messages
/*
WiFi/MQTT enabled relay example implemented on DFRobot Beetle ESP32C3
filename: BeetleESP32cMqttRelay1.ino
project hardware: DFRobot Beetle ESP32C3 board and Seeed Grove Relay board
project function: ESP32 mqtt client connects to the Machinechat MQTT broker and subscribes to multiple topics (including a
virtual toggle switch on the JEDI data dashboard with two states "true" and "false").
The virtual toggle switch value topic is monitored and used to control the state of the relay.
*/
#include "WiFi.h"
#include <WiFiClient.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include "arduino_secrets.h"
// Update these with values suitable for your network.
char ssid[] = SECRET_SSID; // your network SSID (name)
char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP)
// MQTT server info for JEDI Pro on Odyssey Ubuntu machine
const char* mqttServer = "192.168.1.23";
const int mqttPort = 1883;
StaticJsonDocument<256> doc;
int led = 10;
int data1 = 5; //data1 of MQTT json message
int data2 = 5; //data2 of MQTT json message
int data3 = 5; //data3 of MQTT json message
int data4 = 5; //data3 of MQTT json message
bool button = true; //boolean variable of MQTT message
int msg = 0;
const char* timestamp = "dummy data"; //the is the MQTT message timestamp (this works)
String recv_payload;
const char* subtopic1 = "datacache/Button1boolean"; //test button control
const char* subtopic2 = "datacache/SeeedLoRaE5sensorTwo"; //LoRaE5 temp humidity sensor
const char* subtopic3 = "datacache/A84041F1B186136D"; //LHT65N garage temp humidity sensor
// wio terminal wifi
// Beetle esp32c3 wifi
WiFiClient wclient;
PubSubClient client(wclient); // Setup MQTT client
void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
randomSeed(micros());
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
// mqtt message callback
void callback(char* topic, byte* payload, unsigned int length) {
//print out message topic and payload
Serial.print("New message from Subscribe topic: ");
Serial.println(topic);
Serial.print("MQTT payload length = ");
Serial.println(length);
Serial.print("Subscribe JSON payload: ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]); // print mqtt payload
//if payload[i] == "t"
}
Serial.println();
msg = 1; //set message flag = 1 when new subscribe message received
//check subscribe topic for message received and decode
//********************************//
//if message from topic subtopic1
//********************************//
if (strcmp(topic, subtopic1)== 0) {
Serial.print("decode payload from topic ");
Serial.println(topic);
deserializeJson(doc, (const byte*)payload, length); //parse MQTT message
button = doc["value"]; // boolean button value
Serial.print("Button boolean value = ");
Serial.println(button);
//control state of relay
if (button == 1)
{
digitalWrite(led, HIGH);
digitalWrite(6, HIGH);
delay(100);
}
else
{
digitalWrite(led, LOW);
digitalWrite(6, LOW);
delay(100);
}
}
//********************************//
//if message from topic subtopic2
//********************************//
if (strcmp(topic, subtopic2)== 0) {
Serial.print("decode payload from topic ");
Serial.println(topic);
deserializeJson(doc, (const byte*)payload, length); //parse MQTT message
data1 = doc["temperature"];
data2 = doc["humidity"]; //
Serial.print("data1 is LoRaE5 temperature = ");
Serial.println(data1);
Serial.print("data2 is LoRaE5 humidity = ");
Serial.println(data2);
}
//********************************//
//if message from topic subtopic3
//********************************//
if (strcmp(topic, subtopic3)== 0) {
Serial.print("decode payload from topic ");
Serial.println(topic);
deserializeJson(doc, (const byte*)payload, length); //parse MQTT message
data3 = doc["TempF"];
data4 = doc["Hum_SHT"];
Serial.print("data3 = TempF = ");
Serial.println(data3);
Serial.print("data4 = Hum_SHT = ");
Serial.println(data4);
}
}
//connect to mqtt broker on JEDI One and subscribe to topics
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Create a unique client ID using the Wio Terminal MAC address
String MACadd = WiFi.macAddress();
MACadd = "WioTerminal" + MACadd;
String clientID = MACadd;
// Attempt to connect
if (client.connect(clientID.c_str())) {
Serial.println("connected");
// set up MQTT topic subscription note: topic needs to be "datacache/" + Device on JEDI One
Serial.println("subscribing to topics:");
Serial.println(subtopic1);
client.subscribe(subtopic1);
Serial.println(subtopic2);
client.subscribe(subtopic2);
Serial.println(subtopic3);
client.subscribe(subtopic3);
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void setup() {
pinMode(led,OUTPUT);
//pinMode(7, INPUT); //switch input
pinMode(6, OUTPUT); //relay control input
Serial.begin(115200);
setup_wifi();
client.setServer(mqttServer, 1883); //set mqtt server
client.setCallback(callback);
}
Main loop checks if connected, checks for MQTT messages and updates Grove Relay board state
void loop() {
// try reconnecting to WiFi if not connected
if (WiFi.status() != WL_CONNECTED) {
Serial.println("not connected to WiFi, try reconnecting");
WiFi.disconnect();
delay(5000);
setup_wifi();
}
// check if connected to mqtt broker
if (!client.connected()) {
reconnect();
}
if (msg == 1) { // check if new callback message
msg = 0; // reset message flag
}
Serial.println("debug - in main loop");
delay(1000);
client.loop();
}
4 - Example Serial Monitor output from Arduino code when subscribed to MQTT topic
Several Print statements have been inserted in the example Arduino code to help during debug and code modifications. Example serial monitor output when subscribed topic received is shown below.
5 - Latest source code for the BeetleESP32cMqttRelay1.ino application is on github at below link:
Installing JEDI Pro
If Machinechat JEDI is not already installed see below:
Getting Started with machinechat’s JEDI One IoT Platform
JEDI MQTT Broker - Subscribing to a topic
JEDI topics include all data coming into JEDI One from any source. From within the MQTT client code or application, subscribe to a topic as follows:
For a specific data stream:
datacache/TargetID
Where datacache is the fixed, top level topic from JEDI One, and TargetID is the TargetID or IP address of the data stream of interest.
For this project example:
datastream will be datacache/Button1boolean
mqttServer is 192.168.1.23
mqttPort is 1883
(note: for additional info see Machinechat article Adding Controls to Data Dashboards )
Setting up JEDI Pro
1 - When creating a control, a data metric needs to be created to hold the value from the control. Select Device Dashboard from the navigation panel on the left side of JEDI
2 - Add Data Source
3 - Add Control JEDI dashboard
4 - Add virtual toggle switch to JEDI dashboard
5 - Example JEDI virtual toggle switch control.
Conclusion
A flexible and capable WiFi enabled electromechanical relay is easily implemented with two small development boards, a DFRobot BeetleESP32 module and a Grove Relay board. Virtual toggle switch control of the WiFi relay is implemented using the control capabililty of the JEDI data dashboard and JEDI’s MQTT broker. An MQTT client running on the ESP32 provides MQTT control of the WiFi relay by a virtual toggle switch control on the JEDI data dashboard. Machinechat’s JEDI IoT data management provides MQTT access to any data it is collecting as well as additional processing, alerts or other actions as required.
References
- DFRobot - Beetle ESP32C3 Wiki link
- Seeed - Grove Relay Product Page
- Seeed - Grove Relay Wiki Page
- Getting Started with machinechat’s JEDI One IoT Platform
- Arduino - How to use ArduinoJson with PubSubClient?
- Machinechat Product Guide - Built In MQTT Broker - Data Collector
- Machinechat Product Guide - MQTT Broker - Subscribing to a topic
- HIVEMQ - MQTT Essentials
- Machinechat Article - Adding Controls to Data Dashboards