IoT Sensors and Actuators
A comprehensive guide to sensors and actuators for IoT embedded systems, covering sensor types, interfaces, data processing, and practical implementation examples.
IoT Sensors and Actuators
Sensors and actuators form the foundation of IoT systems, enabling devices to interact with the physical world. This guide explores various sensor and actuator types, their interfaces, data processing techniques, and practical implementation examples for IoT embedded systems.
Sensors and Actuators in IoT
Sensors convert physical phenomena into electrical signals, while actuators convert electrical signals into physical actions. Together, they enable IoT devices to perceive their environment and effect changes, creating the bridge between the digital and physical worlds.
Sensor Types
IoT applications use a wide variety of sensors to measure different physical parameters.
Sensor Interfaces
Sensors connect to microcontrollers through various interfaces, each with different characteristics.
Common digital interfaces include:
- I2C: Inter-Integrated Circuit, two-wire interface
- SPI: Serial Peripheral Interface, four-wire interface
- UART: Universal Asynchronous Receiver-Transmitter
- One-Wire: Single-wire interface (e.g., Dallas DS18B20)
- CAN: Controller Area Network, common in automotive
- Modbus: Industrial communication protocol
Digital interfaces offer noise immunity and standardized communication protocols.
Sensor Data Processing
Raw sensor data often requires processing to extract meaningful information.
Sensor Data Challenges
Sensor data can be noisy, drift over time, or be affected by environmental factors. Proper processing techniques are essential to extract accurate and reliable measurements.
Signal Conditioning
// Example of signal conditioning for a temperature sensor
float conditionTemperature(float rawValue) {
// Apply calibration factors
float calibratedValue = rawValue * CALIBRATION_FACTOR + OFFSET;
// Apply low-pass filter to reduce noise
static float filteredValue = 0;
const float alpha = 0.1; // Filter coefficient (0-1)
filteredValue = alpha * calibratedValue + (1 - alpha) * filteredValue;
return filteredValue;
}
Data Validation
// Example of data validation for sensor readings
bool validateSensorReading(float value, float minValue, float maxValue) {
// Check if value is within expected range
if (value < minValue || value > maxValue) {
return false;
}
// Check for sudden changes (could indicate sensor failure)
static float lastValue = 0;
float change = fabs(value - lastValue);
lastValue = value;
if (change > MAX_ALLOWED_CHANGE) {
return false;
}
return true;
}
Data Fusion
// Example of sensor fusion for orientation estimation
void updateOrientation(float accelX, float accelY, float accelZ,
float gyroX, float gyroY, float gyroZ,
float *roll, float *pitch, float *yaw) {
// Complementary filter for orientation estimation
static float rollAngle = 0, pitchAngle = 0, yawAngle = 0;
// Calculate angles from accelerometer
float accelRoll = atan2(accelY, accelZ) * 180.0 / PI;
float accelPitch = atan2(-accelX, sqrt(accelY * accelY + accelZ * accelZ)) * 180.0 / PI;
// Integrate gyroscope data
float dt = 0.01; // Time step (seconds)
rollAngle += gyroX * dt;
pitchAngle += gyroY * dt;
yawAngle += gyroZ * dt;
// Complementary filter (high-pass for gyro, low-pass for accelerometer)
const float alpha = 0.96;
*roll = alpha * (rollAngle + gyroX * dt) + (1 - alpha) * accelRoll;
*pitch = alpha * (pitchAngle + gyroY * dt) + (1 - alpha) * accelPitch;
*yaw = yawAngle; // Yaw from gyro only (no magnetic reference)
// Update stored angles
rollAngle = *roll;
pitchAngle = *pitch;
yawAngle = *yaw;
}
Actuator Types
Actuators convert electrical signals into physical actions, enabling IoT devices to interact with the environment.
Common electrical actuators include:
- DC Motors: Simple rotation with varying speed
- Servo Motors: Precise position control
- Stepper Motors: Precise rotation in discrete steps
- Solenoids: Linear motion for valves and locks
- Relays: Electrically controlled switches
- LEDs: Light output for indicators and displays
Electrical actuators are widely used in IoT applications for control and feedback.
Actuator Control
Controlling actuators requires appropriate driver circuits and control algorithms.
Practical Implementation
Let's look at a practical example of a smart home temperature control system using sensors and actuators.
Hardware Setup
// Pin definitions
#define TEMP_SENSOR_PIN GPIO_NUM_4 // I2C temperature sensor
#define HUMIDITY_SENSOR_PIN GPIO_NUM_5 // I2C humidity sensor
#define HEATER_RELAY_PIN GPIO_NUM_12 // Relay control for heater
#define AC_RELAY_PIN GPIO_NUM_13 // Relay control for AC
#define FAN_PWM_PIN GPIO_NUM_14 // PWM control for fan
#define LED_STATUS_PIN GPIO_NUM_2 // Status LED
Sensor Reading
// Read temperature and humidity from DHT22 sensor
bool readEnvironmentData(float *temperature, float *humidity) {
// Initialize DHT22 sensor
dht_t dht;
dht.gpio = HUMIDITY_SENSOR_PIN;
dht.type = DHT_TYPE_AM2301;
// Read sensor data
esp_err_t ret = dht_read_data(&dht, temperature, humidity);
if (ret != ESP_OK) {
return false;
}
// Validate readings
if (!validateSensorReading(*temperature, -40.0, 80.0) ||
!validateSensorReading(*humidity, 0.0, 100.0)) {
return false;
}
return true;
}
Control Logic
// Control HVAC based on temperature
void controlHVAC(float temperature, float targetTemp, float hysteresis) {
// Calculate temperature difference
float tempDiff = targetTemp - temperature;
// Control heating
if (tempDiff > hysteresis) {
// Too cold, turn on heater
gpio_set_level(HEATER_RELAY_PIN, 1);
gpio_set_level(AC_RELAY_PIN, 0);
// Set fan speed based on temperature difference
int fanSpeed = map(tempDiff, hysteresis, 5.0, 30, 100);
fanSpeed = constrain(fanSpeed, 30, 100);
ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, fanSpeed);
ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0);
}
// Control cooling
else if (tempDiff < -hysteresis) {
// Too hot, turn on AC
gpio_set_level(HEATER_RELAY_PIN, 0);
gpio_set_level(AC_RELAY_PIN, 1);
// Set fan speed based on temperature difference
int fanSpeed = map(-tempDiff, hysteresis, 5.0, 30, 100);
fanSpeed = constrain(fanSpeed, 30, 100);
ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, fanSpeed);
ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0);
}
// Temperature is within acceptable range
else {
// Turn off both heater and AC
gpio_set_level(HEATER_RELAY_PIN, 0);
gpio_set_level(AC_RELAY_PIN, 0);
// Set fan to minimum speed
ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 30);
ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0);
}
}
Main Loop
// Main application loop
void app_main() {
// Initialize GPIO
gpio_config_t io_conf = {
.pin_bit_mask = (1ULL << HEATER_RELAY_PIN) | (1ULL << AC_RELAY_PIN) | (1ULL << LED_STATUS_PIN),
.mode = GPIO_MODE_OUTPUT,
.pull_up_en = GPIO_PULLUP_DISABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE
};
gpio_config(&io_conf);
// Initialize PWM for fan control
ledc_timer_config_t ledc_timer = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.duty_resolution = LEDC_TIMER_8_BIT,
.timer_num = LEDC_TIMER_0,
.freq_hz = 25000,
.clk_cfg = LEDC_AUTO_CLK
};
ledc_timer_config(&ledc_timer);
ledc_channel_config_t ledc_channel = {
.gpio_num = FAN_PWM_PIN,
.speed_mode = LEDC_LOW_SPEED_MODE,
.channel = LEDC_CHANNEL_0,
.intr_type = LEDC_INTR_DISABLE,
.timer_sel = LEDC_TIMER_0,
.duty = 0,
.hpoint = 0
};
ledc_channel_config(&ledc_channel);
// Initialize I2C for sensors
i2c_config_t i2c_config = {
.mode = I2C_MODE_MASTER,
.sda_io_num = SDA_PIN,
.scl_io_num = SCL_PIN,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = 100000
};
i2c_param_config(I2C_NUM_0, &i2c_config);
i2c_driver_install(I2C_NUM_0, I2C_MODE_MASTER, 0, 0, 0);
// Target temperature and hysteresis
float targetTemp = 22.0; // 22°C
float hysteresis = 0.5; // ±0.5°C
while (1) {
// Read environment data
float temperature, humidity;
if (readEnvironmentData(&temperature, &humidity)) {
// Control HVAC based on temperature
controlHVAC(temperature, targetTemp, hysteresis);
// Publish data to MQTT
char payload[64];
snprintf(payload, sizeof(payload),
"{\"temp\": %.2f, \"humidity\": %.2f, \"target\": %.2f}",
temperature, humidity, targetTemp);
mqtt_publish("home/climate", payload);
// Blink LED to indicate activity
gpio_set_level(LED_STATUS_PIN, 1);
vTaskDelay(pdMS_TO_TICKS(100));
gpio_set_level(LED_STATUS_PIN, 0);
}
// Wait before next reading
vTaskDelay(pdMS_TO_TICKS(60000)); // 1 minute
}
}
Next Steps
Now that you understand IoT sensors and actuators, you can explore: