Building a local telemetry station requires mixing digital communication buses, analog ADC conversions, and digital output drives. The layout below details the wiring of our multi-sensor node. We use a DHT22 environmental sensor (transmitting digital packets over a single line), an LDR photoresistor (forming an analog voltage divider read by the ESP32 12-bit ADC controller), and a PIR motion sensor. For outputs, we control a 5V magnetic relay module (isolated via optocoupler) and a piezo buzzer alarm.
2. Part 1: Step-by-Step Individual Commands & Library Configurations
Follow these detailed steps to install dependencies in the Arduino IDE, build the physical layout on the breadboard, and deploy the automated calibration code.
STEP 1
Install the DHT Sensor Library via Library Manager
Open the library manager inside the Arduino IDE on your VirtualBox Linux VM (or Windows host) to retrieve the required device drivers.
Arduino IDE GUI Steps:
1. Launch the Arduino IDE.
2. Go to the top menu bar, click "Tools" -> "Manage Libraries..." (or click the stacked-books icon on the left vertical menu panel).
3. In the search input field, type "DHT sensor library".
4. Scroll down to locate the package titled "DHT sensor library" by Adafruit.
5. Click the "Install" button. A window will pop up asking to install dependencies (such as "Adafruit Unified Sensor" library).
6. Click the button "Install All" to ensure all mathematical helper classes are loaded.
We open the Library Manager to download Adafruit's environmental sensor drivers, which handle the precise digital handshake timing required to decode raw pulses from the DHT22.
STEP 2
Wire Power and Ground Rails for Multi-Sensor Board
Before adding the sensors, establish shared power buses from your microcontroller module pins to the outer rails of the breadboard.
Wiring Steps:
1. Disconnect the microcontroller module from the USB port to cut power.
2. Run a RED jumper wire from the pin labeled "3V3" on the ESP32 to the top RED positive rail of the breadboard.
3. Run a BLACK jumper wire from the pin labeled "GND" on the ESP32 to the top BLUE negative rail of the breadboard.
4. Run a red jumper wire from the top positive rail to the bottom positive rail, and a black jumper wire from the top ground rail to the bottom ground rail.
We bridge the power pins of the ESP32 to both breadboard rails to create shared power buses, enabling us to power multiple sensors and actuators simultaneously.
STEP 3
Wire the DHT22 Temperature & Humidity Sensor
Wire the DHT22 sensor pins. This sensor requires a pull-up resistor on its data pin to prevent signal floating.
Wiring Steps:
1. Place the DHT22 sensor into the breadboard (pins facing you: Pin 1 on left, Pin 4 on right).
2. Connect Pin 1 (VCC) of the DHT22 to the positive red power rail.
3. Connect Pin 2 (DATA) of the DHT22 to ESP32 Pin "GPIO 15".
4. Place a 10kΩ resistor (Brown, Black, Orange, Gold) between DHT22 Pin 1 and Pin 2. (This acts as the required pull-up).
5. Connect Pin 4 (GND) of the DHT22 to the negative blue ground rail. (Leave Pin 3 unconnected).
We wire the DHT22 and add a pull-up resistor to hold the data line high when idle, allowing the sensor's open-drain output transistor to pulse the line low to send data packets.
STEP 4
Wire the Analog LDR Voltage Divider Circuit
Build a voltage divider to translate the LDR's light-dependent resistance into a proportional voltage that can be read by the analog-to-digital converter.
Wiring Steps:
1. Place the LDR (photoresistor) into the breadboard so its leads span columns 20 and 21.
2. Connect Column 20 to the positive red power rail.
3. Connect Column 21 to ESP32 Pin "GPIO 34" (Analog input pin).
4. Place a 10kΩ resistor from Column 21 to the negative blue ground rail. (This forms the bottom half of the divider).
We build a voltage divider using the LDR and a 10kΩ resistor, converting light-dependent resistance changes into a voltage range of 0V to 3.3V that the ESP32's ADC can measure.
STEP 5
Wire the PIR Motion Sensor, Buzzer, and Relay
Complete the wiring by adding the digital motion sensor and output devices to the remaining control pins.
Wiring Steps:
1. Connect the PIR sensor: VCC pin to positive rail, GND pin to negative ground rail, and OUT (signal) pin to ESP32 Pin "GPIO 13".
2. Connect the Piezo Buzzer: Long leg (positive) to ESP32 Pin "GPIO 14", short leg (negative) to the ground rail.
3. Connect the 5V Relay module: VCC pin to the positive rail (5V or 3.3V depending on module specifications), GND pin to the ground rail, and IN (signal) pin to ESP32 Pin "GPIO 12".
We connect the PIR sensor to monitor digital inputs, and wire the buzzer and relay to output pins, enabling the ESP32 to trigger alarms and control electrical loads.
STEP 6
Upload Telemetry Station Firmware and Check Outputs
Compile and upload the firmware. Open the Serial Monitor (speed set to 115200 baud) to view the live sensor readings.
Upload & Run:
1. Reconnect your ESP32 board to your PC/VM using the USB cable.
2. Click the circular checkmark icon in the top toolbar to verify/compile the code.
3. Click the circular arrow icon in the top toolbar to upload the code to the ESP32.
4. Click the magnifying glass icon in the top-right corner to open the Serial Monitor.
5. In the Serial Monitor window, click the Baud Rate dropdown in the bottom-right corner and select "115200 baud".
6. Observe the log. It should output: temperature, humidity, analog light value, and motion state.
We upload the compiled firmware and open the Serial Monitor at 115200 baud to view real-time calculations and verify the threshold-based control logic is functioning as intended.
3. Telemetry Decision & Automation Logic Flow
The firmware running on the ESP32 continuously polls the physical sensors and executes a decision matrix. The workflow chart below shows the sequence from reading physical values to evaluating alarm rules and adjusting output states.
4. Part 2: Complete Telemetry Station Code & Line-by-Line Breakdown
Copy the C++ code below and paste it into a new sketch folder in your Arduino IDE. The breakdown explains the library initializations, ADC reading methods, and mathematical threshold comparisons.
Line-by-Line Code Breakdown
#include <DHT.h>: Imports Adafruit's DHT sensor library, which provides built-in methods for reading temperature and humidity values.
#define DHTPIN 15: Defines ESP32 GPIO pin 15 as the communication line connected to the DHT22 data pin.
#define DHTTYPE DHT22: Specifies that we are using the DHT22 model (AM2302) rather than the older DHT11 sensor.
DHT dht(DHTPIN, DHTTYPE);: Instantiates a DHT object using our defined pin number and model type.
const int LDR_PIN = 34;: Assigns ESP32 GPIO pin 34 (ADC1 channel 6) to read the analog voltage divider output from the LDR.
const int PIR_PIN = 13;: Assigns GPIO pin 13 to monitor the digital output of the PIR motion sensor.
const int RELAY_PIN = 12;: Assigns GPIO pin 12 to drive the 5V relay module output.
const int BUZZER_PIN = 14;: Assigns GPIO pin 14 to control the piezo buzzer alarm.
const float TEMP_OFFSET = -0.5;: Defines a calibration offset of -0.5°C to correct for self-heating inside the enclosure.
dht.begin();: Initializes the internal state and timing parameters of the DHT library.
float t = dht.readTemperature();: Reads the temperature from the DHT22 sensor and returns the value as a float in Celsius.
int rawLDR = analogRead(LDR_PIN);: Reads the LDR divider voltage using the ESP32's 12-bit ADC, returning a raw integer value between 0 and 4095.
int motion = digitalRead(PIR_PIN);: Reads the logic state of the PIR motion sensor (returns HIGH if motion is detected, otherwise LOW).
float calibratedTemp = t + TEMP_OFFSET;: Applies the calibration offset to the raw temperature reading.
if (calibratedTemp > 28.0 || (motion == HIGH && rawLDR < 300)): Checks the alert thresholds. The alarm triggers if the temperature exceeds 28°C, or if motion is detected in low light conditions (LDR < 300).
digitalWrite(RELAY_PIN, HIGH);: Sends 3.3V to the relay control pin, closing the relay contacts to activate the fan.
tone(BUZZER_PIN, 1000);: Generates a 1000Hz frequency square wave on the buzzer pin to sound the alarm.
noTone(BUZZER_PIN);: Stops generating a frequency on the buzzer pin, turning off the alarm.
Complete Telemetry Firmware
// Practice Project 3: Multi-Sensor & Actuator Interfacing Station#include<DHT.h>#defineDHTPIN 15
#defineDHTTYPE DHT22
// Instantiate the DHT sensor objectDHTdht(DHTPIN, DHTTYPE);
// Hardware Pin Mapping ConstantsconstintLDR_PIN = 34; // Analog pin for light sensor (ADC1_CH6)constintPIR_PIN = 13; // Digital input pin for PIR motion sensorconstintRELAY_PIN = 12; // Digital output pin for Relay module controlconstintBUZZER_PIN = 14; // Digital output pin for active buzzer tone// Calibration FactorconstfloatTEMP_OFFSET = -0.5; // Temperature calibration offset in Celsiusvoidsetup() {
// Initialize serial terminal communicationSerial.begin(115200);
Serial.println("Starting Telemetry Station Build...");
// Initialize DHT Sensordht.begin();
// Configure input pinspinMode(PIR_PIN, INPUT);
// Configure output pinspinMode(RELAY_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
// Start with outputs turned offdigitalWrite(RELAY_PIN, LOW);
digitalWrite(BUZZER_PIN, LOW);
}
voidloop() {
// Read temperature and humidityfloathumidity = dht.readHumidity();
floatraw_temp = dht.readTemperature();
// Read analog light sensor valueintraw_ldr = analogRead(LDR_PIN);
// Read digital motion sensor stateintmotion = digitalRead(PIR_PIN);
// Validate sensor readingsif (isnan(humidity) || isnan(raw_temp)) {
Serial.println("Error: Failed to read from DHT22 sensor!");
return;
}
// Apply calibration offsetfloatcalibrated_temp = raw_temp + TEMP_OFFSET;
// Print data values to serial monitorSerial.print("Temp: "); Serial.print(calibrated_temp); Serial.print(" C | ");
Serial.print("Humid: "); Serial.print(humidity); Serial.print(" % | ");
Serial.print("Light: "); Serial.print(raw_ldr); Serial.print(" | ");
Serial.print("Motion: "); Serial.println(motion == HIGH ? "DETECTED" : "NONE");
// Evaluate threshold decisions// Alert Condition A: Temperature exceeds 28°C (cooling fan triggered)// Alert Condition B: Motion detected under dark conditions (security breach triggered)if (calibrated_temp > 28.0 || (motion == HIGH && raw_ldr < 300)) {
Serial.println(" ALERT: Threshold breached! Activating Relay and Buzzer...");
digitalWrite(RELAY_PIN, HIGH); // Turn on Relay (activates fan/cooler)tone(BUZZER_PIN, 1000); // Sound warning tone at 1000Hz frequency
} else {
digitalWrite(RELAY_PIN, LOW); // Turn off RelaynoTone(BUZZER_PIN); // Silence active buzzer
}
// Wait 2 seconds between cycles to maintain DHT22 timing limitsdelay(2000);
}
5. Deliverables Summary
Created Artifacts
Production firmware C++ sketch code: telemetry_station.ino.
Detailed wiring diagram detailing pins, resistors, and electrical rails.
Verification Proof
Close-up photograph of your breadboard displaying the wired sensors and active modules.
Screenshot of the Serial Monitor showing a log output: Temp: 28.5 C | Humid: 65 % | Light: 250 | Motion: DETECTED -> ALERT triggered.
6. Closing Explanation: Why We Did This & What It Accomplishes
Architectural Intent & Operational Impact
Why We Did This
Reading multiple sensors on a single node demonstrates how to manage different communication interfaces (analog, single-wire digital, and logic inputs) concurrently.
Applying calibration factors on-chip corrects for environmental noise and component variance, ensuring accurate data ingestion before transmission.
Using a pull-up resistor on the DHT22 data line stabilizes the communication bus, preventing packet loss during high-speed sampling.
What This Accomplishes
Integrates sensor inputs with actuator controls, demonstrating the core feedback loops used in home automation and industrial security systems.
Teaches developers how to read and calibrate analog inputs, enabling the integration of various resistive sensors (like LDRs or soil moisture probes).
Builds the foundation for IoT nodes that compile data locally before transmitting telemetry payloads over network layers like MQTT.