assignment
• write and test a program for an embedded system using a microcontroller to interact (with input &/or output devices) and communicate (with wired or wireless connections)
• browse through the data sheet for a microcontroller
extra credit: assemble the system
for this week, I want to connect to an OLED screen
goals
connecting to the barduino
connecting the display to barduino
display "hello"
what i need
- OLED display
- barduino
- programming environment (Arduino IDE)
- breadboard and jumper wires
connecting to the barduino
the LED on the Barduino on pin 05 lights up when I connect it to my laptop with USB-C
tried a test code
const int LED_PIN = 48; // built-in Barduino LED
void setup() {
pinMode(LED_PIN, OUTPUT);
}
void loop() {
digitalWrite(LED_PIN, HIGH);
delay(500);
digitalWrite(LED_PIN, LOW);
delay(500);
}
error: could not find a valid board
error: didn't specify pin
error: failed to connect to the board
I asked chatGPT for help since I was stuck on the error messages.
enable USB CDC on Boot
on the top bar, tools -> port -> select your board
do this by disconnecting and connecting the ardiono to identify the correct port to select the new one
also added pin 48 because i accidentally had deleted that line of code earlier.
the board is connected and the light is blinking.
digitally simulating a heart with wokwi
soldering pins to the OLED display and the Barduino
p.s i spent a few days trying to use wires without soldering pins- and failing miserably. none if the hacks work and I agree that breadboard has too many problems and soldering pins has a way higher success rate.
once i soldered the pins, everything worked much better. I connected the OLED display to the Barduino without any issues.
I finally figure out how to display "Hello". I had to download the Adafruit SSD1306, SSD1106 library and the Adafruit GFX library.
I connected the pins of the oled display to the I2C connectors already present on the Barduino as follows:
3V3 - 3V3
GND - GND
SDA - SDA
SCK - SCL
//arduino code
#include
#include
#include
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
void setup() {
Serial.begin(115200);
delay(200);
Wire.begin();
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("SSD1306 not found");
while (true);
}
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(20, 25);
display.println("hello");
display.display();
}
void loop() {
}
I wanted to read the datasheets of the microcontroller I am using, and the one commonly used for other projects in the fablab. And because I was in such a reading mood, I also read the datasheet of the e-paper display that I want to connect.
I did this by asking ChatGPT to "explain the document to me in detail like i am new to electronics, summarise the important points and explain the acronyms"
i read the datasheet of the ESP32 (since it is on the barduino given by the fablab)
I uploaded the pdf of each data sheet. These datasheets are heavy with information. Like an encyclopaedia. I will have to keep referring to them based on the projects that I work on.
ESP32
1. What this device actually is
The ESP32-S3-WROOM-1 is a microcontroller module with WiFi and Bluetooth.
Think of it like:
Tiny computer for electronics projects
It contains:
- CPU (processor)
- memory
- WiFi
- Bluetooth
- input/output pins
- hardware for sensors, motors, screens
All in one chip.
it can be programmed using:
- Arduino IDE
- ESP-IDF
- MicroPython
Your Barduino board basically has this chip on it.
2. what is inside
The module contains several major systems:
Power
↓
CPU (brain)
↓
Memory
↓
Peripherals (interfaces)
↓
GPIO pins
↓
External devices
Inside the ESP32 module there are also:
- antenna
- crystal oscillator
- flash memory
The block diagram on page 9 shows this architecture.
Main blocks:
3.3V power
↓
ESP32-S3 processor
↓
Flash memory
↓
PSRAM (optional)
↓
WiFi + Bluetooth radio
↓
GPIO pins
3. Key specs you should remember
These are the important numbers.
CPU
Xtensa LX7 dual core processor
Meaning:
- 2 processors
- each runs up to 240 MHz
For comparison:
Arduino Uno → 16 MHz
ESP32 → 240 MHz
So ESP32 is ~15x faster.
Memory
From the datasheet:
| Memory type | Size |
|---|---|
| ROM | 384 KB |
| SRAM | 512 KB |
| RTC memory | 16 KB |
| Flash | up to 16 MB |
| PSRAM | up to 16 MB |
Explanation:
ROM
→ permanent system code
SRAM
→ working memory while running
Flash
→ where your program is stored
PSRAM
→ extra memory for big tasks (images, AI)
4. Important acronyms explained
This is where most beginners get lost.
Here are the key ones.
MCU
Microcontroller Unit
Small computer that runs embedded programs.
Examples:
- Arduino
- ESP32
- Raspberry Pi Pico
SoC
System on Chip
A chip that contains many components together.
- CPU
- WiFi
- Bluetooth
- memory
- peripherals
All integrated.
GPIO
General Purpose Input Output
Pins you control with code.
Example:
digitalWrite(LED, HIGH)
Pins can be:
- input
- output
- analog
- communication
The ESP32-S3 has 36 GPIO pins.
ADC
Analog to Digital Converter
Converts voltage to numbers.
Example:
sensor voltage → number
Example:
0V → 0
3.3V → 4095
Used for:
- sensors
- potentiometers
- temperature
PWM
Pulse Width Modulation
Fake analog output using digital pulses.
Example:
- LED brightness
- motor speed
- servo control
SPI
Serial Peripheral Interface
High-speed communication protocol.
Used for:
- displays
- SD cards
- flash memory
- sensors
Pins:
MOSI
MISO
SCK
CS
I2C
Inter-Integrated Circuit
Two-wire communication protocol.
Pins:
SDA → data
SCL → clock
Used for:
- sensors
- RTC modules
- OLED displays
UART
Universal Asynchronous Receiver Transmitter
Serial communication.
Example:
USB serial monitor
GPS module
Bluetooth module
I2S
Inter-IC Sound
Audio communication.
Used for:
- microphones
- audio DACs
- speakers
USB OTG
USB On The Go
Allows device to act as:
- USB host
- USB device
Example:
ESP32 can connect to:
- keyboard
- storage
- computer
PSRAM
Pseudo Static RAM
Extra memory used for:
- images
- video
- AI models
5. Power requirements
The chip runs on:
3.0V – 3.6V
Typical:
3.3V
From the datasheet:
Recommended: 3.3V
Max: 3.6V
Never connect 5V directly to GPIO pins.
6. Important pins
From the pin table in the datasheet.
Important ones:
Power pins
3V3 → power
GND → ground
EN pin
EN = enable
If HIGH → chip runs
If LOW → chip off
UART pins
TXD0 → transmit
RXD0 → receive
Used for:
- programming
- serial monitor
GPIO pins
Example:
IO4
IO5
IO6
IO7
These can be used for:
- sensors
- buttons
- LEDs
7. Boot system
When ESP32 starts, it decides how to start the program.
Controlled by certain pins.
Main boot modes:
SPI Boot
Normal mode.
The chip loads your program from flash memory.
Download Boot
Used when uploading code.
Controlled by:
GPIO0
GPIO46
From the datasheet boot table.
8. Communication interfaces (very important)
UART
3 UART controllers.
Speed up to:
5 Mbps
Used for:
- debugging
- serial communication
- programming
I2C
2 I2C buses.
Speed:
100 kbit/s (standard)
400 kbit/s (fast)
Used for sensors.
SPI
Multiple SPI controllers.
Used for:
- displays
- flash
- SD cards
SPI can run up to:
120 MHz
Very fast.
USB Serial / JTAG
Allows debugging directly via USB.
No extra chip needed.
9. Sensors inside the chip
The chip has some built-in sensors.
Temperature sensor
Measures chip temperature.
Range:
-40°C to 125°C
Used mainly for internal monitoring.
Touch sensors
14 capacitive touch pins.
Detects finger touch.
Used for:
touch buttons
interactive panels
10. Power modes
This is very important for IoT devices.
ESP32 has several power states.
Active
Everything running.
WiFi can draw up to:
~355 mA
Modem sleep
WiFi off.
Power:
~13–40 mA
Light sleep
Most systems paused.
Power:
~240 µA
Deep sleep
Almost everything off.
Power:
~7–190 µA
Used for battery devices.
11. What you can connect to ESP32
GPIO
connect sensors, LEDs, motors
SPI
connect:
- e-ink displays
- TFT displays
- SD cards
I2C
connect:
- sensors
- OLED screens
- RTC clocks
WiFi
connect to:
- APIs
- weather data
- IoT systems
Bluetooth
connect to:
- phones
- BLE devices
12. Simple mental model
Think of ESP32 as:
Brain → CPU
Memory → RAM + Flash
Nerves → GPIO pins
Language → SPI / I2C / UART
Internet → WiFi
Wireless → Bluetooth
Sensors → ADC / touch
“Demonstrate and compare the toolchains and development workflows for available embedded architectures.”
Goals for the assignment
- Show how to program different embedded systems
- Explain the tools used to program them
- Compare how the programming process works for each system
To answer these questions
- How do we program different microcontrollers?
- What software tools are used?
- What steps are needed to upload code?
- Which system is easier or more powerful?
Terminology:
Embedded Architecture
An embedded architecture is the type of microcontroller or processor system you are programming.
Examples:
| Architecture | Example Boards |
|---|---|
| AVR | Arduino Uno, ATtiny |
| ARM Cortex | STM32 boards |
| ESP32 architecture | ESP32, Barduino |
| RP2040 | Raspberry Pi Pico |
In my case:
- Barduino 4.0.2 → ESP32-S3 architecture
Toolchain
A toolchain is the set of software tools used to turn code into a program running on a microcontroller.
Typical toolchain steps:
Code → Compile → Link → Upload → Run
Example toolchain:
| Step | Tool |
|---|---|
| Write code | Arduino IDE / VSCode |
| Compile code | GCC compiler |
| Create firmware | linker |
| Upload firmware | esptool / avrdude |
| Run program | microcontroller |
So toolchain = all the software tools used to build and upload code.
Comparison of Toolchains and Development Workflows for Embedded Architectures
In embedded systems development, different microcontroller architectures require different toolchains and development workflows. A toolchain refers to the set of software tools used to compile, build, and upload firmware to a microcontroller. The development workflow describes the sequence of steps developers follow when programming and testing embedded hardware.
For this comparison, we explored three commonly used embedded architectures:
- AVR architecture (Arduino Uno / ATmega328P)
- ESP32 architecture (ESP32 / Barduino)
- ARM Cortex architecture (STM32 family)
These platforms represent beginner, intermediate, and professional-level embedded systems commonly used in digital fabrication and prototyping.
1. AVR Architecture (Arduino Uno / ATmega328P)
Overview
The AVR architecture is an 8-bit microcontroller platform developed by Atmel (now Microchip). It is widely used in the Arduino ecosystem and is often the first platform beginners use when learning embedded programming.
Example boards:
- Arduino Uno
- Arduino Nano
- ATtiny series
The simplicity of the architecture and its large community make it ideal for rapid prototyping and educational purposes.
Toolchain
The typical AVR toolchain includes:
- Arduino IDE – code editor and development environment
- AVR-GCC Compiler – compiles C/C++ code into machine code
- AVRDUDE – uploads compiled firmware to the microcontroller
The Arduino IDE simplifies the process by integrating compilation and uploading into a single interface.
Development Workflow
Typical workflow:
- Write code using the Arduino IDE
- Compile the code using the AVR-GCC compiler
- The IDE generates firmware from the compiled code
- AVRDUDE uploads the firmware via USB
- The microcontroller executes the program
Advantages
- Very easy to learn
- Large documentation and community support
- Simple development environment
- Reliable for basic electronics projects
Limitations
- Limited processing power (8-bit)
- Small memory capacity
- No built-in wireless connectivity
- Slower clock speed compared to modern microcontrollers
2. ESP32 Architecture (ESP32 / Barduino)
Overview
The ESP32 architecture is a modern 32-bit microcontroller platform developed by Espressif. It is widely used for Internet of Things (IoT) applications due to its built-in wireless capabilities.
Example boards:
- ESP32 DevKit
- Barduino (used at Fab Lab Barcelona)
- ESP32-S3 boards
The ESP32 offers significantly greater performance and functionality than traditional AVR microcontrollers.
Toolchain
Typical ESP32 development uses:
- Arduino IDE or PlatformIO – development environment
- ESP32 Toolchain (Xtensa GCC) – compiles code for ESP32 architecture
- ESPTool – uploads firmware to the ESP32
Before programming ESP32 boards in Arduino IDE, the ESP32 board package must be installed.
Development Workflow
Typical workflow:
- Install ESP32 board support in the Arduino IDE
- Write code in C/C++ using Arduino libraries
- Compile code using the ESP32 GCC toolchain
- Upload firmware using ESPTool
- ESP32 executes the firmware
Advantages
- 32-bit processor
- High clock speeds (up to ~240 MHz)
- Built-in WiFi and Bluetooth
- More RAM and storage
- Suitable for IoT and networked devices
Limitations
- Slightly more complex setup than Arduino
- Higher power consumption
- Debugging can be more complex for beginners
3. ARM Cortex Architecture (STM32)
Overview
The ARM Cortex architecture is widely used in professional embedded systems and industrial electronics. STM32 microcontrollers are based on ARM Cortex-M processors and provide high performance with advanced peripheral support.
Example boards:
- STM32 Nucleo
- STM32 Discovery
- Various industrial embedded systems
These systems are commonly used in robotics, industrial control, and consumer electronics.
Toolchain
Typical STM32 development toolchain includes:
- STM32CubeIDE or Keil MDK – integrated development environment
- ARM GCC Compiler – compiles code for ARM architecture
- ST-Link Programmer – uploads firmware to the microcontroller
These development environments provide advanced debugging and hardware configuration tools.
Development Workflow
Typical workflow:
- Configure the microcontroller using STM32CubeIDE
- Write embedded C code
- Compile code using the ARM GCC toolchain
- Upload firmware using ST-Link programmer
- Run and debug the program on the hardware
Advantages
- High performance 32-bit processors
- Extensive peripheral support
- Professional debugging tools
- Widely used in industry
Limitations
- More complex setup
- Steeper learning curve
- Requires deeper knowledge of embedded systems
Comparison of Architectures
| Feature | AVR (Arduino) | ESP32 | ARM (STM32) |
|---|---|---|---|
| Processor Type | 8-bit | 32-bit | 32-bit |
| Typical Clock Speed | ~16 MHz | Up to 240 MHz | Up to 400 MHz |
| Wireless Connectivity | No | WiFi + Bluetooth | Usually external modules required |
| Development Difficulty | Beginner | Intermediate | Advanced |
| Common Uses | Education, basic electronics | IoT devices, wireless systems | Industrial and professional embedded systems |
Conclusion
Each embedded architecture provides different capabilities depending on the complexity of the project.
The AVR architecture offers simplicity and accessibility for beginners learning embedded systems. The ESP32 architecture introduces more powerful processing capabilities along with integrated wireless communication, making it ideal for IoT and connected devices. The ARM Cortex architecture, such as STM32, provides professional-level performance and advanced debugging tools used in industrial applications.
Understanding the differences in toolchains and development workflows across these architectures helps developers select the appropriate platform for their project requirements.
Week 4 – Electronics Programming
Class notes from the global lecture and local sessions.
dani shows us wokwi to digitally simulate circuits and microcontrollers.
the code
the output
What are Computers?
Computers are machines designed to perform calculations and logical operations automatically. At their core, they are calculating machines that process information using electrical signals. A computer can be instructed to carry out sequences of arithmetic or logical operations through programming.
The development of modern computers accelerated significantly during wartime. During the Second World War, computers were developed to perform complex calculations for tasks such as ballistics, cryptography, and navigation. These technologies later evolved into the computing systems that we use today.
All computers ultimately operate using binary numbers, which means they represent information using only two states: 0 and 1. These states correspond to electrical signals such as low voltage and high voltage. Logical operations are performed using structures called logic gates.
Logic Gates
Logic gates are the fundamental building blocks of digital electronics. They take binary inputs and produce binary outputs according to logical rules. Every computer processor is built from millions or billions of these gates.
- AND – output is true only if both inputs are true
- OR – output is true if at least one input is true
- NOT – reverses the input value
- NAND, NOR, XOR – more complex logical combinations
By combining many logic gates together, engineers can build circuits capable of performing very complex computations.
Hardware Basics
During the lecture we reviewed the fundamental components of electronic hardware used in computing systems.
PCB – Printed Circuit Board
A PCB is a board used to mechanically support and electrically connect electronic components. It contains conductive pathways, also called traces, that allow electrical signals to travel between components.
These traces are typically made of copper and are etched onto a non-conductive material such as fiberglass. The PCB provides both the physical structure and the electrical connectivity for the circuit.
IC – Integrated Circuit
An integrated circuit is a small semiconductor chip that contains many electronic components such as transistors, resistors, and capacitors integrated into a single device. ICs can perform many different functions depending on their design.
Examples of integrated circuits include:
- microprocessors
- timers
- memory chips
- amplifiers
- communication controllers
Integrated circuits are extremely important because they allow very complex circuits to be implemented in extremely small physical sizes.
MCU – Microcontroller Unit
A microcontroller unit (MCU) is a compact integrated circuit designed to control a specific task inside an embedded system. Unlike a full computer processor, a microcontroller integrates several important components on one chip.
- a processor (CPU)
- memory
- input/output pins
- communication interfaces
- timers and other peripherals
Microcontrollers are widely used in embedded devices such as robots, sensors, appliances, and Internet of Things systems.
Programming Microcontrollers
To make a microcontroller perform tasks, we write programs that define how the device should behave. These programs must eventually be translated into machine code that the microcontroller can execute.
Compiling Code
When we write code in a human-readable programming language, it must be converted into machine instructions. This process is called compiling.
The Arduino development environment compiles the code written in the Arduino programming language into a binary file. This binary file is then uploaded to the microcontroller.
Some systems instead use interpreters, such as MicroPython. In that case the code is interpreted and executed line by line on the microcontroller rather than compiled into a single binary file beforehand.
Arduino IDE
In this class we used the Arduino IDE to write and upload programs. IDE stands for Integrated Development Environment. It provides a user interface that makes programming microcontrollers easier.
The Arduino IDE includes several important tools:
- a code editor for writing programs
- a compiler that converts code into machine instructions
- a serial monitor for debugging and communication
- tools for uploading programs to microcontrollers
The Arduino language is based primarily on C and C++, although its simplified structure makes it easier for beginners to learn.
Installing Boards in Arduino IDE
Before uploading programs, the IDE needs to know how to communicate with specific microcontrollers. This is done by installing board packages.
In our case we needed to install support for the ESP32 microcontroller.
The process included:
- updating the Arduino IDE to the latest version
- opening the Boards Manager
- adding the ESP32 board repository link
- installing the board package
I initially had the IDE installed already but needed to update it. After updating, I added the board manager URLs one by one until the ESP32 board package installed successfully.
Structure of an Arduino Program
Every Arduino program follows a basic structure consisting of two main functions.
Setup Function
The setup() function runs once when the program starts. It is typically used for initialization tasks.
- configuring pin modes
- starting communication protocols
- initializing variables
- loading libraries
Loop Function
The loop() function runs continuously after setup finishes. This function controls the main behavior of the program.
The code inside loop() executes repeatedly as long as the microcontroller is powered.
Program Execution
Like most programming languages, Arduino code is executed sequentially from top to bottom. Instructions are processed in order, and the microcontroller follows these instructions exactly as written.
Simulation with Wokwi
During the class we also experimented with simulation tools. Using Wokwi, we simulated microcontroller behavior without needing to run the code directly on hardware.
One of the exercises was to simulate an LED blinking in Morse code to send an SOS signal.
I modified the program to repeatedly transmit the phrase "hola guapa" in Morse code instead, which was a fun way to experiment with timing and loops.
Programming Syntax
One important concept we discussed is that programming languages are case-sensitive.
For example:
- uppercase names usually represent classes or types
- lowercase names often represent functions or variables
This means that small differences in capitalization can change the meaning of the program or cause errors.
Programming Languages in Embedded Systems
When programming microcontrollers and computers, we rarely interact directly with the electrical signals of the machine. Instead, we use programming languages that allow humans to write instructions in a readable form. These instructions are eventually translated into machine instructions that the processor can execute.
There are several levels of programming languages depending on how close they are to the hardware.
Machine Code
Machine code is the lowest level language that a processor can understand. It is written entirely in binary numbers composed of 0s and 1s. These binary instructions directly control the processor’s operations.
Each processor architecture has its own machine code format. This means a program compiled for one processor cannot run on another processor unless it is recompiled for that architecture.
Writing programs directly in machine code is extremely difficult because it is not human-readable and requires precise knowledge of the processor's internal instruction set.
Assembly Language
Assembly language is a slightly higher-level representation of machine code. Instead of writing binary numbers directly, programmers use short symbolic instructions called mnemonics.
- MOV – move data between registers
- ADD – add two values
- SUB – subtract values
- JMP – jump to another instruction
Each assembly instruction corresponds directly to a machine instruction executed by the processor. Although assembly is easier to read than raw binary, it still requires deep understanding of the processor architecture.
High-Level Languages
High-level programming languages are designed to be easier for humans to read and write. Languages such as C, C++, Python, and Arduino allow programmers to express complex logic using simpler syntax.
These languages are not directly understood by the microcontroller. Instead, they must be translated into machine code using compilers or interpreters.
The Arduino programming language used in the Arduino IDE is based on C/C++, but it simplifies many aspects of programming so that beginners can quickly start controlling hardware.
The Embedded Programming Toolchain
When code is written for a microcontroller, it goes through several stages before it can run on the hardware. This sequence of steps is called the toolchain.
The toolchain converts human-readable code into machine instructions that can be executed by the microcontroller.
- source code
- compilation
- linking
- binary generation
- uploading to the device
Compiler
The compiler converts high-level code written in languages such as C or Arduino into lower-level instructions. During this stage, the compiler checks the code for errors and translates it into machine instructions specific to the target processor.
The output of this stage is usually an object file containing machine instructions.
Linker
The linker combines multiple compiled files together and resolves references between them. For example, if a program uses external libraries, the linker connects those libraries with the compiled program.
This step ensures that all required functions and variables are properly connected before the program is executed.
Binary File
After compilation and linking are complete, the toolchain generates a final binary file. This binary file contains the complete machine instructions that will run on the microcontroller.
The binary file is usually stored in formats such as:
- .bin
- .hex
- .elf
These files represent the compiled program in a format that can be transferred to the microcontroller.
Uploading to the Microcontroller
The final stage of the toolchain is uploading the compiled binary file to the microcontroller's memory. This is usually done through a communication interface such as USB, UART, or a programming header.
The Arduino IDE automatically performs this step when the user presses the upload button. The IDE compiles the code, creates the binary file, and transfers it to the board.
Microcontroller Architecture
A microcontroller is essentially a small computer integrated into a single chip. It contains several components that work together to execute programs and interact with external devices.
Unlike desktop computers, microcontrollers are designed for embedded applications where they perform specific tasks inside larger systems.
Main Components of a Microcontroller
- CPU (Central Processing Unit) – executes program instructions
- Flash Memory – stores the program code
- RAM – temporary memory used while the program runs
- GPIO Pins – allow the microcontroller to interact with external components
- Peripherals – built-in modules such as timers, communication interfaces, and analog converters
GPIO – General Purpose Input Output
GPIO pins allow the microcontroller to interact with the outside world. These pins can be configured as either inputs or outputs.
- input – reading signals from sensors or buttons
- output – controlling LEDs, motors, or other devices
Through these pins, the microcontroller can sense its environment and control physical systems.
Communication Interfaces
Microcontrollers often include communication protocols that allow them to interact with other devices.
- UART – serial communication used for debugging and programming
- I2C – communication with sensors and peripherals
- SPI – high-speed communication with displays and memory devices
These interfaces allow microcontrollers to connect with sensors, displays, storage devices, and other electronic components.
Example: ESP32 Microcontroller
In this course we used the ESP32 microcontroller. The ESP32 is a powerful microcontroller widely used in embedded systems and Internet of Things applications.
Some of its features include:
- dual-core processor
- WiFi connectivity
- Bluetooth communication
- multiple GPIO pins
- analog and digital interfaces
These features make the ESP32 a versatile platform for building connected electronic systems.
Key Takeaways
- Computers operate using binary logic and logic gates.
- Microcontrollers combine processors, memory, and peripherals on a single chip.
- Arduino IDE provides an accessible environment for programming embedded systems.
- Programs must be compiled into machine instructions before being executed.
- Arduino programs are structured around setup() and loop() functions.
- Simulation tools such as Wokwi allow testing code before running it on physical hardware.
- Programming syntax and capitalization are important for correct execution.