Week 4 Embedded Programming

This week I learned the basics of embedded programming and how microcontrollers work with input, output, and communication.

Group assignment

Demonstrate and compare the toolchains and development workflows for different embedded architectures.

Individual Assignment

Exploring Xiao Rp2040

I went through the RP2040 Datasheet that provides a detailed understanding of the icrocontroller

  • Data sheet of RP2040link.
  • The chip name is based on the following naming convention:

    The following diagram represents the system architecture of the RP2040 microcontroller.

    Some of the key features of the RP2040 include:

  • Dual ARM Cortex-M0+ processor cores, up to 133 MHz
  • 264 KB of on-chip SRAM, organized into 6 banks
  • 30 multifunction GPIO pins
  • 6 dedicated I/O pins for SPI Flash (supports XIP – Execute In Place)
  • Dedicated hardware support for commonly used peripherals
  • Programmable I/O (PIO) for extended peripheral support
  • 4-channel ADC with internal temperature sensor, 500 ksps, 12-bit conversion
  • USB 1.1 Host/Device support
  • Pin Out diagram

    A "pinout diagram" is a diagram or list that shows the arrangement and function of the pins (or terminals) on an electronic component or connector, helping users understand how to connect and interact with the device. Shown below is the pinout diagram of a xiao rp2040 microcontroller.

    Each individual GPIO pin can be connected to an internal peripheral through the GPIO functions defined below. Some internal peripheral connections are available in multiple locations, providing system-level flexibility. The SIO, PIO0, and PIO1 blocks can be connected to all GPIO pins and are controlled by software (or software-controlled state machines). Therefore, they can be used to implement a wide range of functions.

    Understanding Arduino IDE and Micropython

    Micropython

    MicroPython is a lightweight version of Python designed for microcontrollers, while the Arduino IDE is a platform used for writing and uploading code to microcontroller boards, typically using C/C++. Both allow easy interaction with hardware through GPIO pins, sensors, and actuators.

    Arduino IDE

  • Arduino idelink.
  • It is a software environment for programming Arduino microcontroller boards. Arduin IDE provides an easy-to-use interface for writing, compiling, and uploading code to the board. It is widely used in hobbyist, DIY, and educational projects for electronics and robotics. It includes very helpful libraries and built-in functions to get started with a program and simplifies hardware interaction.

    Programming

    This week, I experimented with programming a microcontroller using both the Arduino IDE (C/C++) and Thonny (MicroPython).

    To understand how programming works, we began by writing a simple LED blinking program.

    Toolchain Comparison

  • Arduino IDE is best for beginners because it has many libraries and examples.
  • MicroPython is best for quick testing because you can run code fast without compiling.
  • Pico SDK is best for professional projects because it gives full control and maximum performance.
  • Trying out Arduino IDE

    Hardware Setup

    I tested the code using the Seeed Studio XIAO RP2040 with the following components:

  • xiao RP2040
  • LED
  • Resistor (220Ω)
  • Push button
  • Breadboard
  • Jumper wires
  • PC (Arduino IDE)
  • The resistor value was selected using the resistor colour code.link.
  • Why a Resistor is Needed:LEDs do not have internal resistance to limit current. So, if an LED is connected directly to a 5V supply, it may draw too much current and burn out.
  • I had to install Arduino IDE first as this was my first time using it.

    I found the Arduino IDE interface easy to understand and user-friendly. It also provides many reference libraries and built-in example codes, which makes it easier to learn and follow

    To begin programming, we need to set up a new sketch according to the board being used. Go to Tools → Board and select the correct board (in this case, the Seeed Studio XIAO RP2040). Since this board is not available by default in the Arduino IDE, we need to install the required board package using the official Board Manager URL provided on the Seeed Studio website.

    To do this, go to File → Preferences and paste the URL into Additional Boards Manager URLs, then click OK. After that, open Tools → Board → Boards Manager, search for Raspberry Pi Pico/RP2040, and install the package. Once installed, the XIAO RP2040 board becomes available for selection in the Arduino IDE.

    Experiment 01: Blink Program from Library

    I used a Seeed Studio XIAO RP2040 board and connected an external LED to it. I then used the built-in example code to blink the LED..

    Board Pinout

  • LED → D2
  • Resistor value (1Ω)
  • GND connections
  • connection diagram

    Code

    /*
      Blink
    
      Turns an LED on for one second, then off for one second, repeatedly.
    
      Most Arduinos have an on-board LED you can control. On the UNO, MEGA and ZERO
      it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN is set to
      the correct LED pin independent of which board is used.
      If you want to know what pin the on-board LED is connected to on your Arduino
      model, check the Technical Specs of your board at:
      https://docs.arduino.cc/hardware/
    
      modified 8 May 2014
      by Scott Fitzgerald
      modified 2 Sep 2016
      by Arturo Guadalupi
      modified 8 Sep 2016
      by Colby Newman
    
      This example code is in the public domain.
    
      https://docs.arduino.cc/built-in-examples/basics/Blink/
    */
    
    // the setup function runs once when you press reset or power the board
    void setup() {
      // initialize digital pin LED_BUILTIN as an output.
      pinMode(LED_BUILTIN, OUTPUT);
    }
    
    // the loop function runs over and over again forever
    void loop() {
      digitalWrite(LED_BUILTIN, HIGH);  // turn the LED on (HIGH is the voltage level)
      delay(1000);                      // wait for a second
      digitalWrite(LED_BUILTIN, LOW);   // turn the LED off by making the voltage LOW
      delay(1000);                      // wait for a second
    }
    

    After writing the code, click the tick (✓) button to compile and verify the sketch. Once the compilation is successful, click the arrow (→) Upload button to upload the program to the board.

    Experiment 02: Aeroplane Blink (RP2040)

    This was my second trial using the RP2040, where I implemented an aeroplane-style LED blinking pattern.

    #define LED_PIN 2
    
    void setup() {
      pinMode(LED_PIN, OUTPUT);
    }
    
    void loop() {
      // Flash flash (like airplane)
      digitalWrite(LED_PIN, HIGH);
      delay(100);
      digitalWrite(LED_PIN, LOW);
      delay(100);
    
      digitalWrite(LED_PIN, HIGH);
      delay(100);
      digitalWrite(LED_PIN, LOW);
      delay(700);  // long gap before repeating
    }
    

    The aeroplane blink output was very satisfying and relaxing to watch. I also experimented by changing the delay values to adjust the blinking speed and pattern.

    Experiment 03 – LED Chaser (RP2040)

    This was my third trial on the RP2040. In this experiment, I programmed five LEDs to blink continuously in a sequence, similar to party lights.

    int leds[] = {2, 3, 4, 5, 6};
    
    void setup() {
      for (int i = 0; i < 5; i++) {
        pinMode(leds[i], OUTPUT);
      }
    }
    
    void loop() {
      for (int i = 0; i < 5; i++) {
        digitalWrite(leds[i], HIGH);
        delay(150);
        digitalWrite(leds[i], LOW);
      }
    }
    

    Experiment 04: LED Display Output Test

    Components Required
    Main Parts
  • Seeed Studio XIAO RP2040
  • OLED Display (I2C) (Usually 0.96 inch SSD1306, 128×64)
  • Connection Items
  • Jumper wires (4 wires)
  • USB Type-C cable (to power + upload code)
  • Breadboard (if you want neat wiring)
  • Connection diagram

    link.

    In this experiment, I tested an LED display using the RP2040. The results were really cool, and I got a wonderful output. I recorded this output using a HeroShot video

    #include 
    #include 
     
    #ifdef U8X8_HAVE_HW_SPI
    #include 
    #endif
    #ifdef U8X8_HAVE_HW_I2C
    #include 
    #endif
    
    U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
     
    void setup(void) {
      Wire.begin();
      u8g2.begin();
    }
     
    void loop(void) {
      u8g2.clearBuffer();                   // clear the internal memory
      u8g2.setFont(u8g2_font_ncenB08_tr);   // choose a suitable font
      u8g2.drawStr(0,10,"ALI  AG. HERE");    // write something to the internal memory
      u8g2.drawStr(0,30,"FROM"); 
      u8g2.drawStr(0,50,"FABLAB KOCHI!"); 
      u8g2.sendBuffer();                    // transfer internal memory to the display
      delay(1000);  
    }
    

    HERO SHOT

    Experiment 05: Push Button with Serial Monitor Output

    push circut diagram
    Components Required
  • XIAO RP2040
  • Push button (tactile switch)
  • Breadboard
  • Jumper wires
  • USB cable (for power + upload)
  • In this experiment, I interfaced a push button with the Seeed Studio XIAO RP2040 and displayed the button status on the Serial Monitor. Whenever the button was pressed, the microcontroller detected the input and printed the output message through serial communication.

    code
    #define BTN D1      // D1
    #define LED D2      // D2
    
    bool lastState = HIGH;
    
    void setup() {
      pinMode(BTN, INPUT_PULLUP);
      pinMode(LED, OUTPUT);
    
      Serial.begin(115200);
      delay(1000);
    
      Serial.println("Serial Monitor Started!");
      Serial.println("Press the button to toggle LED.");
    }
    
    void loop() {
      bool currentState = digitalRead(BTN);
    
      // Detect button press (HIGH -> LOW)
      if (lastState == HIGH && currentState == LOW) {
        Serial.println("Button Pressed!");
    
        // Toggle LED
        digitalWrite(LED, !digitalRead(LED));
    
        if (digitalRead(LED) == HIGH) {
          Serial.println("LED ON");
        } else {
          Serial.println("LED OFF");
        }
    
        delay(200); // small debounce
      }
    
      lastState = currentState;
    }
    

    Testing MicroPython in Thonny

  • Thonnylink.
  • This was the second software I used this week: Thonny, for programming the RP2040 using MicroPython.

    Experiment 01: RGB Rainbow Effect

    In the Thonny interface, go to Tools → Options to open the settings.

    Select the Interpreter tab and set the device to MicroPython (Raspberry Pi Pico). Then choose the port option “Try to detect port automatically.”

    Connect Seeed Studio XIAO RP2040 to the PC and Light It Up

    Step 1: Press and hold the BOOT button, then connect the Seeed Studio XIAO RP2040 to the PC using a Type-C cable. If the connection is successful, a new drive named “RPI-RP2” will appear on the computer.

    Step 2: Click Install or update MicroPython. Thonny will automatically detect the connected device and display it under Target Volume. In the MicroPython version selection below, we can leave it as the default option.

    Click the Install button and wait until the installation status shows Done. After that, close the window. Once the firmware installation is complete, the following information will appear in the Thonny interface.

    Step 4: Upload and run the code by clicking the “Run current script” button. The first time you run a program, Thonny will ask where you want to save the script file. You can choose either This Computer or Raspberry Pi Pico. If everything is working correctly, the onboard LED will blink on and off once per second. At the same time, an increasing number will be displayed in the Shell as output.

    The connection is commplete and now we can proceed to the other projects.

    import array, time
    from machine import Pin
    import rp2
    
    # Configure the number of WS2812 LEDs.
    #brightness = 0.2
    @rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True,pull_thresh=24)
    def ws2812():
        T1 = 2
        T2 = 5
        T3 = 3
        wrap_target()
        label("bitloop")
        out(x, 1) .side(0) [T3 - 1]
        jmp(not_x, "do_zero") .side(1) [T1 - 1]
        jmp("bitloop") .side(1) [T2 - 1]
        label("do_zero")
        nop() .side(0) [T2 - 1]
        wrap()
    class WS2812():        
        def __init__(self, pin_num, led_count, brightness = 0.5):
            self.Pin = Pin
            self.led_count = led_count
            self.brightness = brightness
            self.sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=Pin(pin_num))
            self.sm.active(1)
            self.ar = array.array("I", [0 for _ in range(led_count)])
            
        def pixels_show(self):
            dimmer_ar = array.array("I", [0 for _ in range(self.led_count)])
            for i,c in enumerate(self.ar):
                r = int(((c >> 8) & 0xFF) * self.brightness)
                g = int(((c >> 16) & 0xFF) * self.brightness)
                b = int((c & 0xFF) * self.brightness)
                dimmer_ar[i] = (g<<16) + (r<<8) + b
            self.sm.put(dimmer_ar, 8)
            time.sleep_ms(10)
    
        def pixels_set(self, i, color):
            self.ar[i] = (color[1]<<16) + (color[0]<<8) + color[2]
    
        def pixels_fill(self, color):
            for i in range(len(self.ar)):
                self.pixels_set(i, color)
    
        def color_chase(self,color, wait):
            for i in range(self.led_count):
                self.pixels_set(i, color)
                time.sleep(wait)
                self.pixels_show()
            time.sleep(0.2)
        def wheel(self, pos):
        # Input a value 0 to 255 to get a color value.
        # The colours are a transition r - g - b - back to r.
            if pos < 0 or pos > 255:
                return (0, 0, 0)
            if pos < 85:
                return (255 - pos * 3, pos * 3, 0)
            if pos < 170:
                pos -= 85
                return (0, 255 - pos * 3, pos * 3)
            pos -= 170
            return (pos * 3, 0, 255 - pos * 3)
    
    
        def rainbow_cycle(self, wait):
            for j in range(255):
                for i in range(self.led_count):
                    rc_index = (i * 256 // self.led_count) + j
                    self.pixels_set(i, self.wheel(rc_index & 255))
                self.pixels_show()
                time.sleep(wait)
    
    
    

    By saving the code in .py format and running it in Thonny, I was able to see the output directly in the Shell. This is how I completed my first experiment using MicroPython.

    For my final project development, I prefer to continue using the Arduino IDE, because it feels more structured for building complete projects. At the same time, MicroPython is also useful for quick testing and learning, and both platforms provide many examples and resources to explore

    what i learned in week04

    In Week 04, I learned the basics of embedded programming and how to control real hardware using code. I understood how microcontrollers work, how GPIO pins behave as real HIGH/LOW electrical signals, and how small hardware mistakes can affect the output.

    I worked with two toolchains:

  • Arduino IDE (C/C++) for compiling and uploading firmware
  • Thonny (MicroPython) for running scripts interactively
  • By the end of the week, I learned how to read a datasheet, understand pin mapping, build breadboard circuits, use resistors correctly, control LEDs (blink, aeroplane blink, chaser light), and use a push button with Serial Monitor output

    Useful links

  • Blink
  • References

  • RP2040 Data sheetlink.
  • Arduino idelink.
  • Thonnylink.
  • Seeed Studiolink.