10  Common Sensors & MEMS

In 60 Seconds

The most common IoT sensors include DHT22 (temperature and humidity, $3-5), DS18B20 (multi-point temperature via 1-Wire, $2-3), BME280 (temperature, humidity, and pressure in one I2C chip, $5-10), MPU6050 (6-axis motion, $3-8), and PIR/ultrasonic for presence and distance. MEMS accelerometers work by measuring capacitance changes from a tiny proof mass displaced by acceleration. Choose sensors by balancing accuracy, power, cost, interface, and environmental needs.

Key Concepts
  • DHT11 vs. DHT22: Both digital temperature/humidity sensors using the same protocol; DHT11 (+-2 C, +-5% RH, 0-50 C) is cheaper but less accurate than DHT22 (+-0.5 C, +-2-5% RH, -40 to +80 C); use DHT22 for any accuracy-sensitive application
  • PIR Motion Sensor (HC-SR501): Passive Infrared sensor detecting movement from thermal radiation changes; binary output; adjustable sensitivity and delay time via potentiometers; detects humans up to approximately 7 m
  • HC-SR04 Ultrasonic Range Finder: Measures distance 2 cm to 4 m by timing a 40 kHz ultrasonic burst echo; distance_cm = pulseIn(ECHO, HIGH) x 0.0343 / 2; affected by soft surfaces, extreme angles, and temperature variation
  • BME280 Pressure/Temperature/Humidity: I2C/SPI sensor with pressure range 300-1100 hPa (+-1 hPa), temperature, and humidity; can derive altitude from pressure using the barometric formula with approximately +-1 m precision
  • MPU-6050 IMU: 6-axis MEMS IMU with 3-axis accelerometer (+-2/4/8/16 g) and 3-axis gyroscope (+-250/500/1000/2000 deg/s) on a single I2C chip; includes onboard DMP for motion processing
  • MQ-Series Gas Sensors: Electrochemical sensors for specific gases (MQ-2: LPG/methane, MQ-7: CO, MQ-135: air quality); analog output proportional to concentration; require 24-48 hour burn-in period for accurate readings
  • LDR (Light Dependent Resistor): A photoresistor whose resistance drops from ~1 Mohm in darkness to ~100 ohm in bright light; nonlinear response makes it best for threshold control rather than accurate lux measurement
  • MFRC522 RFID Module: 13.56 MHz ISO/IEC 14443-A RFID reader with SPI interface; reads MIFARE Classic cards; typical read range 3-5 cm; used for access control and identification in IoT systems

Learning Objectives

After completing this chapter, you will be able to:

  • Identify common IoT sensors and compare their specifications
  • Explain how MEMS (Micro-Electro-Mechanical Systems) accelerometers convert motion into electrical signals
  • Select appropriate sensor options for temperature, motion, distance, and environmental sensing based on project constraints
  • Diagnose sensor issues by applying principles of sensor physics and datasheet parameters

This chapter introduces the sensors you will encounter most often in IoT projects. A DHT22 measures temperature and humidity (like a digital weather station), a PIR sensor detects when someone walks past (like a motion-activated light), and an ultrasonic sensor measures distance using sound waves (like parking sensors on a car). Most of these cost just a few dollars and connect to a microcontroller with only a few wires.

10.1 Prerequisites

10.2 Common IoT Sensor Comparison

~30 min | Intermediate | P06.C08.U07

This comprehensive comparison table helps you select the right sensor for your specific IoT application.

Sensor Type Measures Range Interface Power Cost Common Uses
Temperature (DHT22) Temp, Humidity -40 to 80°C Single-wire Low $3-5 HVAC, weather
Temperature (DS18B20) Temperature -55 to 125°C 1-Wire Very Low $2-3 Industrial, water
Motion (PIR) Infrared motion 3-7m Digital GPIO Low $1-3 Security, lighting
Motion (Radar) Doppler motion 5-10m Digital GPIO Medium $5-15 Presence detection
Distance (Ultrasonic) Distance 2cm–4m Trigger/Echo Medium $2-5 Parking, level
Distance (ToF) Distance 3cm–2m I2C Low $5-15 Robotics, gesture
Light (LDR) Ambient light ~1–100k lux Analog Very Low $0.50 Day/night sensing
Light (VEML7700) Lux 0–120k lux I2C Low $3-6 Smart lighting
Accelerometer Motion, tilt +/-2–16g I2C/SPI Low $2-8 Wearables, impact
Air Quality (MQ-x) Gas, smoke Varies Analog High $3-10 Safety, pollution
Choosing the Right Sensor

Consider these factors:

  1. Accuracy - How precise does measurement need to be?
  2. Power - Battery-powered or mains?
  3. Environment - Indoor, outdoor, harsh conditions?
  4. Cost - Per-unit budget for deployment scale?
  5. Interface - Analog, digital (I2C, SPI, UART)?

10.3 Temperature Sensors

10.3.1 DHT22 (Temperature + Humidity)

Specifications:

  • Temperature: -40 to 80°C, +/-0.5°C accuracy
  • Humidity: 0-100% RH, +/-2% RH typical (+/-5% RH max)
  • Interface: Single-wire digital
  • Sampling rate: Max 0.5 Hz (1 reading per 2 seconds)
  • Price: $3-5

Best for: Indoor environmental monitoring, smart home

Limitations: Slow (2s between readings), no I2C option

10.3.2 DS18B20 (1-Wire Temperature)

Specifications:

  • Temperature: -55 to 125°C, +/-0.5°C accuracy (in -10 to +85°C range; +/-2°C outside)
  • Interface: 1-Wire (multiple sensors on one pin)
  • Resolution: 9-12 bit configurable
  • Price: $2-3

Best for: Multi-point temperature monitoring, waterproof applications

Unique feature: Multiple sensors share one GPIO pin (1-Wire bus)

10.3.3 BME280 (Temp + Humidity + Pressure)

Specifications:

  • Temperature: -40 to 85°C, +/-1°C accuracy
  • Humidity: 0-100% RH, +/-3% accuracy
  • Pressure: 300-1100 hPa, +/-1 hPa accuracy
  • Interface: I2C or SPI
  • Price: $5-10

Best for: Weather stations, altitude sensing, indoor air quality

10.4 Temperature Sensor Decision Framework

With so many temperature sensor options, choosing the right one requires matching specifications to your actual application requirements:

Decision Framework: Which Temperature Sensor?

Start with your accuracy requirement:

If you need… Choose Cost Why
+/-2°C (comfort sensing) DHT11 $1-2 Cheapest. Adequate for “is the room comfortable?”
+/-0.5°C (environmental monitoring) DHT22 or DS18B20 $3-5 Standard for most IoT projects
+/-1°C (weather stations, general monitoring) BME280 $5-10 Also measures humidity + pressure
+/-0.2°C (food safety, HVAC control) SHT31 $8-15 Factory calibrated, high repeatability
+/-0.1°C (laboratory, medical) PT100 RTD or MAX31865 $15-50 NIST-traceable, wide temperature range

Then consider your constraints:

Constraint Best Choice Why
Multiple sensors on one wire DS18B20 1-Wire bus: 10+ sensors on a single GPIO pin
Need humidity too DHT22 or BME280 Combined sensor reduces BOM and wiring
Waterproof required DS18B20 (waterproof variant) Available in sealed stainless steel probe
Battery-powered (years of life) BME280 0.1 uA typical sleep current (0.3 uA max); supports forced mode for minimal duty cycle
Hostile environment (>100°C) Thermocouple + MAX31855 Range to 1260°C for industrial applications

Common mistake: Choosing BME280 for a project that only needs temperature. At $5-10 per unit, you are paying for humidity and pressure you may not need. A $2-3 DS18B20 is better value if temperature is all you require.

10.5 Motion Sensors

10.5.1 PIR (Passive Infrared)

Specifications:

  • Detection range: 3-7m, 120-degree field of view
  • Output: Digital HIGH/LOW
  • Response time: ~0.5-1 second
  • Power: ~60 uA quiescent (PIR sensor element at 3.3V); complete HC-SR501 module draws ~50 mA at 5V
  • Price: $1-3

Best for: Security, lighting automation, occupancy

How it works: Detects changes in infrared radiation (body heat)

10.5.2 MPU6050 (6-axis IMU)

Specifications:

  • Accelerometer: +/-2/4/8/16g selectable
  • Gyroscope: +/-250/500/1000/2000 degrees/sec
  • Interface: I2C
  • Sample rate: Up to 1kHz
  • Price: $3-8

Best for: Motion tracking, orientation sensing, wearables

10.6 How MEMS Accelerometers Actually Work

The MPU6050 and similar motion sensors rely on MEMS (Micro-Electro-Mechanical Systems) technology. Understanding the physics behind these devices helps you choose the right one and interpret data correctly.

10.6.1 The Harmonic Oscillator Model

Many sensors can be modeled as mechanical harmonic oscillators – a mass on a spring:

How It Works:

  1. Proof mass (m): A tiny mass (~0.1 to 5 milligrams) suspended by microscopic springs
  2. Acceleration causes displacement: When the chip accelerates, the proof mass lags behind
  3. Measure displacement: On-chip electronics measure the displacement \(\Delta z\) via capacitance changes between interleaved plates
  4. Calculate acceleration: Using the factory-calibrated spring constant and mass, the chip computes: \(a = k \cdot \Delta z / m\)

Maximum Frequency (Bandwidth):

The highest frequency an accelerometer can measure is determined by its resonant frequency:

\[f_{max} = \frac{1}{2\pi}\sqrt{\frac{k}{m}}\]

  • Stiffer springs (higher k) -> higher frequency response but lower sensitivity
  • Lighter proof mass (lower m) -> higher frequency response
  • Trade-off: High-bandwidth accelerometers are less sensitive to small accelerations

Consider a MEMS accelerometer with spring constant \(k = 50\) N/m and proof mass \(m = 0.5\) mg (\(5 \times 10^{-7}\) kg):

\[f_{max} = \frac{1}{2\pi}\sqrt{\frac{50}{5 \times 10^{-7}}} = \frac{1}{2\pi}\sqrt{10^{8}} = \frac{10{,}000}{6.283} \approx 1{,}592 \text{ Hz}\]

The usable bandwidth is roughly 20–30% of the resonant frequency (depending on damping), giving approximately 320–480 Hz for this design. The ADXL345, for example, achieves a 1.6 kHz signal bandwidth by using a lighter proof mass and stiffer spring, trading sensitivity for higher frequency response.

Real MEMS accelerometer parameters vary widely by design: proof masses range from ~0.1 to 5 mg, spring constants from ~0.1 to 50 N/m, and resonant frequencies from hundreds of Hz to tens of kHz. The values above are representative of a general-purpose, moderate-sensitivity device. Consult individual datasheets for exact parameters.

10.6.2 Capacitive Displacement Measurement

MEMS accelerometers typically use capacitive sensing:

\[C = \frac{\epsilon_0 \cdot A}{d}\]

As the proof mass moves, d changes, changing capacitance. Electronics measure this capacitance change and calculate displacement.

10.6.2.1 MEMS Resonant Frequency Calculator

Explore the trade-off between spring stiffness, proof mass, and bandwidth:

10.7 Distance Sensors

10.7.1 HC-SR04 (Ultrasonic Distance)

Specifications:

  • Range: 2cm to 400cm
  • Accuracy: +/-3mm
  • Interface: Trigger/Echo (digital GPIO)
  • Beam angle: ~15 degrees
  • Price: $2-5

Best for: Parking sensors, tank level monitoring, obstacle avoidance

How it works: Sends a 40 kHz ultrasonic pulse and measures the echo return time. Distance = (time x speed of sound) / 2.

10.7.1.1 Ultrasonic Distance Calculator

Use this calculator to convert echo pulse duration to distance, accounting for ambient temperature (which affects the speed of sound in air):

10.7.2 VL53L0X (Time-of-Flight Distance)

Specifications:

  • Range: 30mm to 2000mm
  • Accuracy: +/-3% at distances up to 2m
  • Interface: I2C
  • Update rate: Up to 50 Hz
  • Price: $5-15

Best for: Gesture sensing, robotics, precise distance measurement

How it works: Emits a 940 nm infrared laser pulse and measures the round-trip time of flight to calculate distance with millimeter precision.

10.8 Environmental Sensors

10.8.1 MQ-135 (Air Quality)

Specifications:

  • Detects: NH3, NOx, alcohol, benzene, smoke, CO2
  • Range: 10-300 ppm (NH3), 10-1000 ppm (benzene)
  • Interface: Analog voltage
  • Power: 150mA (5V) - continuous heating required
  • Price: $3-8

Critical: Requires 24-48 hour burn-in before accurate readings!

10.8.2 BME680 (Environmental Gas)

Specifications:

  • Temperature, humidity, pressure + gas resistance
  • VOC sensing for indoor air quality
  • Interface: I2C/SPI
  • Price: $10-15

Best for: Indoor air quality monitoring, smart home

10.9 Sensor Deployment Cost Estimator

When planning an IoT deployment, estimating the total sensor cost across multiple nodes helps you choose the right sensors for your budget:

10.10 Code Example: Multi-Sensor I2C Scanner and Reader

This MicroPython example for ESP32 demonstrates a practical pattern for discovering and reading multiple I2C sensors on a shared bus. It automatically detects which sensors are connected and reads available data:

from machine import I2C, Pin
import time

class MultiSensorReader:
    """Discover and read common I2C sensors on a shared bus.

    Automatically identifies connected sensors by I2C address
    and reads all available measurements in a single scan cycle.
    """
    # Known I2C addresses for common IoT sensors
    KNOWN_SENSORS = {
        0x76: "BME280/BMP280",
        0x77: "BME280/BMP280 (alt)",
        0x68: "MPU6050",
        0x44: "SHT31",
        0x23: "BH1750 (light)",
        0x10: "VEML7700 (light)",
        0x48: "ADS1115 (ADC)",
    }

    def __init__(self, sda_pin=21, scl_pin=22, freq=400000):
        self.i2c = I2C(0, sda=Pin(sda_pin), scl=Pin(scl_pin),
                       freq=freq)
        self.detected = {}

    def scan(self):
        """Scan I2C bus and identify connected sensors."""
        addresses = self.i2c.scan()
        self.detected = {}
        for addr in addresses:
            name = self.KNOWN_SENSORS.get(addr, f"Unknown (0x{addr:02x})")
            self.detected[addr] = name
            print(f"  Found: {name} at 0x{addr:02X}")

        if not self.detected:
            print("  No I2C devices found. Check wiring:")
            print("  - SDA -> GPIO21, SCL -> GPIO22")
            print("  - 4.7k pull-up resistors on both lines")
        return self.detected

    def read_bme280_raw(self, addr=0x76):
        """Read temperature from BME280 (simplified).

        Production code should use the full compensation formula
        from the BME280 datasheet with calibration constants.
        """
        if addr not in self.detected:
            return None
        # Trigger forced measurement (ctrl_meas register)
        self.i2c.writeto_mem(addr, 0xF4, bytes([0x25]))
        time.sleep_ms(50)
        # Read raw temperature (registers 0xFA-0xFC)
        data = self.i2c.readfrom_mem(addr, 0xFA, 3)
        raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4)
        # Approximate temperature (actual requires calibration)
        temp_c = raw / 5120.0 - 30.0  # rough approximation
        return {"temperature_c": round(temp_c, 1), "raw_adc": raw}

    def read_mpu6050(self, addr=0x68):
        """Read accelerometer from MPU6050."""
        if addr not in self.detected:
            return None
        # Wake up MPU6050 (power management register)
        self.i2c.writeto_mem(addr, 0x6B, bytes([0x00]))
        time.sleep_ms(10)
        # Read 6 bytes of accelerometer data (XYZ, 2 bytes each)
        data = self.i2c.readfrom_mem(addr, 0x3B, 6)
        # Convert to signed 16-bit integers, scale to g
        def to_signed(msb, lsb):
            val = (msb << 8) | lsb
            return val - 65536 if val > 32767 else val

        scale = 16384.0  # +/-2g range default
        ax = to_signed(data[0], data[1]) / scale
        ay = to_signed(data[2], data[3]) / scale
        az = to_signed(data[4], data[5]) / scale
        return {"accel_g": (round(ax, 2), round(ay, 2), round(az, 2))}

    def read_all(self):
        """Read all detected sensors and return combined dict."""
        results = {}
        if 0x76 in self.detected or 0x77 in self.detected:
            addr = 0x76 if 0x76 in self.detected else 0x77
            results["bme280"] = self.read_bme280_raw(addr)
        if 0x68 in self.detected:
            results["mpu6050"] = self.read_mpu6050()
        return results

# Usage on ESP32
reader = MultiSensorReader(sda_pin=21, scl_pin=22)
print("Scanning I2C bus...")
reader.scan()
# Output:
#   Found: BME280/BMP280 at 0x76
#   Found: MPU6050 at 0x68

data = reader.read_all()
if "bme280" in data and data["bme280"]:
    print(f"Temperature: {data['bme280']['temperature_c']}°C")
if "mpu6050" in data and data["mpu6050"]:
    print(f"Acceleration: {data['mpu6050']['accel_g']} g")

Why this pattern matters: Real IoT deployments often combine multiple sensors on a shared I2C bus. The scan-detect-read pattern avoids hardcoding addresses and gracefully handles missing sensors, making the firmware more robust across different hardware configurations.

10.11 Lab Setup Guide

10.11.1 Setting Up Your Sensor Lab Environment

For hands-on sensor work, you need:

Hardware:

  • ESP32 or Arduino board
  • Breadboard and jumper wires
  • USB cable for programming
  • Multimeter (for debugging)
  • Sensors (DHT22, BMP280, etc.)

Software:

  • Arduino IDE or PlatformIO
  • Sensor libraries (installed via Library Manager)
  • Serial monitor for debugging

Common Connections:

Sensor VCC GND Data/SDA CLK/SCL Notes
DHT22 3.3V GND GPIO4 - 10k pull-up on data
BMP280 3.3V GND GPIO21 GPIO22 I2C address 0x76/0x77
DS18B20 3.3V GND GPIO5 - 4.7k pull-up on data
MPU6050 3.3V GND GPIO21 GPIO22 I2C address 0x68
Key Takeaway

For most IoT projects, a handful of sensors covers nearly every need: BME280 for comprehensive environmental monitoring, DS18B20 for multi-point temperature, PIR for presence detection, and MPU6050 for motion tracking. MEMS technology enables tiny, low-power motion sensors using microscopic mechanical structures. Gas sensors (MQ series) require continuous heating and a 24-48 hour burn-in, making them unsuitable for battery-powered applications.

Remember our IoT friends – Sammy the Sensor, Max the Microcontroller, Bella the Battery, and Lila the LED? Time to see what they think about the most popular sensors in the IoT world!

Sammy the Sensor (DS18B20) is a temperature expert: “I am waterproof, I cost only 3 dollars, and you can chain dozens of me on a single wire! Each of us has a unique name so Max can tell us apart.”

The DHT22 is a combo sensor: “I measure BOTH temperature AND humidity in one package! Perfect for knowing if your room is comfortable. Just remember – I need 2 seconds between readings.”

The BME280 is the overachiever: “I measure temperature, humidity, AND air pressure! I can even estimate altitude by checking how the pressure changes. And I speak I2C, so I only need 2 wires.”

Max the Microcontroller introduced the MPU6050: “This tiny chip has a microscopic mass on a spring inside! When you tilt or shake it, the mass moves, and the chip measures how much. It can feel acceleration AND rotation!”

Bella the Battery warned about the MQ gas sensors: “Those guys use 150 milliamps CONTINUOUSLY to heat their sensing element. That is like leaving a flashlight on all the time. Not great for my battery life!”

Lila the LED summed it up: “Five sensors, a few dollars each, and you can measure almost anything!”

10.12 Summary

Key common sensor takeaways:

  1. Temperature: DHT22 for simple, DS18B20 for multi-point, BME280 for multi-parameter
  2. Motion: PIR for presence, accelerometer for movement/tilt
  3. Distance: Ultrasonic for long range, ToF for precision
  4. Environmental: MQ series needs burn-in, BME680 for comprehensive monitoring
  5. MEMS sensors: Tiny mechanical systems with capacitive readout
Concept Related To Connection
MEMS Accelerometer Capacitive Sensing Displacement changes gap between plates
I2C Multi-Sensor Address Conflicts Each device needs unique 7-bit address
Gas Sensor Burn-in Heater Element 24-48h stabilizes sensing layer chemistry
DS18B20 1-Wire Unique ID Each sensor has factory-programmed 64-bit ROM
BME280 Combo Cost vs Integration 3-in-1 sensor cheaper than 3 separate chips

10.13 Try It Yourself

Challenge: Connect three I2C sensors to one ESP32 and read all of them in a single loop.

Sensors: BMP280 (0x76), MPU6050 (0x68), BH1750 (0x23)

Your task: Write code that: 1. Scans the I2C bus and identifies all three sensors 2. Reads temperature from BMP280 3. Reads acceleration from MPU6050 4. Reads light level from BH1750 5. Displays all readings every second

Hint: All sensors share GPIO21 (SDA) and GPIO22 (SCL) with 4.7kΩ pull-ups.

Click for starter code
#include <Wire.h>

void setup() {
  Serial.begin(115200);
  Wire.begin(21, 22); // SDA, SCL

  // Scan I2C bus
  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);
    }
  }
}

void loop() {
  // Read BMP280 temperature (0x76)
  // Read MPU6050 accelerometer (0x68)
  // Read BH1750 light (0x23)

  delay(1000);
}

Common Pitfalls

MQ-series sensors require a 24-48 hour burn-in period on first use to stabilize the sensing film resistance, plus a clean-air baseline calibration to set the Rs/R0 ratio. Using them immediately from the package produces wildly inaccurate readings. Budget time for burn-in in any project timeline.

The speed of sound changes approximately 0.6 m/s per degree C. At 0 C it is 331 m/s; at 40 C it is 355 m/s. Using the standard 340 m/s constant introduces a 4% distance error across this range. For accurate measurement, measure ambient temperature and correct the sound speed in firmware.

The HC-SR501 detects rapid changes in IR radiation, not just human motion. Direct sunlight moving across the sensor, HVAC vent airflow, and passing vehicle headlights all trigger false detections. Shield from these sources or implement a software debounce requiring multiple consecutive events within a time window.

The BMP280 (no humidity) and BME280 (with humidity) look identical and share the same I2C address options. Using a BMP280 library with a BME280 (or vice versa) gives wrong readings. Verify which variant is installed by checking if humidity registers return non-zero values in a diagnostic sketch.

10.14 What’s Next

Now that you know common sensors, explore these related topics:

Chapter Focus Why It Matters
Sensor Specifications Accuracy, resolution, and precision definitions Interpret the specs listed in this chapter with full understanding
Hands-On Labs Build projects with DHT22, MPU6050, and ultrasonic sensors Apply what you learned by wiring and programming real sensors
Reading Datasheets Extracting key parameters from manufacturer datasheets Verify interface requirements and electrical limits before connecting sensors
Selection Guide Systematic sensor comparison methodology Make informed sensor choices for production IoT deployments
Common Mistakes Top 10 sensor pitfalls and how to prevent them Avoid wasted time from pull-up errors, burn-in omissions, and wiring faults

Continue to Hands-On Labs ->