4. Embedded Programming

This week's assignment tasks are listed below:

  1. group assignment:
    • demonstrate and compare the toolchains and development workflows for available embedded architectures
  2. individual assignment:

Work Plan

Img: Week 4 Work Plan

Group Assignment

4.1. Comparing Toolchains and Development Workflows of Different Computer Architectures.

We learnt about different toolchains of different microcontrollers from different computer architectures. Along with that we compared our results to Rasberry Pi also, which is a full fledged computer rather than a microcontroller.


Toolchains and Development Workflows of different Microcontrollers and Rasberry Pi

For more information, read our group assignment.

Individual Assignment

4.2. Browse through the Data Sheet for your Microcontroller

The official datasheet for the RP2040 has been linked here.

Img: Coverpage of documentation
RP2040 official datasheet from Rasberry Pi

Name of the Chip: RP2040

Name of the chip
Source: Pg 9 of the data sheet

The chip is called RP2040. It is called so because

Speed: 133MHz

The dual cores can run upto 133 MHz. It has two phase-locked loops (PLLs) that provide a fixed 48MHz clock for USB or for Analog Digital Converter (ADC) , and a flexible system clock up to 133MHz for high power applications.

Memory: 264 kB SRAM & no onboard flash memory

The RP2040 has 264 kB of embedded Static Random Access Memory (SRAM; a type of volatile memory) for temporary memory storage and 0B for flash memory (permanent storage; a type of non-volatile memory)

Pins: 36 GPIO Pins, out of which 30 are digital I/O Pins, which also include 4 Pins that can accept both digital and analogue input.

Among the GPIO pins, GPIO 0-25 accept accept digital inputs, whereas GPIO 26-29 can accept both analogue and digital signal input and output digital signals.

Datasheet RP2040 pinout
RP2040 QFN-56 package pinout

Communication protocols supported: UART, I2C, and SPI

Img: DatasheetRP2040Communication
Source: pg 235 in data sheet

Analog to Digital Converter: The RP2040 has an internal ADC.

It has 5 inputs. 4 inputs are available on the pins shared with GPIO (GPIO 26-29), while one input is connected to an internal temperature sensor

Img: Datasheet of RP2040 with ADC
Source: pg 556 in the data sheet

Operating and Logic Voltage: 1.8 to 3.3 V (preferrably 3.3 V)

Along with the previous datasheet, I refered another datasheet from Rasberry Pi called 'Hardware design with RP2040', which states that the RP240 requires 3.3V


Source: pg 7 in Hardware design with RP2040

Source: pg 151 in the official data sheet

Based on this Reddit post a logic voltage of x means that the microcontroller will read a value equal to or close to x as 1 or digital HIGH and any value close to zero Volts as 0 or digital LOW. Hence the logic voltage of the RP2040 is also 3.3V

Maximum Tolerable Current and Voltage: 3.83V and 100 mA

Img: Max Voltage
pg 613 in the official datasheet
Img: Max Current
pg 160 in the official datasheet

4.3. Writing a Program for your Microcontroller

Controlling an LED using a Button using a Rasberry Pi Pico

Once I learnt the basic syntax with the help of examples from our instructors, I wrote a simple piece of code written in Mycropython using a Rasberry Pico development board (includes RP2040 chip) to control the LED using a button, using an example Blink program

First we import the required modules. Because we only need to import specific objects, ie. 'Pin' class from 'machine' & 'sleep' function from 'time' we only import using the commmand: from x import y

Then we name a variable led where we state that Pin 0 wil be an OUTPUT Pin, meaning an voltage will be sent to it, which will be used to light up the LED.

We also name a second variable named button which is connected to pin 2 on the Rasberry Pi Pico. We set it as an INPUT pin, meaning it will take voltage readings from the push button. Additionally, using the PIN.PULL_UP method, we set pin to a default 'HIGH' state until the button is pressed.

To make neat connections I used a breadboard, added the components to make an electrical circuit. The following image shows how they are connected internally

Source: How to connect a circuit on a breadboard by EMT laboratories

I have previously tinkered with simple circuits in the past so I knew how to connect simple devices like LEDs and switch buttons. Since an LED is a diode, it cannot be connected in any manner. The Anode (A) is the bent end that should be connected to the digital I/O pins and the Cathode (C) should be connected to the ground (GND) pin. Also, a 1K resistor should be connected in series with the LED to stop it from drawing too much current.

Once I have placed all the components, I then connect all the devices using wires. You can see which are the GND pins by hovering on top of the board.

I added a While True:statement to add a loop that goes on infinitely

Make sure to check the file type! When testing the Micropython script will not work in a sketch.ino file. It should be a main.py file

To test the button values, I added a Serial output using the command print(button.value()). But when running, nothing showed up on the console. I tried commenting different parts of the code to see if an LED lights up using the command led.value(1) but it did not work

In situations like this, I take a break and come back to the problem with a fresh mind.

And it worked! I realized my error was that I did not connect my resistor to the circuit.Once I changed this, the code started working and the LED starting lighting up

But when I uncommented all the code lines, the code again did not work.

I decided to use the commenting approach again to understand where the problem was, and found out it was a problem with the statement about declaring the variable button

I knew it was a problem with the PIN.PULL_UP command since it was the code was running without it, even though you would then run into issues with sreading the correct button state due to the problem with floating values

I then realized that I used the wrong syntax PIN instead of Pin while writing the command Pin.PULL_UP.

Once I corrected it, the code is now running

Inside the While Trueloop I added an if statement stating that if the button value is 0 (the 'ON' state) using the if button.value()==0. The == operator means to see if 'check if x = y'. If it satisfies that condition, it then goes inside the if code block and switches on the LED using the command led.value()=1.We then add a delay of 1 second using the sleep(1)command. We then repeat the same process for when the button is OFF

But the code did not work again

With the help of my instructor, the error was resolved when the indentation was corrected

The code is now running.

I now added a Serial Output using the print command to state when the LED is on and when it is OFF and commented the print(button.value()) As long as the button is pressed, the LED will remain ON and a message confirming the same will be displayed in the terminal. When the button is not pressed, the LED remains OFF which is also confirmed by another message in the terminal.

The following is the code I wrote:

  
                        from machine import Pin
                        from utime import sleep

                        led = Pin(0, Pin.OUT)
                        button = Pin(2,Pin.IN,Pin.PULL_UP)

                        while True:
                            # print(button.value())
                            if button.value()==0: #Button not pressed
                                led.value(1) #led remains 'ON'
                                print ("LED is ON")
                                sleep(1)
                            # Repeat for when button is pressed
                            if button.value()==1: #Button not pressed
                                led.value(0) #led remains 'OFF'
                                print ("LED is OFF")
                                sleep(1) #Add delay for 1
                    

LED Blink using a PIO in the Rasberry Pi Pico

A PIO (Programmable Input/Output) is a programmable piece of hardware that can be customized to perform high speed but non-complex programming tasks in the background independant of the cores, which means the main processor core is free to take on more tasks that take more computing power.

They are especially useful for communicating with serial devices with no hardware support, for pulse width modulation, etc. To know more check this web article that provides an overview of what a PIO is and its potential usefullness.

The RP2040 has two identical PIOs, each containing 4 state machines that share memory, ie. you can send 32 'words' or instructions to it a time.

Img:Datasheet with RP2040
PIO; Source: pg310 in the official datasheet
State Machine; Source pg 310 in the official datasheet

Programming: Each instruction is written in one clock cycle, ie., 32 instructions can be sent in 32 clock cycle. This frequency can be adjusted to adjust the clock cycle, like I have done in my program.

I used the Digikey tutorial to program using the PIO, along with referring to the RP2040 Datasheet and Raspberry Pi Pico-series Python SDK documentation for reference.


Source: 'Raspberry Pi Pico and RP2040 - MicroPython Part 3: PIO' by Digikey

Source: pg 310 in 'RP2040 Datasheet'

Source: pg 19 in 'Raspberry Pi Pico-series Python SDK'

I also used ChatGPT to simplify the meanings of many of the technical terms that were being used in the tutorial and documentation. List of all prompts used have been added (check References)

This is the github documentation that describes how each insruction is programmed.

In Wokwi simulation

This is the code for the same

                        import rp2
                        from machine import Pin
                        import utime

                        @rp2.asm_pio(set_init=(rp2.PIO.OUT_LOW))
                        def blink ():
                            wrap_target()
                            set(pins,1) [31]
                            nop() [31]
                            nop() [31]
                            nop() [31]
                            nop() [31]
                            #160 cycles
                            set (pins,10) [31]
                            nop() [31]
                            nop() [31]
                            nop() [31]
                            nop() [31]
                            wrap()
                        
                        sm = rp2.StateMachine(0,blink,freq=2000,set_base=machine.Pin(25))

                        while True:
                            print("State machine starting...")
                            sm.active(1)
                            utime.sleep(1)
                            print("State machine stopping...")
                            sm.active(0)
                            utime.sleep(1)
                    

Testing it on on a development board

I tested my code in a development board called Seeed Xiao RP2040

Try different languages &/or development environments

I used ATtiny 1614 and Arduino IDE and UPDI tool chain to make an LED blink.

This is the code I used for the same:

                    #define LED 10

                    void setup(){
                    pinMode(LED,OUTPUT);
                    }

                    void loop(){
                    digitalWrite(LED,HIGH);
                    delay(1000);
                    digitalWrite(LED,LOW);
                    delay(1000);
                    }
                

More information can be found in the group assignment.

Using the STM32 microcontroller

This time I wanted to do something more relevant to my final project. Since I was already familiar programming in C++ with the Arduino IDE and based on a suggestion by my instructor Sibin, I chose to simulate a program in the NUCLEO-C031C6

Based on the databrief of the STM32 Nucleo-64 development board & the datasheet of the STM32C031C6 microcontroller.

When I was facing some difficulty finding all required information, my instructor told me to use STM32CUbeMX software, which is a graphical tool normally used to configure STM32 microntrollers and microprocessors.

Pins for SWD debugging

I used it here to find other information that I was not able to get easily from the datasheet, for eg: the pins for SWD debugging.

Conclusion

This week I learnt the following:

References

  1. Week 4 Group Assignment: Comparing Toolchains and Development Workflows of Different Computer Architectures.
  2. Offical datasheet for RP2040 by Rasberry Pi
  3. Abouts CPU Cores
  4. About the ARM Cortex-M0+ processor
  5. Wikipedia article on the ARM architecture family
  6. Wikipedia article explaining the floor function
  7. Wikipedia article explaining flash memory.
  8. "Raspberry Pi Pico Getting Started Tutorial with MicroPython" Tutorial by Yusro explaining the significance of each of the digits in the name of the chip RP2040
  9. Phased-locked loop by Wikipedia
  10. What is Analog to Digital Converter & Its Working by elprocus.com
  11. An article on Static Random Access Memory by Unacademy
  12. The Ultimate Guide to QFN Package by anysilicon.com
  13. Hardware design with RP2040
  14. What is the logic level voltage of the Arduino microcontroller? by a Reddit user
  15. 'Getting Started with Seeed Studio XIAO RP2040' by Seeed Studio
  16. 'What is PIO?' by Rasberry Pi
  17. RP2040 Datasheet
  18. Raspberry Pi Pico-series Python SDK
  19. Github documentation for the rp2 module, used to program the PIO in RP2040

  20. AI: ChatGPT prompts
    What is a PIO in RP2040
    What are state machines
    Explain what @rp2.asm_pio(set_init=rp2.PIO.OUT_LOW) means
    Explain wrap_target
    Explain the concept in a manner that a person with no understanding of programming can understand
    What do you mean by 32 instructions in state machines
    Are 32 instructions 32 bits?
    What is a bit
    What is a byte

Design Files

  1. Design Files: Week 4 Embedded Programming Wokwi and Arduino IDE code files