6. Embedded Programming¶
Welcome to this week’s documentation focusing on embedded programming, where we delve into the fascinating world of microcontrollers by programming the Quentorres board with the Xiao SAMD21 microcontroller to display a Morse code message using both Arduino IDE and CircuitPython workflows.
Learning Outcomes:
- Implement programming protocols.
Group Assignment Summary:¶
For this week’s group assignment, our focus was on exploring microcontroller datasheets and comparing the performance and development workflows of various architectures. Here’s a brief overview of our findings:
Microcontroller Datasheet Exploration¶
We primarily focused on the Xiao SAMD21 microcontroller, which powers the Quentorres board. By analyzing the datasheets for both the microcontroller and the Quentorres board, we gained valuable insights into the hardware specifications, pin configurations, and peripheral capabilities.
Key points discovered: - The Xiao SAMD21 microcontroller features a 32-bit ARM Cortex-M0+ CPU running at up to 48MHz, with 256KB of flash memory and 32KB of SRAM. - The Quentorres board offers 11 PWM pins, 11 general digital pins, 11 analog pins, and 1 I2C interface, along with essential components like reset and user buttons, LEDs, and a USB connector.
Architectures Comparison¶
We compared the Xiao SAMD21 with other microcontrollers available in our lab, including Arduino Mega, Arduino Uno, and Raspberry Pi RP2040 Zero. Here’s a summary of our comparison:
Microcontroller | Xiao SAMD21 | Arduino Mega | Arduino Uno | Raspberry Pi RP2040 Zero |
---|---|---|---|---|
Bit Size | 32-bit | 8-bit | 8-bit | 32-bit |
Max Clock | 48MHz | 16MHz | 16MHz | 133MHz |
CPU/Family/Arch | ARM Cortex-M0+ | AVR ATMEGA2560 | AVR ATMEGA328P | ARM Cortex-M0+ |
Storage | 256KB flash/32KB SRAM | 256KB flash/8KB SRAM | 32KB flash/2KB SRAM | 2MB flash |
I/O Pins | 20 general digital, 11 PWM, 6 Analog | 54 digital, 15 analog, 15 PWM | 14 digital, 6 analog, 6 PWM | 26 digital, 3 analog |
Operating Voltage | 3.3 volts | 5 volts | 5 volts | 3.3 volts |
Connectivity | - | - | - | Bluetooth, UART, SPI, I2C, GPIO |
Price | $5 | $10 | $5 | $4 |
Source | Datasheet | Datasheet | Datasheet | Datasheet |
Observations and Pros/Cons¶
- Each microcontroller has its own strengths and weaknesses, making them suitable for different projects and applications.
- Arduino Mega offers a high number of I/O pins and ample storage space but uses an 8-bit architecture.
- Arduino Uno balances simplicity and functionality but has limited I/O pins and storage.
- Xiao SAMD21 provides a 32-bit architecture with higher clock speed and ample I/O options considering its compact size.
- Raspberry Pi RP2040 Zero offers enhanced performance and connectivity options at a competitive price.
Individual Assignment:¶
Introduction¶
This week’s individual assignment builds upon the Quentorres board, a device crafted and documented during the Electronics Production week. The Quentorres board is powered by the Xiao SAMD21 microcontroller, providing a compact yet powerful platform for embedded programming tasks. For this week’s assignment, we aim to utilize the capabilities of the Quentorres board by programming it to display a Morse code message using one of its built-in LEDs.
Objective¶
- The primary objective of this assignment is to familiarize ourselves with embedded programming concepts using the Quentorres board and the Xiao SAMD21 microcontroller. By programming the board to display a Morse code message, we aim to understand the process of interfacing with hardware, writing code to control peripherals, and translating abstract concepts into tangible output.
To achieve this objective, I will be implementing two workflows:
- Programming with Arduino IDE: Utilizing the Arduino IDE to write and upload code to the Quentorres board. This workflow provides a familiar environment for embedded programming, enabling us to leverage the vast Arduino ecosystem and libraries.
- Programming with CircuitPython: In addition to Arduino IDE, we will explore programming the Quentorres board using CircuitPython. This workflow offers a high-level programming language and simplified syntax, making it accessible for beginners while still powerful enough for advanced projects.
By exploring both workflows, we aim to gain a comprehensive understanding of embedded programming paradigms and choose the most suitable approach for our future projects.
Materials:¶
Materials required for the assignment:
- Quentorres board
- Xiao SAMD21 microcontroller
- USB cable
- Computer with Arduino IDE and CircuitPython installed
Workflow 1: Programming with Arduino IDE¶
1. Setup¶
follow steps from link
- Connect the Quentorres board to your computer using the USB cable.
- Download and open the Arduino IDE.
- Add Seeed Studio XIAO RP2040 board package to your Arduino IDE
Navigate to File > Preferences, and fill Additional Boards Manager URLs with the url below:
https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
- Select your board and port.
2. Writing Morse Code Program¶
// Pin Definitions
#define BUTTON_PIN D1 // Change to the pin you're using for the button
#define LED_PIN D0 // Change to the pin you're using for the LED
// Morse Code Definitions
const int dotDelay = 250; // Time for a dot
const int dashDelay = 3 * dotDelay; // Time for a dash
const int spaceDelay = 3 * dotDelay; // Time between letters
const int wordDelay = 7 * dotDelay; // Time between words
// Morse Code Dictionary
const char* morseCode[] = {
".-", // A
"-...", // B
"-.-.", // C
"-..", // D
".", // E
"..-.", // F
"--.", // G
"....", // H
"..", // I
".---", // J
"-.-", // K
".-..", // L
"--", // M
"-.", // N
"---", // O
".--.", // P
"--.-", // Q
".-.", // R
"...", // S
"-", // T
"..-", // U
"...-", // V
".--", // W
"-..-", // X
"-.--", // Y
"--.." // Z
};
void setup() {
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
}
void loop() {
if (digitalRead(BUTTON_PIN) == HIGH) { // Check if button is pressed
sendMessage("Naim Al Haj Ali"); // Change the message here
delay(1000); // debounce
}
}
void sendMessage(const char* message) {
for (int i = 0; message[i] != '\0'; i++) {
if (message[i] == ' ') {
delay(wordDelay);
} else {
char c = toupper(message[i]);
int index = c - 'A';
if (index >= 0 && index < 26) {
flashMorseCode(morseCode[index]);
}
delay(spaceDelay);
}
}
}
void flashMorseCode(const char* morse) {
for (int i = 0; morse[i] != '\0'; i++) {
if (morse[i] == '.') {
digitalWrite(LED_PIN, HIGH);
delay(dotDelay);
digitalWrite(LED_PIN, LOW);
} else if (morse[i] == '-') {
digitalWrite(LED_PIN, HIGH);
delay(dashDelay);
digitalWrite(LED_PIN, LOW);
}
delay(dotDelay); // Space between elements of the same letter
}
}
3. Explanation of the Code¶
- Pin Definitions: Defines the pins for the button and LED on the Quentorres board.
- Morse Code Definitions: Sets the time durations for dots, dashes, spaces between letters, and spaces between words.
- Morse Code Dictionary: Stores the Morse code representations for each letter of the alphabet.
- Setup(): Initializes the pins for input (button) and output (LED).
- loop(): Checks if the button is pressed and sends the message when it is.
- sendMessage(): Converts the specified message into Morse code and flashes the LED accordingly.
- flashMorseCode(): Flashes the LED based on the Morse code representation of a single character.
4. Uploading the Program¶
a. Select the appropriate board and port in the Arduino IDE. b. Compile and upload the program to the Quentorres board. c. Verify the functionality of the LED displaying the Morse code message.
After uploading the code and testing it, the following message is displayed in the Arduino IDE:
Sketch uses 34404 bytes (13%) of program storage space. Maximum is 262144 bytes.
This indicates that the program utilizes 13% of the available program storage space on the Quentorres board, ensuring efficient usage of resources.
5. Running the Program¶
Upon viewing the demonstration, it is evident that the Quentorres board accurately displays the Morse code for “Naim Al Haj Ali” through its built-in LED. The blinking patterns have been cross-referenced with a Morse code chart to ensure precision and correctness.
“NAIM AL HAJ ALI” in Morse code is: -. .- .. – / .- .-.. / .... .- .— / .- .-.. ..
6. Communicating With The Board¶
For this part, I chose to alter the code to communicate with the controller using the serial monitor in the Arduino IDE so that the user can input the message through the serial monitor, which would then be changed into Morse code.
Edited Morse Code Program to utilize Serial Input¶
// Pin Definitions
#define BUTTON_PIN D1 // Change to the pin you're using for the button
#define LED_PIN D0 // Change to the pin you're using for the LED
// Morse Code Definitions
const int dotDelay = 250; // Time for a dot
const int dashDelay = 3 * dotDelay; // Time for a dash
const int spaceDelay = 3 * dotDelay; // Time between letters
const int wordDelay = 7 * dotDelay; // Time between words
// Morse Code Dictionary
const char* morseCode[] = {
".-", // A
"-...", // B
"-.-.", // C
"-..", // D
".", // E
"..-.", // F
"--.", // G
"....", // H
"..", // I
".---", // J
"-.-", // K
".-..", // L
"--", // M
"-.", // N
"---", // O
".--.", // P
"--.-", // Q
".-.", // R
"...", // S
"-", // T
"..-", // U
"...-", // V
".--", // W
"-..-", // X
"-.--", // Y
"--.." // Z
};
void setup() {
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
Serial.begin(9600); // Initialize serial communication
}
void loop() {
if (Serial.available() > 0) { // Check if serial data is available
String message = Serial.readStringUntil('\n'); // Read the message from serial monitor
sendMessage(message); // Send the message in Morse code
}
}
void sendMessage(const char* message) {
for (int i = 0; message[i] != '\0'; i++) {
if (message[i] == ' ') {
delay(wordDelay);
} else {
char c = toupper(message[i]);
int index = c - 'A';
if (index >= 0 && index < 26) {
flashMorseCode(morseCode[index]);
}
delay(spaceDelay);
}
}
}
void flashMorseCode(const char* morse) {
for (int i = 0; morse[i] != '\0'; i++) {
if (morse[i] == '.') {
digitalWrite(LED_PIN, HIGH);
delay(dotDelay);
digitalWrite(LED_PIN, LOW);
} else if (morse[i] == '-') {
digitalWrite(LED_PIN, HIGH);
delay(dashDelay);
digitalWrite(LED_PIN, LOW);
}
delay(dotDelay); // Space between elements of the same letter
}
}
Explanation of the Modified Code¶
In this modified version of the code, the Arduino IDE program waits for input from the serial monitor. Once a message is received, it converts the message to Morse code and displays it using the LED. This modification enhances user interaction and allows for dynamic message display on the Quentorres board.
- Pin Definitions: Defines the pins used for the button and LED on the Quentorres board.
- Morse Code Definitions: Specifies the durations for dots, dashes, spaces between letters, and spaces between words in Morse code.
- Morse Code Dictionary: Stores the Morse code representations for each letter of the alphabet.
- Setup(): Initializes the pins for input (button) and output (LED), and begins serial communication.
- loop(): Continuously checks for serial input. When a message is received from the serial monitor, it triggers the
sendMessage()
function. - sendMessage(): Converts the received message into Morse code using the Morse code dictionary and calls
flashMorseCode()
to flash the LED accordingly. - flashMorseCode(): Flashes the LED based on the Morse code representation of a single character, with appropriate delays for dots, dashes, and inter-character spacing.
Uplading the Program¶
The program was uploaded in the same way as the previous version.
Running the Program¶
Message is inserted in the serial monitor and used as an inout for the program to run.
Workflow 2: Programming with CircuitPython¶
1. Setup¶
follow steps from link
-
Connect the Quentorres board to your computer using the USB cable.
-
Install the necessary drivers if required.
-
Download the official CircuitPython Bootloader for Seeed Studio XIAO SAMD21. A .uf2 should be downloaded.
- Entering the DFU bootloader mode by using a jumper to short connect RST Pins twice quickly.
-
An external drive named Arduino should appear in your PC. Drag the the downloaded CircuitPython uf2 files to the Arduino drive.
-
Once loaded the CircuitPython bootloader, unplug the USB Type-C and re-connect. A new external drive called CIRCUITPY should appear.
- Write you python program and name it main.py and drag it onto the CIRCUITPY drive.
I used VS Studio
- Download and Open VS Studio Code.
- Intsall Circuit Python extension.
- Open main.py and edit code.
2. Writing Morse Code Program¶
import time
import board
import digitalio
# Define button and LED pins
button_pin = board.BUTTON_A
led_pin = board.D13
# Morse Code Definitions
dot_delay = 0.25 # Time for a dot
dash_delay = 3 * dot_delay # Time for a dash
space_delay = 3 * dot_delay # Time between letters
word_delay = 7 * dot_delay # Time between words
# Morse Code Dictionary
morse_code = {
'A': '.-', 'B': '-...', 'C': '-.-.',
'D': '-..', 'E': '.', 'F': '..-.',
'G': '--.', 'H': '....', 'I': '..',
'J': '.---', 'K': '-.-', 'L': '.-..',
'M': '--', 'N': '-.', 'O': '---',
'P': '.--.', 'Q': '--.-', 'R': '.-.',
'S': '...', 'T': '-', 'U': '..-',
'V': '...-', 'W': '.--', 'X': '-..-',
'Y': '-.--', 'Z': '--..', ' ': ' '
}
# Initialize button and LED
button = digitalio.DigitalInOut(button_pin)
button.direction = digitalio.Direction.INPUT
button.pull = digitalio.Pull.UP
led = digitalio.DigitalInOut(led_pin)
led.direction = digitalio.Direction.OUTPUT
def flash_morse_code(morse):
for char in morse:
if char == '.':
led.value = True
time.sleep(dot_delay)
elif char == '-':
led.value = True
time.sleep(dash_delay)
led.value = False
time.sleep(dot_delay) # Space between elements of the same letter
def send_message(message):
for char in message:
char_upper = char.upper()
if char_upper in morse_code:
flash_morse_code(morse_code[char_upper])
time.sleep(space_delay)
else:
# If the character is not in Morse code dictionary, ignore it
pass
time.sleep(word_delay) # Wait between words
# Main loop
while True:
if not button.value: # Check if button is pressed
send_message("NAIM AL HAJ ALI") # Change the message here
time.sleep(0.5) # debounce
3. Explanation of the Code¶
- This CircuitPython code defines the button and LED pins, Morse code definitions, and initializes the button and LED.
- The
flash_morse_code()
function flashes the LED according to the Morse code patterns. - The
send_message()
function converts the message to Morse code and flashes the LED accordingly. - The main loop continuously checks if the button is pressed and sends the message “NAIM AL HAJ ALI” in Morse code when pressed.
4. Uploading the Program¶
- Select the appropriate board and port in your code editor.
- Save the CircuitPython program to the Quentorres board.
- Verify the functionality of the LED displaying the Morse code message.
5. Running the Program¶
Upon viewing the demonstration, it is evident that the Quentorres board accurately displays the Morse code for “Naim Al Haj Ali” through its built-in LED. The blinking patterns have been cross-referenced with a Morse code chart to ensure precision and correctness.
“NAIM AL HAJ ALI” in Morse code is: -. .- .. – / .- .-.. / .... .- .— / .- .-.. ..