Writing firmware that runs on microcontrollers to control hardware, reading sensors, processing data, and driving outputs like LEDs and motors under tight memory and power constraints.
Embedded programming is the process of writing firmware that runs on a microcontroller or microprocessor to control hardware components and perform specific tasks. It enables the system to read inputs from sensors, process data, and control outputs such as motors, LEDs, and displays, operating continuously with limited memory and power resources.
During Week 4 of Fab Academy, we dived deep into microcontrollers, explored different programming languages, and wrapped up with a series of assignments.
As a lab we compared the toolchains and development workflows for the embedded architectures we had on hand. The full write up lives on our group assignment page. Here is what I took from it and how it shaped the path I chose for my own work.
We looked at three ways to write and flash firmware for an ESP32: the Arduino IDE, ESP-IDF, and PlatformIO. They all end up talking to the same chip, but they feel very different to use and they trade ease of use against control.
| Arduino IDE | Simplest to start. One window, one Verify button, one Upload button. It hides the build system and gives you the Arduino core (pinMode, digitalWrite, Serial). Huge library ecosystem. Best for learning and quick prototypes. Less control over the lower layers and the board config can feel hidden. |
| ESP-IDF | Espressif's own framework. You work in C with FreeRTOS, menuconfig, and CMake. Full control of every peripheral and memory setting. This is what production ESP32 firmware usually ships on. Steeper to learn and slower to get a first blink running. |
| PlatformIO | A build system and package manager that runs inside VS Code. It can target both the Arduino core and ESP-IDF, manages libraries per project, and keeps the board config in one platformio.ini file. More setup than the Arduino IDE but far more repeatable across machines and boards. |
The pattern is clear. The Arduino IDE trades control for speed, ESP-IDF trades speed for control, and PlatformIO sits in the middle with proper project files and dependency tracking. Because my goal this week was to interact and communicate fast, I started in the Arduino IDE and the Wokwi simulator, which both use the Arduino core. As ORDER, my final project, grows I plan to move into PlatformIO so the build stays the same on every machine in the lab.
The ESP32 is a powerful and versatile microcontroller with built-in WiFi and Bluetooth, making it ideal for IoT projects. It features multiple GPIO pins, analog and digital inputs, and supports I2C, SPI, and UART communication, all while staying energy-efficient.
I opened the Espressif datasheet and read through it before writing any code, because it is the device I am building ORDER around. The button at the right opens the same PDF I used. The numbers that mattered to me were the operating voltage of 3.3V (so a 5V signal can damage a pin), the 12-bit ADC for reading analog sensors, the GPIO count, and the three serial buses I would lean on later. I pulled the key figures into the table below.
| Core | Tensilica Xtensa Dual-Core 32-bit LX6 |
| Voltage | 3.3V |
| Clock Speed | Up to 240 MHz |
| Flash Memory | Typically 4MB |
| SRAM | 520 KB |
| GPIO Pins | Up to 36 configurable |
| ADC | 12-bit ADC (analog inputs) |
| DAC | 2x 8-bit outputs |
| WiFi | 802.11 b/g/n, station, soft-AP, P2P |
| Bluetooth | v4.2 BR/EDR and BLE |
| Power | Ultra-low power sleep modes |
A dual-core, WiFi + Bluetooth capable microcontroller built for the Internet of Things. Low power, high performance, and easy to prototype with.
Serial comms, sensors, GPS, modems
High-speed, displays, SD cards
Multi-device via two wires (SDA & SCL)
Automotive/industrial variants
Motors, LEDs, servos
Analog read and output
Switches, LEDs, relays
I read through the ESP32 datasheet and pulled out the parts that actually change how I write code and wire pins. This is my quick reference for the rest of the embedded weeks.
| Item | Value |
|---|---|
| Core | Xtensa dual core LX6, up to 240 MHz |
| Memory | 520 KB SRAM, 448 KB ROM, 16 KB RTC SRAM |
| Radios | WiFi 802.11 b/g/n (up to 150 Mbps), Bluetooth 4.2 and BLE |
| Working voltage | 2.3 to 3.6 V, use 3.3 V, supply 500 mA or more |
| GPIOs | 34 programmable pins |
| ADC | 12 bit, up to 18 channels |
| DAC | two 8 bit, true analog out |
| Touch | 10 capacitive touch pins |
| Buses | 4 SPI, 2 I2C, 2 I2S, 3 UART, CAN (TWAI), 16 channel LED PWM |
| Deep sleep | about 10 microamps |
| Bus | Typical ESP32 pins |
|---|---|
| UART0 (USB serial and flashing) | TX on GPIO1, RX on GPIO3 |
| I2C (Arduino default) | SDA on GPIO21, SCL on GPIO22 |
| SPI (VSPI) | MOSI 23, MISO 19, SCK 18, CS 5 |
The pins above are the common defaults. The ESP32 has a GPIO matrix, so most buses can be moved to other pins in code, as long as I avoid the flash pins and the input only pins.
GPIO0 decides the boot mode at reset. Held low it enters download mode so a new program can be written over UART, released high it just runs the program already in flash. That is exactly what the BOOT button does, and the EN pin (CHIP_PU) is the reset. So the flashing dance is: hold BOOT, tap EN, upload, release BOOT.
Using Wokwi, a browser-based circuit simulator, to prototype the classic blink LED without any physical hardware. Follow along step by step:
Sign up on Wokwi, then click Create New Project
Select ESP32 as the target microcontroller board
Started testing with the built-in LED, but LED_BUILTIN is a reserved keyword and caused a conflict
Defined a custom pin variable to replace the reserved keyword and resolved the conflict
Drew the full circuit schematic inside the Wokwi workspace
Added a protection resistor, even though ESP32 pin current is limited, this is best practice for circuit safety
Full Working Demonstration, the LED blinks as programmed

The full code I used. You can copy it and paste it straight into the Arduino IDE or Wokwi. I gave my LED pin its own name so it does not clash with the reserved keyword.
// ESP32 blink, my own pin name so LED_BUILTIN does not clash
int ledPin = 2;
void setup() {
pinMode(ledPin, OUTPUT);
}
void loop() {
digitalWrite(ledPin, HIGH);
delay(1000);
digitalWrite(ledPin, LOW);
delay(1000);
}
Arduino is a beginner-friendly microcontroller with great input/output support, though it lacks built-in wireless connectivity. Inputs, push buttons, temperature sensors, light sensors, soil moisture sensors, let it sense the environment. Outputs, LEDs, motors, relays, buzzers, displays, let it respond and act.
By processing input data through programmed logic and generating appropriate outputs, Arduino can automate systems for robotics, home automation, and smart agriculture. For this section we used Tinkercad, a browser-based simulator by Autodesk.
Opened Tinkercad and started with a fresh circuit workspace
Searched for and added the Arduino board to the workspace
Added remaining components, resistor, battery, LED, and push button
Wired all components together following the circuit diagram
Circuit fully connected and verified
Labelled the circuit for clarity before writing code
Writing the Code, programmed the button input and LED output logic in C++
Simulation, ran the simulation and adjusted the resistor value because the LED brightness was too low
I studied a great deal this week and interacted extensively with inputs and outputs using beginner-friendly microcontrollers. I worked with low-level languages like C++, and I am now building my Python skills to use Thonny IDE as confidently as I use the Arduino IDE.
Blinking an LED is the board interacting with the world through a local output. The next step the assignment asks for is to communicate, so the board sends data off the chip and not only flips a pin. The simplest path is the serial port over the USB cable. I started the serial line at 115200 baud and printed a counter once a second, so I could watch the board talk in the Serial Monitor while the same loop kept the LED blinking. This is wired communication.
This is the same sketch as the blink, with the serial calls added. Copy it into the Arduino IDE or Wokwi, then open the Serial Monitor at 115200 baud to see the messages.
// ESP32 interact and communicate
// the LED is the local output, Serial is the wired link back to my computer
int ledPin = 2;
int blinkCount = 0;
void setup() {
pinMode(ledPin, OUTPUT);
Serial.begin(115200);
Serial.println("ESP32 is awake and listening");
}
void loop() {
digitalWrite(ledPin, HIGH);
delay(1000);
digitalWrite(ledPin, LOW);
delay(1000);
blinkCount = blinkCount + 1;
Serial.print("Blink number ");
Serial.println(blinkCount);
}Serial over USB is the wired link. The reason I picked the ESP32 in the first place is that it also carries the wireless path I need for ORDER. The same chip does WiFi (802.11 b/g/n) and Bluetooth Low Energy, so later weeks the board will send orders over WiFi instead of a cable. The serial print I run here is the first rung of that ladder. I prove the board can talk on the wire now, then move the same idea onto WiFi and BLE when the project needs it.
