OC
OceanRemote
Low-code IoT platform
← Back to Course

LED and Relay Control Examples

💡 LED and Relay Control - Complete Guide for IoT Automation

🔌 What You'll Learn in This Lesson:

  • Control LEDs as indicators for system status
  • Master relay modules to control water pumps, lights, and motors
  • Understand active LOW vs active HIGH relays
  • Build complete irrigation control systems
  • Add status indicators to your farm automation projects

📊 LED vs Relay - What's the Difference?

Component Purpose Typical Load Voltage
LED Visual indicator 20mA 3.3V
Relay Module Switch high-power devices 10A 250V AC / 30V DC Controls 110-240V AC
💡 Understanding Relay Logic:

Most relay modules are active LOW:
digitalWrite(RELAY_PIN, LOW) → Relay ON (circuit closed)
digitalWrite(RELAY_PIN, HIGH) → Relay OFF (circuit open)

🔌 Complete Wiring Diagrams

💡 LED Wiring (Indicator Light)

LED Connections (Current flows from Anode to Cathode):
┌─────────────────────────────────────────────────────────────┐
│  ESP32 GPIO4  ───► 220Ω Resistor ───► LED Anode (long leg)  │
│  ESP32 GND     ─────────────────────► LED Cathode (short leg)│
└─────────────────────────────────────────────────────────────┘

Resistor calculation (Ohm's Law):
R = (V_source - V_LED) / I_LED
R = (3.3V - 2.0V) / 0.02A = 65Ω minimum
220Ω is safe for all LEDs (5-10mA)
    

💧 Relay Wiring (Water Pump)

Relay Module (Active LOW):
┌─────────────────────────────────────────────────────────────┐
│  ESP32 GPIO5   ──────────────────────────► Relay IN pin    │
│  ESP32 3.3V    ──────────────────────────► Relay VCC       │
│  ESP32 GND     ──────────────────────────► Relay GND       │
└─────────────────────────────────────────────────────────────┘

High-Power Circuit (Use thick wire!):
┌─────────────────────────────────────────────────────────────┐
│  12V Battery (+)  ───► Relay COM ───► Relay NO  ───► Pump (+) │
│  12V Battery (-)  ────────────────────────────────► Pump (-) │
│                                                            │
│  When Relay ON: COM connected to NO → Pump runs           │
└─────────────────────────────────────────────────────────────┘
    
⚠️ SAFETY WARNING:

Relays can control high voltage (110-240V AC)! Always:

  • Disconnect power when wiring
  • Use properly rated wire (at least 18 AWG for pumps)
  • Keep ESP32 and high-voltage circuits separated
  • Use an enclosure to prevent accidental contact

📖 Complete LED Control Examples

1. Basic LED Blink (Indicator)

/*
 * Basic LED Blink - System Status Indicator
 * LED blinks to show system is running
 */

#define LED_PIN 4

void setup() {
    pinMode(LED_PIN, OUTPUT);
    Serial.begin(115200);
    Serial.println("✅ System started - LED blinking");
}

void loop() {
    // Blink pattern: on for 1 second, off for 1 second
    digitalWrite(LED_PIN, HIGH);
    Serial.println("🔴 LED ON");
    delay(1000);
    
    digitalWrite(LED_PIN, LOW);
    Serial.println("⚫ LED OFF");
    delay(1000);
}
    

2. Status LED - Shows WiFi Connection

/*
 * Status LED Indicator
 * LED behavior indicates system status
 * 
 * - Fast blink: Connecting to WiFi
 * - Slow blink: WiFi connected, working
 * - Solid ON: Error or maintenance mode
 */

#include 

#define STATUS_LED 4

const char* ssid = "YOUR_WIFI";
const char* password = "YOUR_PASSWORD";

void setup() {
    pinMode(STATUS_LED, OUTPUT);
    Serial.begin(115200);
    
    // Fast blink while connecting
    for (int i = 0; i < 10; i++) {
        digitalWrite(STATUS_LED, HIGH);
        delay(100);
        digitalWrite(STATUS_LED, LOW);
        delay(100);
    }
    
    Serial.println("📡 Connecting to WiFi...");
    WiFi.begin(ssid, password);
    
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    
    Serial.println("\n✅ WiFi connected!");
    
    // Slow blink pattern for normal operation
}

void normalBlink() {
    digitalWrite(STATUS_LED, HIGH);
    delay(2000);
    digitalWrite(STATUS_LED, LOW);
    delay(2000);
}

void errorBlink() {
    digitalWrite(STATUS_LED, HIGH);
    delay(500);
    digitalWrite(STATUS_LED, LOW);
    delay(500);
    digitalWrite(STATUS_LED, HIGH);
    delay(500);
    digitalWrite(STATUS_LED, LOW);
    delay(2000);
}

void loop() {
    if (WiFi.status() == WL_CONNECTED) {
        normalBlink();
    } else {
        errorBlink();
    }
}
    

💧 Complete Relay Control Examples

1. Basic Water Pump Control

/*
 * Basic Water Pump Control
 * Turn pump on/off with simple functions
 */

#define RELAY_PIN 5

void setup() {
    pinMode(RELAY_PIN, OUTPUT);
    digitalWrite(RELAY_PIN, HIGH);  // Start with pump OFF
    Serial.begin(115200);
    Serial.println("💧 Water pump controller ready");
}

void waterPump(int seconds) {
    Serial.printf("💧 Pump ON for %d seconds\n", seconds);
    digitalWrite(RELAY_PIN, LOW);   // Relay ON → Pump runs
    delay(seconds * 1000);
    digitalWrite(RELAY_PIN, HIGH);  // Relay OFF → Pump stops
    Serial.println("💧 Pump OFF");
}

void loop() {
    // Example: Water for 5 seconds every minute
    waterPump(5);
    delay(55000);  // Wait 55 seconds (total 60 seconds cycle)
}
    

2. Soil Moisture-Based Irrigation (Full Automation)

/*
 * Smart Irrigation System
 * Waters crops automatically based on soil moisture
 * 
 * Components:
 * - Soil moisture sensor on GPIO32
 * - Relay on GPIO5 (controls water pump)
 * - LED on GPIO4 (status indicator)
 */

#include 
#include 

// Pin definitions
#define SOIL_SENSOR_PIN 32
#define RELAY_PIN 5
#define STATUS_LED 4

// WiFi (for sending data)
const char* ssid = "YOUR_WIFI";
const char* password = "YOUR_PASSWORD";
const char* token = "YOUR_TOKEN";

// Soil moisture calibration
const int DRY_VALUE = 3800;
const int WET_VALUE = 1500;
const int WATER_THRESHOLD = 35;   // Water below 35%
const int WATER_DURATION = 10;     // Water for 10 seconds

// System state
bool isWatering = false;
unsigned long wateringStartTime = 0;

void setup() {
    Serial.begin(115200);
    
    pinMode(RELAY_PIN, OUTPUT);
    pinMode(STATUS_LED, OUTPUT);
    digitalWrite(RELAY_PIN, HIGH);  // Pump OFF
    digitalWrite(STATUS_LED, LOW);
    
    Serial.println("========================================");
    Serial.println("🌱 Smart Irrigation System v1.0");
    Serial.println("   Waters automatically when soil is dry");
    Serial.println("========================================");
}

int readSoilMoisture() {
    int raw = analogRead(SOIL_SENSOR_PIN);
    int moisture = map(raw, DRY_VALUE, WET_VALUE, 0, 100);
    moisture = constrain(moisture, 0, 100);
    return moisture;
}

void startWatering() {
    isWatering = true;
    wateringStartTime = millis();
    digitalWrite(RELAY_PIN, LOW);   // Pump ON
    digitalWrite(STATUS_LED, HIGH); // LED ON to show watering
    Serial.println("💧 WATERING STARTED");
}

void stopWatering() {
    isWatering = false;
    digitalWrite(RELAY_PIN, HIGH);  // Pump OFF
    digitalWrite(STATUS_LED, LOW);  // LED OFF
    Serial.println("💧 WATERING STOPPED");
    
    // Optional: Send notification to cloud
    sendWateringComplete();
}

void sendWateringComplete() {
    if (WiFi.status() == WL_CONNECTED) {
        HTTPClient http;
        http.begin("https://api.oceanremote.net/device/state");
        http.addHeader("Content-Type", "application/x-www-form-urlencoded");
        
        String data = "token=" + String(token);
        data += "&irrigation=completed";
        http.POST(data);
        http.end();
    }
}

void loop() {
    if (isWatering) {
        // Check if watering duration is complete
        if (millis() - wateringStartTime >= (WATER_DURATION * 1000)) {
            stopWatering();
        }
    } else {
        // Check soil moisture and decide to water
        int moisture = readSoilMoisture();
        
        Serial.print("💧 Soil moisture: ");
        Serial.print(moisture);
        Serial.println("%");
        
        if (moisture < WATER_THRESHOLD) {
            Serial.println("⚠️ Soil too dry! Starting irrigation...");
            startWatering();
        }
        
        // Blink LED to show system is alive
        digitalWrite(STATUS_LED, HIGH);
        delay(50);
        digitalWrite(STATUS_LED, LOW);
    }
    
    delay(30000);  // Check soil every 30 seconds
}
    

3. Multi-Zone Irrigation System

/*
 * Multi-Zone Irrigation System
 * Control up to 5 separate watering zones
 * Perfect for farms with different crop sections
 */

#define ZONE1_RELAY 5
#define ZONE2_RELAY 16
#define ZONE3_RELAY 17
#define ZONE4_RELAY 18
#define ZONE5_RELAY 19

// Zone configuration
struct Zone {
    int relayPin;
    const char* name;
    int waterDuration;  // seconds
};

Zone zones[] = {
    {ZONE1_RELAY, "Tomatoes", 15},
    {ZONE2_RELAY, "Maize", 10},
    {ZONE3_RELAY, "Vegetables", 12},
    {ZONE4_RELAY, "Fruit Trees", 20},
    {ZONE5_RELAY, "Nursery", 8}
};

const int ZONE_COUNT = 5;

void setup() {
    Serial.begin(115200);
    
    for (int i = 0; i < ZONE_COUNT; i++) {
        pinMode(zones[i].relayPin, OUTPUT);
        digitalWrite(zones[i].relayPin, HIGH);  // All OFF initially
        Serial.printf("✅ Zone %d: %s ready\n", i+1, zones[i].name);
    }
    
    Serial.println("\n💧 Multi-Zone Irrigation System Ready");
    Serial.println("   Watering zones in sequence...\n");
}

void waterZone(int zoneIndex) {
    Zone *z = &zones[zoneIndex];
    
    Serial.printf("💧 Watering Zone %d: %s (%d seconds)\n", 
                  zoneIndex + 1, z->name, z->waterDuration);
    
    digitalWrite(z->relayPin, LOW);   // Pump ON
    delay(z->waterDuration * 1000);
    digitalWrite(z->relayPin, HIGH);  // Pump OFF
    
    Serial.printf("✅ Zone %d complete\n\n", zoneIndex + 1);
}

void loop() {
    for (int i = 0; i < ZONE_COUNT; i++) {
        waterZone(i);
        delay(5000);  // Pause between zones
    }
    
    Serial.println("🔄 Complete cycle finished. Waiting 1 hour...\n");
    delay(3600000);  // Wait 1 hour before next cycle
}
    
📖 Real-World Application - Ghanaian Vegetable Farm:

A small farm automated irrigation for 5 different vegetable sections:

  • 💧 Setup: ESP32 + 5 relay module + 5 solenoid valves
  • 💡 LED indicators showed which zone was active
  • 📈 Result: 40% water savings, 30% yield increase
  • Time saved: Farmer saved 2 hours daily previously spent on manual watering

"Now I can water different sections automatically while I work on other tasks!" - Farmer, Ghana

📊 Relay Logic Reference

Relay Type ON Command OFF Command Most Common
Active LOW LOW (0) HIGH (1) ✅ 90% of modules
Active HIGH HIGH (1) LOW (0) Rare
🎉 Congratulations!

You've mastered LED and relay control for farm automation!

✅ LED status indicators for system feedback

✅ Relay control for pumps, lights, and valves

✅ Automatic soil moisture-based irrigation

✅ Multi-zone irrigation systems

Your crops will now get water exactly when they need it!

📚 Quick Reference - Digital Output:
pinMode(pin, OUTPUT);              // Configure pin as output
digitalWrite(pin, HIGH);           // Set pin to 3.3V
digitalWrite(pin, LOW);            // Set pin to 0V
digitalWrite(RELAY, LOW);          // Active LOW relay ON
digitalWrite(RELAY, HIGH);         // Active LOW relay OFF
💡 Key Takeaways:
  • Apply these concepts directly to your farm or project.
  • Take notes on important details for the quiz.
  • Use the button below to track your progress.