553  Sensor Applications

Real-World IoT Implementation Examples

sensing
applications
smart-home
automation
Author

IoT Textbook

Published

January 19, 2026

Keywords

smart home, environmental monitoring, servo control, relay switching, MQTT, automation

553.1 Learning Objectives

By the end of this chapter, you will be able to:

  • Build a complete smart home environmental monitoring system with MQTT integration
  • Implement sensor-actuator feedback loops for automated control
  • Design temperature-controlled relay switching with hysteresis to prevent rapid cycling
  • Select appropriate sensors for common IoT applications
  • Apply real-world control logic patterns to sensor-driven automation

553.2 Introduction

This chapter brings together sensor interfacing, data processing, and actuation into complete, practical IoT applications. Each example demonstrates the full sensor-to-action pipeline, from reading physical measurements to triggering real-world responses.

553.3 Smart Home Environmental Monitoring

25 min | Intermediate | P06.C09.U05a

A complete environmental monitoring system combining multiple sensors with cloud connectivity and automated responses.

// Complete environmental monitoring system
#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
#include <Wire.h>
#include <BH1750.h>

// Sensors
DHT dht(4, DHT22);
BH1750 lightMeter;

// Wi-Fi and MQTT
WiFiClient espClient;
PubSubClient mqtt(espClient);

// Thresholds
#define TEMP_HIGH 28.0
#define TEMP_LOW 18.0
#define HUMIDITY_HIGH 70.0
#define LIGHT_THRESHOLD 200.0

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

  // Initialize sensors
  dht.begin();
  Wire.begin();
  lightMeter.begin();

  // Connect to Wi-Fi
  connectWiFi();

  // Connect to MQTT
  mqtt.setServer("mqtt.example.com", 1883);
  connectMQTT();
}

void loop() {
  if (!mqtt.connected()) {
    connectMQTT();
  }
  mqtt.loop();

  // Read sensors
  float temp = dht.readTemperature();
  float humidity = dht.readHumidity();
  float light = lightMeter.readLightLevel();

  // Check conditions and take actions
  if (temp > TEMP_HIGH) {
    Serial.println("Temperature too high! Turning on AC");
    mqtt.publish("home/ac", "ON");
  } else if (temp < TEMP_LOW) {
    Serial.println("Temperature too low! Turning on heater");
    mqtt.publish("home/heater", "ON");
  }

  if (humidity > HUMIDITY_HIGH) {
    Serial.println("Humidity too high! Turning on dehumidifier");
    mqtt.publish("home/dehumidifier", "ON");
  }

  if (light < LIGHT_THRESHOLD) {
    Serial.println("Dark! Turning on lights");
    mqtt.publish("home/lights", "ON");
  } else {
    mqtt.publish("home/lights", "OFF");
  }

  // Publish sensor data
  String payload = "{\"temp\":" + String(temp) +
                   ",\"humidity\":" + String(humidity) +
                   ",\"light\":" + String(light) + "}";
  mqtt.publish("home/sensors", payload.c_str());

  delay(60000);  // 1 minute
}

void connectWiFi() {
  WiFi.begin("SSID", "password");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWi-Fi connected");
}

void connectMQTT() {
  while (!mqtt.connected()) {
    if (mqtt.connect("ESP32_Home_Sensor")) {
      Serial.println("MQTT connected");
    } else {
      delay(5000);
    }
  }
}

553.4 Sensor-Controlled Servo Motor

20 min | Intermediate | P06.C09.U05b

Servo Motors in IoT: Servo motors provide precise angular positioning, making them ideal for automated control systems. Combined with sensors, they create feedback-controlled actuators.

Specifications (SG90 Servo):

  • Rotation Range: 0 to 180 degrees
  • Control: PWM signal (1000-2000us pulse width)
  • Torque: 1.8kg/cm at 5V
  • Speed: 0.1s/60 degrees at 5V
  • Power: 5V, 100-250mA (moving), 10mA (idle)

553.4.1 Application Example: Automated Blinds Control

#include <ESP32Servo.h>

#define SERVO_PIN 18
#define LDR_PIN 34

Servo blindsServo;

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

  // Attach servo
  blindsServo.attach(SERVO_PIN, 1000, 2000);  // min, max pulse width

  // Configure ADC
  analogReadResolution(12);
  analogSetAttenuation(ADC_11db);

  Serial.println("Automated Blinds Control");
}

void loop() {
  // Read light sensor
  int lightLevel = analogRead(LDR_PIN);
  float lightPercent = (lightLevel / 4095.0) * 100;

  // Map light level to servo angle
  // High light = close blinds (180 degrees)
  // Low light = open blinds (0 degrees)
  int servoAngle = map(lightLevel, 0, 4095, 0, 180);

  // Move servo
  blindsServo.write(servoAngle);

  // Display status
  Serial.print("Light: ");
  Serial.print(lightPercent, 1);
  Serial.print("% | Servo Angle: ");
  Serial.print(servoAngle);
  Serial.print(" deg | Blinds: ");

  if (servoAngle < 45) {
    Serial.println("Fully Open");
  } else if (servoAngle < 135) {
    Serial.println("Partially Open");
  } else {
    Serial.println("Fully Closed");
  }

  delay(1000);
}
TipLearning Points

Observe:

  • Sensor-Actuator Feedback Loop: Light sensor to decision logic to servo control
  • PWM Servo Control: Pulse width (1000-2000us) determines angle (0-180 degrees)
  • Map Function: Converts sensor range to actuator range
  • Proportional Control: Servo angle proportional to light level
  • Real-time Response: System continuously adjusts to changing conditions

Control Logic:

High Light (bright)  -> Angle 180 deg -> Blinds CLOSED (shade interior)
Medium Light         -> Angle 90 deg  -> Blinds HALF (moderate light)
Low Light (dark)     -> Angle 0 deg   -> Blinds OPEN (maximize daylight)

Real-World Applications:

  • Automated Blinds/Curtains: Adjust based on time of day and sunlight
  • Solar Panel Tracking: Follow sun position for maximum efficiency
  • Smart Vents: Open/close based on temperature readings
  • Robotic Arms: Position based on distance sensor feedback
  • Camera Pan/Tilt: Track objects detected by motion sensors

Experiment:

  • Add hysteresis: only move servo if light changes by >10%
  • Implement smooth transitions instead of immediate movements
  • Add manual override with buttons
  • Create schedules: fully open in morning, close at noon
  • Use temperature sensor to control ventilation servo

553.5 Temperature-Controlled Relay Switching

20 min | Intermediate | P06.C09.U05c

Relays in IoT: Relays are electrically operated switches that allow low-power microcontrollers to control high-power AC/DC devices safely. Essential for home automation and industrial control.

Relay Specifications:

  • Control: 3.3V or 5V DC signal
  • Switch: 10A @ 250VAC or 10A @ 30VDC (typical)
  • Isolation: Optical/electrical isolation between control and load
  • Types: SPST, SPDT, DPDT
  • Response Time: 10-15ms

553.5.1 Application Example: Temperature-Controlled Fan

#include <DHT.h>

#define DHT_PIN 4
#define RELAY_PIN 13

#define TEMP_THRESHOLD_ON 28.0   // Turn fan ON above 28C
#define TEMP_THRESHOLD_OFF 26.0  // Turn fan OFF below 26C (hysteresis)

DHT dht(DHT_PIN, DHT22);
bool fanState = false;

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

  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, LOW);  // Fan initially OFF

  dht.begin();

  Serial.println("Temperature-Controlled Fan System");
}

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

  if (isnan(temperature) || isnan(humidity)) {
    Serial.println("Failed to read from DHT sensor!");
    delay(2000);
    return;
  }

  // Control logic with hysteresis to prevent rapid switching
  if (!fanState && temperature > TEMP_THRESHOLD_ON) {
    // Turn fan ON
    fanState = true;
    digitalWrite(RELAY_PIN, HIGH);
    Serial.println("Temperature HIGH - Fan turned ON");
  }
  else if (fanState && temperature < TEMP_THRESHOLD_OFF) {
    // Turn fan OFF
    fanState = false;
    digitalWrite(RELAY_PIN, LOW);
    Serial.println("Temperature OK - Fan turned OFF");
  }

  // Display status
  Serial.print("Temp: ");
  Serial.print(temperature, 1);
  Serial.print("C | Humidity: ");
  Serial.print(humidity, 1);
  Serial.print("% | Fan: ");
  Serial.println(fanState ? "ON" : "OFF");

  delay(2000);
}
TipLearning Points

Observe:

  • Hysteresis Control: Different ON/OFF thresholds (28C ON, 26C OFF) prevent rapid switching
  • Relay Switching: GPIO pin controls relay coil, relay contacts switch high-power load
  • Electrical Isolation: Relay physically separates low-voltage control from high-voltage load
  • State Management: Boolean flag tracks fan state between loop iterations
  • Safety: Microcontroller never directly touches high-voltage circuits

Hysteresis Explanation:

Temperature Rising: 24C -> 26C -> 28C -> [FAN TURNS ON]
Temperature Falling: 30C -> 28C -> 26C -> [FAN TURNS OFF]

Without Hysteresis (bad):
27.9C -> OFF, 28.1C -> ON, 27.9C -> OFF... (rapid switching damages relay!)

With Hysteresis (good):
Temperature must fall to 26C before turning off again

Real-World Applications:

  • HVAC Control: Heating/cooling systems with thermostats
  • Irrigation Systems: Pump control based on soil moisture
  • Lighting Control: Turn on/off high-wattage lights
  • Industrial Automation: Motor control, conveyor systems
  • Safety Systems: Emergency shutoffs, fire suppression
  • Appliance Automation: Coffee makers, heaters, refrigerators

Safety Considerations:

  • Never work on AC circuits while powered
  • Use proper gauge wire for current load
  • Ensure relay rating exceeds load requirements
  • Add flyback diodes for inductive loads (motors, solenoids)

Experiment:

  • Add multiple temperature zones with different thresholds
  • Implement time delays: keep fan on for minimum 5 minutes
  • Add manual override button
  • Log switching events to detect relay wear
  • Implement β€œsmart” scheduling: different thresholds for day/night

553.6 Sensor Selection Guide

15 min | Intermediate | P06.C09.U04

553.6.1 Comparison of Common Temperature Sensors

Sensor Range Accuracy Interface Power Cost Use Case
DHT22 -40 to 80C 0.5C 1-Wire digital 1.5mA $ General purpose, humidity too
DS18B20 -55 to 125C 0.5C 1-Wire 1.5mA $ Multiple sensors, waterproof
LM35 -55 to 150C 0.5C Analog 60uA $ Simple, low power
BME280 -40 to 85C 1C I2C/SPI 3.6uA \[ | Pressure, humidity, altitude | | TMP117 | -55 to 125C | 0.1C | I2C | 3.5uA | \]$ High precision applications

553.6.2 Sensor Interface Decision Tree

%%{init: {'theme':'base', 'themeVariables': {'primaryColor':'#2C3E50','primaryTextColor':'#fff','primaryBorderColor':'#16A085','lineColor':'#16A085','secondaryColor':'#E67E22','tertiaryColor':'#ECF0F1','fontSize':'13px'}}}%%
flowchart TD
    Start[Sensor Selection Decision]
    Q1{Need multiple<br/>sensors?}
    Q2{Speed critical?<br/>MHz needed?}
    Q3{Just ON/OFF?}
    Q4{Digital output<br/>available?}

    I2C[I2C Protocol<br/>2 wires, multiple devices]
    SPI[SPI Protocol<br/>4 wires, high speed]
    Digital[Digital GPIO<br/>Simple HIGH/LOW]
    UART[UART/Serial<br/>Async communication]
    Analog[Analog ADC<br/>Voltage reading]

    Start --> Q1
    Q1 -->|Yes| Q2
    Q1 -->|No| Q3
    Q2 -->|Yes| SPI
    Q2 -->|No| I2C
    Q3 -->|Yes| Digital
    Q3 -->|No| Q4
    Q4 -->|Yes| UART
    Q4 -->|No| Analog

    style Start fill:#2C3E50,stroke:#16A085,color:#fff
    style I2C fill:#16A085,stroke:#2C3E50,color:#fff
    style SPI fill:#16A085,stroke:#2C3E50,color:#fff
    style Digital fill:#16A085,stroke:#2C3E50,color:#fff
    style UART fill:#16A085,stroke:#2C3E50,color:#fff
    style Analog fill:#16A085,stroke:#2C3E50,color:#fff
    style Q1 fill:#E67E22,stroke:#2C3E50,color:#fff
    style Q2 fill:#E67E22,stroke:#2C3E50,color:#fff
    style Q3 fill:#E67E22,stroke:#2C3E50,color:#fff
    style Q4 fill:#E67E22,stroke:#2C3E50,color:#fff

Figure 553.1: Sensor Interface Protocol Selection: Decision Tree for I2C, SPI, or Analog

553.7 Practice Exercises

Objective: Build a multi-sensor system using I2C bus and resolve address conflicts.

Scenario: Connect BMP280 (pressure, 0x76), BH1750 (light, 0x23), and two MPU6050 IMUs (both default to 0x68) to an ESP32.

Tasks:

  1. I2C Address Scanning: Write code to scan I2C bus and detect all connected devices
  2. Address Conflict Resolution: MPU6050 has AD0 pin for address selection (0x68 or 0x69). Modify hardware to use different addresses
  3. Read All Sensors: Implement code to read from all 4 sensors in a single loop
  4. Timing Analysis: Measure read time at 100kHz vs 400kHz I2C speed
  5. Error Handling: Implement timeout and disconnection detection

Implementation Starter:

#include <Wire.h>

void scanI2C() {
    Serial.println("Scanning I2C bus...");
    for(byte addr = 1; addr < 127; addr++) {
        Wire.beginTransmission(addr);
        if (Wire.endTransmission() == 0) {
            Serial.printf("Found device at 0x%02X\n", addr);
        }
    }
}

// Exercise: Add code to read from all 4 sensors
// Exercise: Add error handling for sensor failures

Objective: Minimize power consumption for battery-powered sensor node.

Scenario: Battery-powered weather station (ESP32 + BME280 + BH1750) transmitting via LoRa every 15 minutes. Battery: 2000 mAh. Target lifetime: 1 year.

Tasks:

  1. Power Budget Analysis: Calculate current consumption for each component
  2. Lifetime Calculation: With sensors always on and ESP32 waking every 15 minutes, calculate battery lifetime
  3. Sensor Power Management: Implement code to power sensors on/off using GPIO-controlled MOSFET
  4. Buffering Strategy: Buffer 8 readings and transmit every 2 hours. Calculate power savings
  5. Adaptive Sampling: If temperature changes < 0.5C in 1 hour, reduce sampling to 30 minutes

Implementation Starter:

#define SENSOR_POWER_PIN 13

void powerOnSensors() {
    digitalWrite(SENSOR_POWER_PIN, HIGH);
    delay(100);  // Sensor stabilization time
}

void powerOffSensors() {
    digitalWrite(SENSOR_POWER_PIN, LOW);
}

void loop() {
    powerOnSensors();
    // Read sensors
    float temp = bme.readTemperature();
    powerOffSensors();

    // Buffer and transmit logic
    esp_deep_sleep(15 * 60 * 1000000);  // 15 minutes
}

Objective: Build complete data pipeline with calibration, filtering, validation, and anomaly detection.

Scenario: Industrial temperature monitoring using 10 DS18B20 sensors. Sensors require calibration and readings must be validated before sending to cloud.

Tasks:

  1. Two-Point Calibration: Calibrate all 10 sensors using ice bath (0C) and boiling water (100C). Store calibration coefficients in EEPROM/SPIFFS
  2. Data Validation: Implement checks:
    • Range validation: Reject readings outside -40C to 125C
    • Rate-of-change: Flag readings changing > 5C/minute (sensor malfunction)
    • Cross-sensor validation: If one sensor differs > 10C from average of others, flag as outlier
  3. Median Filtering: Apply 5-sample median filter to each sensor to remove spikes
  4. Anomaly Detection: If 3 consecutive readings from same sensor fail validation, send maintenance alert
  5. Data Logging: Format validated data as JSON with timestamps, calibrated values, and quality flags

553.8 Summary

This chapter covered real-world sensor applications:

  • Smart Home Monitoring: Multi-sensor environmental monitoring with MQTT integration
  • Servo Control: Light-responsive automated blinds using PWM servo control
  • Relay Switching: Temperature-controlled fan with hysteresis to prevent rapid cycling
  • Sensor Selection: Comparison of common temperature sensors and interface selection
  • Practical Patterns: Sensor-actuator feedback loops, state management, safety isolation

553.9 What’s Next

The next chapter provides a hands-on Sensor Calibration Lab using the Wokwi simulator, where you will implement two-point calibration, signal conditioning, and EEPROM storage.