Skip to content
IRC-Coding IRC-Coding
IoT fundamentals Embedded systems Sensors Microcontrollers Raspberry Pi Arduino Edge computing

IoT & Embedded Systems Fundamentals

Learn IoT and embedded systems: sensors, microcontrollers, Raspberry Pi, Arduino, and edge computing with practical examples.

S

schutzgeist

2 min read
IoT & Embedded Systems Fundamentals

IoT & Embedded Systeme Grundlagen: Sensoren, Mikrocontroller, Raspberry Pi, Arduino & Edge Computing

This article is a comprehensive introduction to IoT & Embedded Systems Fundamentals – including sensors, microcontrollers, Raspberry Pi, Arduino and edge computing with practical examples.

In a Nutshell

IoT and embedded systems are networked, specialized computers that connect physical devices to the internet and process data in real-time.

Compact technical description

IoT (Internet of Things) is a network of connected physical devices that collect, process, and exchange data via sensors over the internet.

Core components:

Embedded Systems

  • Microcontrollers: ARM Cortex-M, AVR, PIC
  • Microprocessors: ARM Cortex-A, x86, RISC-V
  • Operating Systems: Embedded Linux, RTOS, FreeRTOS
  • Memory: Flash, EEPROM, RAM, SD cards

Sensors and Actuators

  • Environmental Sensors: Temperature, humidity, pressure
  • Motion Sensors: Acceleration, gyroscope, magnetometer
  • Optical Sensors: Camera, infrared, ultrasonic
  • Actuators: Motors, servos, relays, LEDs

Communication Protocols

  • Wireless: WiFi, Bluetooth, LoRaWAN, Zigbee
  • Wired: I2C, SPI, UART, CAN, Ethernet
  • IoT Protocols: MQTT, CoAP, HTTP/REST, WebSocket
  • Edge Protocols: gRPC, Protocol Buffers

Edge Computing

  • Data Processing: Local processing instead of cloud
  • Latency Optimization: Real-time processing
  • Bandwidth Efficiency: Reduced data transmission
  • Offline Capability: Operation without internet connection

Exam-relevant key points

  • IoT: Internet of Things, networked physical devices
  • Embedded Systems: Specialized computer systems
  • Sensors: Temperature, motion, optical sensors
  • Microcontrollers: ARM Cortex-M, AVR, PIC
  • Raspberry Pi: Single-board computer with Linux
  • Arduino: Open-source microcontroller platform
  • Edge Computing: Local data processing
  • RTOS: Real-Time Operating System
  • MQTT: Message Queuing Telemetry Transport
  • IHK-relevant: Modern embedded systems development and IoT

Core Components

  1. Hardware: Microcontrollers, processors, sensors
  2. Firmware: Low-level software, drivers, bootloader
  3. Operating Systems: Embedded Linux, RTOS, FreeRTOS
  4. Communication: Protocols, networks, security
  5. Edge Computing: Local processing, analytics
  6. Cloud Integration: Data transmission, storage
  7. Power Management: Energy efficiency, battery management
  8. Security: Encryption, authentication, updates

Practical Examples

1. Arduino IoT Sensor Node with MQTT

#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
#include <ArduinoJson.h>
#include <NTPClient.h>
#include <WiFiUdp.h>

// WiFi configuration
const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";

// MQTT configuration
const char* mqtt_server = "mqtt.example.com";
const int mqtt_port = 1883;
const char* mqtt_username = "your_username";
const char* mqtt_password = "your_password";
const char* client_id = "arduino_sensor_01";

// Sensor configuration
#define DHT_PIN 4
#define DHT_TYPE DHT22
#define LIGHT_PIN A0
#define MOTION_PIN 2
#define BUZZER_PIN 5
#define LED_PIN 13

// Topics
const char* temp_topic = "iot/sensors/temperature";
const char* humidity_topic = "iot/sensors/humidity";
const char* light_topic = "iot/sensors/light";
const char* motion_topic = "iot/sensors/motion";
const char* status_topic = "iot/sensors/status";
const char* control_topic = "iot/sensors/control";

// Timing
unsigned long lastSensorRead = 0;
const long sensorInterval = 5000; // 5 seconds
unsigned long lastStatusUpdate = 0;
const long statusInterval = 60000; // 1 minute

// Global objects
WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);
DHT dht(DHT_PIN, DHT_TYPE);
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org");

// Sensor data structure
struct SensorData {
  float temperature;
  float humidity;
  int lightLevel;
  bool motionDetected;
  unsigned long timestamp;
};

// Device status
struct DeviceStatus {
  bool wifiConnected;
  bool mqttConnected;
  float batteryLevel;
  int uptime;
  String firmwareVersion;
};

void setup() {
  Serial.begin(115200);
  while (!Serial) delay(10);
  
  Serial.println("IoT Sensor Node starting...");
  
  // Initialize pins
  pinMode(LED_PIN, OUTPUT);
  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(MOTION_PIN, INPUT_PULLUP);
  
  // Initialize sensors
  dht.begin();
  
  // Initialize NTP client
  timeClient.begin();
  timeClient.setTimeOffset(3600); // UTC+1
  
  // Connect to WiFi
  connectWiFi();
  
  // Connect to MQTT
  connectMQTT();
  
  // Initialize time
  timeClient.update();
  
  Serial.println("IoT Sensor Node ready!");
  blinkLED(3, 200);
}

void loop() {
  // Handle WiFi connection
  if (WiFi.status() != WL_CONNECTED) {
    connectWiFi();
  }
  
  // Handle MQTT connection
  if (!mqttClient.connected()) {
    connectMQTT();
  }
  
  // Update NTP time
  timeClient.update();
  
  // Read sensors periodically
  if (millis() - lastSensorRead >= sensorInterval) {
    readAndPublishSensors();
    lastSensorRead = millis();
  }
  
  // Update status periodically
  if (millis() - lastStatusUpdate >= statusInterval) {
    publishStatus();
    lastStatusUpdate = millis();
  }
  
  // Handle MQTT messages
  mqttClient.loop();
  
  // Check for motion interrupt
  checkMotion();
  
  delay(100);
}

void connectWiFi() {
  Serial.println("Connecting to WiFi...");
  
  WiFi.begin(ssid, password);
  
  int attempts = 0;
  while (WiFi.status() != WL_CONNECTED && attempts < 30) {
    delay(500);
    Serial.print(".");
    attempts++;
  }
  
  if (WiFi.status() == WL_CONNECTED) {
    Serial.println("\nWiFi connected!");
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
    digitalWrite(LED_PIN, HIGH);
  } else {
    Serial.println("\nFailed to connect to WiFi");
    digitalWrite(LED_PIN, LOW);
  }
}

void connectMQTT() {
  Serial.println("Connecting to MQTT...");
  
  mqttClient.setServer(mqtt_server, mqtt_port);
  mqttClient.setCallback(mqttCallback);
  
  int attempts = 0;
  while (!mqttClient.connected() && attempts < 10) {
    Serial.print("Attempting MQTT connection...");
    
    if (mqttClient.connect(client_id, mqtt_username, mqtt_password)) {
      Serial.println("connected!");
      
      // Subscribe to control topic
      mqttClient.subscribe(control_topic);
      
      // Publish connection message
      publishConnectionStatus(true);
      
    } else {
      Serial.print("failed, rc=");
      Serial.print(mqttClient.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
      attempts++;
    }
  }
  
  if (!mqttClient.connected()) {
    Serial.println("Failed to connect to MQTT");
  }
}

void mqttCallback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  
  String message = "";
  for (int i = 0; i < length; i++) {
    message += (char)payload[i];
  }
  Serial.println(message);
  
  // Parse JSON message
  DynamicJsonDocument doc(1024);
  DeserializationError error = deserializeJson(doc, message);
  
  if (error) {
    Serial.println("Failed to parse JSON");
    return;
  }
  
  // Handle control commands
  if (String(topic) == control_topic) {
    handleControlCommand(doc);
  }
}

void handleControlCommand(JsonDocument& command) {
  String cmd = command["command"];
  
  if (cmd == "buzz") {
    int duration = command["duration"] | 1000;
    buzz(duration);
  } else if (cmd == "led") {
    bool state = command["state"];
    digitalWrite(LED_PIN, state ? HIGH : LOW);
  } else if (cmd == "restart") {
    Serial.println("Restarting device...");
    ESP.restart();
  } else if (cmd == "sleep") {
    int duration = command["duration"] | 10;
    Serial.println("Going to sleep for " + String(duration) + " seconds");
    ESP.deepSleep(duration * 1000000);
  }
}

void readAndPublishSensors() {
  SensorData data;
  
  // Read temperature and humidity
  data.temperature = dht.readTemperature();
  data.humidity = dht.readHumidity();
  
  // Read light level
  data.lightLevel = analogRead(LIGHT_PIN);
  
  // Read motion sensor
  data.motionDetected = digitalRead(MOTION_PIN) == HIGH;
  
  // Get timestamp
  data.timestamp = timeClient.getEpochTime();
  
  // Check for valid readings
  if (isnan(data.temperature) || isnan(data.humidity)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
  
  // Publish sensor data
  publishSensorData(data);
  
  // Print sensor data
  Serial.println("Sensor Data:");
  Serial.print("Temperature: ");
  Serial.print(data.temperature);
  Serial.println("°C");
  Serial.print("Humidity: ");
  Serial.print(data.humidity);
  Serial.println("%");
  Serial.print("Light: ");
  Serial.println(data.lightLevel);
  Serial.print("Motion: ");
  Serial.println(data.motionDetected ? "Yes" : "No");
  Serial.print("Timestamp: ");
  Serial.println(data.timestamp);
}

void publishSensorData(SensorData& data) {
  // Create JSON document
  DynamicJsonDocument doc(1024);
  
  doc["device_id"] = client_id;
  doc["timestamp"] = data.timestamp;
  doc["temperature"] = data.temperature;
  doc["humidity"] = data.humidity;
  doc["light_level"] = data.lightLevel;
  doc["motion_detected"] = data.motionDetected;
  
  // Serialize JSON
  String jsonStr;
  serializeJson(doc, jsonStr);
  
  // Publish to topics
  mqttClient.publish(temp_topic, String(data.temperature).c_str());
  mqttClient.publish(humidity_topic, String(data.humidity).c_str());
  mqttClient.publish(light_topic, String(data.lightLevel).c_str());
  mqttClient.publish(motion_topic, String(data.motionDetected).c_str());
  
  // Publish combined data
  mqttClient.publish("iot/sensors/combined", jsonStr.c_str());
}

void publishStatus() {
  DeviceStatus status;
  
  status.wifiConnected = (WiFi.status() == WL_CONNECTED);
  status.mqttConnected = mqttClient.connected();
  status.batteryLevel = getBatteryLevel();
  status.uptime = millis() / 1000;
  status.firmwareVersion = "1.0.0";
  
  // Create JSON document
  DynamicJsonDocument doc(1024);
  
  doc["device_id"] = client_id;
  doc["timestamp"] = timeClient.getEpochTime();
  doc["wifi_connected"] = status.wifiConnected;
  doc["mqtt_connected"] = status.mqttConnected;
  doc["battery_level"] = status.batteryLevel;
  doc["uptime"] = status.uptime;
  doc["firmware_version"] = status.firmwareVersion;
  doc["free_heap"] = ESP.getFreeHeap();
  doc["cpu_freq"] = ESP.getCpuFreqMHz();
  
  // Serialize JSON
  String jsonStr;
  serializeJson(doc, jsonStr);
  
  // Publish status
  mqttClient.publish(status_topic, jsonStr.c_str());
}

void publishConnectionStatus(bool connected) {
  DynamicJsonDocument doc(512);
  
  doc["device_id"] = client_id;
  doc["timestamp"] = timeClient.getEpochTime();
  doc["connected"] = connected;
  doc["ip_address"] = WiFi.localIP().toString();
  doc["mac_address"] = WiFi.macAddress();
  
  String jsonStr;
  serializeJson(doc, jsonStr);
  
  mqttClient.publish("iot/sensors/connection", jsonStr.c_str());
}

void checkMotion() {
  static bool lastMotionState = false;
  bool currentMotionState = digitalRead(MOTION_PIN) == HIGH;
  
  if (currentMotionState && !lastMotionState) {
    // Motion detected
    Serial.println("Motion detected!");
    
    // Immediate motion notification
    DynamicJsonDocument doc(256);
    doc["device_id"] = client_id;
    doc["timestamp"] = timeClient.getEpochTime();
    doc["motion_detected"] = true;
    doc["alert_type"] = "motion";
    
    String jsonStr;
    serializeJson(doc, jsonStr);
    
    mqttClient.publish("iot/sensors/alert", jsonStr.c_str());
    
    // Alert buzzer
    buzz(200);
  }
  
  lastMotionState = currentMotionState;
}

float getBatteryLevel() {
  // Read battery voltage (assuming voltage divider)
  int rawValue = analogRead(A0);
  float voltage = rawValue * (3.3 / 4096.0) * 2.0; // Voltage divider factor
  
  // Convert to percentage (assuming 3.0V to 4.2V range)
  float percentage = ((voltage - 3.0) / 1.2) * 100.0;
  percentage = constrain(percentage, 0.0, 100.0);
  
  return percentage;
}

void buzz(int duration) {
  tone(BUZZER_PIN, 1000, duration);
}

void blinkLED(int times, int delayMs) {
  for (int i = 0; i < times; i++) {
    digitalWrite(LED_PIN, HIGH);
    delay(delayMs);
    digitalWrite(LED_PIN, LOW);
    delay(delayMs);
  }
}

// OTA Update functionality
void checkForOTAUpdate() {
  // This would implement OTA update checking
  // For simplicity, just print status
  Serial.println("Checking for OTA updates...");
}

// Power management
void enterDeepSleep(int seconds) {
  Serial.println("Entering deep sleep...");
  ESP.deepSleep(seconds * 1000000);
}

void wakeFromDeepSleep() {
  Serial.println("Waking from deep sleep...");
  // Reinitialize peripherals after wake
}

2. Raspberry Pi Edge Computing with Python

import time
import json
import threading
import queue
import subprocess
import os
import signal
import sys
from datetime import datetime
import logging
import sqlite3
import paho.mqtt.client as mqtt
import picamera
import RPi.GPIO as GPIO
import Adafruit_DHT
import board
import busio
import adafruit_ads1x15.ads1115 as ADS
from adafruit_ads1x15.analog_in import AnalogIn
import numpy as np
import cv2
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing import image
import tensorflow as tf

class IoTEdgeGateway:
    def __init__(self, config_file='config.json'):
        """Initialize IoT Edge Gateway"""
        self.config = self.load_config(config_file)
        self.setup_logging()
        self.setup_gpio()
        self.setup_sensors()
        self.setup_camera()
        self.setup_mqtt()
        self.setup_database()
        self.setup_ml_models()
        
        # Data queues
        self.sensor_queue = queue.Queue()
        self.image_queue = queue.Queue()
        self.control_queue = queue.Queue()
        
        # Runtime state
        self.running = True
        self.threads = []
        
        # Register signal handlers
        signal.signal(signal.SIGINT, self.signal_handler)
        signal.signal(signal.SIGTERM, self.signal_handler)
        
        self.logger.info("IoT Edge Gateway initialized")
    
    def load_config(self, config_file):
        """Load configuration from JSON file"""
        try:
            with open(config_file, 'r') as f:
                return json.load(f)
        except FileNotFoundError:
            self.logger.error(f"Config file {config_file} not found")
            return self.get_default_config()
    
    def get_default_config(self):
        """Get default configuration"""
        return {
            "mqtt": {
                "broker": "localhost",
                "port": 1883,
                "username": "",
                "password": "",
                "client_id": "edge_gateway_01"
            },
            "sensors": {
                "dht_pin": 4,
                "light_pin": 18,
                "motion_pin": 24,
                "ads1115_address": 0x48
            },
            "camera": {
                "resolution": (640, 480),
                "framerate": 30,
                "rotation": 0
            },
            "database": {
                "path": "iot_data.db"
            },
            "ml_models": {
                "object_detection": "models/object_detection.h5",
                "anomaly_detection": "models/anomaly_detection.h5"
            },
            "processing": {
                "sensor_interval": 5,
                "image_interval": 10,
                "batch_size": 32
            }
        }
    
    def setup_logging(self):
        """Setup logging configuration"""
        logging.basicConfig(
            level=logging.INFO,
            format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
            handlers=[
                logging.FileHandler('edge_gateway.log'),
                logging.StreamHandler(sys.stdout)
            ]
        )
        self.logger = logging.getLogger(__name__)
    
    def setup_gpio(self):
        """Setup GPIO pins"""
        GPIO.setmode(GPIO.BCM)
        GPIO.setwarnings(False)
        
        # Setup pins
        self.dht_pin = self.config['sensors']['dht_pin']
        self.light_pin = self.config['sensors']['light_pin']
        self.motion_pin = self.config['sensors']['motion_pin']
        
        # Setup motion pin as input with pull-up
        GPIO.setup(self.motion_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
        
        # Add interrupt for motion detection
        GPIO.add_event_detect(self.motion_pin, GPIO.RISING, 
                           callback=self.motion_detected, bouncetime=300)
        
        self.logger.info("GPIO setup completed")
    
    def setup_sensors(self):
        """Setup sensor interfaces"""
        # DHT22 sensor
        self.dht_sensor = Adafruit_DHT.DHT22
        
        # ADS1115 ADC for analog sensors
        i2c = busio.I2C(board.SCL, board.SDA)
        self.ads = ADS.ADS1115(i2c)
        self.ads.gain = 1  # +/- 4.096V
        
        # Analog channels
        self.light_channel = AnalogIn(self.ads, ADS.P0)
        self.temp_channel = AnalogIn(self.ads, ADS.P1)
        self.humidity_channel = AnalogIn(self.ads, ADS.P2)
        
        self.logger.info("Sensors setup completed")
    
    def setup_camera(self):
        """Setup camera interface"""
        try:
            self.camera = picamera.PiCamera()
            self.camera.resolution = tuple(self.config['camera']['resolution'])
            self.camera.framerate = self.config['camera']['framerate']
            self.camera.rotation = self.config['camera']['rotation']
            
            # Camera warm-up
            time.sleep(2)
            
            self.logger.info("Camera setup completed")
        except Exception as e:
            self.logger.error(f"Camera setup failed: {e}")
            self.camera = None
    
    def setup_mqtt(self):
        """Setup MQTT client"""
        self.mqtt_client = mqtt.Client(self.config['mqtt']['client_id'])
        
        # Set callbacks
        self.mqtt_client.on_connect = self.mqtt_on_connect
        self.mqtt_client.on_message = self.mqtt_on_message
        self.mqtt_client.on_disconnect = self.mqtt_on_disconnect
        
        # Set credentials if provided
        if self.config['mqtt']['username']:
            self.mqtt_client.username_pw_set(
                self.config['mqtt']['username'],
                self.config['mqtt']['password']
            )
        
        # Connect to broker
        try:
            self.mqtt_client.connect(
                self.config['mqtt']['broker'],
                self.config['mqtt']['port'],
                60
            )
            self.mqtt_client.loop_start()
            self.logger.info("MQTT client connected")
        except Exception as e:
            self.logger.error(f"MQTT connection failed: {e}")
    
    def setup_database(self):
        """Setup SQLite database"""
        self.db_path = self.config['database']['path']
        self.init_database()
        self.logger.info("Database setup completed")
    
    def init_database(self):
        """Initialize database tables"""
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        
        # Sensor data table
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS sensor_data (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
                sensor_type TEXT,
                sensor_id TEXT,
                value REAL,
                unit TEXT,
                processed BOOLEAN DEFAULT FALSE
            )
        ''')
        
        # Image data table
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS image_data (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
                filename TEXT,
                objects_detected TEXT,
                confidence REAL,
                processed BOOLEAN DEFAULT FALSE
            )
        ''')
        
        # System status table
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS system_status (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
                cpu_usage REAL,
                memory_usage REAL,
                disk_usage REAL,
                temperature REAL,
                uptime INTEGER
            )
        ''')
        
        conn.commit()
        conn.close()
    
    def setup_ml_models(self):
        """Setup machine learning models"""
        self.models = {}
        
        try:
            # Load object detection model
            if os.path.exists(self.config['ml_models']['object_detection']):
                self.models['object_detection'] = load_model(
                    self.config['ml_models']['object_detection']
                )
                self.logger.info("Object detection model loaded")
            
            # Load anomaly detection model
            if os.path.exists(self.config['ml_models']['anomaly_detection']):
                self.models['anomaly_detection'] = load_model(
                    self.config['ml_models']['anomaly_detection']
                )
                self.logger.info("Anomaly detection model loaded")
                
        except Exception as e:
            self.logger.error(f"ML model loading failed: {e}")
    
    def mqtt_on_connect(self, client, userdata, flags, rc):
        """MQTT connection callback"""
        if rc == 0:
            self.logger.info("Connected to MQTT broker")
            # Subscribe to control topics
            client.subscribe("edge/gateway/control")
            client.subscribe("edge/sensors/+/control")
        else:
            self.logger.error(f"MQTT connection failed with code {rc}")
    
    def mqtt_on_message(self, client, userdata, msg):
        """MQTT message callback"""
        try:
            topic = msg.topic
            payload = json.loads(msg.payload.decode())
            
            self.logger.info(f"Received message on {topic}: {payload}")
            
            # Handle control messages
            if "control" in topic:
                self.control_queue.put((topic, payload))
                
        except Exception as e:
            self.logger.error(f"MQTT message processing failed: {e}")
    
    def mqtt_on_disconnect(self, client, userdata, rc):
        """MQTT disconnection callback"""
        self.logger.warning(f"MQTT disconnected with code {rc}")
    
    def motion_detected(self, channel):
        """Motion detection interrupt handler"""
        timestamp = datetime.now().isoformat()
        
        # Publish motion alert
        alert = {
            "device_id": self.config['mqtt']['client_id'],
            "timestamp": timestamp,
            "alert_type": "motion",
            "location": "entrance"
        }
        
        self.mqtt_client.publish("edge/alerts/motion", json.dumps(alert))
        
        # Trigger image capture
        if self.camera:
            self.image_queue.put(("motion", timestamp))
        
        self.logger.info("Motion detected and alert published")
    
    def read_dht_sensor(self):
        """Read DHT22 sensor data"""
        humidity, temperature = Adafruit_DHT.read_retry(
            self.dht_sensor, self.dht_pin
        )
        
        if humidity is not None and temperature is not None:
            return {
                "temperature": temperature,
                "humidity": humidity,
                "timestamp": datetime.now().isoformat()
            }
        else:
            self.logger.error("Failed to read DHT sensor")
            return None
    
    def read_analog_sensors(self):
        """Read analog sensor data"""
        try:
            # Read light sensor
            light_voltage = self.light_channel.voltage
            light_level = (light_voltage / 3.3) * 100  # Convert to percentage
            
            # Read temperature sensor (if using analog temp sensor)
            temp_voltage = self.temp_channel.voltage
            # Convert voltage to temperature (example conversion)
            analog_temp = (temp_voltage - 0.5) * 100  # LM35 conversion
            
            # Read humidity sensor (if using analog humidity sensor)
            humidity_voltage = self.humidity_channel.voltage
            analog_humidity = (humidity_voltage / 3.3) * 100
            
            return {
                "light_level": light_level,
                "analog_temperature": analog_temp,
                "analog_humidity": analog_humidity,
                "timestamp": datetime.now().isoformat()
            }
        except Exception as e:
            self.logger.error(f"Analog sensor reading failed: {e}")
            return None
    
    def capture_image(self, trigger="scheduled"):
        """Capture image from camera"""
        if not self.camera:
            return None
        
        try:
            timestamp = datetime.now().isoformat()
            filename = f"images/capture_{timestamp.replace(':', '-')}.jpg"
            
            # Capture image
            self.camera.capture(filename)
            
            # Process image with ML models
            processed_image = self.process_image(filename)
            
            return {
                "filename": filename,
                "timestamp": timestamp,
                "trigger": trigger,
                "processed": processed_image
            }
        except Exception as e:
            self.logger.error(f"Image capture failed: {e}")
            return None
    
    def process_image(self, image_path):
        """Process image with ML models"""
        try:
            # Load and preprocess image
            img = image.load_img(image_path, target_size=(224, 224))
            img_array = image.img_to_array(img)
            img_array = np.expand_dims(img_array, axis=0)
            img_array = img_array / 255.0
            
            result = {}
            
            # Object detection
            if 'object_detection' in self.models:
                predictions = self.models['object_detection'].predict(img_array)
                result['objects'] = self.decode_predictions(predictions)
            
            # Anomaly detection
            if 'anomaly_detection' in self.models:
                anomaly_score = self.models['anomaly_detection'].predict(img_array)[0][0]
                result['anomaly_score'] = float(anomaly_score)
                result['is_anomaly'] = anomaly_score > 0.5
            
            return result
            
        except Exception as e:
            self.logger.error(f"Image processing failed: {e}")
            return None
    
    def decode_predictions(self, predictions):
        """Decode ML model predictions"""
        # This would depend on the specific model
        # Example implementation
        class_names = ['person', 'car', 'bicycle', 'dog', 'cat']
        
        # Get top predictions
        top_indices = np.argsort(predictions[0])[-5:][::-1]
        results = []
        
        for i, index in enumerate(top_indices):
            results.append({
                "class": class_names[index],
                "confidence": float(predictions[0][index]),
                "rank": i + 1
            })
        
        return results
    
    def store_sensor_data(self, sensor_data):
        """Store sensor data in database"""
        try:
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            for sensor_type, value in sensor_data.items():
                if sensor_type == "timestamp":
                    continue
                
                cursor.execute('''
                    INSERT INTO sensor_data (sensor_type, sensor_id, value, unit)
                    VALUES (?, ?, ?, ?)
                ''', (sensor_type, "gateway_01", value, self.get_unit(sensor_type)))
            
            conn.commit()
            conn.close()
            
        except Exception as e:
            self.logger.error(f"Database storage failed: {e}")
    
    def get_unit(self, sensor_type):
        """Get unit for sensor type"""
        units = {
            "temperature": "°C",
            "humidity": "%",
            "light_level": "%",
            "analog_temperature": "°C",
            "analog_humidity": "%"
        }
        return units.get(sensor_type, "")
    
    def get_system_status(self):
        """Get system status information"""
        try:
            # CPU usage
            cpu_usage = psutil.cpu_percent()
            
            # Memory usage
            memory = psutil.virtual_memory()
            memory_usage = memory.percent
            
            # Disk usage
            disk = psutil.disk_usage('/')
            disk_usage = disk.percent
            
            # CPU temperature
            try:
                temp = subprocess.check_output(['vcgencmd', 'measure_temp'])
                cpu_temp = float(temp.decode().split('=')[1].split("'")[0])
            except:
                cpu_temp = 0.0
            
            # Uptime
            uptime = time.time() - psutil.boot_time()
            
            return {
                "cpu_usage": cpu_usage,
                "memory_usage": memory_usage,
                "disk_usage": disk_usage,
                "temperature": cpu_temp,
                "uptime": uptime,
                "timestamp": datetime.now().isoformat()
            }
            
        except Exception as e:
            self.logger.error(f"System status check failed: {e}")
            return None
    
    def sensor_worker(self):
        """Worker thread for sensor data collection"""
        self.logger.info("Sensor worker started")
        
        while self.running:
            try:
                # Read DHT sensor
                dht_data = self.read_dht_sensor()
                if dht_data:
                    self.sensor_queue.put(("dht", dht_data))
                
                # Read analog sensors
                analog_data = self.read_analog_sensors()
                if analog_data:
                    self.sensor_queue.put(("analog", analog_data))
                
                # Get system status
                system_status = self.get_system_status()
                if system_status:
                    self.sensor_queue.put(("system", system_status))
                
                # Sleep for interval
                time.sleep(self.config['processing']['sensor_interval'])
                
            except Exception as e:
                self.logger.error(f"Sensor worker error: {e}")
                time.sleep(1)
    
    def image_worker(self):
        """Worker thread for image processing"""
        self.logger.info("Image worker started")
        
        while self.running:
            try:
                # Get image capture request
                if not self.image_queue.empty():
                    trigger, timestamp = self.image_queue.get(timeout=1)
                    
                    # Capture image
                    image_data = self.capture_image(trigger)
                    if image_data:
                        # Publish image data
                        self.mqtt_client.publish(
                            "edge/gateway/images",
                            json.dumps(image_data)
                        )
                        
                        # Store in database
                        self.store_image_data(image_data)
                
                # Periodic image capture
                else:
                    image_data = self.capture_image("scheduled")
                    if image_data:
                        self.mqtt_client.publish(
                            "edge/gateway/images",
                            json.dumps(image_data)
                        )
                        self.store_image_data(image_data)
                
                # Sleep for interval
                time.sleep(self.config['processing']['image_interval'])
                
            except queue.Empty:
                continue
            except Exception as e:
                self.logger.error(f"Image worker error: {e}")
                time.sleep(1)
    
    def control_worker(self):
        """Worker thread for control commands"""
        self.logger.info("Control worker started")
        
        while self.running:
            try:
                # Get control command
                topic, command = self.control_queue.get(timeout=1)
                
                self.logger.info(f"Processing control command: {command}")
                
                # Handle commands
                if command.get("command") == "restart":
                    self.restart_system()
                elif command.get("command") == "shutdown":
                    self.shutdown_system()
                elif command.get("command") == "capture_image":
                    self.image_queue.put(("manual", datetime.now().isoformat()))
                elif command.get("command") == "update_config":
                    self.update_config(command.get("config", {}))
                
            except queue.Empty:
                continue
            except Exception as e:
                self.logger.error(f"Control worker error: {e}")
                time.sleep(1)
    
    def data_processor(self):
        """Worker thread for data processing and publishing"""
        self.logger.info("Data processor started")
        
        while self.running:
            try:
                # Process sensor data
                if not self.sensor_queue.empty():
                    sensor_type, data = self.sensor_queue.get(timeout=1)
                    
                    # Store in database
                    self.store_sensor_data(data)
                    
                    # Publish to MQTT
                    topic = f"edge/sensors/{sensor_type}"
                    self.mqtt_client.publish(topic, json.dumps(data))
                    
                    # Check for anomalies
                    if sensor_type == "system":
                        self.check_system_anomalies(data)
                
                time.sleep(0.1)
                
            except queue.Empty:
                continue
            except Exception as e:
                self.logger.error(f"Data processor error: {e}")
                time.sleep(1)
    
    def check_system_anomalies(self, system_data):
        """Check for system anomalies"""
        anomalies = []
        
        # Check CPU usage
        if system_data.get("cpu_usage", 0) > 80:
            anomalies.append("high_cpu_usage")
        
        # Check memory usage
        if system_data.get("memory_usage", 0) > 85:
            anomalies.append("high_memory_usage")
        
        # Check disk usage
        if system_data.get("disk_usage", 0) > 90:
            anomalies.append("high_disk_usage")
        
        # Check temperature
        if system_data.get("temperature", 0) > 70:
            anomalies.append("high_temperature")
        
        # Publish anomalies if any
        if anomalies:
            alert = {
                "device_id": self.config['mqtt']['client_id'],
                "timestamp": datetime.now().isoformat(),
                "alert_type": "system_anomaly",
                "anomalies": anomalies,
                "system_data": system_data
            }
            
            self.mqtt_client.publish("edge/alerts/system", json.dumps(alert))
            self.logger.warning(f"System anomalies detected: {anomalies}")
    
    def store_image_data(self, image_data):
        """Store image data in database"""
        try:
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            cursor.execute('''
                INSERT INTO image_data (filename, objects_detected, confidence, processed)
                VALUES (?, ?, ?, ?)
            ''', (
                image_data["filename"],
                json.dumps(image_data.get("processed", {})),
                0.0,  # Default confidence
                image_data.get("processed") is not None
            ))
            
            conn.commit()
            conn.close()
            
        except Exception as e:
            self.logger.error(f"Image data storage failed: {e}")
    
    def restart_system(self):
        """Restart the system"""
        self.logger.info("System restart requested")
        self.running = False
        
        # Restart after cleanup
        subprocess.run(['sudo', 'reboot'])
    
    def shutdown_system(self):
        """Shutdown the system"""
        self.logger.info("System shutdown requested")
        self.running = False
        
        # Shutdown after cleanup
        subprocess.run(['sudo', 'shutdown', '-h', 'now'])
    
    def update_config(self, new_config):
        """Update configuration"""
        self.config.update(new_config)
        
        # Save new config
        with open('config.json', 'w') as f:
            json.dump(self.config, f, indent=2)
        
        self.logger.info("Configuration updated")
    
    def start(self):
        """Start the edge gateway"""
        self.logger.info("Starting IoT Edge Gateway")
        
        # Start worker threads
        self.threads = [
            threading.Thread(target=self.sensor_worker, daemon=True),
            threading.Thread(target=self.image_worker, daemon=True),
            threading.Thread(target=self.control_worker, daemon=True),
            threading.Thread(target=self.data_processor, daemon=True)
        ]
        
        for thread in self.threads:
            thread.start()
        
        self.logger.info("All worker threads started")
    
    def stop(self):
        """Stop the edge gateway"""
        self.logger.info("Stopping IoT Edge Gateway")
        
        self.running = False
        
        # Stop MQTT client
        self.mqtt_client.loop_stop()
        self.mqtt_client.disconnect()
        
        # Cleanup GPIO
        GPIO.cleanup()
        
        # Wait for threads to finish
        for thread in self.threads:
            thread.join(timeout=5)
        
        self.logger.info("IoT Edge Gateway stopped")
    
    def signal_handler(self, signum, frame):
        """Handle system signals"""
        self.logger.info(f"Received signal {signum}")
        self.stop()
        sys.exit(0)
    
    def run(self):
        """Main run loop"""
        try:
            self.start()
            
            # Keep main thread alive
            while self.running:
                time.sleep(1)
                
        except KeyboardInterrupt:
            self.logger.info("Keyboard interrupt received")
        except Exception as e:
            self.logger.error(f"Unexpected error: {e}")
        finally:
            self.stop()

if __name__ == "__main__":
    # Import psutil for system monitoring
    import psutil
    
    # Create and run edge gateway
    gateway = IoTEdgeGateway()
    gateway.run()

3. Embedded C++ for Microcontrollers

#include <Arduino.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <RTClib.h>
#include <DHT.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <EEPROM.h>
#include <FreeRTOS.h>
#include <task.h>

// Configuration constants
#define WIFI_SSID "YOUR_WIFI_SSID"
#define WIFI_PASSWORD "YOUR_WIFI_PASSWORD"
#define MQTT_SERVER "mqtt.example.com"
#define MQTT_PORT 1883
#define MQTT_CLIENT_ID "embedded_device_01"
#define MQTT_USERNAME "your_username"
#define MQTT_PASSWORD "your_password"

// Pin definitions
#define DHT_PIN 4
#define BMP_SDA_PIN 21
#define BMP_SCL_PIN 22
#define SD_CS_PIN 5
#define LED_PIN 2
#define BUZZER_PIN 12
#define RELAY_PIN 13
#define BUTTON_PIN 0

// Sensor types
#define DHT_TYPE DHT22

// Task priorities
#define SENSOR_TASK_PRIORITY 2
#define COMM_TASK_PRIORITY 3
#define CONTROL_TASK_PRIORITY 1
#define DATA_LOGGER_TASK_PRIORITY 1

// Task stack sizes
#define SENSOR_TASK_STACK_SIZE 2048
#define COMM_TASK_STACK_SIZE 4096
#define CONTROL_TASK_STACK_SIZE 2048
#define DATA_LOGGER_TASK_STACK_SIZE 2048

// Data structures
struct SensorData {
    float temperature;
    float humidity;
    float pressure;
    float altitude;
    unsigned long timestamp;
    bool valid;
};

struct SystemStatus {
    bool wifiConnected;
    bool mqttConnected;
    bool sdCardPresent;
    float batteryLevel;
    int uptime;
    int freeHeap;
    float cpuTemperature;
    unsigned long lastSensorRead;
    unsigned long lastMQTTMessage;
};

struct ControlCommand {
    String command;
    String parameters;
    unsigned long timestamp;
    bool processed;
};

// Global objects
DHT dhtSensor(DHT_PIN, DHT_TYPE);
Adafruit_BMP280 bmp280;
RTC_DS3231 rtc;
WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);

// Data queues
QueueHandle_t sensorDataQueue;
QueueHandle_t controlCommandQueue;
QueueHandle_t logDataQueue;

// Semaphores
SemaphoreHandle_t wifiMutex;
SemaphoreHandle_t mqttMutex;
SemaphoreHandle_t sensorMutex;
SemaphoreHandle_t sdMutex;

// Global variables
SystemStatus systemStatus;
TaskHandle_t sensorTaskHandle;
TaskHandle_t commTaskHandle;
TaskHandle_t controlTaskHandle;
TaskHandle_t dataLoggerTaskHandle;

// Function prototypes
void sensorTask(void *pvParameters);
void communicationTask(void *pvParameters);
void controlTask(void *pvParameters);
void dataLoggerTask(void *pvParameters);
void connectWiFi();
void connectMQTT();
void mqttCallback(char* topic, byte* payload, unsigned int length);
void publishSensorData(SensorData& data);
void publishSystemStatus();
void handleControlCommand(ControlCommand& command);
void logData(String message);
void setupSensors();
void setupSDCard();
void setupRTC();
void buttonISR();
void alertUser(int beeps, int duration);
void enterDeepSleep(int seconds);
void wakeFromDeepSleep();

void setup() {
    Serial.begin(115200);
    Serial.println("Embedded IoT Device starting...");
    
    // Initialize GPIO
    pinMode(LED_PIN, OUTPUT);
    pinMode(BUZZER_PIN, OUTPUT);
    pinMode(RELAY_PIN, OUTPUT);
    pinMode(BUTTON_PIN, INPUT_PULLUP);
    
    // Setup interrupts
    attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), buttonISR, FALLING);
    
    // Initialize semaphores
    wifiMutex = xSemaphoreCreateMutex();
    mqttMutex = xSemaphoreCreateMutex();
    sensorMutex = xSemaphoreCreateMutex();
    sdMutex = xSemaphoreCreateMutex();
    
    // Initialize queues
    sensorDataQueue = xQueueCreate(10, sizeof(SensorData));
    controlCommandQueue = xQueueCreate(5, sizeof(ControlCommand));
    logDataQueue = xQueueCreate(20, sizeof(String[50]));
    
    // Setup hardware
    setupSensors();
    setupSDCard();
    setupRTC();
    
    // Initialize system status
    systemStatus = {
        .wifiConnected = false,
        .mqttConnected = false,
        .sdCardPresent = false,
        .batteryLevel = 0.0,
        .uptime = 0,
        .freeHeap = ESP.getFreeHeap(),
        .cpuTemperature = 0.0,
        .lastSensorRead = 0,
        .lastMQTTMessage = 0
    };
    
    // Create FreeRTOS tasks
    xTaskCreate(
        sensorTask,
        "SensorTask",
        SENSOR_TASK_STACK_SIZE,
        NULL,
        SENSOR_TASK_PRIORITY,
        &sensorTaskHandle
    );
    
    xTaskCreate(
        communicationTask,
        "CommTask",
        COMM_TASK_STACK_SIZE,
        NULL,
        COMM_TASK_PRIORITY,
        &commTaskHandle
    );
    
    xTaskCreate(
        controlTask,
        "ControlTask",
        CONTROL_TASK_STACK_SIZE,
        NULL,
        CONTROL_TASK_PRIORITY,
        &controlTaskHandle
    );
    
    xTaskCreate(
        dataLoggerTask,
        "DataLoggerTask",
        DATA_LOGGER_TASK_STACK_SIZE,
        NULL,
        DATA_LOGGER_TASK_PRIORITY,
        &dataLoggerTaskHandle
    );
    
    // Alert user that system is ready
    alertUser(3, 200);
    
    Serial.println("Embedded IoT Device ready!");
}

void loop() {
    // Main loop is handled by FreeRTOS tasks
    vTaskDelay(pdMS_TO_TICKS(1000));
}

void sensorTask(void *pvParameters) {
    Serial.println("Sensor task started");
    
    SensorData sensorData;
    const TickType_t xDelay = pdMS_TO_TICKS(5000); // 5 seconds
    
    while (1) {
        // Take sensor mutex
        if (xSemaphoreTake(sensorMutex, pdMS_TO_TICKS(100)) == pdTRUE) {
            // Read DHT sensor
            float humidity = dhtSensor.readHumidity();
            float temperature = dhtSensor.readTemperature();
            
            // Read BMP280 sensor
            float pressure = bmp280.readPressure();
            float altitude = bmp280.readAltitude(1013.25); // Sea level pressure
            
            // Check if readings are valid
            if (!isnan(humidity) && !isnan(temperature) && pressure > 0) {
                sensorData.temperature = temperature;
                sensorData.humidity = humidity;
                sensorData.pressure = pressure / 100.0; // Convert to hPa
                sensorData.altitude = altitude;
                sensorData.timestamp = millis();
                sensorData.valid = true;
                
                // Update system status
                systemStatus.lastSensorRead = millis();
                systemStatus.freeHeap = ESP.getFreeHeap();
                
                // Send data to queue
                if (xQueueSend(sensorDataQueue, &sensorData, pdMS_TO_TICKS(100)) != pdTRUE) {
                    Serial.println("Failed to send sensor data to queue");
                }
                
                // Log sensor data
                String logMessage = "Sensor: T=" + String(temperature) + 
                                  "C, H=" + String(humidity) + 
                                  "%, P=" + String(sensorData.pressure) + "hPa";
                logData(logMessage);
                
            } else {
                Serial.println("Invalid sensor readings");
                sensorData.valid = false;
                
                // Log error
                logData("ERROR: Invalid sensor readings");
            }
            
            xSemaphoreGive(sensorMutex);
        } else {
            Serial.println("Failed to take sensor mutex");
        }
        
        vTaskDelay(xDelay);
    }
}

void communicationTask(void *pvParameters) {
    Serial.println("Communication task started");
    
    const TickType_t xDelay = pdMS_TO_TICKS(1000); // 1 second
    
    while (1) {
        // Handle WiFi connection
        if (xSemaphoreTake(wifiMutex, pdMS_TO_TICKS(100)) == pdTRUE) {
            if (WiFi.status() != WL_CONNECTED) {
                connectWiFi();
            }
            
            systemStatus.wifiConnected = (WiFi.status() == WL_CONNECTED);
            xSemaphoreGive(wifiMutex);
        }
        
        // Handle MQTT connection
        if (systemStatus.wifiConnected) {
            if (xSemaphoreTake(mqttMutex, pdMS_TO_TICKS(100)) == pdTRUE) {
                if (!mqttClient.connected()) {
                    connectMQTT();
                }
                
                systemStatus.mqttConnected = mqttClient.connected();
                
                // Process MQTT messages
                mqttClient.loop();
                
                xSemaphoreGive(mqttMutex);
            }
        }
        
        // Publish sensor data
        SensorData sensorData;
        if (xQueueReceive(sensorDataQueue, &sensorData, pdMS_TO_TICKS(100)) == pdTRUE) {
            if (sensorData.valid && systemStatus.mqttConnected) {
                publishSensorData(sensorData);
                systemStatus.lastMQTTMessage = millis();
            }
        }
        
        // Publish system status periodically
        static unsigned long lastStatusPublish = 0;
        if (millis() - lastStatusPublish > 60000) { // Every minute
            if (systemStatus.mqttConnected) {
                publishSystemStatus();
                lastStatusPublish = millis();
            }
        }
        
        vTaskDelay(xDelay);
    }
}

void controlTask(void *pvParameters) {
    Serial.println("Control task started");
    
    ControlCommand command;
    const TickType_t xDelay = pdMS_TO_TICKS(500); // 0.5 seconds
    
    while (1) {
        // Process control commands
        if (xQueueReceive(controlCommandQueue, &command, pdMS_TO_TICKS(100)) == pdTRUE) {
            handleControlCommand(command);
        }
        
        // Monitor system health
        static unsigned long lastHealthCheck = 0;
        if (millis() - lastHealthCheck > 30000) { // Every 30 seconds
            // Check free heap
            if (ESP.getFreeHeap() < 1000) {
                logData("WARNING: Low memory");
                alertUser(2, 100);
            }
            
            // Check uptime
            systemStatus.uptime = millis() / 1000;
            
            // Check battery level (if implemented)
            systemStatus.batteryLevel = getBatteryLevel();
            
            lastHealthCheck = millis();
        }
        
        vTaskDelay(xDelay);
    }
}

void dataLoggerTask(void *pvParameters) {
    Serial.println("Data logger task started");
    
    String logMessage;
    const TickType_t xDelay = pdMS_TO_TICKS(1000); // 1 second
    
    while (1) {
        // Process log messages
        if (xQueueReceive(logDataQueue, &logMessage, pdMS_TO_TICKS(100)) == pdTRUE) {
            // Print to serial
            Serial.println(logMessage);
            
            // Write to SD card if available
            if (systemStatus.sdCardPresent) {
                if (xSemaphoreTake(sdMutex, pdMS_TO_TICKS(100)) == pdTRUE) {
                    writeLogToSD(logMessage);
                    xSemaphoreGive(sdMutex);
                }
            }
        }
        
        vTaskDelay(xDelay);
    }
}

void connectWiFi() {
    Serial.println("Connecting to WiFi...");
    
    WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
    
    int attempts = 0;
    while (WiFi.status() != WL_CONNECTED && attempts < 30) {
        vTaskDelay(pdMS_TO_TICKS(500));
        Serial.print(".");
        attempts++;
    }
    
    if (WiFi.status() == WL_CONNECTED) {
        Serial.println("\nWiFi connected!");
        Serial.print("IP address: ");
        Serial.println(WiFi.localIP());
        digitalWrite(LED_PIN, HIGH);
        logData("WiFi connected: " + WiFi.localIP().toString());
    } else {
        Serial.println("\nFailed to connect to WiFi");
        digitalWrite(LED_PIN, LOW);
        logData("ERROR: WiFi connection failed");
    }
}

void connectMQTT() {
    Serial.println("Connecting to MQTT...");
    
    mqttClient.setServer(MQTT_SERVER, MQTT_PORT);
    mqttClient.setCallback(mqttCallback);
    
    int attempts = 0;
    while (!mqttClient.connected() && attempts < 10) {
        Serial.print("Attempting MQTT connection...");
        
        if (mqttClient.connect(MQTT_CLIENT_ID, MQTT_USERNAME, MQTT_PASSWORD)) {
            Serial.println("connected!");
            
            // Subscribe to control topics
            mqttClient.subscribe("embedded/control");
            mqttClient.subscribe("embedded/" + String(MQTT_CLIENT_ID) + "/control");
            
            logData("MQTT connected");
            
        } else {
            Serial.print("failed, rc=");
            Serial.print(mqttClient.state());
            Serial.println(" try again in 5 seconds");
            vTaskDelay(pdMS_TO_TICKS(5000));
            attempts++;
        }
    }
    
    if (!mqttClient.connected()) {
        Serial.println("Failed to connect to MQTT");
        logData("ERROR: MQTT connection failed");
    }
}

void mqttCallback(char* topic, byte* payload, unsigned int length) {
    Serial.print("Message arrived [");
    Serial.print(topic);
    Serial.print("] ");
    
    String message = "";
    for (int i = 0; i < length; i++) {
        message += (char)payload[i];
    }
    Serial.println(message);
    
    // Parse JSON message
    DynamicJsonDocument doc(1024);
    DeserializationError error = deserializeJson(doc, message);
    
    if (error) {
        Serial.println("Failed to parse JSON");
        logData("ERROR: Failed to parse MQTT message");
        return;
    }
    
    // Create control command
    ControlCommand command;
    command.command = doc["command"] | "";
    command.parameters = doc["parameters"] | "";
    command.timestamp = millis();
    command.processed = false;
    
    // Send command to control task
    if (xQueueSend(controlCommandQueue, &command, pdMS_TO_TICKS(100)) != pdTRUE) {
        Serial.println("Failed to send control command to queue");
    }
}

void publishSensorData(SensorData& data) {
    if (xSemaphoreTake(mqttMutex, pdMS_TO_TICKS(100)) == pdTRUE) {
        // Create JSON document
        DynamicJsonDocument doc(1024);
        
        doc["device_id"] = MQTT_CLIENT_ID;
        doc["timestamp"] = data.timestamp;
        doc["temperature"] = data.temperature;
        doc["humidity"] = data.humidity;
        doc["pressure"] = data.pressure;
        doc["altitude"] = data.altitude;
        
        // Serialize JSON
        String jsonStr;
        serializeJson(doc, jsonStr);
        
        // Publish to topics
        mqttClient.publish("embedded/sensors/temperature", String(data.temperature).c_str());
        mqttClient.publish("embedded/sensors/humidity", String(data.humidity).c_str());
        mqttClient.publish("embedded/sensors/pressure", String(data.pressure).c_str());
        mqttClient.publish("embedded/sensors/combined", jsonStr.c_str());
        
        xSemaphoreGive(mqttMutex);
    }
}

void publishSystemStatus() {
    if (xSemaphoreTake(mqttMutex, pdMS_TO_TICKS(100)) == pdTRUE) {
        // Create JSON document
        DynamicJsonDocument doc(1024);
        
        doc["device_id"] = MQTT_CLIENT_ID;
        doc["timestamp"] = millis();
        doc["wifi_connected"] = systemStatus.wifiConnected;
        doc["mqtt_connected"] = systemStatus.mqttConnected;
        doc["sd_card_present"] = systemStatus.sdCardPresent;
        doc["battery_level"] = systemStatus.batteryLevel;
        doc["uptime"] = systemStatus.uptime;
        doc["free_heap"] = systemStatus.freeHeap;
        doc["cpu_temperature"] = systemStatus.cpuTemperature;
        doc["last_sensor_read"] = systemStatus.lastSensorRead;
        doc["last_mqtt_message"] = systemStatus.lastMQTTMessage;
        
        // Serialize JSON
        String jsonStr;
        serializeJson(doc, jsonStr);
        
        // Publish status
        mqttClient.publish("embedded/status", jsonStr.c_str());
        
        xSemaphoreGive(mqttMutex);
    }
}

void handleControlCommand(ControlCommand& command) {
    Serial.println("Processing control command: " + command.command);
    
    if (command.command == "buzz") {
        int duration = command.parameters.toInt();
        if (duration == 0) duration = 1000;
        alertUser(1, duration);
        
    } else if (command.command == "led") {
        bool state = (command.parameters == "on");
        digitalWrite(LED_PIN, state ? HIGH : LOW);
        
    } else if (command.command == "relay") {
        bool state = (command.parameters == "on");
        digitalWrite(RELAY_PIN, state ? HIGH : LOW);
        
    } else if (command.command == "restart") {
        Serial.println("Restarting device...");
        logData("System restart requested");
        vTaskDelay(pdMS_TO_TICKS(1000));
        ESP.restart();
        
    } else if (command.command == "sleep") {
        int seconds = command.parameters.toInt();
        if (seconds == 0) seconds = 10;
        Serial.println("Going to sleep for " + String(seconds) + " seconds");
        logData("Entering deep sleep for " + String(seconds) + " seconds");
        enterDeepSleep(seconds);
        
    } else if (command.command == "get_status") {
        publishSystemStatus();
        
    } else {
        Serial.println("Unknown command: " + command.command);
        logData("WARNING: Unknown control command: " + command.command);
    }
    
    command.processed = true;
}

void logData(String message) {
    String logEntry = String(millis()) + ": " + message;
    
    // Send to logger queue
    if (xQueueSend(logDataQueue, &logEntry, pdMS_TO_TICKS(100)) != pdTRUE) {
        Serial.println("Failed to send log message to queue");
    }
}

void setupSensors() {
    Serial.println("Setting up sensors...");
    
    // Initialize DHT sensor
    dhtSensor.begin();
    
    // Initialize BMP280
    if (!bmp280.begin(BMP280_ADDRESS_ALT)) {
        Serial.println("Could not find BMP280 sensor!");
        logData("ERROR: BMP280 sensor not found");
    } else {
        Serial.println("BMP280 sensor initialized");
        logData("BMP280 sensor initialized");
    }
    
    Serial.println("Sensors setup completed");
}

void setupSDCard() {
    Serial.println("Setting up SD card...");
    
    if (SD.begin(SD_CS_PIN)) {
        Serial.println("SD card initialized");
        systemStatus.sdCardPresent = true;
        logData("SD card initialized");
        
        // Create log file if it doesn't exist
        File logFile = SD.open("/log.txt", FILE_WRITE);
        if (logFile) {
            logFile.println("\n=== System Restart ===");
            logFile.close();
        }
    } else {
        Serial.println("SD card initialization failed");
        systemStatus.sdCardPresent = false;
        logData("ERROR: SD card initialization failed");
    }
}

void setupRTC() {
    Serial.println("Setting up RTC...");
    
    if (rtc.begin()) {
        if (rtc.lostPower()) {
            Serial.println("RTC lost power, setting to compile time");
            rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
        }
        Serial.println("RTC initialized");
        logData("RTC initialized");
    } else {
        Serial.println("Couldn't find RTC");
        logData("ERROR: RTC not found");
    }
}

void writeLogToSD(String message) {
    File logFile = SD.open("/log.txt", FILE_WRITE);
    if (logFile) {
        DateTime now = rtc.now();
        logFile.print(now.timestamp(DateTime::TIMESTAMP_FULL));
        logFile.print(": ");
        logFile.println(message);
        logFile.close();
    }
}

void buttonISR() {
    // Button press interrupt
    static unsigned long lastInterrupt = 0;
    unsigned long interruptTime = millis();
    
    if (interruptTime - lastInterrupt > 200) { // Debounce
        // Create manual capture command
        ControlCommand command;
        command.command = "capture";
        command.parameters = "manual";
        command.timestamp = interruptTime;
        command.processed = false;
        
        // Send to control task
        xQueueSendFromISR(controlCommandQueue, &command, NULL);
        
        // Alert user
        alertUser(1, 100);
    }
    
    lastInterrupt = interruptTime;
}

void alertUser(int beeps, int duration) {
    for (int i = 0; i < beeps; i++) {
        tone(BUZZER_PIN, 1000, duration);
        vTaskDelay(pdMS_TO_TICKS(duration * 2));
    }
}

float getBatteryLevel() {
    // Read battery voltage (assuming voltage divider)
    int rawValue = analogRead(A0);
    float voltage = rawValue * (3.3 / 4096.0) * 2.0; // Voltage divider factor
    
    // Convert to percentage (assuming 3.0V to 4.2V range)
    float percentage = ((voltage - 3.0) / 1.2) * 100.0;
    percentage = constrain(percentage, 0.0, 100.0);
    
    return percentage;
}

void enterDeepSleep(int seconds) {
    // Configure wake-up sources
    esp_sleep_enable_timer_wakeup(seconds * 1000000); // Convert to microseconds
    esp_sleep_enable_ext0_wakeup(GPIO_NUM_0, 0); // Wake on button press
    
    // Enter deep sleep
    esp_deep_sleep_start();
}

void wakeFromDeepSleep() {
    // This function is called after waking from deep sleep
    Serial.println("Waking from deep sleep...");
    
    // Reinitialize peripherals
    setupSensors();
    setupSDCard();
    
    // Check wake-up reason
    esp_sleep_wakeup_cause_t wakeup_reason = esp_sleep_get_wakeup_cause();
    
    switch (wakeup_reason) {
        case ESP_SLEEP_WAKEUP_TIMER:
            Serial.println("Wakeup caused by timer");
            break;
        case ESP_SLEEP_WAKEUP_EXT0:
            Serial.println("Wakeup caused by external signal (RTC GPIO)");
            break;
        default:
            Serial.println("Wakeup was not caused by deep sleep");
            break;
    }
}

IoT Architecture

Layered Model

graph TD
    A[Physical Layer] --> B[Sensor/Actuator Layer]
    B --> C[Edge Computing Layer]
    C --> D[Network Layer]
    D --> E[Cloud Layer]
    E --> F[Application Layer]
    
    A1[Sensors, Actuators] --> A
    B1[Microcontrollers, Gateways] --> B
    C1[Edge Processing, Analytics] --> C
    D1[WiFi, LoRaWAN, 5G] --> D
    E1[Cloud Services, Storage] --> E
    F1[Web Apps, Mobile Apps] --> F

Embedded Systems Comparison

Microcontroller vs. Microprocessors

CharacteristicMicrocontrollerMicroprocessor
IntegrationHigh (CPU + Periphery)Low (CPU only)
CostLowMedium to High
Power ConsumptionVery LowMedium to High
PerformanceLimitedHigh
MemoryInternal, limitedExternal, flexible
ApplicationEmbedded, IoTGeneral Purpose

IoT Platforms

PlatformProtocolsEdge ComputingCloud IntegrationLicense
ArduinoWiFi, EthernetLimitedCloud ServicesOpen Source
Raspberry PiWiFi, EthernetYesFull IntegrationOpen Source
ESP32WiFi, BluetoothYesMQTT, HTTPOpen Source
NVIDIA JetsonWiFi, EthernetYesNVIDIA CloudCommercial

Communication Protocols

Wireless Protocols

ProtocolRangeData RatePower ConsumptionApplication
WiFi50-100m150-600 MbpsHighIndoor, High-Speed
Bluetooth10-100m1-3 MbpsMediumPersonal Area
LoRaWAN2-15km0.3-50 kbpsVery LowLong Range
Zigbee10-100m250 kbpsLowMesh Networks

IoT Protocols

ProtocolTypeOverheadQoSApplication
MQTTPublish/SubscribeLow3 LevelsReal-time
CoAPRequest/ResponseVery LowNoneConstrained
HTTP/RESTRequest/ResponseHighTCPWeb Integration
WebSocketFull-DuplexMediumTCPReal-time

Edge Computing Concepts

Edge vs. Cloud Processing

AspectEdge ComputingCloud Computing
LatencyMillisecondsSeconds
BandwidthReducedHigh
OfflinePossibleNot possible
ScalabilityLimitedUnlimited
CostVariablePredictable

Edge Computing Applications

  • Predictive Maintenance: Local analysis of sensor data
  • Video Analytics: Real-time object detection
  • Industrial IoT: Control of production systems
  • Smart Cities: Traffic analysis and control

Advantages and Disadvantages

Advantages of IoT & Embedded Systems

  • Automation: Reduction of manual work
  • Real-time Monitoring: Immediate status information
  • Efficiency: Process optimization
  • Scalability: Flexible adaptation to demand
  • Cost Savings: Reduction of operating costs

Disadvantages

  • Security Risks: Attack surface for hackers
  • Complexity: Integration and maintenance
  • Dependency: Failure due to network problems
  • Data Protection: Collection of personal data
  • Compatibility: Different standards

Common Exam Questions

  1. What is the difference between microcontroller and microprocessor? Microcontrollers integrate CPU, memory, and periphery on a single chip, while microprocessors contain only the CPU and require external components.

  2. Explain Edge Computing! Edge Computing processes data locally on devices near the data source instead of in the cloud to reduce latency and save bandwidth.

  3. When do you use which IoT protocol? MQTT for real-time communication, CoAP for resource-constrained devices, HTTP/REST for web integration, WebSocket for bidirectional communication.

  4. What are the main requirements for embedded systems? Reliability, real-time capability, low power consumption, cost-effective production, long lifespan, and maintenance-free operation.

Important Sources

  1. https://www.arduino.cc/
  2. https://www.raspberrypi.org/
  3. https://mqtt.org/
  4. https://www.espressif.com/en/products/socs/esp32
Back to Blog
Share: