Arduino • Environmental sensing • Beginner project

A pocket-sized weather station.

Measure the air. Notice the rain. Read the conditions at a glance. This compact build combines a DHT11 temperature-and-humidity sensor, a rain detection module and a 16×2 I2C LCD, all coordinated by an Arduino.

HUMIDITY · %
🌦️
TEMP · °C
3 sensors / interfacesDHT11, rain module and I2C display
2 digital data pinsD2 for DHT11, D3 for rain signal
16 × 2 charactersLive local readout on the LCD
01 / Introduction

What are we building?

A simple weather station is an electronic system that observes selected environmental conditions and presents the readings in a form that people can understand. In this project, the Arduino reads relative humidity and ambient temperature from a DHT11 sensor, checks a rain sensor's digital output, and prints the information on an I2C liquid-crystal display.

Weather information is useful in homes, gardens, classrooms, greenhouses and small outdoor experiments. A local station can help a user notice whether a room is becoming humid, whether the temperature is rising, or whether rain has reached a sensor plate. Unlike a professional meteorological instrument, this low-cost prototype is intended for learning and basic indication rather than certified forecasting. It does not predict tomorrow's weather; it reports what its sensors detect at the place where they are installed.

The project is especially suitable for beginners because it demonstrates three important embedded-system ideas in one build: collecting data from sensors, making a simple decision from a digital input, and presenting information through a display. The DHT11 communicates temperature and humidity through a single digital data wire. The rain module provides a digital HIGH/LOW indication. The LCD uses the I2C bus, which reduces the number of Arduino pins required compared with a conventional parallel LCD connection.

02 / Bill of materials

Components used

🧠

Arduino Uno

The microcontroller board. It runs the sketch, reads sensor signals, controls the LCD and coordinates the timing of the system. An Uno is used in the wiring diagram, although compatible Arduino boards can also work with suitable pin changes.

🌡️

DHT11 sensor

A digital sensor module that reports ambient temperature and relative humidity. It is inexpensive and easy to use, making it common in beginner projects. Its accuracy and operating range are limited compared with higher-grade sensors.

🌧️

Rain sensor module

Usually made from a conductive patterned sensing plate and a small comparator board. The plate responds to water bridging its tracks. The module's digital output is connected to Arduino pin D3.

▤

16×2 I2C LCD

A character display with an I2C backpack. It shows two rows of sixteen characters. The backpack commonly uses a PCF8574 expander, allowing the LCD to communicate over SDA and SCL.

🔌

Jumper wires

Male-to-male or suitable Dupont leads connect power, ground and signal pins. Use short, secure connections and check the labels on each module before powering the circuit.

⚡

USB / 5 V supply

A USB cable powers and programs the Arduino Uno. The board's 5 V and GND pins distribute power to modules that are designed for 5 V operation. Check module specifications before connecting them.

03 / Component theory

The science behind the modules

DHT11: temperature and humidity

The DHT11 combines a humidity-sensitive element, a temperature-sensing element and a small internal controller. The humidity element changes its electrical characteristics as moisture in the surrounding air changes. The temperature element measures the local temperature. Internal electronics convert these measurements into a digital data frame.

The Arduino does not measure an analog voltage from the DHT11. Instead, a library handles the sensor's timed one-wire-style communication protocol and returns numerical readings. The DHT11 is typically specified for approximately 0–50 °C and 20–80% relative humidity, with modest accuracy (commonly around ±2 °C and ±5% RH; check the exact manufacturer's datasheet). It is best suited to demonstrations and general indication, not precision climate control.

Allow the sensor to acclimatize to its environment. Avoid placing it next to a regulator, motor, direct sunlight or warm Arduino components, because local heating can distort the reading. A bare four-pin DHT11 and a three-pin breakout may have different pin layouts, so follow the markings or datasheet for your exact part.

Rain plate and comparator

The common rain sensor has a plate with interleaved conductive tracks. When the plate is dry, the electrical resistance between tracks is relatively high. Water droplets create conductive paths between tracks, changing the resistance. A companion module often contains an LM393 comparator and a potentiometer. The comparator compares the sensor signal with an adjustable threshold and produces a digital output.

This project reads only the module's digital output (DO). The program interprets LOW as rain and HIGH as no rain. That polarity is common, but not universal: some modules or wiring arrangements may behave differently. Test by observing the DO pin or temporarily printing its state to the Serial Monitor. If your module reports the opposite state, reverse the two messages in the sketch.

Rain plates can corrode when left wet or powered continuously. Rinse residue when appropriate, dry the plate after tests, and consider powering the plate only during brief measurements in a more advanced design. Do not expose the Arduino, LCD or breadboard to rain.

I2C LCD: displaying the readings

A standard 16×2 LCD can be controlled using several parallel data and control wires. An I2C backpack adds an I/O expander so the Arduino can send display commands over two signal lines: SDA (data) and SCL (clock). On an Arduino Uno, SDA is A4 and SCL is A5; the dedicated SDA/SCL header pins, where present, are electrically connected to the same bus.

The address in the supplied sketch is 0x27. Some backpacks use 0x3F or another address. If the backlight turns on but no text appears, check the contrast potentiometer and confirm the I2C address with an I2C scanner sketch. The display library used in the code must match the installed library's API.

Arduino: controller and logic

The Arduino Uno is built around an ATmega328P microcontroller. A sketch configures input and output pins, reads digital data, calls sensor-library functions, and updates the display. In this project D2 is reserved for the DHT11 data line and D3 for the rain module's digital output. The I2C interface uses A4/A5 on the Uno.

The microcontroller operates at 5 V logic on a typical Uno. Share a common ground between all modules so that signal voltages have a common reference. Never connect a signal or supply pin simply because it physically fits: verify voltage requirements and pin labels first.

04 / Operation

Working principle

Power-up and initialization

When power is applied, setup() initializes the I2C LCD, switches on its backlight, starts Serial communication at 9600 baud and configures the rain sensor pin as an input. The DHT11 object is associated with digital pin 2.

Acquire temperature and humidity

Inside loop(), the program calls readHumidity() and readTemperature(). The DHT11 library communicates with the sensor and returns values. The results are stored in integer variables.

Validate the readings

The condition temperature >= 0 && humidity >= 0 checks that both returned values are non-negative. If either reading is negative, the LCD is not refreshed in that pass. This is a simple check; the exact error convention depends on the DHT11 library version.

Display the measurements

The first LCD row shows humidity as a percentage and temperature in degrees Celsius. The expression (char)0xdf requests the degree symbol from the LCD character set. The second row is selected using setCursor(0,1).

Detect rain and repeat

The program reads the rain module on D3. A HIGH state displays “It's not Raining”; a LOW state displays “It's Raining”. The loop repeats continuously, so the display is refreshed whenever a valid DHT11 reading is obtained.

05 / Circuit design

Connection diagram

The SVG diagram below shows an Arduino Uno-style connection plan. It assumes a DHT11 module with a labelled DATA pin, a rain module with a digital DO output, and a 5 V I2C LCD backpack.

ARDUINO UNOATmega328P controller DIGITAL / POWER / I2C D2D35VGNDA4 / SDAA5 / SCL DHT11VCC DATA GND RAIN MODULEVCC DO GND 16×2 I2C LCDVCC · GND · SDA · SCL DATA → D2DO → D35V5VSDA → A4SCL → A5
Module pinArduino Uno connectionPurpose
DHT11 VCC5VSensor power (if the module supports 5 V)
DHT11 DATAD2Digital sensor communication
DHT11 GNDGNDCommon reference
Rain module VCC5VModule power
Rain module DOD3Digital wet/dry signal
Rain module GNDGNDCommon reference
LCD VCC / GND5V / GNDDisplay and backpack power
LCD SDA / SCLA4 / A5I2C data and clock
06 / Firmware

Full Arduino code

Code
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHT11.h>

#define rainSensor 3

DHT11 dht11(2);
LiquidCrystal_I2C lcd(0x27, 16, 2);

int temperature, humidity;

void setup()
{
  lcd.init();
  lcd.backlight();
  lcd.begin(16, 2);
  Serial.begin(9600);
  pinMode(rainSensor, INPUT);
}

void loop()
{
  humidity = dht11.readHumidity();
  temperature = dht11.readTemperature();

  if (temperature >= 0 && humidity >= 0)
  {
    lcd.clear();
    lcd.print("H:");
    lcd.print(humidity);
    lcd.print("%");
    lcd.print(", T:");
    lcd.print(temperature);
    lcd.print((char)0xdf);
    lcd.print("C");

    lcd.setCursor(0, 1);

    if (digitalRead(3) == HIGH)
    {
      lcd.print("It's not Raining");
    }
    else
    {
      lcd.print("It's Raining");
    }
  }
}

Code explanation

#include <Wire.h> loads Arduino's I2C communication library. The LCD backpack communicates through this bus, so the library is a foundational dependency.

#include <LiquidCrystal_I2C.h> makes the I2C LCD control functions available, including initialization, backlight control, cursor placement and printing characters.

#include <DHT11.h> loads the DHT11 sensor library. This library translates the sensor's timed digital protocol into temperature and humidity values.

#define rainSensor 3 creates a readable name for digital pin 3. The supplied sketch later uses digitalRead(3) directly; using digitalRead(rainSensor) would be equivalent and easier to maintain.

DHT11 dht11(2); creates a DHT11 object and assigns its data connection to Arduino digital pin 2.

LiquidCrystal_I2C lcd(0x27, 16, 2); creates an LCD object at I2C address 0x27 with sixteen columns and two rows. If your display has a different address, this value must be changed.

int temperature, humidity; declares two integer variables to hold the latest readings. Integer storage means the displayed values have no decimal places.

void setup() is executed once after reset or power-up. All one-time configuration belongs in this function.

lcd.init(); initializes the LCD interface. Some LiquidCrystal_I2C library versions use slightly different initialization calls, so follow the examples supplied with your installed library.

lcd.backlight(); turns on the display's backlight so the characters can be seen.

lcd.begin(16,2); configures a 16-column, 2-row display in library versions that support this call. Some versions do not require both init() and begin(); if compilation fails or initialization behaves oddly, use the exact initialization sequence documented by your library rather than blindly calling both.

Serial.begin(9600); starts serial communication at 9600 bits per second. The supplied sketch does not print debug messages yet, but the Serial Monitor can be used during testing by adding diagnostic Serial.print() calls.

pinMode(rainSensor, INPUT); configures D3 as an input so the Arduino can read the rain module's digital output.

void loop() runs repeatedly for as long as the board is powered. It is the repeating measurement and display routine.

humidity = dht11.readHumidity(); requests relative humidity from the DHT11 and stores the returned value in humidity.

temperature = dht11.readTemperature(); requests temperature in degrees Celsius and stores it in temperature.

if (temperature >= 0 && humidity >= 0) allows the display update only when both values are zero or greater. The && operator means both tests must be true. Confirm your library's documented error return values; this test is tailored to the supplied sketch's expected behaviour.

lcd.clear(); clears previous characters. Clearing on every pass is simple, although it can cause visible flicker. A refined version can overwrite fixed character positions instead.

lcd.print("H:"); prints a humidity label. The next print statement writes the numeric humidity value, followed by a percent sign.

lcd.print(", T:"); adds a separator and temperature label. The following statements print the temperature, the LCD degree character (code 0xDF on many compatible character LCDs), and the letter C.

lcd.setCursor(0, 1); moves the cursor to column zero of the second row. LCD row indexing starts at zero, so row 1 means the visible second line.

if (digitalRead(3) == HIGH) reads the rain sensor's digital output. If it is HIGH, the program prints “It's not Raining”. Otherwise it prints “It's Raining”. This matches active-LOW rain modules; test your own module's polarity.

07 / Bring-up checklist

Testing and troubleshooting

LCD backlight but no text

Adjust the small contrast potentiometer on the I2C backpack. Confirm the I2C address (0x27 is common, not guaranteed) and check SDA/SCL wiring. Run an I2C scanner if needed.

DHT11 values invalid

Check DATA is on D2, verify VCC/GND orientation, and confirm the installed DHT11 library matches the sketch's API. A bare sensor may need a pull-up resistor. Keep wires short.

Rain message reversed

Some modules use different output polarity or threshold settings. Observe the DO pin in dry and wet conditions, then swap the two displayed messages if necessary. Adjust the module potentiometer carefully.

08 / Evaluation

Advantages and disadvantages

Advantages

  • Low cost: the modules are widely available and suitable for student prototypes.
  • Beginner friendly: the wiring and program demonstrate fundamental Arduino concepts.
  • Immediate feedback: temperature, humidity and rain status are visible without a computer.
  • Compact wiring: I2C reduces the number of LCD signal wires.
  • Expandable: the Arduino can accept additional sensors or communication modules.
  • Useful demonstrations: it connects environmental science with electronics and programming.

Disadvantages

  • Limited DHT11 performance: its accuracy, resolution and measurement range are modest.
  • No forecasting: it reports local sensor conditions and cannot predict weather systems.
  • Rain plate maintenance: exposed conductive tracks can corrode or collect dirt.
  • Binary rain status: the supplied code does not quantify rainfall intensity.
  • Display limitations: a 16×2 LCD has little space for graphs, history or detailed diagnostics.
  • Library variation: different DHT11 and LCD libraries may require code changes.
  • Local influence: sunlight, heat sources, airflow and sensor placement can bias readings.
09 / Next iteration

Future scope and upgrades

Upgrade the sensor

Replace the DHT11 with a DHT22/AM2302 or a BME280 for improved measurement range and performance. Update the library and wiring according to the replacement sensor's documentation.

Measure rainfall amount

Add a tipping-bucket rain gauge with a pulse output. Counting calibrated tips over time can estimate rainfall accumulation, unlike the simple wet/dry plate.

Wireless monitoring

Use an ESP32 or ESP8266 to publish readings over Wi-Fi to a local dashboard or IoT platform. Add authentication and avoid exposing an unsecured device directly to the public internet.

Store a data history

Add a real-time clock and microSD card to timestamp and save measurements. Historical records make it possible to plot daily temperature and humidity changes.

Smarter display and alerts

Show min/max values, comfort indicators or a rolling average. A buzzer or LED can provide a local alert when a threshold is crossed, with user-adjustable limits.

Improve reliability

Add a weather-resistant enclosure, cable glands, sensor ventilation, watchdog recovery and non-blocking update timing. Keep the rain plate separate from protected electronics.

10 / Conclusion

A small build with big learning value

This Arduino weather station demonstrates how sensors, a microcontroller and a display can work together to turn environmental changes into useful information. The DHT11 provides temperature and relative humidity, the rain module supplies a digital wet/dry indication, and the I2C LCD presents the readings locally. The project is inexpensive, easy to understand and adaptable for classroom demonstrations or simple sheltered monitoring.

For dependable results, verify the exact pinout and voltage requirements of each module, confirm the I2C address, use compatible libraries, and test the rain sensor's output polarity. Treat the readings as approximate observations rather than professional weather data. With better sensors, data logging and wireless connectivity, this simple prototype can grow into a much more capable environmental monitoring station.