Arduino Projects

DIY IoT Hydroponic & Aquaculture Monitor with Arduino Nano, ESP-01, and Blynk

Introduction: Why Bother Monitoring Water Anyway?

IoT Aquaculture project

If you’ve ever tried growing plants in a hydroponic system or keeping fish in an aquaculture tank, you already know one thing: water quality is king. It’s like the air we breathe—get it wrong and everything goes downhill fast. That’s where the magic of DIY IoT comes in. With just a few low-cost components like an Arduino Nano, ESP-01 WiFi module, turbidity sensor, TDS sensor, and pH sensor, you can build a smart water monitoring system.

And here’s the best part: you don’t have to stand over your tank or plants 24/7. Thanks to IoT, your water readings—pH, total dissolved solids (TDS), and turbidity—can be tracked remotely on your smartphone using the Blynk dashboard.

Temeperature sensor, Turbidity sensor and pH sensor

In this guide, I’ll walk you through how we built a portable, battery-powered, IoT-enabled water quality monitor. We’ll talk about the components, how they fit together, why they matter, and where you can take the project next.

Why IoT Matters in Hydroponics and Aquaculture

Hydroponics and aquaculture have one thing in common: everything depends on the condition of water. If the pH level shifts, plants stop absorbing nutrients. If turbidity increases, fish suffer from stress. If TDS rises too high, both systems struggle.

IoT dashboard of the project design.

IoT makes it easy to monitor these parameters in real-time. Instead of waiting for plants to wilt or fish to act strangely, you get instant alerts and live data streamed to your phone. Think of it as having a lab assistant working around the clock, checking water quality while you sleep.

The Hardware Components

Arduino Nano – The Brains of the Project

Arduino Nano

The Arduino Nano acts as the main controller. It reads data from all the sensors, processes it, and then communicates with the ESP-01 for IoT functions. It’s small, affordable, and easy to program in Arduino IDE.

ESP-01 WiFi Module – The Gateway to IoT

The ESP8266-01 (ESP-01) is what connects your system to the internet. Without it, your readings would stay trapped inside the Arduino. With it, the data goes straight to the Blynk IoT dashboard, letting you see your water quality on your phone from anywhere.

Sensors That Do the Real Work

sensor module
  • pH Sensor Module: Measures acidity or alkalinity of water. Perfect for ensuring nutrient absorption in hydroponics or healthy conditions in fish tanks.
  • TDS Sensor Module: Reads Total Dissolved Solids—basically, how many salts and minerals are dissolved in water.
  • Turbidity Sensor Module: Tracks how clear or cloudy the water is. High turbidity could mean dirt, algae, or waste buildup.
ds18b20

The DS18B20 Temperature sensor module was also very useful in determining the temperature of the water solution at any given time. Since it was already waterproofed encased. we immersed it into the container as shown in the picture above.

Power Supply Setup

buck converter and the rest

We used two 3.7V Li-ion batteries in series and a DC-DC buck converter to step down the voltage to about 3.7V for the ESP-01. This way, the setup is portable and independent of wall sockets.

Supporting Components

  • Veroboard: To solder everything permanently.
  • Female header pins: For easy Arduino Nano removal and re-use.
  • SPST Red Switch: A simple on/off power control.
  • JST connectors: To attach/detach sensors as needed.
  • Pattress box (3×6 inch): To house the electronics safely.

How the System Is Assembled

Imagine building a LEGO set, but instead of colorful bricks, you have sensors, wires, and boards. The veroboard acts like the foundation. The Arduino Nano plugs into female headers, which means you can replace it without re-soldering. The ESP-01 connects via pins, powered through the buck converter.

other components

Wiring is neat with JST connectors, which makes replacing sensors a plug-and-play experience. The SPST switch ensures you don’t drain the batteries accidentally.

On the outside, the pattress box keeps everything protected while the water sample sits in a transparent container, making testing simple and safe.

You may also like to read this: DIY Weather Station with DHT11 Sensor.

Software and IoT Integration

Arduino IDE and Programming the Arduino Nano Board

Arduino source code

All the sensors talk to the Arduino Nano, and we write a program (sketch) on Arduino IDE to read their values. It then sends this data to the ESP-01 using Serial Communication protocol.

The Arduino Code for the Arduino Nano board

// Include the libraries we need
#include <OneWire.h>
#include <DallasTemperature.h>
#include <SoftwareSerial.h>
#include "DFRobot_PH.h"
#include <EEPROM.h>

SoftwareSerial mySerial(6, 5);  // RX, TX

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS A2
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

//for turbidity
unsigned char str[5] = {};        //Serial receives data
unsigned char col;
unsigned int distance = 0;
unsigned char a[5] = {  0x18, 0x05, 0x00, 0x01, 0x0D};

//for tds sensor
#define TdsSensorPin A1
#define VREF 5.0      // analog reference voltage(Volt) of the ADC
#define SCOUNT  30           // sum of sample point
int analogBuffer[SCOUNT];    // store the analog value in the array, read from ADC
int analogBufferTemp[SCOUNT];
int analogBufferIndex = 0,copyIndex = 0;
float averageVoltage = 0,temperature = 25;
float tdsValue;

//for pH sensor
#define PH_PIN A3
float voltage,phValue = 25;
DFRobot_PH ph;
 float tempC;

void setup() {
  Serial.begin(115200);
  mySerial.begin(9600);
  // Start up the library
  sensors.begin();
  pinMode(TdsSensorPin,INPUT);
  ph.begin();
}

float tdsSensor(){
   static unsigned long analogSampleTimepoint = millis();
   if(millis()-analogSampleTimepoint > 40U)     //every 40 milliseconds,read the analog value from the ADC
   {
     analogSampleTimepoint = millis();
     analogBuffer[analogBufferIndex] = analogRead(TdsSensorPin);    //read the analog value and store into the buffer
     analogBufferIndex++;
     if(analogBufferIndex == SCOUNT) 
         analogBufferIndex = 0;
   }   
   static unsigned long printTimepoint = millis();
   if(millis()-printTimepoint > 800U)   {
      printTimepoint = millis();
      for(copyIndex=0;copyIndex<SCOUNT;copyIndex++)
        analogBufferTemp[copyIndex]= analogBuffer[copyIndex];
      averageVoltage = getMedianNum(analogBufferTemp,SCOUNT) * (float)VREF / 1024.0; // read the analog value more stable by the median filtering algorithm, and convert to voltage value
      float compensationCoefficient=1.0+0.02*(temperature-25.0);    //temperature compensation formula: fFinalResult(25^C) = fFinalResult(current)/(1.0+0.02*(fTP-25.0));
      float compensationVolatge=averageVoltage/compensationCoefficient;  //temperature compensation
      tdsValue=(133.42*compensationVolatge*compensationVolatge*compensationVolatge - 255.86*compensationVolatge*compensationVolatge + 857.39*compensationVolatge)*0.5; //convert voltage value to tds value
      //Serial.print("voltage:");
      //Serial.print(averageVoltage,2);
      //Serial.print("V   ");
      // Serial.print("TDS Value:");
      // Serial.print(tdsValue,0);
      // Serial.println("ppm");
   }
   return tdsValue;
}

int getMedianNum(int bArray[], int iFilterLen){
      int bTab[iFilterLen];
      for (byte i = 0; i<iFilterLen; i++)
      bTab[i] = bArray[i];
      int i, j, bTemp;
      for (j = 0; j < iFilterLen - 1; j++) 
      {
      for (i = 0; i < iFilterLen - j - 1; i++) 
          {
        if (bTab[i] > bTab[i + 1]) 
            {
        bTemp = bTab[i];
            bTab[i] = bTab[i + 1];
        bTab[i + 1] = bTemp;
         }
      }
      }
      if ((iFilterLen & 1) > 0)
    bTemp = bTab[(iFilterLen - 1) / 2];
      else
    bTemp = (bTab[iFilterLen / 2] + bTab[iFilterLen / 2 - 1]) / 2;
      return bTemp;
}

float tempSensor(){
  // call sensors.requestTemperatures() to issue a global temperature 
  // request to all devices on the bus
  // Serial.print("Requesting temperatures...");
  sensors.requestTemperatures(); // Send the command to get temperatures
  // Serial.println("DONE");
  // After we got the temperatures, we can print them here.
  // We use the function ByIndex, and as an example get the temperature from the first sensor only.
  tempC = sensors.getTempCByIndex(0);

  // Check if reading was successful
  if(tempC != DEVICE_DISCONNECTED_C) 
  {
    // Serial.print("Temperature for the device 1 (index 0) is: ");
    // Serial.println(tempC);
  } 
  else  {
    // Serial.println("Error: Could not read temperature data");
  }
  return tempC;
}


float pHSensor(){
  tempSensor();
  static unsigned long timepoint = millis();
    if(millis()-timepoint>1000U){                  //time interval: 1s
        timepoint = millis();
        temperature = tempSensor();         // read your temperature sensor to execute temperature compensation
        voltage = analogRead(PH_PIN)/1024.0*5000;  // read the voltage
        phValue = ph.readPH(voltage, temperature);  // convert voltage to pH with temperature compensation
        // Serial.print("temperature:");
        // Serial.print(temperature, 1);
        // Serial.print("^C  pH:");
        // Serial.println(phValue,2);
    }
    ph.calibration(voltage,temperature);           // calibration p
    return phValue, temperature;
}


int turbiditySensor(){
mySerial.write(a, 5);
  while (!mySerial.available());
  while (mySerial.available() > 0) //Detect if there is data on serial port 
  {
      for (int i = 0; i < 5; i++)
      {
        str[i]=mySerial.read();
        delay(5);
      }
      // Serial.println(str[3],DEC);
      mySerial.flush();
  } 
  return str[3];
}


void loop() {
  tdsSensor();
  pHSensor();
  turbiditySensor();
  // tempSensor();
  
  
  Serial.print(tdsValue);      Serial.print("A");
  Serial.print(phValue);       Serial.print("B");
  Serial.print(tempC);   Serial.print("C");
  Serial.print(str[3]);     Serial.print("D");
  Serial.print("\n");
  delay(500);
}

Explanation of the Arduino Code for Transmitter Side

This Arduino code is designed to read data from various sensors and transmit that data via Serial communication to an ESP-01 module. The sensors include a temperature sensor, a TDS (Total Dissolved Solids) sensor, a pH sensor, and a turbidity sensor. Below is a detailed breakdown of the code.

Libraries and Setup
libraries used
  • OneWire: This library allows communication with devices that use the OneWire protocol, such as temperature sensors.
  • DallasTemperature: This library is specifically for Dallas temperature sensors, which are commonly used in various applications.
  • SoftwareSerial: This library enables serial communication on other digital pins of the Arduino, allowing for communication with the ESP-01 module.
  • DFRobot_PH: This library is used for reading pH values from a pH sensor.
  • EEPROM: This library allows for reading and writing data to the EEPROM memory of the Arduino.
software serial communication

This line initializes a software serial port on pins 6 (RX) and 5 (TX) for communication with the ESP-01.

The temperature sensor is connected to pin A2, and an instance of the OneWire and DallasTemperature classes is created for reading temperature data.

Sensor Initialization
sensor declaration

The code initializes several sensors:

  • TDS Sensor: Connected to pin A1.
  • pH Sensor: Connected to pin A3.
  • Turbidity Sensor: Communicates via the software serial port.
Setup Function
The setup function of the Arduino code_2

The setup() function initializes the serial communication at different baud rates for the Arduino and ESP-01, starts the temperature sensor library, and sets the TDS sensor pin as an input.

Sensor Functions

TDS Sensor Function
float tdsSensor() {
// Code to read and calculate TDS value
}

This function reads the analog value from the TDS sensor every 40 milliseconds, stores it in a buffer, and calculates the TDS value using a temperature compensation formula. The TDS value is derived from the voltage reading.

Temperature Sensor Function
float tempSensor() {
  // Code to read temperature
}

This function requests temperature readings from the Dallas temperature sensor and returns the temperature in Celsius.

Loop Function

void loop() {
tdsSensor();
pHSensor();
turbiditySensor();

Serial.print(tdsValue); Serial.print("A");
Serial.print(phValue); Serial.print("B");
Serial.print(tempC); Serial.print("C");
Serial.print(str[3]); Serial.print("D");
Serial.print("\n");
delay(500);
}

The loop() function continuously reads data from the TDS, pH, and turbidity sensors. It then prints the values to the Serial monitor, appending specific letters to identify each value. The loop runs every 500 milliseconds.

Programming The ESP-01 With Arduino IDE

#include <SoftwareSerial.h>
/*ESP-01 pins are GPIO, Tx is GPIO1 (here define as 1, code line 6),
*/#define rxPin 0 // GPIO0 is the pin next to the ESP-01 Rx pin. The Rx (GPIO3), the Tx (GPIO1)
#define txPin 2 //GPIO2
#define pumpVirtualPin 1

SoftwareSerial nodeMCU(rxPin, txPin);

#define BLYNK_TEMPLATE_ID "TMPL2bPdN-5lm"
#define BLYNK_TEMPLATE_NAME "IoT Aquaculture Monitoring Project"
#define BLYNK_AUTH_TOKEN "XODdqSnfZEzEC99weZMpRGt7-IY5XZjg"

/* Comment this out to disable prints and save space */#define BLYNK_PRINT Serial

int Button;

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "Galaxy A51 917E";
char pass[] = "tosin@345";

BlynkTimer timer;

char c;
String dataIn;
int8_t indexOfA, indexOfB,indexOfC, indexOfD;
String data1, data2, data3, data4;

BLYNK_WRITE(V3) {
  Button = param.asInt();
    if (Button==1){
      digitalWrite(pumpVirtualPin, HIGH);
    }
else if(Button==0){
 digitalWrite(pumpVirtualPin, LOW);
    }
}

void setup(){
  // Debug console
  Serial.begin(115200);
  nodeMCU.begin(115200);

  pinMode(pumpVirtualPin, OUTPUT);

  Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
   // Setup a function to be called every second
  //timer.setInterval(1000L, parse_data);
}

void recvData(){
  while(nodeMCU.available() >0){
  c = nodeMCU.read();
 
   if( c == '\n'){
    break;
  }

  else{
    dataIn += c;
  }
}

if(c == '\n'){
  //Serial.println(c);
  parse_data();

  Serial.println("data 1= " + data1);
  Serial.println("data 2= " + data2);
  Serial.println("data 3= " + data3);
  Serial.println("............................");
  
  c = 0;
  dataIn = "";
  }
}

void loop(){
  recvData();

  Blynk.run();
  timer.run();
   
}

void parse_data(){
  indexOfA = dataIn.indexOf("A");
  indexOfB = dataIn.indexOf("B");
  indexOfC = dataIn.indexOf("C");
  indexOfD = dataIn.indexOf("D");
 

  data1 = dataIn.substring(0, indexOfA);
  data2 = dataIn.substring(indexOfA+1, indexOfB);
  data3 = dataIn.substring(indexOfB+1, indexOfC);
  data4 = dataIn.substring(indexOfC+1, indexOfD);
  
   float ch1 = data1.toFloat();
   float ch2 = data2.toFloat();
   float ch3 = data3.toFloat();
   int ch4 = data4.toInt();
 
   
    Blynk.virtualWrite(V0, ch1);
    Blynk.virtualWrite(V1, ch2);
    Blynk.virtualWrite(V2, ch3);
    Blynk.virtualWrite(V3, ch4);
   

 
}

The Arduino code above shows how the ESP-01 receives the data read from Arduino Nano. And then sends this to the Blynk IoT dashboard for monitoring and real-time feedback to the user.

Blynk IoT Dashboard

IoT Blynk platform

Here’s where things get fun. With Blynk, you can design your own dashboard—sliders, graphs, widgets—to monitor real-time values of pH, TDS, Temperature and turbidity. You can even set up notifications if the values cross safe thresholds. However, for this particular design, we didn’t see the need to include an in-app alerts.

showing the IoT Aquaculture hydroponics project

We did design the Blynk dashboard to run on both PC and mobile platforms so that is can be used anywhere. The mobile version was looking different that is because we used radial gauges to monitoring their readings and measurements.

To know how to set up the Blynk 2.0 dashboard for a particular project, you can read this project IoT Light Bulb – Remote Control Light Bulb Blynk App.

Answers To Common Questions

What sensors are needed for hydroponic water quality monitoring?

You’ll need at least pH, TDS, turbidity, and temperature sensor, in our case, we used the DS18B20 Temperature sensor (waterproof type) For aquaculture, you might also add dissolved oxygen (DO) and ammonia sensors.

How does the ESP8266 connect an Arduino to Blynk?

The Arduino sends sensor readings to the ESP-01 via serial communication. The ESP-01 then transmits this data over WiFi to the Blynk cloud server, which pushes it to your smartphone or PC as in our own case. Since we could take the monitoring readings and measurements either using our smart phone or using the Personal Computer (PC).

Can you measure turbidity and TDS with an Arduino?

Yes. The turbidity sensor uses light scattering, while the TDS sensor measures electrical conductivity. Both provide analog signals the Arduino can read easily.

You can also read up on the topic: Smart Farming Solutions for Sustainable Agriculture Practices

How do you power an ESP8266 from Li-ion batteries?

You use a DC-DC buck converter to step down voltage from ~7.4V (two batteries in series) to ~3.7V–3.8V, which is safe for the ESP-01.

What are typical pH, TDS, turbidity ranges for aquaponics?

  • pH: 6.5–7.5
  • TDS: 500–1200 ppm
  • Turbidity: Below 5 NTU for hydroponics, below 10 NTU for aquaculture

Soldering, Coupling and Enclosure

soldering and coupling the IoT based project

Assembling the project together is another feat. You would have to know how to connect and manage the cables for the project design. It would be advisable to find a way to make the batteries rechargeable.

Openings for the casing to ensure entry of the module sensors and to easily connect the USB programming cords to program the boards. This example is shown in the image above too.

Calibration and Testing

testing the Turbidity sensor_non contact type

Sensors don’t work straight out of the box like a plug-in kettle. They need calibration.

  • pH: Use buffer solutions (pH 4, 7, 10).
  • TDS: Compare with a handheld TDS meter and adjust with calibration factor.
  • Turbidity: Test with clear water vs. muddy water to set thresholds.

Once calibrated, dip the sensors in your transparent container of water and check the dashboard readings. We checked our sensor modules individually. As shown above, our non-contact turbidity sensor module was tested, so was the TDS and pH sensor module using different solutions.

Real-World Benefits of This Setup

  • Remote monitoring saves time and effort.
  • Cost-effective compared to commercial water monitoring stations.
  • Portable thanks to battery power and compact enclosure.
  • Customizable—you can add or remove sensors as needed.

Limitations You Should Know

Nothing’s perfect. Here are some issues we faced:

  • Battery drain if WiFi signal is weak.
  • Sensor drift over time requiring re-calibration.
  • Not waterproof unless properly sealed.
  • Limited ESP-01 GPIO pins (you may upgrade to ESP32 in future).

Best Tips and Recommendations For this Project Design

Best power supply for ESP8266 in battery systems

Use a step-down buck converter with Li-ion batteries. Alternatively, small 3.7V LiPo batteries with protection circuits work well.

Blynk dashboard for water quality monitoring

The dashboard can show real-time charts, digital displays, and even push alerts if pH or TDS levels drift out of range.

H3: IoT hydroponics monitoring with Arduino Nano

This project is exactly that—affordable, DIY, and effective for small-scale growers.

Future Enhancements

The project doesn’t have to stop here. Some ideas:

  • You can choose to add dissolved oxygen sensors.
  • Use solar panels to charge batteries.
  • Upgrade to ESP32 for more GPIOs and built-in WiFi.
  • Integrate machine learning to predict water quality trends.

Conclusion – Why You Should Try This

Building your own DIY IoT hydroponic and aquaculture monitor isn’t just a fun project. It’s practical, cost-saving, and future-ready. Whether you’re into gardening, fish farming, or just tinkering with electronics, this setup gives you control over water quality at your fingertips.

It’s like having superpowers—you can “see” what’s happening in your water without dipping a finger in. And once you’ve tried it, you’ll never want to go back to guesswork.

FAQs

Q1: Can this system be used for both hydroponics and aquaculture?

Yes. The same sensors (pH, TDS, turbidity and Temperature) apply to both, though aquaculture may need extra sensors like dissolved oxygen.

Q2: How long do the batteries last?

It depends on WiFi usage and sensor power draw, but typically 6–12 hours of continuous operation. With optimization, it can last longer.

Q3: Do I need internet to use this system?

Yes, the ESP-01 relies on WiFi. But you could set up a local server if internet access is limited.

Q4: Is this project beginner-friendly?

Absolutely. If you can follow simple wiring and upload sketches in Arduino IDE, you’re good to go.

Q5: Can I expand the project in future?

Definitely. You can add temperature, DO, ammonia, or even automate pumps and feeders with relays.

smartechlabs

Recent Posts

The Role of Food in Korean Movies and Dramas

Introduction The role of Food in Korean Movies The Role of Food in Korean Movies…

1 week ago

How To Build An IoT Home Automation & Surveillance with ESP32 Cam, Arduino & Blynk

Introduction https://youtu.be/Dfv_-Rp0FEw Imagine being able to switch off your lights, monitor your room, or get…

2 weeks ago

Sustainable Living the African Way: What Your Grandma Knew That You Forgot

Introduction Remember how your grandma tended her garden, cooked with local grains, and built with…

1 month ago

The Making of Nigeria: How a Nation Was Forged by Colonialism

Have you ever wondered how a country as diverse and dynamic as Nigeria came to…

2 months ago

Crowning Glory: A Journey Through Africa’s 10 Most Renowned Royal Headwear

Have you ever wondered about the powerful symbols that adorn the heads of kings and…

2 months ago

The Degree Delusion: Why a University Diploma Isn’t the Only Path to a Great Career

Have you ever felt it? That nagging pressure, that pervasive idea that unless you've got…

2 months ago

This website uses cookies.