Hi all, this is my first big arduino project (for myself). I want to connect my esp32 to firebase, where I put mock data to firebase and control the microcontroller.
Here is a brief explanation, I want to create a water quality control, where for example, pH is low, servo will work to put in pH buffer, when oxygen level low, I will make sure the water pump work, and another servo is for feeding fish.
But here is my problem. i want how do I connect all that on my esp32, and make sure it work? here are the list of items that I bought,
- esp32
- water pump
- relay
- 2 servos
- 6v external power supply (4 AA 1.5v battery)
My plan is to connect 3v3 pin to waterpump and servo, while 5v pin to both my servos. Now I have problem, where my water pump is constantly working, although it should not. and my feeder servo is not working. Please help me.
here is part of my code:
// Pin Definitions
#define PH_SERVO_PIN 13
#define FEEDER_SERVO_PIN 12
#define WATER_PUMP_PIN 21
FirebaseData fbdo;
FirebaseAuth auth;
FirebaseConfig config;
Servo phServo;
Servo feederServo;
unsigned long sendDataPrevMillis = 0;
bool signupOK = false;
bool hasRotated = false;
// Status Flags
bool isPHNormal = true;
bool isDONormal = true;
bool isTempNormal = true;
// NTP Time Client Setup
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 8 * 3600, 60000); // UTC+8 time
void setup() {
Serial.begin(115200);
// Initialize Water Pump Pin
pinMode(WATER_PUMP_PIN, OUTPUT);
digitalWrite(WATER_PUMP_PIN, LOW); // Ensure pump is off initially
// Wi-Fi Connection
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
Serial.print("Connecting to Wi-Fi");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(300);
}
Serial.println("\nConnected to Wi-Fi!");
// Firebase Initialization
config.api_key = API_KEY;
config.database_url = DATABASE_URL;
if (Firebase.signUp(&config, &auth, "", "")) {
Serial.println("Firebase connected.");
signupOK = true;
} else {
Serial.printf("Firebase signup error: %s\n", config.signer.signupError.message.c_str());
}
config.token_status_callback = tokenStatusCallback;
Firebase.begin(&config, &auth);
Firebase.reconnectWiFi(true);
// Initialize Servos
phServo.attach(PH_SERVO_PIN);
feederServo.attach(FEEDER_SERVO_PIN);
// Start NTP Client
timeClient.begin();
timeClient.update();
}
void loop() {
if (Firebase.ready() && signupOK && (millis() - sendDataPrevMillis > 10000 || sendDataPrevMillis == 0)) {
sendDataPrevMillis = millis();
// Update NTP Time
timeClient.update();
// Read Sensor Data from Firebase
float pH, DO, temperature;
// Read pH Value
if (Firebase.RTDB.getFloat(&fbdo, "sensors/pH", &pH)) {
Serial.print("pH: ");
Serial.println(pH);
handlePH(pH);
} else {
Serial.println("Failed to retrieve pH value");
Serial.println("REASON: " + fbdo.errorReason());
}
// Read Dissolved Oxygen (DO) Value
if (Firebase.RTDB.getFloat(&fbdo, "sensors/DO", &DO)) {
Serial.print("DO: ");
Serial.println(DO);
handleDO(DO);
} else {
Serial.println("Failed to retrieve DO value");
Serial.println("REASON: " + fbdo.errorReason());
}
// Read Temperature Value
if (Firebase.RTDB.getFloat(&fbdo, "sensors/temperature", &temperature)) {
Serial.print("Temperature: ");
Serial.println(temperature);
handleTemperature(temperature);
} else {
Serial.println("Failed to retrieve temperature value");
Serial.println("REASON: " + fbdo.errorReason());
}
// Feeding Fish at Specific Intervals or Conditions
feedFish(); // Implement your feeding logic here
}
}
// Function to handle pH adjustments
void handlePH(float pH) {
if (pH < 6.5 && isPHNormal) {
adjustPH();
isPHNormal = false;
} else if (pH >= 6.5 && pH <= 8.5 && !isPHNormal) {
stopPHAdjustment();
isPHNormal = true;
}
}
// Function to adjust pH using servo
void adjustPH() {
Serial.println("Adjusting pH...");
phServo.write(180); // Adjust pH in one direction
delay(1000); // Run servo for 1 second
phServo.write(90); // Stop the servo
delay(1000); // Wait before next action
logAction("pH adjusted");
}
// Function to stop pH adjustment
void stopPHAdjustment() {
Serial.println("Stopping pH adjustment...");
phServo.write(90); // Set servo to neutral position
logAction("pH adjustment stopped");
}
// Function to handle Dissolved Oxygen (DO) levels
void handleDO(float DO) {
if (DO < 3.0 && isDONormal) {
activateWaterPump("DO level low");
isDONormal = false;
} else if (DO >= 5.0 && !isDONormal) {
deactivateWaterPump("DO level normal");
isDONormal = true;
}
}
// Function to handle Temperature control
void handleTemperature(float temperature) {
if ((temperature < 26.0 || temperature > 32.0) && isTempNormal) {
activateWaterPump("Temperature out of range");
isTempNormal = false;
} else if (temperature >= 26.0 && temperature <= 32.0 && !isTempNormal) {
deactivateWaterPump("Temperature normal");
isTempNormal = true;
}
}
// Function to activate the water pump with logging
void activateWaterPump(const char* reason) {
Serial.println("Activating water pump...");
digitalWrite(WATER_PUMP_PIN, HIGH); // Turn on water pump
logAction(reason);
}
// Function to deactivate the water pump with logging
void deactivateWaterPump(const char* reason) {
Serial.println("Deactivating water pump...");
digitalWrite(WATER_PUMP_PIN, LOW); // Turn off water pump
logAction(reason);
}
// Function to feed fish
void feedFish() {
// Example: Feed fish every hour
static unsigned long lastFeedTime = 0;
const unsigned long feedInterval = 3600000; // 1 hour in milliseconds
if (millis() - lastFeedTime >= feedInterval) {
Serial.println("Feeding fish...");
feederServo.write(180); // Activate feeder servo
delay(1000); // Run servo for 1 second
feederServo.write(90); // Stop the servo
delay(1000); // Wait before next action
logAction("Fish fed");
lastFeedTime = millis();
}
}
// Log actions to Firebase
void logAction(const char* action) {
timeClient.update(); // Ensure the latest time is fetched
unsigned long epochTime = timeClient.getEpochTime(); // Get epoch time
FirebaseJson json;
json.set("action", action);
json.set("epoch", epochTime);
// Push JSON to Firebase
if (Firebase.RTDB.pushJSON(&fbdo, "actionHistory", &json)) {
Serial.println("Action logged successfully.");
} else {
Serial.println("Failed to log action.");
Serial.println("REASON: " + fbdo.errorReason());
}
}
should I do them separately? like using another esp32 to control the water pump. please help me





