Back to Embedded Systems Hardware Engineering Series

Part 2: Prototyping & Proof of Concept

April 17, 2026 Wasil Zafar 40 min read

Turn your electronics knowledge into working circuits — breadboarding techniques, development board selection (STM32 Nucleo & ESP32 DevKit), sensor integration patterns, and systematic debugging with a multimeter.

Table of Contents

  1. From Theory to Wires
  2. Breadboarding Fundamentals
  3. Development Boards
  4. Sensor Integration
  5. Systematic Debugging
  6. Exercises
  7. BOM Builder Tool
  8. Conclusion & Next Steps

From Theory to Wires

In Part 1, you learned the electrical theory. Now it’s time to touch actual hardware. Prototyping is where you validate ideas before committing to a PCB design that costs money and takes weeks to manufacture. A $5 breadboard prototype can save you $500 in PCB revisions.

The golden rule of hardware: Never design a PCB for a circuit you haven’t prototyped. Even experienced engineers breadboard first to verify sensor behaviour, power consumption, and timing before committing to a layout.

A Brief History of Prototyping

1960s Engineers built prototypes by hand-wiring point-to-point on metal chassis — slow, error-prone, and required expert soldering skills.
1971 Ronald J. Portugal patents the solderless breadboard (US Patent 3,619,671), enabling rapid circuit assembly without soldering.
1980s Wire-wrap boards become popular for semi-permanent prototypes in telecom and industrial equipment.
2005 Arduino launches, democratising embedded prototyping for hobbyists, students, and artists worldwide.
2012 ESP8266 brings WiFi to the maker community for under $3, sparking the IoT prototyping explosion.
Today Same-day PCB prototyping services and sub-$5 dev boards mean ideas go from breadboard to product faster than ever.
Analogy Prototyping in hardware is like writing a rough draft of an essay. You wouldn’t submit your first draft to a publisher — you write it, revise it, get feedback, and polish it. A breadboard is your rough draft. A perfboard is your revised draft. A custom PCB is the published version. Skipping the draft stage means expensive rewrites (board respins).

Three Stages of Prototyping

Prototyping Pipeline
flowchart LR
    BB["Stage 1
Breadboard
Quick & disposable"] --> PB["Stage 2
Perfboard / Protoboard
Semi-permanent"] PB --> DEV["Stage 3
Dev Board Shield
Close to final form"] BB -.->|"Validate concept"| PB PB -.->|"Validate integration"| DEV DEV -.->|"Ready for PCB"| PCB["Custom PCB
(Part 4+)"]
Stage Medium When to Use Cost Durability
Breadboard Solderless breadboard Initial concept validation, testing individual sub-circuits $3–15 Minutes to days
Perfboard Solder-on prototype board Proven circuit needs to run reliably for weeks/months $2–10 Weeks to months
Dev Board Shield Stackable PCB for dev boards Custom peripherals on top of Nucleo/Arduino form factor $5–25 Months

Breadboarding Fundamentals

Breadboard Anatomy

A solderless breadboard has a grid of holes connected internally by metal clips. Understanding the connection pattern is essential:

Breadboard Internal Connections
flowchart TD
    subgraph Power["Power Rails (horizontal)"]
        P1["+V ━━━━━━━━━━━━━━━━━━━━"]
        P2["GND ━━━━━━━━━━━━━━━━━━━━"]
    end
    subgraph Top["Terminal Strips (vertical, 5-hole groups)"]
        T1["a b c d e — connected vertically"]
    end
    subgraph Gap["Centre Gap (DIP IC straddler)"]
        G1["═══════════════════"]
    end
    subgraph Bottom["Terminal Strips (vertical, 5-hole groups)"]
        B1["f g h i j — connected vertically"]
    end
    Power --> Top
    Top --> Gap
    Gap --> Bottom
                            
Power rail break: On full-size breadboards (830 tie-points), the power rails often have a break in the middle. Always use a jumper wire to bridge the gap, or your circuit will only work on one half!

Wiring Best Practices

Clean wiring isn’t just aesthetic — it prevents intermittent faults, makes debugging faster, and teaches the discipline you’ll need for PCB routing later.

Rule Why It Matters
Red = power, black = ground Universal colour convention prevents reverse connections
Keep wires flat and short Reduces inductance, crosstalk, and accidental disconnects
Signal wires in different colours Blue for I2C SDA, yellow for SCL, green for SPI, etc.
Decoupling caps near ICs 100nF ceramic as close to VDD/GND pins as possible
One component per column Prevents accidental shorts between adjacent component leads

Common Breadboard Mistakes

Top 5 Breadboard Failure Modes

Debugging Essential
  1. Loose connections: Components not fully seated. Push firmly until you feel the clip grip the lead.
  2. Power rail gap: Half the board has no power. Bridge both + and − rails at the centre break.
  3. Missing decoupling: MCU resets randomly under load. Add 100nF + 10μF near the power pins.
  4. Short circuits from trimmed leads: Clipped component leads fall into the board and create hidden shorts. Always trim over a bin.
  5. Ground loops: Multiple ground paths create noise. Use a single star-ground point for analog circuits.

Development Boards

Development boards provide a complete MCU system with power regulation, programming interface, and broken-out GPIO pins. They let you focus on your application rather than the basic MCU support circuit.

STM32 Nucleo Family

The STM32 Nucleo boards from STMicroelectronics are the industry-standard prototyping platform for ARM Cortex-M microcontrollers. They include an on-board ST-LINK debugger, Arduino-compatible headers, and Morpho extension connectors.

Board MCU Core Clock Flash RAM Best For
Nucleo-F103RB STM32F103RB Cortex-M3 72 MHz 128KB 20KB Learning basics
Nucleo-F411RE STM32F411RE Cortex-M4F 100 MHz 512KB 128KB DSP, audio
Nucleo-F446RE STM32F446RE Cortex-M4F 180 MHz 512KB 128KB Motor control, USB
Nucleo-H743ZI STM32H743ZI Cortex-M7 480 MHz 2MB 1MB High-performance
/* STM32 Nucleo — Blink LED (Bare-Metal HAL)
 * Board: Nucleo-F411RE, LED on PA5
 * IDE: STM32CubeIDE — create project via CubeMX
 */

#include "stm32f4xx_hal.h"

int main(void)
{
    /* Initialise HAL and system clock */
    HAL_Init();
    SystemClock_Config();  /* Generated by CubeMX */

    /* Enable GPIOA clock */
    __HAL_RCC_GPIOA_CLK_ENABLE();

    /* Configure PA5 as push-pull output */
    GPIO_InitTypeDef gpio = {0};
    gpio.Pin   = GPIO_PIN_5;
    gpio.Mode  = GPIO_MODE_OUTPUT_PP;
    gpio.Pull  = GPIO_NOPULL;
    gpio.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOA, &gpio);

    /* Blink loop — 500ms on, 500ms off */
    while (1)
    {
        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
        HAL_Delay(500);
    }
}

ESP32 DevKit

The ESP32 from Espressif is the go-to choice for WiFi and Bluetooth-enabled embedded projects. The DevKit boards are breadboard-friendly and can be programmed with Arduino IDE, ESP-IDF, or MicroPython.

## ESP32 — Blink LED + WiFi Scan (MicroPython)
## Flash MicroPython firmware, then upload this script

import machine
import network
import time

# Configure LED on GPIO2 (built-in blue LED on most DevKits)
led = machine.Pin(2, machine.Pin.OUT)

# Blink 3 times to show boot
for i in range(3):
    led.on()
    time.sleep_ms(200)
    led.off()
    time.sleep_ms(200)

# Scan for WiFi networks
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
networks = wlan.scan()

print(f"Found {len(networks)} WiFi networks:")
for ssid, bssid, channel, rssi, authmode, hidden in networks:
    auth_names = ["OPEN", "WEP", "WPA-PSK", "WPA2-PSK", "WPA/WPA2-PSK"]
    auth = auth_names[authmode] if authmode < len(auth_names) else "UNKNOWN"
    print(f"  {ssid.decode():.<30} Ch{channel:>2}  {rssi}dBm  {auth}")

Development Board Selection Guide

Board Selection Decision Tree
flowchart TD
    START{"What do you need?"} -->|"WiFi / BLE
connectivity"| ESP["ESP32 DevKit
~$5-10"] START -->|"Real-time control
bare-metal"| STM["STM32 Nucleo
~$12-25"] START -->|"Quick prototype
beginner"| ARD["Arduino Uno
~$5-15"] START -->|"Linux + cameras
ML inference"| RPI["Raspberry Pi
~$35-75"] START -->|"Ultra-low power
BLE beacon"| NRF["nRF52840 DK
~$40"] ESP -->|"Need more GPIO"| STM STM -->|"Need WiFi"| ESP ARD -->|"Outgrew it"| STM
Feature Arduino Uno STM32 Nucleo ESP32 DevKit Raspberry Pi
Architecture AVR 8-bit ARM Cortex-M Xtensa dual-core ARM Cortex-A
Clock Speed 16 MHz Up to 480 MHz 240 MHz 1.5+ GHz
WiFi/BLE No (shield req’d) No (external) Yes (built-in) Yes (built-in)
Debugger No Yes (ST-LINK) JTAG (external) No (use GDB)
ADC 6ch, 10-bit 16+ch, 12-bit 18ch, 12-bit None (external)
Best For Learning Professional embedded IoT + connectivity Linux + vision + ML

Sensor Integration Patterns

Sensors are the eyes and ears of your embedded system. This section covers the three most common interfacing methods: I2C digital sensors, analog sensors with ADC, and simple digital I/O.

I2C Sensors (Digital Bus)

I2C (Inter-Integrated Circuit) uses just two wires — SDA (data) and SCL (clock) — to communicate with multiple sensors on the same bus. Each sensor has a unique 7-bit address.

I2C Bus with Multiple Sensors
flowchart LR
    MCU["MCU
I2C Master"] --> SDA["SDA (data)"] MCU --> SCL["SCL (clock)"] SDA --> S1["BME280
Temp/Hum/Press
Addr: 0x76"] SCL --> S1 SDA --> S2["BH1750
Light Sensor
Addr: 0x23"] SCL --> S2 SDA --> S3["MPU6050
Accel/Gyro
Addr: 0x68"] SCL --> S3 SDA -.->|"4.7kΩ pull-up to VDD"| VDD["3.3V"] SCL -.->|"4.7kΩ pull-up to VDD"| VDD
## I2C Sensor Scan — Find all devices on the bus
## For ESP32 with MicroPython

import machine

# Configure I2C bus (ESP32: SDA=GPIO21, SCL=GPIO22)
i2c = machine.I2C(0, scl=machine.Pin(22), sda=machine.Pin(21), freq=400000)

# Scan for all devices on the bus
devices = i2c.scan()
print(f"I2C scan found {len(devices)} device(s):")
for addr in devices:
    # Common sensor addresses
    known = {
        0x23: "BH1750 (light)",
        0x3C: "SSD1306 (OLED)",
        0x48: "ADS1115 (ADC)",
        0x50: "AT24C32 (EEPROM)",
        0x68: "MPU6050 (IMU) / DS3231 (RTC)",
        0x76: "BME280 (env sensor)",
        0x77: "BMP280 (pressure)",
    }
    name = known.get(addr, "Unknown")
    print(f"  0x{addr:02X} — {name}")
Output
I2C scan found 3 device(s):
  0x23 — BH1750 (light)
  0x68 — MPU6050 (IMU) / DS3231 (RTC)
  0x76 — BME280 (env sensor)
## Read BME280 Temperature/Humidity/Pressure
## For ESP32 with MicroPython + bme280 library

import machine
import time

# Minimal BME280 raw register read (no external library needed)
i2c = machine.I2C(0, scl=machine.Pin(22), sda=machine.Pin(21), freq=400000)
BME280_ADDR = 0x76

# Read chip ID to verify connection
chip_id = i2c.readfrom_mem(BME280_ADDR, 0xD0, 1)
print(f"BME280 Chip ID: 0x{chip_id[0]:02X} (expected 0x60)")

# Configure: forced mode, oversampling x1 for temp/hum/press
i2c.writeto_mem(BME280_ADDR, 0xF2, b'\x01')  # Humidity oversampling x1
i2c.writeto_mem(BME280_ADDR, 0xF4, b'\x25')  # Temp x1, Press x1, Forced mode

time.sleep_ms(50)  # Wait for measurement

# Read raw data (8 bytes from 0xF7)
data = i2c.readfrom_mem(BME280_ADDR, 0xF7, 8)
press_raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4)
temp_raw = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4)
hum_raw = (data[6] << 8) | data[7]
print(f"Raw readings — Temp: {temp_raw}, Press: {press_raw}, Hum: {hum_raw}")
print("(Compensation formulas needed for calibrated values — see BME280 datasheet)")
Output
BME280 Chip ID: 0x60 (expected 0x60)
Raw readings — Temp: 524288, Press: 331776, Hum: 32768
(Compensation formulas needed for calibrated values — see BME280 datasheet)

Analog Sensors & ADC Reading

Analog sensors output a voltage proportional to the measured quantity. The MCU’s ADC (Analog-to-Digital Converter) reads this voltage and converts it to a digital value.

## Analog Sensor Reading — Temperature with NTC Thermistor
## For ESP32 with MicroPython

import machine
import math

# Configure ADC on GPIO34 (ESP32 ADC1_CH6)
adc = machine.ADC(machine.Pin(34))
adc.atten(machine.ADC.ATTN_11DB)  # 0-3.3V range
adc.width(machine.ADC.WIDTH_12BIT)  # 12-bit resolution (0-4095)

# NTC thermistor parameters (10kΩ at 25°C, B=3950)
R_SERIES = 10000   # Series resistor (voltage divider partner)
B_COEFF = 3950     # B-coefficient from datasheet
T_REF = 298.15     # Reference temp in Kelvin (25°C)
R_REF = 10000      # Resistance at reference temp

# Read 10 samples and average
samples = [adc.read() for _ in range(10)]
adc_avg = sum(samples) / len(samples)

# Convert ADC to resistance (voltage divider formula)
if adc_avg > 0 and adc_avg < 4095:
    r_ntc = R_SERIES * adc_avg / (4095 - adc_avg)

    # Steinhart-Hart simplified (B-parameter equation)
    temp_k = 1 / (1/T_REF + (1/B_COEFF) * math.log(r_ntc / R_REF))
    temp_c = temp_k - 273.15

    print(f"ADC raw: {adc_avg:.0f} / 4095")
    print(f"NTC resistance: {r_ntc:.0f} Ω")
    print(f"Temperature: {temp_c:.1f} °C")
else:
    print("ADC reading out of range — check wiring")
Output
ADC raw: 2048 / 4095
NTC resistance: 10012 Ω
Temperature: 25.0 °C
Analogy An ADC is like a ruler for voltage. Just as a 30cm ruler with millimetre markings can measure lengths to 1mm precision (300 divisions), a 12-bit ADC with a 3.3V reference measures voltage to 0.8mV precision (4096 divisions). More bits = finer markings = better resolution.

Digital I/O & Actuators

Digital outputs control LEDs, relays, and motors. Digital inputs read buttons, switches, and interrupt signals. The key concepts: pull-up/pull-down resistors, debouncing, and PWM for variable control.

## Button Input with Debounce + LED PWM Output
## For ESP32 with MicroPython

import machine
import time

# Button on GPIO15 with internal pull-up
button = machine.Pin(15, machine.Pin.IN, machine.Pin.PULL_UP)

# LED on GPIO2 with PWM (variable brightness)
pwm = machine.PWM(machine.Pin(2), freq=1000)

# Software debounce — read button state with 50ms settling
def read_button_debounced(pin, delay_ms=50):
    """Read button with debounce. Returns True if pressed (active LOW)."""
    if pin.value() == 0:  # Button pressed (pulled to GND)
        time.sleep_ms(delay_ms)
        if pin.value() == 0:  # Still pressed after debounce
            return True
    return False

# Cycle LED brightness on each button press
brightness_levels = [0, 256, 512, 768, 1023]  # 0-1023 PWM range
level_index = 0

print("Press button to cycle LED brightness...")
while True:
    if read_button_debounced(button):
        level_index = (level_index + 1) % len(brightness_levels)
        duty = brightness_levels[level_index]
        pwm.duty(duty)
        print(f"Brightness: {duty/1023*100:.0f}% (duty={duty})")
        # Wait for button release
        while button.value() == 0:
            time.sleep_ms(10)
    time.sleep_ms(10)

Systematic Debugging

Debugging is where most prototyping time is spent. A systematic approach saves hours of frustration.

Multimeter Mastery

A digital multimeter (DMM) is your most important debugging tool. Master these four measurements:

Measurement Mode Probe Placement What You’re Checking
DC Voltage V⎓ (DC) Across the component (parallel) Power rail = 3.3V? GPIO HIGH = VDD?
Continuity 🔊 (beep mode) Between two points Is this wire connected? Any shorts?
Resistance Ω Across the component (power OFF!) Is this the right resistor? Is the IC shorted?
DC Current A⎓ (DC) In series with the load (break the circuit) How much current is my MCU drawing?
Current measurement safety: To measure current, you must break the circuit and put the multimeter IN SERIES. Never connect the ammeter across a voltage source (parallel) — this creates a near-short-circuit and can blow the multimeter fuse or damage components.

The Debug Workflow

Hardware Debug Flowchart
flowchart TD
                    A["Circuit doesn't work"] --> B{"Check power supply
V_DD = expected?"} B -->|"No"| C["Fix power:
check USB, regulator,
decoupling caps"] B -->|"Yes"| D{"Check connections
continuity test"} D -->|"Open circuit"| E["Reseat wires,
check solder joints"] D -->|"All connected"| F{"Check signals
with scope/logic analyser"} F -->|"No signal"| G["Check MCU config:
GPIO mode, clock enable,
pin mapping"] F -->|"Signal present"| H{"Signal correct?
Right frequency/level?"} H -->|"Wrong level"| I["Level mismatch:
add level shifter
or voltage divider"] H -->|"Wrong timing"| J["Check clock config,
baud rate, prescaler"] H -->|"Looks correct"| K["Check peripheral:
sensor address,
register config"]

Serial Monitor Debugging

The serial monitor (UART) is the embedded equivalent of console.log(). Use it systematically:

/* Serial Debug Macros for STM32 HAL
 * Redirect printf to UART2 (connected to ST-LINK virtual COM)
 * Add to your main.c or a debug.h header
 */

#include <stdio.h>
#include "stm32f4xx_hal.h"

extern UART_HandleTypeDef huart2;  /* Defined by CubeMX */

/* Redirect printf to UART2 */
int _write(int file, char *ptr, int len)
{
    HAL_UART_Transmit(&huart2, (uint8_t *)ptr, len, HAL_MAX_DELAY);
    return len;
}

/* Debug macros with file/line info */
#define DEBUG_PRINT(fmt, ...) \
    printf("[%lu] " fmt "\r\n", HAL_GetTick(), ##__VA_ARGS__)

#define DEBUG_HEX(label, data, len) do { \
    printf("[%lu] %s: ", HAL_GetTick(), label); \
    for (int i = 0; i < len; i++) printf("%02X ", data[i]); \
    printf("\r\n"); \
} while(0)

/* Usage example in main loop */
/*
    DEBUG_PRINT("ADC value: %d (%.2fV)", adc_raw, adc_raw * 3.3 / 4095);
    DEBUG_PRINT("I2C sensor addr 0x%02X responded", sensor_addr);
    DEBUG_HEX("BME280 raw", buffer, 8);
*/

BOM Builder Tool

Case Study: Nest Learning Thermostat Prototype

Real-World Product Design

Background: When Tony Fadell and Matt Rogers founded Nest Labs in 2010, they prototyped the first Nest Thermostat using off-the-shelf dev boards, breadboards, and hand-soldered perfboards — exactly the techniques covered in this article.

  • Stage 1 (Breadboard): Temperature sensor + humidity sensor + LCD display + WiFi module on a breadboard to prove the concept of a cloud-connected thermostat.
  • Stage 2 (Perfboard): Integrated the motion sensor (occupancy detection) and learning algorithm firmware on a semi-permanent prototype for weeks of testing in a real home.
  • Stage 3 (Custom PCB): Designed a round PCB to fit the iconic circular form factor, going through 14 board revisions before production.

Lesson: Even a $3.2 billion product (Google acquired Nest in 2014) started on a breadboard. Prototyping isn’t a shortcut — it’s the professional process.

Case Study: I2C Bus Debugging in the Field

Debugging Common Pitfall

Problem: An engineer’s I2C bus with 3 sensors worked perfectly on a short breadboard but failed intermittently when wires were extended to 30cm for an enclosure prototype.

  • Symptom: BME280 returned 0xFF for all registers. I2C scan found 0 devices.
  • Root cause: Long wires added capacitance (~50pF), slowing the signal edges below I2C timing thresholds. The 4.7kΩ pull-ups were too weak.
  • Fix: Replaced 4.7kΩ pull-ups with 2.2kΩ to increase drive current, and reduced bus speed from 400kHz to 100kHz.

Lesson: Always prototype with the same wire lengths you’ll use in the final product. Bus capacitance scales with wire length.

Exercises

Exercise 1: Build a Sensor Station

Using a breadboard and an ESP32 DevKit, build a temperature and light monitoring station:

  1. Wire a 10kΩ NTC thermistor as a voltage divider to an ADC pin
  2. Connect an I2C BH1750 light sensor (or LDR + resistor divider)
  3. Add two LEDs: green for “normal” and red for “alert” temperature
  4. Print readings to serial monitor every 2 seconds
  5. Turn on the red LED when temperature exceeds 30°C

Hint: Don’t forget 100nF decoupling caps near the ESP32 power pins. Use GPIO34-39 for ADC inputs (input-only pins). The I2C pull-ups are usually built into breakout boards.

Exercise 2: Debug Challenge

Your colleague hands you a breadboard with an STM32 Nucleo, a BME280 sensor, and an OLED display. “Nothing works.” Describe the exact steps you would follow to debug it:

  1. What is the first thing you measure and why?
  2. If power is correct, what do you check next?
  3. How do you verify the I2C bus is electrically working?
  4. How do you isolate whether the problem is the sensor or the display?

Hint: Follow the debug flowchart: Power → Connections → Signals → Configuration. Use the multimeter continuity mode for step 2 and an I2C scan script for step 3.

Exercise 3: Breadboard-to-Perfboard Transition

You have a working breadboard prototype of a 3.3V-powered system with an STM32 Nucleo, a BME280 (I2C), an SSD1306 OLED (I2C), and two status LEDs. Now you need to transfer it to a perfboard for long-term testing:

  1. Plan your perfboard layout. Which components should be placed closest to the MCU and why? Draw a rough component placement sketch (on paper or in a drawing tool).
  2. The BME280 needs to measure ambient air temperature, not board temperature. How would you position it on the perfboard? What mounting technique would you use?
  3. Calculate the required I2C pull-up resistor values for a bus with 2 devices and 5cm total trace length (~20pF bus capacitance). The target is 400kHz Fast Mode. What is the maximum allowed rise time?
  4. Your perfboard will be powered by a 5V USB supply through an AMS1117-3.3 LDO. Place decoupling capacitors: how many, what values, and where?
  5. After soldering, the OLED works but the BME280 returns all zeros. Describe your debugging approach — what is the most likely cause given that it worked on the breadboard?

Hint: (1) Power components (LDO, bulk cap) first, then MCU, then peripherals by bus distance. (2) Mount BME280 on a small daughter board connected by a short cable, away from heat-generating components. (3) Rise time < 300ns for 400kHz. R_pull = t_rise / (0.8473 × C_bus) = 300ns / (0.8473 × 20pF) ≈ 17.7kΩ max. Use 4.7kΩ for good margin. (4) AMS1117 needs 22µF input + 22µF output (tantalum or electrolytic, not just MLCC — LDO needs ESR for stability). Add 100nF MLCC at MCU VDD pins. (5) Most likely a solder bridge or cold joint on the BME280 I2C lines. Check continuity of SDA/SCL from MCU pin to sensor pin. Then verify address with I2C scan.

BOM Builder Tool

Use this tool to build a Bill of Materials for your prototype and download it as a reference document for ordering components.

Prototype BOM Builder

Enter your prototype details and component list. Download as Word, Excel, or PDF for ordering and documentation.

Draft auto-saved

Conclusion & Next Steps

You now have the practical skills to build working embedded prototypes: breadboarding with clean wiring discipline, choosing the right development board for your project, integrating sensors via I2C and analog ADC, and debugging systematically with a multimeter and serial monitor.

Key takeaways: (1) Prototype every circuit before designing a PCB. (2) STM32 Nucleo for professional bare-metal work, ESP32 for WiFi/BLE projects. (3) Always add 100nF decoupling caps near IC power pins. (4) Debug power first, then connections, then signals. (5) A multimeter and serial monitor will solve 90% of your problems.

Next in the Series

In Part 3: MCU & System Architecture, we’ll dive deep into microcontroller internals — GPIO registers, ADC configuration, hardware timers, interrupt handling, power budgeting, and communication protocols (I2C, SPI, UART, CAN).