keepingfishwithnoidea

Active Member
View Badges
Joined
Oct 4, 2024
Messages
426
Reaction score
237
Location
Maldives
Rating - 0%
0   0   0
Building an Advanced Reef Controller with Arduino Mega and NodeMCU


Maintaining a thriving reef aquarium requires precision and care. With the help of Arduino Mega 2560 and NodeMCU, we can automate many essential tasks, ensuring the perfect environment for marine life. This guide explains how to build a complete reef controller, including temperature regulation, lighting control, water level monitoring, and remote data visualization via a web interface.




Overview of the System


This reef controller automates the following functions:


  • Temperature Control: Monitors water temperature using a DS18B20 sensor and controls a heater via a relay.
  • Lighting Management: Automates aquarium lights with gradual brightness adjustments.
  • Water Level Monitoring: Detects water levels using float switches.
  • Leak Detection: Monitors for potential leaks using water sensors.
  • Data Visualization: Displays real-time data (temperature, water levels, and more) on a web dashboard hosted by NodeMCU.



Component List


Microcontrollers


  • Arduino Mega 2560
  • NodeMCU (ESP8266)

Sensors and Modules


  • virtuabotixRTC (DS1302 Real-Time Clock)
  • DS18B20 Temperature Sensor
  • Adafruit TCS34725 Color Sensor
  • 3-Channel Relay Module
  • Leak Sensors (2 units)
  • Water Level Sensors (2 units)

Actuators


  • Servo Motor (for feeder)

Other Components


  • Jumper Wires
  • Breadboard (optional for prototyping)
  • Resistors (e.g., 10kΩ for pull-ups)
  • Power Supplies (5V and 12V, depending on components)



Hardware Connections


Arduino Mega 2560 Connections


  1. virtuabotixRTC (DS1302):
    • CLK (Clock): D6
    • DAT (Data): D7
    • RST (Reset): D8
    • VCC: 5V
    • GND: GND
  2. DS18B20 Temperature Sensor:
    • Data Pin: D3 (with a 4.7kΩ pull-up resistor to 5V)
    • VCC: 5V
    • GND: GND
  3. Adafruit TCS34725 Color Sensor:
    • SCL: SCL (Pin 21)
    • SDA: SDA (Pin 20)
    • VIN: 5V
    • GND: GND
  4. Relay Module:
    • Relay 1 (Heater): D22
    • Relay 2 (Light): D23
    • Relay 3 (Return Pump): D24
  5. Leak Sensors:
    • Sensor 1 Signal: D4
    • Sensor 2 Signal: D5
    • VCC: 5V
    • GND: GND
  6. Water Level Sensors:
    • Sensor 1 Signal: D11
    • Sensor 2 Signal: D12
    • VCC: 5V
    • GND: GND
  7. Servo Motor (Feeder):
    • Signal: D32
    • VCC: 5V
    • GND: GND

NodeMCU Connections


  1. WiFi Communication: NodeMCU connects to the Arduino Mega via UART for data exchange.
  2. Power: Powered via USB or a 5V source.
  3. Web Server: Hosts a web dashboard for real-time data display.



Software Setup


Arduino Mega Code


The Mega handles sensor inputs, relay outputs, and feeder control. It periodically sends data to the NodeMCU via Serial communication. Key libraries used include:


  • virtuabotixRTC for RTC module
  • DallasTemperature and OneWire for DS18B20
  • Adafruit_TCS34725 for color sensor

Code:
// Arduino Mega 2560 Code
#include <Wire.h>
#include <RTClib.h>
#include <Servo.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Adafruit_TCS34725.h>

// RTC Configuration
RTC_DS1307 rtc;

// DS18B20 Temperature Sensor Configuration
#define ONE_WIRE_BUS 3
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

// Color Sensor (TCS34725)
Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_600MS, TCS34725_GAIN_1X);

// PWM Pins for Lighting
#define DAYLIGHT_PIN 9
#define MOONLIGHT_PIN 10

// Leak Sensors
#define LEAK_SENSOR_1 4
#define LEAK_SENSOR_2 5

// Water Level Sensors
#define WATER_LEVEL_1 11
#define WATER_LEVEL_2 12

// Servo (Feeder)
#define SERVO_PIN 32
Servo feederServo;

// Relay Pins for Pumps
#define RETURN_PUMP_PIN 22
#define HEATER_PIN 23

// Timing Variables
unsigned long lastUpdate = 0;
const unsigned long updateInterval = 1000; // 1 second

// Helper Functions for Lighting Control
float sineWaveBrightness(float t, float startTime, float endTime) {
    if (t < startTime || t > endTime) return 0;
    float phase = (t - startTime) / (endTime - startTime) * 3.14159;
    return sin(phase) * 255;
}

void setup() {
    Serial.begin(9600); // For UART Communication with NodeMCU

    // Initialize RTC
    if (!rtc.begin()) {
        Serial.println("Couldn't find RTC");
        while (1);
    }
    if (!rtc.isrunning()) {
        Serial.println("RTC is NOT running, setting the time...");
        rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // Set RTC to compile time
    }

    // Initialize Sensors
    sensors.begin();
    tcs.begin();

    // Initialize Pins
    pinMode(DAYLIGHT_PIN, OUTPUT);
    pinMode(MOONLIGHT_PIN, OUTPUT);
    pinMode(LEAK_SENSOR_1, INPUT);
    pinMode(LEAK_SENSOR_2, INPUT);
    pinMode(WATER_LEVEL_1, INPUT);
    pinMode(WATER_LEVEL_2, INPUT);

    pinMode(RETURN_PUMP_PIN, OUTPUT);
    pinMode(HEATER_PIN, OUTPUT);
    digitalWrite(RETURN_PUMP_PIN, LOW);
    digitalWrite(HEATER_PIN, LOW);

    // Initialize Servo
    feederServo.attach(SERVO_PIN);
    feederServo.write(0); // Default position
}

void loop() {
    unsigned long currentMillis = millis();

    // Get current time from RTC
    DateTime now = rtc.now();
    int hr = now.hour();
    int min = now.minute();
    float hour = hr + min / 60.0; // Convert to a float for sine wave calculation

    // Lighting Control
    float daylightBrightness = sineWaveBrightness(hour, 7, 9) + sineWaveBrightness(hour, 17, 18);
    analogWrite(DAYLIGHT_PIN, daylightBrightness);

    if (hour >= 18 || hour < 6) {
        analogWrite(MOONLIGHT_PIN, 50); // Low moonlight brightness
    } else {
        analogWrite(MOONLIGHT_PIN, 0);
    }

    // Sensor Monitoring and Actuator Control
    if (currentMillis - lastUpdate >= updateInterval) {
        lastUpdate = currentMillis;

        // Temperature Sensor
        sensors.requestTemperatures();
        float temperature = sensors.getTempCByIndex(0);
        Serial.print("Temperature: ");
        Serial.println(temperature);

        // Leak Sensors
        bool leak1 = digitalRead(LEAK_SENSOR_1);
        bool leak2 = digitalRead(LEAK_SENSOR_2);
        Serial.print("Leak Sensor 1: ");
        Serial.println(leak1 ? "No Leak" : "Leak Detected");
        Serial.print("Leak Sensor 2: ");
        Serial.println(leak2 ? "No Leak" : "Leak Detected");

        // Water Level Sensors
        bool level1 = digitalRead(WATER_LEVEL_1);
        bool level2 = digitalRead(WATER_LEVEL_2);
        Serial.print("Water Level 1: ");
        Serial.println(level1 ? "Normal" : "Low");
        Serial.print("Water Level 2: ");
        Serial.println(level2 ? "Normal" : "Low");

        // Return Pump Control
        digitalWrite(RETURN_PUMP_PIN, level1 ? HIGH : LOW);

        // Heater Control
        if (temperature < 25.0) { // Example threshold
            digitalWrite(HEATER_PIN, HIGH);
        } else {
            digitalWrite(HEATER_PIN, LOW);
        }

        // Communicate data to NodeMCU
        Serial.print("DATA:");
        Serial.print(temperature);
        Serial.print(",");
        Serial.print(leak1);
        Serial.print(",");
        Serial.print(leak2);
        Serial.print(",");
        Serial.print(level1);
        Serial.print(",");
        Serial.println(level2);
    }
}


NodeMCU Code


NodeMCU receives data from the Mega and hosts a simple web server to display temperature, water levels, and other parameters. The server uses HTML and JavaScript for real-time updates via AJAX.


Code:
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <DHT.h>

// WiFi Credentials
const char *ssid = "Your_SSID";
const char *password = "Your_PASSWORD";

// DHT Sensor
#define DHTPIN D4 // GPIO pin where the DHT sensor is connected
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);

// Relay Pins
#define HEATER_PIN D1
#define LIGHT_PIN D2
#define RETURN_PUMP_PIN D3

// Web server on port 80
ESP8266WebServer server(80);

void setup() {
  Serial.begin(115200);
  dht.begin();

  // Initialize relays
  pinMode(HEATER_PIN, OUTPUT);
  pinMode(LIGHT_PIN, OUTPUT);
  pinMode(RETURN_PUMP_PIN, OUTPUT);

  digitalWrite(HEATER_PIN, LOW);
  digitalWrite(LIGHT_PIN, LOW);
  digitalWrite(RETURN_PUMP_PIN, LOW);

  // Connect to WiFi
  Serial.println("Connecting to WiFi...");
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println(".");
  }
  Serial.println("WiFi connected.");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  // Define server routes
  server.on("/", handleRoot);
  server.on("/api/data", handleApiData);
  server.on("/api/control", handleControl);
  server.begin();
  Serial.println("HTTP server started.");
}

void loop() {
  server.handleClient();
}

// Serve HTML page
void handleRoot() {
  String html = R"rawliteral(
    <!DOCTYPE html>
    <html>
    <head>
        <title>Reef Controller</title>
        <style>
            body { font-family: Arial, sans-serif; text-align: center; }
            .control { margin: 20px; }
            button { padding: 10px 20px; font-size: 16px; cursor: pointer; }
        </style>
    </head>
    <body>
        <h1>Reef Controller</h1>
        <div id="temperature">Loading temperature...</div>
        <div id="humidity">Loading humidity...</div>
        <div class="control">
            <h3>Control Panel</h3>
            <button onclick="sendCommand('heater', 1)">Turn Heater ON</button>
            <button onclick="sendCommand('heater', 0)">Turn Heater OFF</button><br><br>
            <button onclick="sendCommand('light', 1)">Turn Light ON</button>
            <button onclick="sendCommand('light', 0)">Turn Light OFF</button><br><br>
            <button onclick="sendCommand('pump', 1)">Turn Pump ON</button>
            <button onclick="sendCommand('pump', 0)">Turn Pump OFF</button>
        </div>
        <script>
            async function fetchData() {
                const response = await fetch('/api/data');
                const data = await response.json();
                document.getElementById('temperature').innerText = `Temperature: ${data.temperature} °C`;
                document.getElementById('humidity').innerText = `Humidity: ${data.humidity} %`;
            }

            async function sendCommand(device, state) {
                const response = await fetch(`/api/control?device=${device}&state=${state}`);
                const result = await response.text();
                alert(result);
            }

            setInterval(fetchData, 5000); // Refresh data every 5 seconds
            fetchData(); // Initial fetch
        </script>
    </body>
    </html>
  )rawliteral";
  server.send(200, "text/html", html);
}

// API to send sensor data
void handleApiData() {
  float temperature = dht.readTemperature();
  float humidity = dht.readHumidity();
  String json = "{\"temperature\": " + String(temperature) + ", \"humidity\": " + String(humidity) + "}";
  server.send(200, "application/json", json);
}

// API to control relays
void handleControl() {
  String device = server.arg("device");
  int state = server.arg("state").toInt();

  if (device == "heater") {
    digitalWrite(HEATER_PIN, state);
    server.send(200, "text/plain", "Heater control successful.");
  } else if (device == "light") {
    digitalWrite(LIGHT_PIN, state);
    server.send(200, "text/plain", "Light control successful.");
  } else if (device == "pump") {
    digitalWrite(RETURN_PUMP_PIN, state);
    server.send(200, "text/plain", "Pump control successful.");
  } else {
    server.send(400, "text/plain", "Invalid device.");
  }
}




Building the System


  1. Hardware Assembly:
    • Connect all components to the Arduino Mega and NodeMCU according to the pin connections listed above.
    • Ensure all grounds (GND) are connected to a common point.
    • Use relays to control high-power components (heater, lights, pump).
  2. Software Upload:
    • Upload the Arduino Mega code to the Mega 2560 using the Arduino IDE.
    • Upload the NodeMCU code to the ESP8266 using the Arduino IDE or another compatible uploader.
  3. Powering the System:
    • Use a 5V power supply for the Arduino Mega and components.
    • Ensure sufficient power for relays and servo motors by using an external power source if required.
  4. Testing:
    • Verify each sensor’s functionality (temperature, water level, and leak sensors).
    • Check the operation of relays (turning heater, lights, and pump on/off).
    • Access the NodeMCU web dashboard via its IP address and confirm real-time data updates.



How It Works


  1. Real-Time Monitoring: The Mega collects data from sensors every second and processes control signals for relays and servos.
  2. Data Transmission: Processed data is sent to NodeMCU over Serial communication.
  3. Web Dashboard: NodeMCU hosts a web server, providing a real-time view of the aquarium's status, accessible on any WiFi-enabled device.
  4. Automation: Relays and servos are triggered based on sensor readings, ensuring the aquarium's environment stays within ideal conditions.



Future Enhancements


  • Water Parameter Testing: Add solenoid valves and sensors for testing parameters like alkalinity and nitrate.
  • Mobile App: Extend the web interface to a dedicated mobile application for remote control and notifications.
  • Camera Integration: Include an IP camera for live monitoring of the aquarium.



This reef controller is an excellent project for enthusiasts looking to automate their aquarium while learning about microcontroller programming and IoT. With some initial effort, you can ensure a stable and thriving environment for your aquatic life!
 
OP
OP
keepingfishwithnoidea

keepingfishwithnoidea

Active Member
View Badges
Joined
Oct 4, 2024
Messages
426
Reaction score
237
Location
Maldives
Rating - 0%
0   0   0
also here is how you can get the server id, after doing this just reupload the code above

Setting Up a Web Server for Your Reef Controller​


Creating a web server for your reef controller allows you to monitor and control your aquarium remotely via any device connected to your local network. Here’s a concise guide to setting it up:


Prerequisites:​


  1. Hardware Required:
    • NodeMCU (ESP8266 or ESP32)
    • USB cable for programming
    • Wi-Fi router (for local network access)
  2. Software Required:
    • Arduino IDE (with ESP8266 or ESP32 board package installed)
    • Necessary libraries: ESPAsyncWebServer, AsyncTCP (ESP32) or ESPAsyncTCP (ESP8266).



Steps to Set Up the Web Server:​


  1. Install Necessary Libraries:
    • Open Arduino IDE.
    • Navigate to Sketch -> Include Library -> Manage Libraries.
    • Search for and install ESPAsyncWebServer and AsyncTCP (for ESP32) or ESPAsyncTCP (for ESP8266).
  2. Write the Code:
    • Use the following example code to create a basic web server:
Code:
#include <WiFi.h>  // For ESP32, use <ESP8266WiFi.h> for ESP8266
#include <ESPAsyncWebServer.h>

const char* ssid = "Your_SSID";
const char* password = "Your_PASSWORD";

AsyncWebServer server(80);

void setup() {
    Serial.begin(115200);
    WiFi.begin(ssid, password);

    while (WiFi.status() != WL_CONNECTED) {
        delay(1000);
        Serial.println("Connecting to WiFi...");
    }

    Serial.println("Connected to WiFi");
    Serial.println(WiFi.localIP());

    // Define a simple web page
    server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
        request->send(200, "text/html", "<h1>Welcome to the Reef Controller</h1>");
    });

    // Start server
    server.begin();
    Serial.println("Web server started.");
}

void loop() {
    // Nothing required here for the web server
}


  1. Upload the Code:
    • Connect your NodeMCU to your computer.
    • Select the appropriate board and port in Arduino IDE.
    • Click on the Upload button.
  2. Access the Web Server:
    • Once the code is uploaded, open the Serial Monitor to find the NodeMCU’s IP address (e.g., 192.168.1.100).
    • Enter the IP address in a web browser connected to the same Wi-Fi network.
    • You should see the message: Welcome to the Reef Controller.



Extending the Web Server:​


  • Add more functionality by creating routes like /temperature, /lights, or /status to display or control specific features.
  • Use a more advanced frontend (e.g., HTML with JavaScript) to create a user-friendly interface.

Troubleshooting Tips:​


  1. Connection Issues:
    • Ensure your SSID and password are correct.
    • Make sure your NodeMCU is within range of your Wi-Fi router.
  2. Library Errors:
    • Confirm that you have installed all required libraries.
    • Ensure the correct board is selected in Arduino IDE.

Final Thoughts:​


Setting up a web server with NodeMCU enables you to manage your reef controller efficiently. Experiment with more features like real-time data updates and controls to enhance the user experience!
 
Last edited:

TOP 10 Trending Threads

HOW MANY TIMES A DAY DO YOU FIDDLE WITH YOUR TANK?

  • 1 - 2 times a day.

    Votes: 31 43.7%
  • 3 - 5 times a day.

    Votes: 9 12.7%
  • 6 - 10 times a day.

    Votes: 5 7.0%
  • 10 - 20 times a day.

    Votes: 1 1.4%
  • Too many times to count...

    Votes: 6 8.5%
  • I don't mess with my tank unless I have to for feeding or required maintenance.

    Votes: 19 26.8%
Back
Top