Creating a Smart Pet Feeder with MQTT and Arduino
The Internet of Things (IoT) technology has enabled us to connect various devices around our homes. In this post, we are going to look at a simple IoT project, an automated pet feeder using an ESP8266 microcontroller and MQTT protocol. You can grab the full code here to follow along: https://github.com/ljmerza/cat-feeder
The MQTT is a machine-to-machine messaging protocol, designed for lightweight data transmission and is widely used in IoT applications.
Here's the code breakdown:
Defining Constants and Variables
The following section of the code is dedicated to defining MQTT topics, credentials, and the pins for our motor, switch, and LED indicator.
// MQTT Topics
#define SET_TOPIC "petfeeder/feed"
#define SET_TOPIC_SUCCESS "petfeeder/feed/success"
#define SET_TOPIC_FAIL "petfeeder/feed/fail"
// Credentials
#define HOSTNAME "fetfeeder"
#define WIFI_SSID "Everyday Im Buffering"
#define WIFI_PASSWORD "thefoxjumpedoverthemoon"
#define MQTT_SERVER "192.168.1.76"
#define MQTT_PORT 1883
#define MOTOR_PIN D0
#define SWITCH_PIN D1
#define LED_PIN D7
Setting up WiFi and MQTT
The function setup_wifi is used to connect to the WiFi network, while the reconnect_mqtt function is for establishing a connection with the MQTT server.
void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(WIFI_SSID);
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
}
void reconnect_mqtt() {
// Loop until we're reconnected
while (!client.connected()) {
// Attempt to connect
if (client.connect(HOSTNAME, MQTT_USERNAME, MQTT_PASSWORD)) {
Serial.println("connected");
client.subscribe(SET_TOPIC);
} else {
// Wait 5 seconds before retrying
delay(5000);
}
}
}
Message Processing
The recieve_mqtt_message function is set as a callback function, which processes incoming messages. It parses the received JSON message to extract the number of scoops of food to dispense, operates the feeder, and then sends a success message.
void recieve_mqtt_message(char* topic, byte* payload, unsigned int length) {
...
// run feeder and send success message
run_feeder(root["scoops"]);
client.publish(SET_TOPIC_SUCCESS, payload, true);
}
The Feeder Mechanism
The run_feeder function turns the motor on for a specific duration for each scoop, then turns it off.
void run_feeder(int scoopsOfFood) {
digitalWrite(MOTOR_PIN, HIGH);
for (int currentScoops = 0; currentScoops < scoopsOfFood; currentScoops++) {
delay(100);
}
digitalWrite(MOTOR_PIN, LOW);
}
In essence, for each scoop, the motor is kept running for a brief period, after which it is stopped. This process is repeated as per the specified number of scoops.