The circuit in question is designed to control an 8-channel relay module using an MCP23017 I/O expander, which is interfaced with an ESP8266 microcontroller. The ESP8266 is responsible for connecting to a Wi-Fi network and communicating with an MQTT server to receive commands for controlling the relays. The MCP23017 expands the limited number of GPIOs available on the ESP8266 to control more devices, in this case, the relays. The relays are actuated by toggle switches connected to the MCP23017, and their state can be remotely monitored and controlled via MQTT. A 5V battery provides power to the circuit, and multiple single-pole single-throw (SPST) toggle switches are used to manually control the relays.
#include <ESP8266WiFi.h>
#include <Adafruit_MCP23017.h>
#include <PubSubClient.h>
const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";
const char* mqtt_server = "YOUR_MQTT_SERVER_ADDRESS";
const char* mqtt_user = "YOUR_MQTT_USER";
const char* mqtt_password = "YOUR_MQTT_PASSWORD";
WiFiClient espClient;
PubSubClient client(espClient);
Adafruit_MCP23017 mcp;
// Relay and switch pin mappings on MCP23017
const uint8_t relayPins[] = {0, 1, 2, 3, 4, 5, 6, 7};
const uint8_t switchPins[] = {8, 9, 10, 11, 12, 13, 14, 15};
bool relayState[8] = {false, false, false, false, false, false, false, false};
void setup() {
Serial.begin(115200);
setupWiFi();
client.setServer(mqtt_server, 1883);
client.setCallback(mqttCallback);
// Initialize MCP23017
mcp.begin(0); // Default address 0x20
// Set up relay pins as output
for (uint8_t i = 0; i < 8; i++) {
mcp.pinMode(relayPins[i], OUTPUT);
mcp.digitalWrite(relayPins[i], LOW); // Ensure relays are OFF initially
}
// Set up switch pins as input with pull-up
for (uint8_t i = 0; i < 8; i++) {
mcp.pinMode(switchPins[i], INPUT);
mcp.pullUp(switchPins[i], HIGH);
}
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
// Monitor switches and toggle corresponding relay
for (uint8_t i = 0; i < 8; i++) {
if (mcp.digitalRead(switchPins[i]) == LOW) { // Switch is pressed
toggleRelay(i);
delay(200); // Debounce delay
}
}
}
// Function to connect to WiFi
void setupWiFi() {
delay(10);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
}
// Function to handle MQTT reconnection
void reconnect() {
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
if (client.connect("ESP8266Client", mqtt_user, mqtt_password)) {
Serial.println("connected");
// Subscribe to relay control topics
for (uint8_t i = 0; i < 8; i++) {
String topic = "living-room/relay" + String(i+1) + "/set";
client.subscribe(topic.c_str());
}
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
// MQTT callback function to process messages
void mqttCallback(char* topic, byte* payload, unsigned int length) {
String message;
for (unsigned int i = 0; i < length; i++) {
message += (char)payload[i];
}
// Control relays based on MQTT message
for (uint8_t i = 0; i < 8; i++) {
String relayTopic = "living-room/relay" + String(i+1) + "/set";
if (String(topic) == relayTopic) {
if (message == "ON") {
setRelay(i, true);
} else if (message == "OFF") {
setRelay(i, false);
}
}
}
}
// Toggle relay function
void toggleRelay(uint8_t relayNum) {
relayState[relayNum] = !relayState[relayNum];
mcp.digitalWrite(relayPins[relayNum], relayState[relayNum] ? HIGH : LOW);
// Publish relay state to MQTT
String stateTopic = "living-room/relay" + String(relayNum+1) + "/state";
client.publish(stateTopic.c_str(), relayState[relayNum] ? "ON" : "OFF");
}
// Set relay state directly
void setRelay(uint8_t relayNum, bool state) {
relayState[relayNum] = state;
mcp.digitalWrite(relayPins[relayNum], state ? HIGH : LOW);
// Publish relay state to MQTT
String stateTopic = "living-room/relay" + String(relayNum+1) + "/state";
client.publish(stateTopic.c_str(), state ? "ON" : "OFF");
}
This code is designed to run on the ESP8266 microcontroller. It initializes the Wi-Fi connection, connects to the MQTT server, and sets up the MCP23017 I/O expander. The ESP8266 monitors the state of the toggle switches through the MCP23017 and toggles the state of the corresponding relay. It also listens for MQTT messages to control the relays remotely and publishes the state of the relays back to the MQTT server.