GuideInternet of ThingsIoT Sensors and Actuators

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.

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.

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: