4. Embedded System Design
Learning Objectives
- List the six stages of the embedded design process in order and explain why order matters
- Distinguish functional requirements from non-functional (power, cost, timing) requirements
- Explain the trade-offs behind choosing a specific MCU for a given application
- Write and trace a small embedded C program that reads a sensor and drives an actuator
- Apply a power budget calculation to choose between polling and interrupt-driven design
- Analyze a design scenario and identify a missing non-functional requirement
Quick Answer
Embedded system design is the structured process of turning a set of requirements into a working combination of hardware and software that meets constraints on cost, power, size, and timing. It's not just "write code for a microcontroller" — it starts with defining precisely what the system must do and under what limits, then flows through architecture design, component selection, implementation, testing, and deployment. Skipping steps (for example, picking a microcontroller before understanding the power budget) is the single most common cause of costly late-stage redesigns in real embedded projects. Good embedded design treats hardware and software choices as inseparable — a decision in one always constrains the other.
The Six-Stage Design Process
1. Requirements gathering — Define what the system must do (functional requirements) and the limits it must operate within (non-functional requirements: power budget, size, cost per unit, response time, operating temperature). Skipping this stage is the root cause of most redesigns — you cannot choose an MCU or sensor intelligently without knowing, for example, that the device must run one year on a coin cell battery.
2. System architecture design — Decide the overall structure: how many subsystems, what communicates with what, whether an RTOS is needed, and what the memory and processing budget looks like.
3. Component selection — Choose the actual MCU, sensors, actuators, and communication modules based on the requirements. This is where power budget, I/O count, peripheral availability (does it have I2C? enough ADC channels?), and cost per unit at your expected volume all get weighed against each other.
4. Implementation — Write the firmware and assemble/wire the hardware, ideally in parallel using hardware-software co-design so integration issues surface early rather than at the end.
5. Testing and validation — Verify the system meets every requirement from stage 1, including the non-functional ones (does it really last a year on that battery? does it really respond within the deadline under worst-case load?).
6. Deployment — Install and configure the system in its real environment, including any provisions for future firmware updates (OTA) or field diagnostics.
Functional vs. Non-Functional Requirements
A common design mistake is treating requirements as only "what the device does." Non-functional requirements are just as binding and often drive the entire component selection:
| Type | Question it answers | Example |
|---|---|---|
| Functional | What must the system do? | "Measure soil moisture every hour and transmit the reading" |
| Non-functional: power | How long must it run unattended? | "Operate 12 months on two AA batteries" |
| Non-functional: timing | How fast must it respond? | "Trigger irrigation valve within 5 seconds of a low-moisture reading" |
| Non-functional: cost | What's the per-unit budget? | "Bill of materials under $8 at 10,000-unit volume" |
| Non-functional: environment | What conditions must it survive? | "Operate from −20°C to 60°C, IP65 rated" |
A design that satisfies the functional requirement perfectly but ignores the power budget (say, by polling a sensor continuously instead of sleeping between readings) will fail in the field even though it "works" on the bench.
Worked Example: Soil Moisture Alert System
Let's walk the full process for a simple but realistic design: a battery-powered soil moisture sensor that lights a warning LED when soil is too dry.
Requirements: Battery-powered (must last months), check moisture every 10 minutes, LED warning if below threshold, minimal cost.
Component selection: An ATmega328P (Arduino-class MCU) with sleep mode support, a resistive soil moisture sensor (analog output), and an LED — all low-cost and low-power.
Implementation — reading the sensor and driving the LED with power-conscious design (sleeping between readings instead of polling continuously):
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/interrupt.h>
#define SENSOR_PIN A0
#define LED_PIN 13
#define DRY_THRESHOLD 400 // ADC value below which soil is "dry"
void setup() {
pinMode(LED_PIN, OUTPUT);
// Configure Watchdog Timer to wake the MCU every ~8 seconds
// (kept short here for illustration; real code would loop ~75 times for 10 min)
}
int read_moisture(void) {
return analogRead(SENSOR_PIN); // 0 (wet) .. 1023 (dry)
}
void loop() {
int moisture = read_moisture();
if (moisture > DRY_THRESHOLD) {
digitalWrite(LED_PIN, HIGH); // soil is dry — warn
} else {
digitalWrite(LED_PIN, LOW);
}
enter_sleep_mode(); // MCU draws microamps instead of milliamps while asleep
}
The key design decision here — sleeping the MCU between readings rather than looping continuously — is what makes the difference between a battery lasting weeks versus months. This is exactly why the power budget non-functional requirement must be known before writing this loop, not discovered after building it.
Testing and validation: Measure actual current draw with a multimeter in both active and sleep states, multiply by expected duty cycle, and confirm the resulting battery life meets the "months" requirement — not just confirm the LED turns on correctly.
Power Budget: A Concrete Calculation
Suppose the MCU draws 20mA active and 6µA asleep, taking 50ms to read the sensor and check the threshold every 10 minutes, from a 2000mAh battery.
- Active time per cycle: 0.05s, at 20mA
- Sleep time per cycle: 599.95s, at 0.006mA
- Average current ≈ (0.05 × 20 + 599.95 × 0.006) / 600 ≈ (1 + 3.6) / 600 ≈ 0.00767 mA
Battery life ≈ 2000mAh / 0.00767mA ≈ 260,000 hours (roughly 29 years) — in practice limited by battery self-discharge, not the circuit. Compare this to never sleeping (constant 20mA draw): 2000/20 = 100 hours, or about 4 days. This single design decision — sleep vs. poll — is the difference between "unusable" and "lasts the product's lifetime."
Why It Matters
Design mistakes made in stage 1 or 3 are exponentially more expensive to fix once you reach stage 5. Choosing an MCU without enough ADC channels means a board respin. Ignoring the power budget means a product recall. This is why professional embedded teams spend real time on requirements and component selection even when it feels like "not coding yet" — because the coding stage is where poor early decisions become impossible to undo cheaply.
Key Terms
| Term | Definition | Related Concept |
|---|---|---|
| Functional requirement | A statement of what the system must do | Non-functional requirement |
| Non-functional requirement | A constraint the system must satisfy (power, cost, timing, environment) | Power budget |
| Power budget | The calculated current/energy consumption target the design must not exceed | Sleep mode, duty cycle |
| Bill of materials (BOM) | The full list and cost of every hardware component in a design | Component selection |
| Duty cycle | The fraction of time a system is actively drawing power versus idle/sleeping | Power budget |
| Sleep mode | A low-power MCU state that retains minimal function while drawing microamps instead of milliamps | Power management |
| Design validation | Confirming the built system meets every original requirement, not just that it "works" | Testing |
Common Mistakes
Misconception: Embedded design starts with picking a microcontroller. Why it's wrong: Choosing hardware before defining requirements almost always leads to a poor fit — wrong number of I/O pins, insufficient battery life, or unnecessary cost — discovered only after significant work is already done. Correct understanding: Design starts with requirements gathering (functional and non-functional); component selection comes only after the system architecture clarifies what's actually needed.
Misconception: If the code runs correctly on the bench, the design is validated. Why it's wrong: "Runs correctly" on the bench, plugged into USB power, says nothing about battery life, worst-case timing under load, or behavior across the required temperature range — all of which are part of the actual requirements. Correct understanding: Validation means testing against every requirement from stage 1, including non-functional ones like power consumption and environmental tolerance, not just functional correctness.
Misconception: Non-functional requirements (power, cost, size) are secondary concerns compared to what the device does. Why it's wrong: In real products, non-functional requirements frequently eliminate otherwise-correct designs — a perfectly functioning prototype that costs 3x the target BOM or drains its battery in days is not shippable. Correct understanding: Non-functional requirements are just as binding as functional ones and often dominate component selection decisions.
Comparison and Connections
| Aspect | Requirements-First Design | Hardware-First (Anti-Pattern) |
|---|---|---|
| Starting point | Define functional + non-functional needs | Pick a familiar MCU/dev board immediately |
| Risk of late redesign | Low — constraints known upfront | High — mismatched I/O, power, or cost discovered late |
| Component selection | Justified by actual requirements | Justified by familiarity or convenience |
| Typical outcome | Design meets power/cost/timing targets | Rework, board respins, or missed specs |
Practice Questions
Recall
-
List the six stages of the embedded design process in order. Answer guidance: Requirements gathering, system architecture design, component selection, implementation, testing and validation, deployment.
-
Give one example each of a functional and a non-functional requirement for a smart doorbell. Answer guidance: Functional — "detect motion and send a notification"; non-functional — "respond within 2 seconds" or "operate on battery for 6 months."
Understanding
-
Explain why component selection should come after requirements gathering, not before. Answer guidance: Without knowing power, cost, and functional constraints, chosen components may be over/under-specified, leading to wasted cost, insufficient battery life, or missing needed peripherals — all discovered too late.
-
In the soil moisture example, why does sleeping the MCU between readings matter more than optimizing the code's execution speed? Answer guidance: The MCU spends the overwhelming majority of time idle between 10-minute readings; sleep current (µA) versus active current (mA) dominates total power consumption far more than shaving milliseconds off a 50ms active window.
Application
-
A team is designing a fire alarm that must sound within 3 seconds of smoke detection and run 5 years on a 9V battery. Identify one functional and two non-functional requirements, and explain how the power one affects MCU choice. Answer guidance: Functional — detect smoke and sound alarm; non-functional — 3-second response time, 5-year battery life. The power requirement forces choosing a low-power MCU with deep sleep modes and an interrupt-driven wake source (smoke sensor triggers wake) rather than a fast-polling design.
-
Using the power budget method shown, calculate approximate battery life if the MCU instead draws 15mA active for 100ms every 5 minutes and 10µA asleep, from a 1000mAh battery. Answer guidance: Average current ≈ (0.1×15 + 299.9×0.01)/300 ≈ (1.5+3.0)/300 ≈ 0.015mA. Battery life ≈ 1000/0.015 ≈ 66,700 hours (~7.6 years), again dominated by sleep current, not active time.
Analysis
-
A design team builds a working prototype on a dev board with a powerful 32-bit MCU, then discovers at production stage that the target BOM cost is exceeded threefold. Diagnose what went wrong in their process and how it should have been avoided. Answer guidance: They skipped or ignored the cost non-functional requirement during component selection, likely choosing the MCU for convenience/familiarity rather than requirement fit. A requirements-first approach would have flagged the cost ceiling before hardware selection, guiding them toward a cheaper MCU meeting the same functional needs.
-
Compare the risk profile of discovering a missing ADC channel during stage 3 (component selection) versus during stage 5 (testing and validation). Answer guidance: At stage 3, the fix is simply choosing a different, still-unbuilt component — low cost. At stage 5, hardware has already been built/assembled, so the fix likely requires a board respin, re-manufacturing, and re-testing — dramatically higher cost and schedule delay.
FAQ
Why does the design process insist on doing requirements before touching hardware, when it feels slower to start? Because the cost of fixing a wrong assumption grows by roughly an order of magnitude at each later stage — a requirement gap caught on paper costs nothing, the same gap caught after building costs a full hardware redesign. The apparent "slowness" upfront prevents much larger delays later.
How detailed do non-functional requirements need to be before starting component selection? Detailed enough to make selection decisions — a vague "should be low power" isn't actionable, but "average current under 10µA, must run 12 months on a CR2032 coin cell" lets you calculate exactly which MCU and sleep strategy will work.
Is hardware-software co-design part of this six-stage process, or a separate methodology? It's a refinement of stage 4 (implementation) — instead of building all hardware first and then writing all software, co-design develops both concurrently with continuous integration, catching mismatches (like a peripheral wired to the wrong pin) far earlier than a strictly sequential approach.
What's the difference between testing and validation? Testing typically means verifying individual pieces work correctly (does this function return the right value?). Validation means confirming the complete system meets the original requirements from stage 1 (does the whole device actually last the required battery life in realistic conditions?). Both are part of stage 5.
Can you skip stages for a simple hobby project? Informally yes — for a one-off LED blinker, formal requirements gathering is overkill. But even experienced engineers mentally run through the same six questions (what should it do, what limits does it face, what parts fit, build it, does it work, deploy it) even when they don't write them down; the process scales down, it doesn't disappear.
Quick Revision
- Six stages: requirements → architecture → component selection → implementation → testing/validation → deployment
- Functional requirements describe behavior; non-functional requirements describe constraints (power, cost, timing, environment)
- Component selection should always follow, not precede, requirements gathering
- Power budget calculations (active current × duty cycle + sleep current × remaining time) determine real battery life
- Sleep mode vs. continuous polling is often the single biggest lever on battery-powered device lifespan
- Validation checks the whole system against every original requirement, not just functional correctness
- Fixing a design flaw gets exponentially more expensive the later it's discovered in the process
- Hardware-software co-design overlaps implementation across hardware and software to catch integration issues early
- A perfectly functional prototype can still fail if it violates a non-functional requirement like cost or power
- Testing on a bench with USB power does not validate battery-powered field performance
Related Topics
Prerequisites: Introduction to Embedded Systems, Embedded System Architecture
Related Topics: Hardware-Software Co-Design, Embedded System Programming, Real-Time Operating Systems
Next Topics: Embedded System Programming (implementation stage in depth), Debugging Embedded Systems (testing and validation in depth)