4. Embedded programming¶
-
Group assignment:
- Compare the performance and development workflows for other 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 your microcontroller
- Program a microcontroller development board to interact and communicate
Group assignment¶
Details of Group assignment can be found here.
This week we got acquainted with two types of boards: Arduino Uno and STM32F3-Discovery. Former student of Fab Academy and current instructor at Fab Lab Armenia Dilijan Onik Babajanyan helped us a lot to understand a new topic for us.
We compared these two controllers by their characteristics: ATMega328P and STM32 F303 xB or xC and compiled the following table:
Feature | ATMega328P | STM32 |
---|---|---|
Architecture | ARM Cortex-M | AVR |
Register size | 8-bits | 32-bits |
Operating conditions | 2.7 - 5.5 V | 2 - 3.6 V |
Flash memory | 32 kB | 128 - 256 kB |
SRAM | 2 kB | up to 40 kB |
Clock speed | 0 - 16 MHz at 4.5 - 5.5 V | 4 - 32 MHz |
Number of hardware timers | 3 | 2 to 20 |
Number of PWM channels | 6 | 1 to 8 |
Number of analog inputs | 6 | 10 to 24 |
Number of digital inputs/outputs | 14 | 16 to 168 |
Interfaces | SPI, I2C, USART | USB, CAN, Ethernet, SPI, I2C, USART, UART, SDIO |
The experiment aimed to compare the performance and development workflows of two microcontrollers: the ATMega328P and the STM32. The experiment tested the maximum frequency of a digital output pulse train generated by each microcontroller.
The experiment tested five different scenarios: Arduino with C++ code and library, Arduino with C code without library, Arduino with assembly code, STM32 with C code, and STM32 with assembly code.
The results showed that the STM32 was significantly more powerful than the ATMega328P, with the STM32 producing a higher frequency of 489 kHz compared to the maximum frequency of 512 kHz for the Arduino with assembly code. The Arduino with C++ code and library had the lowest frequency at 147 kHz.
Working with the Arduino Uno board¶
Installing the Arduino IDE¶
The Arduino IDE is required for programming Arduino boards. It can be downloaded from this link.
How the Arduino IDE works¶
It is designed for different operating systems.
As part of this tutorial, I decided to play around with the Arduino Uno. When the program is opened, there are two functions void setup() and void loop().
The void setup() function is executed once, that is, we can initialize variables (set variables) in it. And the void loop() function is always executed, that is, it is calculated in order to write the logic of the program in it.
Flashing built-in LED¶
The Arduino IDE itself has templates that you can use and get to know how the board works. Let’s look at one of them. To do this, go to File -> Examples -> 01.Basics -> Blink.
As a result, the following code will open
// 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
}
When the code is written, the Arduino IDE has a great ability to verify the code. That is, roughly speaking, it checks spelling errors and shows places where to fix. I will remove ”;” from the code and let’s start verification.
And if there are no errors, then Verify will tell us how much space our program takes, how much space our program can take.
After that, you need to connect the board to the computer via USB and upload the program to it by pressing the Upload button. But an error is thrown
You must specify the desired download port
After this step, you can already upload (Upload) the program to the board. And it will give the following result.
The LED named L lights up for 1 second, goes out for 1 second, and so on.
Flashing built-in LED with different intensity¶
Now, I want to make the LED blink in a certain pattern, slowing down the blinking speed. At the beginning, it should turn on for 100 milliseconds and then turn off for 100 milliseconds. Then, the delay time should increase by 100 milliseconds in each cycle, until it reaches 1000 milliseconds (1 second). To solve this task, programming languages have a wonderful loop called the for loop.
Let’s write such a loop for my task and then explain how it works.
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
for (int i = 0; i <= 10; i++) {
digitalWrite(LED_BUILTIN, HIGH);
delay(i * 100);
digitalWrite(LED_BUILTIN, LOW);
delay(i * 100);
}
}
The setup function sets the operating mode for the built-in LED (on the Arduino Uno board, this is the LED_BUILTIN pin) to signal output mode.
The loop function contains an infinite loop in which a variable i is created for the delay time when turning the LED on and off. Using the digitalWrite(LED_BUILTIN, HIGH) function, the LED is turned on for a certain amount of time, then delayed for i * 100 milliseconds. After that, the LED is turned off with the digitalWrite(LED_BUILTIN, LOW) function, and delayed again for i * 100 milliseconds. Then the loop is repeated, increasing the value of the variable i by 1 until it reaches 10. Thus, with each iteration of the loop, the delay time will increase.
And the result will be the following:
Soft on/off of an external LED (PWM)¶
And now I want to make the LED turn on and off smoothly. I asked Chat GPT to give me the code to solve this problem. Chat GPT gave me a code that I applied to PIN 13, which is connected to the LED:
int ledPin = 13; // pin for LED
int brightness = 0; // current LED brightness
int fadeAmount = 5; // brightness change rate
void setup() {
pinMode(ledPin, OUTPUT); // set pin to output
}
void loop() {
analogWrite(ledPin, brightness); // set the brightness of the LED
brightness += fadeAmount; // increase brightness
if (brightness <= 0 || brightness >= 255) { // if we reached the minimum or maximum
fadeAmount = -fadeAmount; // change the direction of brightness change
}
delay(30); // slight delay for smoothness
}
And when I uploaded the code to the board, I expected to see the LED turn on and off smoothly, but the LED on the board did not give such a result.
I contacted our instructor Babken Chugaszyan with this question, and he helped me figure this out. It turns out that this code is designed to work with PINs that have an 8-bit PWM channel. On the Arduino UNO, there are only 6 of them, which are indicated on the side with a ‘~’ symbol.
In short, Pulse Width Modulation (PWM) is a way of controlling the brightness or speed of a device, such as a motor, by varying the pulse width while maintaining a constant frequency. This method uses a digital source to create an analog signal. The PWM signal consists of two main parameters - the duty cycle, which is responsible for the duration of the pulse, and the frequency, which determines the speed at which these pulses are generated.
There is a very good article PWM in Arduino that can be viewed here.
For this code to work, you need to change the PIN number from
int ledPin = 13; // pin for LED
on the:
int ledPin = 11; // pin for LED
Pin number 11 supports PWM.
The second thing is to connect the LED with one leg to PIN11, and the other to GND. But since the supplied Arduino UNO signals are 3.3 Volts, and the LED is 2 Volts, it is necessary to connect a resistor in series to the LED, which will take on excess voltage.
After doing all these steps and uploading the code to the board, I got the following result:
Soft on/off of the built-in LED¶
But I don’t want to stop there, I want to make the LED on the Arduino UNO board turn on and off smoothly. The solution to this issue lies in the ability of the LED to turn on and off. And in the ability to do all this quickly, invisible to the eye.
It took me 2 hours to find a working code. Let’s write this code and I’ll explain how it works։
int ledPin = 13;
void setup() {
pinMode(ledPin, OUTPUT);
}
void loop() {
for (int i = 1; i <= 100; i++) {
for (int j = 1; j <= 10; j++) {
digitalWrite(ledPin, HIGH);
delayMicroseconds(i * 10);
digitalWrite(ledPin, LOW);
delayMicroseconds((100 - i) * 10);
}
}
for (int i = 100; i >= 1; i--) {
for (int j = 1; j <= 10; j++) {
digitalWrite(ledPin, HIGH);
delayMicroseconds(i * 10);
digitalWrite(ledPin, LOW);
delayMicroseconds((100 - i) * 10); /
}
}
}
In the first for loop, the duty cycle is increased from 1 to 100, which increases the brightness of the LED, and in the nested loop, the delay is set depending on the current value of the duty cycle. Then, in the second for loop, the duty cycle is reduced from 100 to 1, which lowers the brightness of the LED, and in the nested loop, the delay is set again based on the current value of the duty cycle. This allows you to create a smooth fading and flashing effect of the LED.
It turns out that this code uses PWM to change the brightness of the LED.
Let’s take a look at the result of this code:
The effect of smooth turning on and off of the built-in LED is provided.
Working with adafruit FLORA¶
In our laboratory, we also have adafruit FLORA boards. I have a desire to experiment and work with such a board.
Development environment setup¶
To program the adafruit FLORA in Arduino IDE, you need to install the Adafruit_NeoPixel library using the built-in library manager. A detailed guide for installing this library is available here. After installing this library, you will be able to upload code to the adafruit FLORA and experiment with its capabilities.
Work with built-in RGB LED¶
let’s use the code provided on the website to make the RGB LED on the board work.
You need to take the following steps:
-
Copy the code provided on the website (under the Demo Code section) and paste the code into the new sketch in the Arduino IDE.
-
Make sure the board selected in the Tools menu is set to Adafruit Flora.
-
Connect the Flora board to your computer with a USB cable.
-
Press the “Upload” button in the Arduino IDE to upload the code to the board.
The result will be as follows:
Working with external RGB LED¶
In our laboratory, there are also separate RGB LEDs from this company. To turn on the external LED let’s in the code
#define PIN 8
change the pin number to 6
#define PIN 6
After connecting the necessary cables and uploading the code to the board, we get the following result:
Working with STM32F3-Discovery board¶
To work with this type of board, you need your own development environment. It can be downloaded here. It is also easy to install. I have already installed the program, and now I need to create a new project.
As a result, a project will be created. You can see a schematic representation of the STM32 microcontroller.
In this diagram, some default microcontroller pins are already indicated, for example, from PE8 to PE15 are assigned to the LEDs located on the microcontroller.
You can also specify the assignment of free legs by selecting from the list
After all configurations are done, you need to click on Device Configuration Tool Code Generation
As a result, a system of folders with files will be generated in which variables will be created. Basically you can use the file in the following path
Core -> Src -> main.c
There is a loop while (1) in which you can write repetitive code. Since the statement in the while (1) loop brackets is always true, the code will always repeat unless it is interrupted.
We covered this point with Onik Babajanyan. He showed us how to blink board LED. In the while (1) loop, you need to write the following
while (1)
{
HAL_GPIO_WritePin(LD9_GPIO_Port,LD9_Pin, SET);
HAL_Delay(1000);
HAL_GPIO_WritePin(LD9_GPIO_Port,LD9_Pin, RESET);
HAL_Delay(1000);
}
Then the following will happen: LED 9 will light up for 1 second and then go out for 1 second and so on.
And now I want to complicate the task a little, there are 8 LEDs on the board arranged in a circle. I want opposite LEDs to light up at the same time and there was a circular motion and it happened 5 times faster. In this case, we need the following code in a while (1) loop
int time = 200;
while (1)
{
HAL_GPIO_WritePin(LD3_GPIO_Port,LD3_Pin, SET);
HAL_GPIO_WritePin(LD10_GPIO_Port,LD10_Pin, SET);
HAL_Delay(time);
HAL_GPIO_WritePin(LD3_GPIO_Port,LD3_Pin, RESET);
HAL_GPIO_WritePin(LD10_GPIO_Port,LD10_Pin, RESET);
HAL_GPIO_WritePin(LD3_GPIO_Port,LD5_Pin, SET);
HAL_GPIO_WritePin(LD10_GPIO_Port,LD8_Pin, SET);
HAL_Delay(time);
HAL_GPIO_WritePin(LD3_GPIO_Port,LD5_Pin, RESET);
HAL_GPIO_WritePin(LD10_GPIO_Port,LD8_Pin, RESET);
HAL_GPIO_WritePin(LD3_GPIO_Port,LD7_Pin, SET);
HAL_GPIO_WritePin(LD10_GPIO_Port,LD6_Pin, SET);
HAL_Delay(time);
HAL_GPIO_WritePin(LD3_GPIO_Port,LD7_Pin, RESET);
HAL_GPIO_WritePin(LD10_GPIO_Port,LD6_Pin, RESET);
HAL_GPIO_WritePin(LD3_GPIO_Port,LD9_Pin, SET);
HAL_GPIO_WritePin(LD10_GPIO_Port,LD4_Pin, SET);
HAL_Delay(time);
HAL_GPIO_WritePin(LD3_GPIO_Port,LD9_Pin, RESET);
HAL_GPIO_WritePin(LD10_GPIO_Port,LD4_Pin, RESET);
}
The following will happen
Conclusion¶
This week has been very eventful. I worked with three different types of boards: Arduino UNO, Adafruit FLORA, and STM32F3-Discovery. Programming for these boards was done in two different development environments: Arduino IDE and STM32 CubeIDE. Compared to working in the Arduino IDE, I found working in STM32 CubeIDE to be complex and confusing. However, in complex projects where a large number of pins are used, the ability to pre-configure pins can help simplify and reduce code writing time.
This week, I used code to blink LEDs on the boards in different ways. Depending on the logic written, the LEDs blinked in different patterns. I especially enjoyed delving into the topic of pins with built-in PWM capability and learning how to give digital pins PWM capability using code when the pin does not have built-in PWM capability.
Files¶
Arduino UNO
INO - Flashing built-in LED with different intensity
Adafruit FLORA
STM32F3-Discovery