Week 4 : Embedded Programming

Overview

Group Assignment

Group assignment: Demonstrate and compare the toolchains and development workflows for available embedded architectures Document your work to the group work page and reflect on your individual page what you learned

Individual Assignment

Browse through the datasheet for a microcontroller Write and test a program for an embedded system using a microcontroller to interact (with local input &/or output devices) and communicate (with remote wired or wireless connections)

Research

What is architecture in electronics?

In the context of microcontrollers, architecture is the "blueprint" of how the chip's internal brain is wired. It defines how the CPU (core processing unit), memory, and peripherals talk to each other and how the chip executes those instructions.

For this week's assignment, I am comparing two distinct types of architecture (blueprints): AVR and ARM (i'll describe more later)

First, there are a few important things to consider within the blueprint.

  1. Bit Width (8-bit vs 32-bit): This is the size of the "data highway" inside the chip.
  2. Instruction Set: The lamguage and instructions being carried. In my case, both of my chips are RISC (Reduced Instruction Set Computer), but they speak different "languages" (I'll describe this later).
  3. Memory Layout (Harvard vs Von Neumann): This defines how the chip stores and accesses its "to-do list" (code) versus its "work bench" (data).
  4. Register Sets: Think of registers as the chip's "short-term memory" where it holds the values it is currently working on.

I decided to explore two MCU families: ARM and AVR. Next I'll explain their architecture:

AVR architecture:
  1. Bit Width: The bit Width is 8 bit. The CPU processes data in 8-bit chunks (from 0 to 255). If someone is trying to program a large math calculation for example, the CPU has to break it into pretty small pieces which means this is pretty slow but very power efficient for simple tasks.
  2. Instruction Set: As stated above, the AVR chip is RISC; however, the AVR chip speaks a language that uses proprietary instruction sets owned by Microchip. Its designed such that almost every instruction takes exactly one clock cycle, making timing extremely predictable.
  3. Memory Layout: Harvard memory layout phycically seperates paths for instructions and data. Basically, the chip can read and fetch data simultaniously which prevents bottlenecking.
  4. Register Sets: AVR has 32 general use registers
ARM architecture:
  1. Bit Width:The highway for an ARM chip is a LOT wider than an AVR and processes a LOT faster. 32-bit chunks with numbers up to 4 billlion can be processed at a time. It can handle pretty complex tasks quickly (for example, running a Python interpreter)
  2. Instruction Set:ARM licenses the Cortex-M language to other companies who then build the physical hardware around it.
  3. Memory Layout:The Von Neumann matrix is complex where everything lives in one giant map which allows for more flexability. For example, the chip can run code directly out of RAM for extra speed if needed.
  4. Register Sets: AVR is equipt with 13-16 different set of registers that are a lot wider, ARM chips are able to handle the 32 bit numbers more easily.

Comparing toolchains and Development Workflows

I am a remote student and will have to complete the group assignment on my own. I currently have an Adafruit Metro and FabriXiao (from the Czech Republic and my Fabricademy course) available on hand for comparisons. I am concerned about the use of my FabriXiao as I used it heavily in the workshop I attended at FAB 25 in the Czech Republic and also used it extensively during my time as a student in the 2025/2026 Fabricademy course. I hope that I will be able to program and utilize it for this project as well, otherwise, I will need to source another chip. The FabriXiao utilizes the Seeed Studio XIAO-RP2040 board.

I decided to source another chip, I purchased a Xiao RP2040 and will us it below in my comparissons.

I analyzed and compared the toolchains, development workflows, and electrical differences between my available embedded architectures. Specifically, I contrasted the Seeed Studio XIAO RP2040 (running MicroPython via Thonny IDE) with the Adafruit Metro 328 (running C++ via Arduino IDE).

Microcontroller Specs Comparissons

Hardware Feature Seeed Studio Xiao RP2040 Adafruit Metro 328 (ATmega328)
Processor Architecture 32-bit Dual ARM Cortex-M0+ 8-bit AVR RISC
Max Clock Speed 133 MHz 16 MHz
On-Chip SRAM 264 KB 2 KB
Flash Memory 2 MB (External QSPI) 32 KB
Operating Voltage 3.3V 5.0V
Form Factor Style Ultra-compact SMT / Castellated Classic Arduino UNO Revision-3 Footprint
Native Python Runtime Yes(MicroPython / CircuitPython) No(Insufficient SRAM footprint)
Primary Toolchain Thonny IDE / VS Code (PlatformIO) Arduino IDE (C++)
Upload Mechanism Mass Storage (UF2 drag-and-drop via Native USB) USB-to-Serial (Optiboot Bootloader via CP2104 / CH340 chip)
Unique Hardware Blocks Programmable I/O (PIO Blocks) Direct high-current I/O pin drive capabilities (up to 40mA)

Toolchain & Workflow Comparissons

Board Compilation vs. Interpretation Voltage and Electrical Safety Bootloader Triggering
Xiao RP 2040 The Thonny toolchain sends my raw .py text script directly to an active, on-chip Python interpreter. Operates strictly on 3.3V logic (PLEASE view the safety update under this table) Requires holding a physical "BOOT" button while connecting USB to accept a new file system runtime
Adafruit Metro 328 (ATmega328) Requires C++ code to be compiled into a static binary image on my computer before upload. Operates on 5V logic Utilizes an automated onboard USB-to-UART bridge to auto-reset and flash code instantly when hitting "Upload".
A note and update on the table above learned during the System Integraton weekly review: I chose to change my board for my final project from a RP2040 to a RP2350 because of voltage and electrical safety concersn related to the RP2040. The RP2040 can be completely destroyed by electrical faults. To understand these more fully please visit this link: Xiao Charging Situation

Microcontroller Implementation

Microcontroller Exploration & Datasheet Review

I reviewed the official Raspberry Pi RP2040 datasheet to verify how its registers map to the physical layout of the Seeed Studio XIAO footprint.

Core Architectural Features

  1. Processor Core:32-bit Dual-core ARM Cortex-M0+ processing at a native clock speed of 133MHz.
  2. On-Chip Memory:264KB of embedded SRAM divided into six independent banks. This provides the massive memory headroom required to host an on-chip Python runtime interpreter layer.
  3. Storage Execution:2MB of external Flash memory mapped through a high-speed QSPI interface cache block.

Hardware Registers & GPIO Control

  1. SIO Registers: The Single-cycle IO (SIO) block manages high-speed pin manipulation. The GPIO_OUT register drives logic states, and the GPIO_IN register samples incoming voltages.
  2. Direction Registers:The GPIO_OE (Output Enable) register controls whether a pin buffer drives an output or listens as an input.
  3. Pad Control:Individual internal registers handle pull-up or pull-down configuration, allowing me to enable software-defined resistors without hardware modifications.

System Hardware Configuration

I configured a local input device, local output device, and telemetry communication connection using the XIAO RP2040 Pinout Map:

Fusuon360Design
XIAO Pinout Map
Fusuon360Design
XIAO Map Further Described

  1. Local Input Device:A tactile push button wired between physical board pin D2 (which maps directly to chip pin GPIO 28) and Ground (GND).
  2. Local Output Device:The onboard green user indicator LED. According to the schematic, this is mapped internally to chip pin GPIO 25.
  3. Communication Interface:A Virtual Serial COM Port tunnel over the native USB-C line utilizing the standard output stream pipeline (sys.stdout).

Code Example | LED Output Signaling

I wrote a custom MicroPython script that translates the word "SAVED" into rhythmic Morse code signals using the onboard green indicator LED. This serves as a functional confirmation system for my final project to show when data has been successfully written to memory. Since the onboard LEDs are wired in an active-low configuration, the code drops the pin voltage low to turn the LED on and pulls it high to turn it off. It handles nested character loops, timing intervals, and live telemetry outputs concurrently

    # Fab Academy Individual Assignment - Morse Code Telemetry
    # Target Hardware: Seeed Studio XIAO RP2040
    # Language: MicroPython
    
    import machine
    import time
    import sys
    
    # Configure onboard Green LED pin (GPIO 25) as a digital output
    led = machine.Pin(25, machine.Pin.OUT)
    
    # Define precise Morse Code timing units (in seconds)
    DOT_DURATION  = 0.15   # Base time unit
    DASH_DURATION = 0.45   # 3x Dot duration
    ELEMENT_GAP   = 0.15   # Gap between dots and dashes within a letter
    LETTER_GAP    = 0.45   # Gap between letters
    WORD_GAP      = 1.00   # Pause before repeating the word
    
    # Morse Code dictionary structure for the word "SAVED"
    MORSE_WORD = {
        'S': ['.', '.', '.'],
        'A': ['.', '-'],
        'V': ['.', '.', '.', '-'],
        'E': ['.'],
        'D': ['-', '.', '.']
    }
    
    print("--- System Status: Telemetry Saved. Broadcasting Morse Confirmation ---")
    
    while True:
        # Iterate through each letter in the target string sequence
        for letter, sequence in MORSE_WORD.items():
            sys.stdout.write(f"Sending Letter: {letter} | ")
            
            # Iterate through the individual dots and dashes making up the letter
            for element in sequence:
                if element == '.':
                    sys.stdout.write(".")
                    led.value(0)  # Active-Low: LOW turns LED ON
                    time.sleep(DOT_DURATION)
                elif element == '-':
                    sys.stdout.write("-")
                    led.value(0)  # Active-Low: LOW turns LED ON
                    time.sleep(DASH_DURATION)
                
                led.value(1)      # Active-Low: HIGH turns LED OFF
                time.sleep(ELEMENT_GAP)
                
            sys.stdout.write("\n")
            time.sleep(LETTER_GAP) # Structural pause between individual characters
            
        print("--- Word Complete: Data Saved Securely ---")
        time.sleep(WORD_GAP) # Main loop pause before recycling the alert sequence
  

Terminal Console Output Verification

                  --- Thonny Interactive REPL Output ---
          --- System Status: Telemetry Saved. Broadcasting Morse Confirmation ---
          Sending Letter: S | ...
          Sending Letter: A | .-
          Sending Letter: V | ...-
          Sending Letter: E | .
          Sending Letter: D | -..
          --- Word Complete: Data Saved Securely ---
      
Fusuon360Design
Output Verification

Gallery

Electronic Schematics Interactive Wildcat

Video | I will insert video of the functioning circuit soon.

From Vimeo

Sound Waves from George Gally (Radarboy) on Vimeo.


From Youtube