A sensor is a transducer: it converts a physical quantity into an electrical signal a microcontroller can read. Temperature becomes a voltage. Light becomes a current. Acceleration becomes a digital word on an I2C bus. Every thermostat, smartphone, and factory robot depends on this conversion, and the quality of the conversion decides the quality of the whole system.
Quick Takeaways
- Sensors output analog (voltage or current), digital (I2C, SPI, 1-Wire, UART), or PWM/frequency signals.
- Match the output type to your MCU: an ESP32 ADC reads analog sensors, while digital sensors need only two or three GPIO pins.
- Accuracy, resolution, and response time are different specs. A 12-bit ADC does not make a sensor accurate.
- Always check the logic level: connecting a 5V sensor output to a 3.3V GPIO can damage the chip.
| Sensor Type | Measures | Typical Part | Interface | Supply |
|---|---|---|---|---|
| Temperature | °C | DS18B20 | 1-Wire | 3.0–5.5V |
| Temp/Humidity/Pressure | °C, %RH, hPa | BME280 | I2C/SPI | 1.71–3.6V |
| Light | Lux | BH1750 | I2C | 2.4–3.6V |
| Motion (IMU) | Accel/Gyro | MPU6050 | I2C | 2.375–3.46V |
| Distance | cm | HC-SR04 | Trigger/Echo | 5V |
| Gas | Air quality | MQ-135 | Analog | 5V |
How a Sensor Chain Works
Every measurement passes through the same stages:
- Physical quantity: heat, light, force, magnetic field.
- Sensing element: the material that reacts (thermistor, photodiode, piezo crystal, Hall element).
- Signal conditioning: amplification, filtering, offset correction (often an op-amp or built-in ASIC).
- Conversion: an ADC turns voltage into a number.
- Processing: firmware scales the raw value into engineering units.
Integrated digital sensors such as the BME280 bundle stages 2 through 4 in one package. Analog sensors leave the conditioning and conversion to you.
Key Sensor Specifications
Datasheet numbers decide whether a part fits your project.
- Range: the minimum and maximum measurable value (the DS18B20 covers -55°C to +125°C).
- Accuracy: how close the reading is to the true value (the DS18B20 is ±0.5°C from -10°C to +85°C).
- Resolution: the smallest detectable change (9 to 12 bits on the DS18B20, down to 0.0625°C).
- Sensitivity: output change per unit input (for example, 10mV/°C on an LM35).
- Response time: how fast the output follows a change. Thermal sensors in epoxy can lag seconds.
- Linearity and drift: deviation from an ideal straight line, and change over time or temperature.
- Current draw: critical for battery nodes. The BME280 draws about 3.6µA at 1Hz in forced mode.
Analog vs. Digital Sensors
| Feature | Analog | Digital |
|---|---|---|
| Output | Continuous voltage/current | Binary data over a bus |
| MCU Requirement | ADC pin | I2C/SPI/UART/1-Wire pins |
| Noise Immunity | Low (long wires pick up noise) | High (error-checked data) |
| Calibration | Done in firmware | Usually factory-calibrated |
| Cost | Often lower | Slightly higher |
| Example | LM35, MQ-135, LDR | BME280, BH1750, MPU6050 |
Use analog sensors for simple, cheap, fast-response tasks. Use digital sensors when you want calibrated data and fewer wires.
Common Sensor Categories
Temperature Sensors
- Thermistor (NTC): resistance drops as temperature rises. Cheap and sensitive but nonlinear. Use the Steinhart-Hart equation or the beta-parameter model.
- Thermocouple: two dissimilar metals generate a millivolt-level voltage. Handles extreme heat. Needs a cold-junction compensation amplifier like the MAX31855.
- RTD (PT100): platinum resistance, very accurate and stable. Needs a precision front end.
- IC sensors (LM35, DS18B20): linear or digital output, easy to use.
Light Sensors
- LDR (photoresistor): resistance falls in bright light. Slow, imprecise, great for day/night switching.
- Photodiode: generates current proportional to light. Fast. Needs a transimpedance amplifier.
- Digital ambient sensors (BH1750): report lux directly over I2C.
Motion and Orientation Sensors
- Accelerometer: measures acceleration using MEMS capacitive structures.
- Gyroscope: measures angular rate through the Coriolis effect on a vibrating MEMS mass.
- IMU (MPU6050): combines a 3-axis accelerometer and gyroscope in one package. A 9-axis IMU adds a magnetometer.
- PIR: detects infrared changes from moving warm bodies.
Distance and Proximity Sensors
- Ultrasonic (HC-SR04): times an echo. Range about 2cm to 400cm. The ECHO pin outputs 5V, so use a divider on 3.3V boards.
- Time-of-Flight (VL53L0X): measures infrared pulse flight time over I2C. Range to about 2m.
- IR reflective: short-range line following and object detection.
Gas, Pressure, and Magnetic Sensors
- MQ series: heated metal-oxide elements. Need warm-up time and per-sensor calibration.
- Barometric (BMP280, BME280): piezoresistive MEMS membrane gives pressure and altitude.
- Hall effect (A3144, SS49E): output changes with magnetic field. Used for RPM counting and position sensing.
Pinout and Wiring: BME280 on ESP32 (I2C)
| BME280 Pin | ESP32 Pin | Function |
|---|---|---|
| VIN | 3V3 | Power |
| GND | GND | Ground |
| SCL | GPIO22 | I2C clock |
| SDA | GPIO21 | I2C data |
Most breakout boards use I2C address 0x76 (SDO to GND) or 0x77 (SDO to VCC). I2C lines are open-drain, so the bus needs 4.7kΩ pull-up resistors. Many breakouts already include them. Check before adding more.
Firmware: Reading a BME280 with Arduino C++
Install the Adafruit BME280 and Adafruit Unified Sensor libraries from the Library Manager.
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
Adafruit_BME280 bme; // I2C interface
void setup() {
Serial.begin(115200);
Wire.begin(21, 22); // SDA = GPIO21, SCL = GPIO22 on ESP32
// 0x76 is the common address; try 0x77 if init fails
if (!bme.begin(0x76)) {
Serial.println("BME280 not found. Check wiring and address.");
while (true) delay(10);
}
}
void loop() {
float tempC = bme.readTemperature(); // degrees Celsius
float humidity = bme.readHumidity(); // % relative humidity
float pressure = bme.readPressure() / 100.0F; // Pa -> hPa
Serial.printf("T: %.2f C | RH: %.1f %% | P: %.1f hPa\n",
tempC, humidity, pressure);
delay(2000);
}
Firmware: Reading an Analog Sensor with MicroPython
This reads an LM35 (10mV/°C) on an ESP32 ADC pin.
from machine import ADC, Pin
import time
adc = ADC(Pin(34)) # GPIO34 is input-only, good for ADC
adc.atten(ADC.ATTN_11DB) # Full range ~0-3.3V
adc.width(ADC.WIDTH_12BIT) # 0-4095 counts
while True:
# Average 16 samples to reduce noise
raw = sum(adc.read() for _ in range(16)) / 16
voltage = raw / 4095 * 3.3 # Counts -> volts (approximate)
temp_c = voltage / 0.010 # LM35: 10 mV per degree C
print("Temp: {:.1f} C".format(temp_c))
time.sleep(1)
The ESP32 ADC is nonlinear near the rails. For better accuracy, use the factory calibration API or an external ADC like the ADS1115 (16-bit, I2C).
Signal Conditioning Essentials
Raw sensor signals are rarely clean. Apply these fixes:
- Voltage divider: scales 5V outputs to 3.3V logic. Use 10kΩ and 20kΩ resistors for a 2/3 ratio.
- RC low-pass filter: a 1kΩ resistor with a 100nF capacitor gives a cutoff near 1.6kHz and removes high-frequency noise.
- Decoupling capacitor: place a 100nF ceramic capacitor across VCC and GND at the sensor.
- Op-amp buffer: isolates high-impedance sources like thermistor dividers from the ADC sample capacitor.
- Averaging and median filters: cheap firmware filtering for jittery readings.
Sensor Communication Protocols Compared
| Protocol | Wires | Speed | Best For | Trade-off |
|---|---|---|---|---|
| I2C | 2 (SDA, SCL) | 100kHz–3.4MHz | Many sensors on one bus | Address conflicts |
| SPI | 4+ (MOSI, MISO, SCK, CS) | Up to tens of MHz | Fast data (IMUs, ADCs) | More pins |
| UART | 2 (TX, RX) | Up to ~1Mbps | GPS, particulate sensors | One device per port |
| 1-Wire | 1 (+GND) | ~16kbps | Multiple DS18B20 on one pin | Slow |
| Analog | 1 | Limited by ADC | Simple, fast sensing | Noise-prone |
Real-World Project: IoT Weather Station
Build a node that logs temperature, humidity, pressure, and light.
Parts list:
- ESP32 DevKit
- BME280 (I2C 0x76)
- BH1750 (I2C 0x23)
- 4.7kΩ pull-up resistors (if the breakouts lack them)
- 18650 Li-ion cell with a TP4056 charger module
Wiring: Both sensors share GPIO21 (SDA) and GPIO22 (SCL). Different addresses prevent conflicts. Power both from 3V3.
Firmware logic:
- Wake from deep sleep.
- Read both sensors.
- Connect to Wi-Fi and publish via MQTT to a broker such as Mosquitto.
- Return to deep sleep for 5 minutes.
#define uS_TO_S 1000000ULL
#define SLEEP_SECONDS 300 // 5 minutes
void goToSleep() {
esp_sleep_enable_timer_wakeup(SLEEP_SECONDS * uS_TO_S);
esp_deep_sleep_start(); // Drops current draw to ~10 uA on the chip
}
Deep sleep lets a single 18650 cell run the node for months, depending on Wi-Fi connect time.
Troubleshooting Sensor Problems
| Symptom | Likely Cause | Fix |
|---|---|---|
| “Sensor not found” | Wrong I2C address or swapped SDA/SCL | Run an I2C scanner sketch |
| Readings stuck at 0 or max | No power or floating pin | Verify VCC with a multimeter |
| Noisy analog values | Long leads, shared supply noise | Add 100nF cap, average samples |
| Temperature reads high | Self-heating from the MCU or regulator | Move the sensor away from heat sources |
| Random bus lockups | Missing pull-ups or long I2C cables | Use 4.7kΩ pull-ups, shorten wires |
| MQ sensor drifts | Insufficient warm-up | Preheat 24–48 hours initially, then 3+ minutes each boot |
| ESP32 ADC jumps | Wi-Fi active on ADC2 pins | Use ADC1 pins (GPIO32–39) |
Choosing the Right Sensor
- Define the range and accuracy your application needs. Don’t overspec.
- Match the logic level to your MCU (3.3V vs. 5V).
- Pick the interface your free pins support.
- Check power budget for battery projects.
- Verify availability of a maintained library.
- Plan calibration: compare against a trusted reference at least once.
FAQ
What is the difference between a sensor and a transducer?
A transducer converts one form of energy into another. A sensor is a transducer (plus any conditioning) that outputs an electrical signal representing a measured quantity. All sensors are transducers, but not every transducer, such as a speaker, is a sensor.
How do I connect a sensor to an Arduino or ESP32?
Check the sensor’s output type. For analog sensors, connect the signal pin to an ADC-capable pin and call analogRead(). For I2C sensors, connect SDA and SCL, power the module within its rated voltage, and use the manufacturer’s library. Always connect GND first and confirm logic levels.
Why is my sensor reading inaccurate?
Common causes are supply noise, self-heating, poor ADC reference, missing calibration, and wrong scaling. Add decoupling capacitors, average multiple samples, use a precision ADC like the ADS1115, and calibrate against a known reference.
Which sensors are best for beginners?
Start with the DS18B20 (temperature), BME280 (environment), HC-SR04 (distance), and PIR HC-SR501 (motion). They are inexpensive, well documented, and supported by mature libraries.




