Overview
The assignment this week was to browse the datasheet of a microcontroller and write a program that interacts with input and output devices.
I used the Seeed Studio XIAO RP2040 together with Arduino IDE. The week started with a simple blink test and gradually expanded into experiments using an external LED, push button input, a sound sensor module, a servo motor and a potentiometer.
By building small experiments step by step I was able to understand how a microcontroller reads inputs, processes logic and controls hardware outputs.
Learning Process
At the beginning of the week I was not familiar with the workflow of the XIAO RP2040. I needed to understand how to install the correct board package in Arduino IDE and how the uploading process works.
After reading documentation and watching tutorials I successfully configured the board and started testing basic programs. From there I gradually added more hardware components and tested them one by one.
Group Assignment
Comparison Report on Embedded Architecture Toolchains and Development Workflows
There was no separate group assignment page available for this week. So I included the group comparison report directly in this page.
1. Introduction
Embedded systems are widely used in IoT, industrial control, automotive electronics, and many other fields. Different embedded architectures have different toolchains and workflows. These include ARM Cortex-M, AVR, RISC-V, and ESP. This report compares several mainstream architectures and helps explain which platform may fit different projects.
2. Selected Embedded Architectures
Our team selected the following mainstream embedded architectures for comparison:
- ARM Cortex-M, using STM32 as the example
- AVR, using Arduino as the example
- RISC-V, using open-source RISC-V boards as examples
- ESP, using ESP32 as the example
The XIAO RP2040 used in my individual work is also based on an ARM Cortex-M0+ processor. This helped me connect my own board test with the group comparison.
3. Toolchain Comparison
| Architecture | Compiler Tools | IDE / Development Environment | Debugging Tools | Simulation Tools |
|---|---|---|---|---|
| ARM Cortex-M | GCC (arm-none-eabi-gcc), Keil, IAR | STM32CubeIDE, Keil, PlatformIO | J-Link, ST-Link | QEMU, Keil |
| AVR | AVR-GCC, Atmel Studio | Arduino IDE, Atmel Studio, PlatformIO | USBasp, AVR Dragon | Proteus, SimulIDE |
| RISC-V | GCC (riscv64-unknown-elf-gcc) | VS Code + PlatformIO, Freedom Studio | OpenOCD, J-Link | QEMU |
| ESP | GCC (xtensa-esp32-elf-gcc) | Arduino IDE, ESP-IDF, PlatformIO | ESP-Prog, JTAG | Proteus, Tinkercad |
4. Development Workflow Comparison
ARM Cortex-M (STM32)
- Install Toolchain: install GCC for ARM, Keil, or STM32CubeIDE.
- Write Code: use the STM32 HAL library or bare-metal programming.
- Compile: use arm-none-eabi-gcc for compilation.
- Flash to Board: use ST-Link to upload the code.
- Debug: use GDB or OpenOCD for debugging.
AVR (Arduino)
- Install Arduino IDE and the necessary board support package.
- Write Code: develop using C or C++.
- Compile: use AVR-GCC for compilation.
- Flash Program: upload code using USBasp or Arduino Bootloader.
- Debug: use serial printing or Proteus for simulation.
RISC-V
- Install a RISC-V GCC toolchain.
- Set up VS Code, PlatformIO, or Freedom Studio.
- Write Code: develop using C or C++.
- Compile: use riscv64-unknown-elf-gcc for compilation.
- Flash and Debug: use OpenOCD or J-Link.
ESP (ESP32)
- Install ESP-IDF or Arduino IDE.
- Write Code: develop using C or MicroPython.
- Compile: use xtensa-esp32-elf-gcc for compilation.
- Flash Program: upload using USB serial.
- Debug: use ESP-Prog or JTAG.
5. Conclusion
ARM Cortex-M is suitable for industrial and high-performance embedded applications. It has a mature toolchain, but the learning curve can be steep.
AVR, especially Arduino, is ideal for entry-level projects. It is easy to use, but its performance is limited.
RISC-V is an emerging architecture. It is useful for open-source development, although its toolchain is still evolving.
The ESP series is ideal for IoT and wireless communication projects. It offers a rich ecosystem and a user-friendly development process.
Different architectures are suitable for different project scenarios. Developers should choose the most appropriate platform based on their needs.
Programming Experiments
I approached this week as a sequence of small experiments. Each experiment helped me understand a different part of embedded programming.
What is PWM?
PWM means Pulse Width Modulation. It turns a digital pin on and off very quickly.
By changing the on-time ratio, PWM can create different output effects. I used PWM for servo control.
For servo control, different pulse widths represent different angles. The servo reads these pulses and moves to the target angle.
1. Blink — Built-in LED
void setup(){
pinMode(LED_BUILTIN, OUTPUT);
}
void loop(){
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
}
Code reference: This test followed the structure of the Arduino Blink example.
I changed it for the XIAO RP2040 and used LED_BUILTIN.
Reference: Arduino Blink example.
| Component | Code Pin | Connection | What the code does |
|---|---|---|---|
| Built-in LED | LED_BUILTIN | No external wiring was needed. | The code turns the built-in LED on and off every second. |
2. External LED
int led = 3;
void setup(){
pinMode(led, OUTPUT);
}
void loop(){
digitalWrite(led, HIGH);
delay(1000);
digitalWrite(led, LOW);
delay(1000);
}
Code reference: This test used the same basic logic as the Arduino Blink example.
I changed the output pin to match my external LED wiring.
References: Arduino Blink example and Arduino digitalWrite().
3. Button Controlling LED
const int buttonPin = 28;
const int ledPin = 3;
void setup(){
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
}
void loop(){
int buttonState = digitalRead(buttonPin);
if(buttonState == LOW){
digitalWrite(ledPin, HIGH);
}
else{
digitalWrite(ledPin, LOW);
}
}
Code reference: This code was based on Arduino input pull-up logic.
I changed the pins and connected the momentary button to GND.
References: Arduino Input Pullup Serial example and Arduino digitalRead().
I used a momentary push button for this test. It is not a latching switch.
Because I used INPUT_PULLUP, the input pin reads HIGH when the button is not pressed.
When I press the button, the pin connects to GND. Then the pin reads LOW, and the LED turns on.
So the LED only stays on while I keep pressing the button.
| Component | Code Pin | Connection | What the code does |
|---|---|---|---|
| Momentary push button | buttonPin = 28 | One side → pin 28. Other side → GND. | The pin reads LOW only when the button is pressed. |
| External LED and resistor | ledPin = 3 | Pin 3 → resistor → LED → GND. | The LED turns on when buttonState is LOW. |
4. Sound Sensor Toggle LED
const int soundPin = 28;
const int ledPin = 3;
bool ledState = false;
bool lastSoundState = HIGH;
unsigned long lastTriggerTime = 0;
const unsigned long debounceTime = 300;
void setup(){
pinMode(ledPin, OUTPUT);
pinMode(soundPin, INPUT);
digitalWrite(ledPin, LOW);
}
void loop(){
bool soundState = digitalRead(soundPin);
unsigned long now = millis();
if(soundState == LOW && lastSoundState == HIGH){
if(now - lastTriggerTime > debounceTime){
ledState = !ledState;
digitalWrite(ledPin, ledState ? HIGH : LOW);
lastTriggerTime = now;
}
}
lastSoundState = soundState;
}
Code reference: I wrote this toggle logic for my sound sensor test.
The code uses Arduino digitalRead() to read the sensor output.
It also uses millis() to add a short debounce time.
References: Arduino digitalRead() and Arduino millis().
| Component | Code Pin | Connection | What the code does |
|---|---|---|---|
| Sound sensor module | soundPin = 28 | Sensor DO → pin 28. VCC → 3.3V. GND → GND. | A sound trigger changes the digital input state. |
| External LED and resistor | ledPin = 3 | Pin 3 → resistor → LED → GND. | Each valid sound trigger toggles the LED state. |
5. Servo Sweep
#include <Servo.h>
Servo myservo;
int pos = 30;
void setup(){
myservo.attach(1);
}
void loop(){
for(pos = 30; pos <= 150; pos++){
myservo.write(pos);
delay(10);
}
for(pos = 150; pos >= 30; pos--){
myservo.write(pos);
delay(10);
}
}
Code reference: This test followed the basic Servo Sweep example.
I changed the movement range to 30°–150° for my servo test.
Reference: Arduino Servo Motor Basics.
| Component | Code Pin | Connection | What the code does |
|---|---|---|---|
| MG90S servo motor | myservo.attach(1) | Signal → pin 1. VCC → 5V. GND → shared GND. | The servo sweeps from 30° to 150° and back. |
The servo uses PWM-style control pulses. Different pulse widths move the servo to different angles.
6. Potentiometer Controlling Servo
#include <Servo.h>
Servo myservo;
const int potPin = A0;
const int servoPin = 1;
void setup(){
myservo.attach(servoPin);
}
void loop(){
int potValue = analogRead(potPin);
int angle = map(potValue,0,1023,0,180);
myservo.write(angle);
delay(20);
}
Code reference: This test followed the idea of the Arduino Servo Knob example.
I used analogRead() to read the potentiometer.
I used map() to convert the value into a servo angle.
References: Arduino Servo Motor Basics, Arduino analogRead(), and Arduino map().
| Component | Code Pin | Connection | What the code does |
|---|---|---|---|
| Potentiometer | potPin = A0 | Middle pin → A0. Side pins → 3.3V and GND. | The code reads the analog value from the potentiometer. |
| MG90S servo motor | servoPin = 1 | Signal → pin 1. VCC → 5V. GND → shared GND. | The analog value is mapped to a servo angle. |
The potentiometer gives an analog value. The code maps this value from 0–1023 to 0–180 degrees.
Reflection
This week helped me understand how embedded systems connect software and hardware. Simple programs like Blink are useful for verifying that the board works, while sensors and actuators demonstrate how the microcontroller interacts with the environment.
The most interesting part for me was combining sensors and outputs, such as the sound module toggling an LED and the potentiometer controlling a servo motor.
Code Reference and AI Use Statement
Code Reference
The final code was written and tested by myself on the XIAO RP2040. Some code structures followed official Arduino example logic. I changed the pins, wiring, and behavior for my own tests.
| Test | Main reference | How I changed it |
|---|---|---|
| Blink and external LED | Arduino Blink example | I changed the output pin and tested it on the XIAO RP2040. |
| Button input | Arduino Input Pullup Serial example | I used a momentary push button and connected it to GND. |
| Sound sensor toggle | Arduino digitalRead() and Arduino millis() | I wrote the toggle logic and added debounce timing. |
| Servo Sweep | Arduino Servo Motor Basics | I changed the servo angle range to fit my test. |
| Potentiometer Servo | Arduino Servo Knob idea, analogRead(), and map() | I connected the potentiometer to A0 and mapped the value to 0–180°. |
| XIAO RP2040 pinout | Seeed Studio XIAO RP2040 documentation | I used this to understand pinout, PWM pins, and board setup. |
The wiring, uploads, tests, and videos were completed by myself.
AI Use Statement
I used ChatGPT to help improve the documentation text and explain some concepts in simple English.
I also used AI to check whether my button input explanation, PWM explanation, and wiring tables were clear.
I did not use AI to replace the physical testing process. All hardware tests were done by myself.
Prompts Used
- Explain INPUT_PULLUP for a momentary push button in simple Fab Academy documentation text.
- Explain PWM and servo control in simple words.
- Help me rewrite my Week 04 embedded programming documentation with short English sentences.
- Help me organize component wiring tables for my XIAO RP2040 tests.