Chapter 2: Types and Classifications of Embedded Systems

Chapter Objectives

Upon completing this chapter, you will be able to:

  • Understand the fundamental characteristics that differentiate various types of embedded systems.
  • Classify an embedded system as standalone, real-time, networked, or mobile based on its operational requirements and architecture.
  • Analyze the critical timing constraints that define hard and soft real-time systems.
  • Explain the role of connectivity in modern networked and IoT devices.
  • Implement basic examples of standalone and networked systems using a Raspberry Pi 5.
  • Identify common design pitfalls associated with each system classification and propose effective solutions.

Introduction

In our exploration of embedded systems, it quickly becomes apparent that not all are created equal. The tiny processor in a digital watch operates in a world far removed from the complex, interconnected network of sensors managing a smart factory, just as the flight control system of an aircraft faces demands entirely different from those of a smartphone. To navigate this diverse landscape, we need a framework for classification. This chapter provides that framework by categorizing embedded systems based on their functionality and operational constraints. Understanding these classifications—standalone, real-time, networked, and mobile—is not merely an academic exercise. It is a foundational skill for any embedded systems engineer.

The choice of architecture, software, and hardware for a project is dictated almost entirely by the category into which it falls. Will the system operate in complete isolation, or will it communicate with a global network? Must it respond to an event within a few microseconds, or is a slight delay acceptable? Does it need to run for years on a single coin-cell battery? Answering these questions early in the design process is critical to success. By exploring these classifications, you will learn to think like an embedded architect, matching requirements to the correct design patterns. In this chapter, we will move from theory to practice, examining the defining characteristics of each system type and then using our Raspberry Pi 5 to build simple, illustrative examples that bring these concepts to life.

Technical Background

The concept of an embedded system—a computer integrated into a larger mechanical or electrical system—is incredibly broad. To bring order to this diversity, we can establish classifications based on key operational characteristics: the system’s ability to function independently, its relationship with time, its connectivity to other systems, and its mobility. These categories often overlap; a mobile device is also a networked system, and a networked system may have real-time components. However, by examining them individually, we can build a robust mental model for analyzing and designing complex embedded products.

Standalone Embedded Systems

The most fundamental category is the standalone embedded system. These are devices designed to operate in complete isolation from any other computer or network. They are self-contained, performing a dedicated set of tasks based on user inputs and internal programming. Think of a classic digital calculator, a microwave oven, or a simple digital thermostat. These devices are not concerned with internet connectivity, cloud data, or communicating with other systems. Their world is defined by their immediate inputs—button presses, sensor readings—and their direct outputs—displaying a number, turning on a heating element, or activating a compressor.

The architecture of a standalone system is typically straightforward, following a classic input-process-output model. Inputs are received from sensors or a user interface. A microcontroller or a simple microprocessor then processes these inputs according to a fixed program stored in its memory. Finally, the results are sent to output devices like an LCD screen, an LED, or an actuator. The software for these systems is often referred to as “bare-metal” firmware, meaning it runs directly on the hardware without the overhead of a general-purpose operating system like Linux. This simplicity is their greatest strength. They are generally reliable, secure from network-based threats, and highly power-efficient because they are stripped of all non-essential functionality.

While the Raspberry Pi 5, with its powerful processor and rich connectivity options, might seem like overkill for a simple standalone task, it serves as an excellent learning platform. By intentionally ignoring its networking capabilities, we can use it to emulate the focused, self-contained nature of a standalone device, providing a gentle introduction to the core logic of embedded programming before we add the complexities of networking or real-time constraints.

Real-Time Embedded Systems

The next level of complexity introduces the critical dimension of time. A real-time system is one where the correctness of a computation depends not only on its logical result but also on the time at which that result is produced. For many embedded applications, a delayed correct answer is a wrong answer. This temporal dependency, or determinism, is the defining characteristic of real-time systems. Within this category, a crucial distinction is made based on the consequence of missing a deadline.

We can separate real-time systems into two main groups: hard real-time and soft real-time.

A hard real-time system has stringent, non-negotiable deadlines. Missing a deadline constitutes a total system failure, often with catastrophic consequences. The anti-lock braking system (ABS) in a car is a classic example. When a wheel locks up, the system must release and reapply the brake within milliseconds. If it fails to meet this deadline, the system has failed in its primary safety function. Other examples include pacemakers, which must deliver an electrical impulse at a precise interval, and the flight control systems of an aircraft, where a delayed corrective action could be disastrous. These systems are designed with a “pessimistic” view of the world; they must be architected to guarantee a response within the worst-case execution time (WCET) under all possible conditions. This often requires specialized hardware and a Real-Time Operating System (RTOS), which is specifically designed for deterministic task scheduling.

gantt
    title Hard vs Soft Real-Time Deadlines Comparison
    dateFormat X
    axisFormat %s

    section Hard Real-Time System
    Task 1 (Success)     :done, h1, 0, 10
    Deadline 1          :milestone, hd1, 10, 0
    Task 2 (Success)     :done, h2, 15, 25
    Deadline 2          :milestone, hd2, 25, 0
    Task 3 (FAILURE)     :crit, h3, 30, 45
    Deadline 3 (MISSED)  :milestone, hd3, 40, 0
    System Failure       :crit, hf, 45, 50

    section Soft Real-Time System
    Task 1 (Success)     :done, s1, 0, 10
    Deadline 1          :milestone, sd1, 10, 0
    Task 2 (Success)     :done, s2, 15, 25
    Deadline 2          :milestone, sd2, 25, 0
    Task 3 (Degraded)    :active, s3, 30, 50
    Deadline 3 (MISSED)  :milestone, sd3, 40, 0
    Continued Operation  :s4, 50, 60

In contrast, a soft real-time system also has deadlines, but missing them is not catastrophic. Instead, it leads to a degradation in performance or quality of service. A video streaming application on a smart TV is a good example. The system must decode and display a certain number of frames per second to provide smooth playback. If it occasionally misses a deadline, a frame might be dropped, resulting in a momentary stutter or “glitch” in the video. While this is undesirable, it does not cause the entire system to fail. The user experience is degraded, but the system continues to function. Similarly, an industrial data acquisition system might need to log sensor readings every 100 milliseconds. If it occasionally misses a reading, it results in a small gap in the data, but the overall dataset remains largely intact and useful.

The key challenge in any real-time system is managing latency (the delay between an event and the system’s response) and jitter (the variation in that latency). In a hard real-time system, both latency and jitter must be bounded and predictable. A general-purpose operating system like the standard Raspberry Pi OS (a derivative of Debian, a Linux distribution) is not, by its nature, a real-time system. Its scheduler is designed for fairness and throughput, not for deterministic deadlines. It might pause an application to handle a background network task, leading to unpredictable delays. While projects like PREEMPT_RT aim to add real-time capabilities to the Linux kernel, achieving hard real-time performance often requires a dedicated RTOS like FreeRTOS, Zephyr, or QNX.

%%{ init: { 'theme': 'base', 'themeVariables': { 'fontFamily': 'Open Sans' } } }%%
flowchart TD
    subgraph Real-Time System Event
        A["External Event<br><i>(e.g., Sensor Trigger, User Input)</i>"]
    end

    A --> B{Process Event};

    subgraph "Hard Real-Time Path"
        B --> C{Deadline Approaching};
        C -- "Deadline Met" --> D[Action Completed<br><b>Result is Correct</b>];
        C -- "Deadline Missed" --> E["<font color='#1f2937'><b>SYSTEM FAILURE</b></font><br><i>(e.g., Airbag deploys late,<br>ABS fails)</i>"];
    end

    subgraph "Soft Real-Time Path"
        B --> F{Deadline Approaching};
        F -- "Deadline Met" --> G[Action Completed<br><b>Result is Optimal</b>];
        F -- "Deadline Missed" --> H["<font color='#1f2937'><b>DEGRADED QOS</b></font><br><i>(e.g., Video frame dropped,<br>audio stutters)</i>"];
    end

    %% Styling
    classDef primary fill:#1e3a8a,stroke:#1e3a8a,stroke-width:2px,color:#ffffff;
    classDef success fill:#10b981,stroke:#10b981,stroke-width:2px,color:#ffffff;
    classDef decision fill:#f59e0b,stroke:#f59e0b,stroke-width:1px,color:#ffffff;
    classDef process fill:#0d9488,stroke:#0d9488,stroke-width:1px,color:#ffffff;
    classDef failure fill:#ef4444,stroke:#ef4444,stroke-width:2px,color:#ffffff;
    classDef warning fill:#eab308,stroke:#eab308,stroke-width:1px,color:#1f2937;

    class A primary;
    class B process;
    class C,F decision;
    class D,G success;
    class E failure;
    class H warning;

Networked Embedded Systems

For much of computing history, embedded systems were islands of functionality. The transition to networked embedded systems represents one of the most significant shifts in the field, culminating in the modern paradigm of the Internet of Things (IoT). A networked system is designed to communicate with other devices, servers, or the internet. This connectivity transforms a device from a standalone tool into a component of a much larger, intelligent system.

The applications are virtually limitless. A smart thermostat, for example, is a networked embedded system. It doesn’t just read the local temperature; it connects to the internet via Wi-Fi to fetch weather forecasts, allowing it to pre-heat or pre-cool the house more efficiently. It can be controlled remotely via a smartphone app and can send data about energy usage to a cloud server for analysis. This constant flow of information to and from the device unlocks a level of functionality impossible for its standalone counterpart.

The architecture of a networked system includes a communication interface, which could be wired (like Ethernet) or wireless (like Wi-Fi, Bluetooth, LoRaWAN, or cellular). The software stack becomes more complex, requiring network protocols (like TCP/IP), application-layer protocols for data exchange (like MQTT or HTTP), and security measures (like TLS/SSL) to protect data in transit.

%%{ init: { 'theme': 'base', 'themeVariables': { 'fontFamily': 'Open Sans' } } }%%
flowchart TD
    subgraph "Edge Devices"
        A("Sensor Node 1<br><i>(e.g., DHT22)</i>")
        B("Sensor Node 2<br><i>(e.g., Motion Sensor)</i>")
    end

    subgraph "Local Network"
        A -- "Bluetooth LE / LoRaWAN" --> C{"IoT Gateway<br><b>(Raspberry Pi 5)</b>"};
        B -- "Bluetooth LE / LoRaWAN" --> C;
    end

    subgraph "Internet"
         C -- "Wi-Fi / Ethernet<br><b>MQTT over TLS</b>" --> D["Cloud Platform<br><i>(AWS/Azure/Google Cloud)</i>"];
    end

    subgraph "Cloud Services"
        D --> E("Data Storage<br><i>(Database)</i>");
        D --> F("Data Processing<br><i>(Analytics)</i>");
        D --> G("User Application<br><i>(Web/Mobile Dashboard)</i>");
    end

    G -- "HTTPS" --> H(End User);


    %% Styling
    classDef system fill:#8b5cf6,stroke:#8b5cf6,stroke-width:1px,color:#ffffff;
    classDef process fill:#0d9488,stroke:#0d9488,stroke-width:1px,color:#ffffff;
    classDef primary fill:#1e3a8a,stroke:#1e3a8a,stroke-width:2px,color:#ffffff;
    classDef success fill:#10b981,stroke:#10b981,stroke-width:2px,color:#ffffff;

    class A,B system;
    class C primary;
    class D,E,F,G process;
    class H success;

The Raspberry Pi 5 is an ideal platform for exploring networked systems. With its built-in Wi-Fi, Bluetooth, and Gigabit Ethernet, it is perfectly equipped to act as an IoT gateway—a device that aggregates data from smaller, simpler sensor nodes (perhaps connected via Bluetooth or a low-power radio) and uses its more powerful processing and internet connection to forward that data to the cloud. It can also act as an edge device, performing initial data processing and analysis locally (“at the edge” of the network) before sending only the important results to a central server. This reduces network traffic, lowers latency, and can improve privacy by keeping raw data local. The rise of networked systems forces engineers to become proficient not only in embedded programming but also in networking, cybersecurity, and cloud computing.

Mobile Embedded Systems

Our final category, mobile embedded systems, is defined by the constraints of portability. This includes smartphones, tablets, smartwatches, portable medical devices, and logistics scanners. While these devices are almost always networked and often have soft real-time components, their primary design drivers are size, weight, and power (SWaP).

The central challenge in mobile system design is power management. Unlike a device plugged into a wall, a mobile system must operate for a useful period on a finite battery charge. Every hardware component and every line of code must be scrutinized for its energy consumption. Processors in mobile devices employ sophisticated power-saving techniques, such as dynamically adjusting their clock speed (dynamic voltage and frequency scaling) or putting entire subsystems into a deep sleep mode when not in use. The operating system, such as Android or iOS, plays a crucial role in aggressively managing background processes to conserve battery life.

The physical form factor is another defining constraint. Components must be miniaturized and densely packed, which introduces thermal challenges. A powerful processor in a fanless, sealed smartphone case can easily overheat if not managed carefully. The system must be able to throttle its performance to avoid thermal damage.

Finally, mobile systems are characterized by a rich suite of integrated sensors. A modern smartphone contains accelerometers, gyroscopes, magnetometers (for a compass), GPS, ambient light sensors, proximity sensors, and more. These sensors provide the device with a high degree of context awareness, enabling applications from navigation to fitness tracking to augmented reality. The user interface is also paramount, with touchscreens being the primary mode of interaction, demanding a responsive and intuitive software experience.

While we won’t be building a smartphone from scratch, the Raspberry Pi 5, when paired with a battery pack and various sensors, can serve as an excellent prototyping platform for a mobile concept. It allows us to experiment with power consumption strategies, read data from mobile-centric sensors like GPS modules, and understand the trade-offs inherent in designing for portability.

Practical Examples

Theory provides the map, but practical application is the journey. In this section, we will use the Raspberry Pi 5 to build simple projects that embody the characteristics of the system types we’ve discussed. These examples are designed to be illustrative, providing a hands-on feel for the design choices and constraints of each category.

Warning: Always double-check your wiring before powering on the Raspberry Pi. Incorrect connections can permanently damage the Pi or the connected components. It is recommended to disconnect power whenever you are modifying the circuit.

Example 1: A Standalone Temperature & Humidity Monitor

This project emulates a classic standalone device. It will read data from a sensor and display it on a connected LCD screen. It has no network connectivity and performs one dedicated task.

Hardware Required

  • Raspberry Pi 5
  • Breadboard and jumper wires
  • DHT22 (or AM2302) temperature and humidity sensor
  • 16×2 I2C LCD Display
  • 10kΩ resistor (optional, for I2C pull-ups, though many modules have them built-in)

Build and Configuration Steps

  1. Enable I2C: The LCD display uses the I2C communication protocol. You must enable it on your Raspberry Pi.
    • Open a terminal and run sudo raspi-config.
    • Navigate to 3 Interface Options -> I5 I2C.
    • Select <Yes> to enable the ARM I2C interface.
    • Reboot when prompted.
  2. Install Libraries: We need Python libraries to communicate with the sensor and the display.
Bash
# Update your package list
sudo apt update
# Library for the DHT sensor
pip install adafruit-circuitpython-dht
# Library for the I2C LCD
pip install RPLCD

Hardware Integration

Wiring Diagram:

  • DHT22 Sensor:
    • Pin 1 (VCC) -> Raspberry Pi 3.3V (Pin 1)
    • Pin 2 (Data) -> Raspberry Pi GPIO 4 (Pin 7)
    • Pin 4 (GND) -> Raspberry Pi GND (Pin 9)
  • 16×2 I2C LCD:
    • VCC -> Raspberry Pi 5V (Pin 2)
    • GND -> Raspberry Pi GND (Pin 6)
    • SDA -> Raspberry Pi SDA (GPIO 2, Pin 3)
    • SCL -> Raspberry Pi SCL (GPIO 3, Pin 5)

Code Snippet

Create a Python file named standalone_monitor.py. This code initializes the sensor and LCD, then enters an infinite loop to read data and update the display every two seconds.

Python
# standalone_monitor.py
# A simple standalone weather monitor using a Raspberry Pi.

import time
import board
import adafruit_dht
from RPLCD.i2c import CharLCD

# --- Configuration ---
# The I2C address of the LCD. 0x27 is common, but yours might be different.
# Run `i2cdetect -y 1` in the terminal to find the address.
LCD_ADDRESS = 0x27
# The GPIO pin connected to the DHT22 data line.
DHT_PIN = board.D4

# --- Initialization ---
try:
    # Initialize the DHT22 sensor.
    # The 'use_pulseio=False' is important for compatibility with Raspberry Pi.
    dht_device = adafruit_dht.DHT22(DHT_PIN, use_pulseio=False)

    # Initialize the LCD.
    # 'i2c_expander' is typically 'PCF8574' for these modules.
    lcd = CharLCD(i2c_expander='PCF8574', address=LCD_ADDRESS, port=1,
                  cols=16, rows=2, dotsize=8)
    lcd.clear()
    lcd.write_string("Initializing...")
    time.sleep(2)

except Exception as e:
    print(f"Error during initialization: {e}")
    print("Please check wiring and I2C address.")
    exit()

print("Initialization complete. Starting monitor loop...")
lcd.clear()

# --- Main Loop ---
while True:
    try:
        # Read from the sensor. This can sometimes fail, so it's in a try block.
        temperature_c = dht_device.temperature
        humidity = dht_device.humidity

        if temperature_c is not None and humidity is not None:
            # Format the output strings
            temp_str = f"Temp: {temperature_c:.1f} C"
            humidity_str = f"Humidity: {humidity:.1f} %"

            # Write to the LCD
            lcd.cursor_pos = (0, 0) # Row 0, Column 0
            lcd.write_string(temp_str.ljust(16)) # Pad with spaces to clear line
            lcd.cursor_pos = (1, 0) # Row 1, Column 0
            lcd.write_string(humidity_str.ljust(16))

            print(f"Updated display: {temp_str}, {humidity_str}")

    except RuntimeError as error:
        # Errors happen, just print them and continue.
        print(f"Sensor read failed: {error.args[0]}")
        lcd.cursor_pos = (0, 0)
        lcd.write_string("Sensor Error".ljust(16))
        lcd.cursor_pos = (1, 0)
        lcd.write_string("Retrying...".ljust(16))

    except Exception as e:
        print(f"An unexpected error occurred: {e}")
        break

    # Wait 2 seconds before the next reading
    time.sleep(2)

Run and Verify

  1. Save the code.
  2. Run it from the terminal: python standalone_monitor.py
  3. Expected Output: The LCD should first display “Initializing…”, then clear and show the current temperature and humidity, refreshing every two seconds. The terminal will print a confirmation message with each update. This device now functions as a complete, self-contained unit.

Example 2: A Networked (IoT) Weather Station

Now, let’s transform our standalone monitor into a networked IoT device. Instead of just displaying the data locally, it will publish the readings to a central MQTT broker. Another device anywhere on the network can then subscribe to this data.

Tip: MQTT (Message Queuing Telemetry Transport) is a lightweight messaging protocol ideal for IoT. It uses a publish/subscribe model. A device (client) publishes messages to a “topic” on a central server (broker). Other clients can subscribe to that topic to receive the messages.

Build and Configuration Steps

  • Set up an MQTT Broker: You need a broker. You can use a public one for testing (like test.mosquitto.org) or install one on your Raspberry Pi or another computer.
Bash
# To install Mosquitto broker on a Raspberry Pi
sudo apt install mosquitto mosquitto-clients -y
  • Install MQTT Client Library:
Bash
pip install paho-mqtt

Code Snippet

We will modify the previous code. This version will still display data on the LCD but will also send it to the MQTT broker. Create a file named networked_monitor.py.

Python
# networked_monitor.py
# An IoT weather station that publishes data via MQTT.

import time
import board
import adafruit_dht
from RPLCD.i2c import CharLCD
import paho.mqtt.client as mqtt
import json

# --- Configuration ---
LCD_ADDRESS = 0x27
DHT_PIN = board.D4

# MQTT Configuration
MQTT_BROKER = "test.mosquitto.org" # Use a public broker for this example
MQTT_PORT = 1883
# Use a unique topic to avoid collisions with other users
MQTT_TOPIC = "rpi5/class/weather_station/student_01"

# --- Initialization ---
# (Sensor and LCD initialization code is the same as the standalone example)
# ... [Copy the initialization try/except block from standalone_monitor.py here] ...

# --- MQTT Setup ---
def on_connect(client, userdata, flags, rc):
    if rc == 0:
        print("Connected to MQTT Broker!")
    else:
        print(f"Failed to connect, return code {rc}\n")

# Create MQTT client
client = mqtt.Client()
client.on_connect = on_connect
try:
    client.connect(MQTT_BROKER, MQTT_PORT)
    client.loop_start() # Start a background thread to handle network traffic
except Exception as e:
    print(f"Could not connect to MQTT broker: {e}")
    # The device can still function as a standalone monitor if network fails
    
# --- Main Loop ---
while True:
    try:
        temperature_c = dht_device.temperature
        humidity = dht_device.humidity

        if temperature_c is not None and humidity is not None:
            # --- Update LCD (same as before) ---
            temp_str = f"Temp: {temperature_c:.1f} C"
            humidity_str = f"Humidity: {humidity:.1f} %"
            lcd.cursor_pos = (0, 0)
            lcd.write_string(temp_str.ljust(16))
            lcd.cursor_pos = (1, 0)
            lcd.write_string(humidity_str.ljust(16))

            # --- Publish to MQTT ---
            # Create a JSON payload for structured data
            payload = json.dumps({
                "temperature": round(temperature_c, 1),
                "humidity": round(humidity, 1),
                "timestamp": time.time()
            })
            
            result = client.publish(MQTT_TOPIC, payload)
            # result: [0, 1]
            status = result[0]
            if status == 0:
                print(f"Sent `{payload}` to topic `{MQTT_TOPIC}`")
            else:
                print(f"Failed to send message to topic {MQTT_TOPIC}")

    except RuntimeError as error:
        print(f"Sensor read failed: {error.args[0]}")
    
    except Exception as e:
        print(f"An unexpected error occurred: {e}")
        break

    time.sleep(5) # Publish every 5 seconds

Run and Verify

On a separate computer or terminal, install an MQTT client and subscribe to the topic to listen for messages.

Bash
# Make sure you've run 'sudo apt install mosquitto-clients' first
mosquitto_sub -h test.mosquitto.org -t "rpi5/class/weather_station/student_01" -v


The -v flag will print the topic along with the message.

On the Raspberry Pi, run the new script.

Bash
python networked_monitor.py

Expected Output:

  • The Raspberry Pi’s LCD will display the weather data as before.
  • The Pi’s terminal will show messages like “Sent {"temperature": 23.5, ...} to topic…”.
  • The subscriber terminal (on the other computer) will receive and print these messages in real-time:rpi5/class/weather_station/student_01 {"temperature": 23.5, "humidity": 45.1, "timestamp": 1678886400.123}
This demonstrates how connectivity transforms the device, allowing its data to be used far beyond its physical location.

Common Mistakes & Troubleshooting

As you begin to classify and build different types of embedded systems, you will encounter common pitfalls. Recognizing them early can save significant time and frustration.

Mistake / Issue Symptom(s) Troubleshooting / Solution
Misclassifying Real-Time Needs – Motor control is jerky or erratic.
– High-speed data acquisition misses samples.
– System behavior is unpredictable under load.
– Unacceptable “jitter” (variation in response time).
Analyze the true cost of a missed deadline.
– For hard real-time, use a dedicated RTOS like FreeRTOS or Zephyr.
– For soft real-time on Linux, investigate the PREEMPT_RT patch to improve kernel determinism.
Ignoring Power Consumption – Battery-powered device dies in minutes or hours, not days.
– Device gets unexpectedly hot during operation.
– Unstable operation when running on battery vs. wall power.
Design for low power from the start.
– Use processor sleep/deep sleep modes aggressively.
– Avoid polling in tight loops; use interrupt-driven events.
– Choose low-power components and communication protocols.
– Use tools like powertop to analyze usage.
Poor Network Security in IoT – Device is accessible on the public internet with default credentials.
– API keys, passwords, or tokens are hardcoded in source code.
– Communication is sent over unencrypted protocols like http or standard mqtt.
Assume a hostile network environment.
NEVER use default passwords.
– Use encrypted protocols: HTTPS and MQTT over TLS.
– Store credentials securely using an HSM or encrypted storage, not in plaintext.
– Keep all software and libraries updated to patch vulnerabilities.
Wrong Communication Protocol – A battery-powered sensor using Wi-Fi has very short battery life.
– Bluetooth connection is unreliable over the required distance.
– High-bandwidth video stream stutters over LoRaWAN.
Match the protocol to the requirements.
Low Power, Long Range: LoRaWAN
Low Power, Short Range: Bluetooth LE (BLE)
High Bandwidth, Local: Wi-Fi
Wired Reliability: Ethernet

Exercises

These exercises are designed to reinforce the concepts of system classification through hands-on practice with your Raspberry Pi 5.

  1. Standalone System Enhancement:
    • Objective: Modify the standalone weather monitor to incorporate a new input and a new output, reinforcing the self-contained nature of the device.
    • Task: Add a push button to your circuit. Modify the standalone_monitor.py script so that pressing the button toggles the temperature display between Celsius and Fahrenheit.
    • Verification: When you run the script, the display should show Celsius by default. When you press and release the button, the temperature reading should convert to Fahrenheit and update on the display. Pressing it again should switch it back to Celsius.
  2. Simulating Soft Real-Time Constraints:
    • Objective: Understand the concept of jitter in a non-real-time OS.
    • Task: Write a Python script that attempts to blink an LED at a precise 2 Hz frequency (on for 250ms, off for 250ms). In the loop, record the actual time elapsed for each cycle using time.monotonic(). Print the deviation from the target 500ms cycle time. While the LED is blinking, stress the system by running a high-CPU task in another terminal (e.g., sha256sum /dev/zero).
    • Verification: Observe the printed deviation values. You will notice that while the average cycle time is close to 500ms, individual values will vary, and the variation (jitter) will increase significantly when the system is under load. This demonstrates why a general-purpose OS is unsuitable for tasks requiring low jitter.
  3. Creating a Two-Way Networked System:
    • Objective: Build a complete, bidirectional IoT system using MQTT.
    • Task: Use two Raspberry Pis (or one Pi and a computer with an MQTT client).
      • Device A (Controller): Runs a Python script that does not have any sensors. It simply provides a command-line interface where you can type “on” or “off”. When you do, it publishes a message ({"command": "on"} or {"command": "off"}) to an MQTT topic (e.g., rpi5/class/led_control).
      • Device B (Actuator): Has an LED connected to a GPIO pin. It runs a Python script that subscribes to the rpi5/class/led_control topic. When it receives a message, it parses the JSON and turns the LED on or off accordingly.
    • Verification: When you type “on” into the terminal for Device A, the LED on Device B should turn on. When you type “off”, the LED should turn off. This demonstrates a fundamental command-and-control pattern used in countless IoT applications.

Summary

This chapter has provided a structured classification for the vast world of embedded systems. By understanding the core principles of each category, you are better equipped to design and build effective and efficient devices.

  • Standalone Systems are self-contained, isolated devices optimized for a specific task, valuing simplicity and reliability over connectivity.
  • Real-Time Systems are governed by time, where correctness depends on meeting strict deadlines. We distinguished between Hard Real-Time, where a missed deadline is a catastrophic failure, and Soft Real-Time, where it only degrades performance.
  • Networked Systems, the foundation of the IoT, leverage connectivity (Wi-Fi, Ethernet, BLE, etc.) to communicate with other devices and cloud services, unlocking powerful new functionalities.
  • Mobile Systems are defined by their portability, forcing designers to prioritize constraints of size, weight, and especially power consumption.
  • Practical examples using the Raspberry Pi 5 demonstrated how a single platform can be used to prototype systems from each of these categories, highlighting the different software and hardware considerations for each.

By mastering these classifications, you have taken a critical step from being a programmer to becoming an embedded systems architect. This foundational knowledge will be essential as we move on to more advanced topics, such as choosing the right operating system and building custom Linux images for your embedded projects.

Further Reading

  1. “Embedded Systems Architecture: A Comprehensive Guide for Engineers and Programmers” by Tammy Noergaard. A foundational text that provides a deep dive into the hardware and software architecture of embedded systems.
  2. “Mastering Embedded Linux Programming” by Chris Simmonds. An excellent resource that covers the practical aspects of developing for embedded Linux systems, including many topics relevant to networked devices.
  3. The Official Raspberry Pi Documentation. (raspberrypi.com/documentation/) An indispensable resource for hardware specifications, configuration, and tutorials directly from the source.
  4. The MQTT Standard Official Website. (mqtt.org) Provides the official specification and technical information for the MQTT protocol, essential for anyone working on IoT projects.
  5. “Real-Time Concepts for Embedded Systems” by Qing Li and Caroline Yao. A thorough introduction to the principles of real-time systems, including scheduling, RTOS concepts, and inter-task communication.
  6. Zephyr Project Documentation. (docs.zephyrproject.org) Exploring the documentation for a leading open-source RTOS like Zephyr provides deep insight into the architecture and APIs required for real-time and resource-constrained devices.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top