Skip to content

Biomedical-Electronics/prrr

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

IDE Preparation and digital outputs

If you need to review the previous lesson, you can find it here: Hello, World!

IDE preparation

Installing Arduino IDE

The first step is to install the application used to develop Arduino-based programs: Arduino IDE. The acronym IDE stands for Integrated Development Environment. An IDE is an application that provides the necessary tools to develop, compile, deploy, and debug software. To install it, we start by downloading the application from the following link. We want to download Arduino IDE 2, neither Arduino Lab nor other application.

Note

The application is available for multiple Operating Systems (OS). The exercises can be performed on all OSs compatible with the application, but the details of their development, as well as the guarantee of correct functionality, will be based on Windows. Specifically, Windows 11.

Installing Arduino IDE is as simple as running the downloaded .exe file and following the mathematical algorithm Next, Next, Next, ..., and Finish. Detailed instructions on how to click through the different Next steps can be found at this link.

EVB Configuration

Once installed, Arduino IDE can program its own EVBs: Arduino UNO, Arduino Zero, Arduino Due, among others. However, the EVB we will use is a board from STMicroelectronics (STM): the STM32 Nucleo-F401RE. This EVB is compatible with Arduino, but since it is not marketed by the Arduino company, its configuration files need to be imported into the IDE. Fortunately for us, importing the configuration files into Arduino IDE is very easy, and STM provides official configuration files for its EVBs.

The procedure to import the configuration files can be found in one of the repositories of STM's official GitHub account, available at the following link. Just follow the linked step. Do not follow the extra step indicated in the guideline.

The STM32 Nucleo-F401RE EVB

As mentioned earlier, the EVB we will use is the STM32 Nucleo-F401RE from STMicroelectronics. This EVB features the STM32F401RET6U microcontroller from the same manufacturer.

One of the key advantages of EVBs is that they provide a quick and cost-effective way to prototype microcontroller-based devices. For example, the STM32 Nucleo-F401RE has a current retail price of around €15 and already includes an integrated debugger (the electronic circuit required to program the microcontroller). A standalone official debugger alone can cost over €100.

Manufacturers create these EVBs to facilitate entry into their development ecosystem at a low cost, ultimately encouraging developers to adopt their microcontrollers. Another advantage is that the EVB exposes all the microcontroller's pins, making it easier to connect external components during the prototyping phase and eliminating the need to design custom prototype boards—saving significant costs in design, components, manufacturing, and testing.

Below is an image of the EVB we will use.

The schematic of the EVB can be found here. Three other important documents, which we will not yet use in this Arduino practice, are: the microcontroller datasheet, the reference manual for the microcontroller family, and the user manual for the HAL (Hardware Abstraction Layer) libraries.

Now, Let's Say: Hello, World!

Cloning the Repository

In this and all other course practices, a Version Control System (VCS) is used for development, collaboration, and submission of assignments and projects. The details of how VCS works will be gradually introduced in each practice. For now, I ask for a small leap of faith—just follow the Git instructions carefully. We will explain the commands and terms as they appear.

Since this is the first lab session, if you haven't done so already, we will go through the process of cloning the remote repository from GitHub to our computer. This means having a local copy of all the content stored in GitHub and establishing a link to the remote repository. This link will allow us to retrieve versions and branches hosted on the server and push our changes.

To do this, navigate to the main page of the repository Biomedical-Electronics/prrr and copy the link available in the green Clone or Download button. Make sure you copy the link while it says Clone with HTTPS and not Clone with SSH.

Once the link is copied, go to the folder where you want to store your local repository.

Warning

Choose a folder whose path contains only alphanumeric characters (without accents or strange decorations), hyphens, or underscores, and does not contain spaces. If anyone contacts me saying "X doesn't work" and I see their course folders are in Blablabla/One Drive/Enginyeria Biomèdica/Blablabla, I'll be very annoyed! 👿 (Just kidding, but if you encounter any errors, please check this first.)

Recommended examples: on MacOS or Linux, use your home folder; on Windows, you can create a folder like C:/MASB/Blablabla.

Right-click on an empty space (not on any file or folder) and select Git Bash here from the dropdown menu. If this option does not appear, it is likely that Git is not installed. You can install it by downloading it from this link and following the previously described algorithm: Next, Next, Next, ..., and Finish.

Note

It is important to keep in mind that Git and GitHub are different things. Git is the actual VCS and is open source. On the other hand, GitHub is a company that provides a website using Git to store the version history on a remote server, enabling collaboration and sharing (among many other features that we will gradually explore).

When clicking on Git Bash here, a bash terminal will open. There, we execute the following command:

git clone https://github.com/Biomedical-Electronics/prrr.git

If this is our first git clone of a GitHub repository, it will ask for our credentials. We enter them (GitHub email and password). With all of this, the remote repository on GitHub has been cloned to our computer, and we can start working.

Important

When cloning or initializing a repository, a .git folder is created, which is typically hidden. Do not delete this folder, or the version control in your local repository will be lost, and you will not be able to push your work.

One last step is to enter our name and email in the Git configuration so that they appear when we make commits to our local repository. The name and email can be set for just the current repository or globally for all repositories. We will do the latter. First, we enter the folder that has been created for us:

cd prrr

And there, we enter:

git config --global user.name "Albert"
git config --global user.email "<Sorry, your email is not public. Replace all this (including <>) with your actual email.>"

If we removed the --global from the command, we would be setting the name and email only for the current repository. (Therefore, do not use --global if you are on a shared computer with different repositories).

Here comes the first leap of faith. Run the following command:

git switch -c digital-outputs

With this command, you create a branch named digital-outputs and switch to it. A branch is a separate line of development in the repository where you can work in parallel without interfering with the main development or with other team members. By the end of the practice, there will be more than one branch. From here on, do not close the terminal as we will use it to make various commits. (If you close the terminal: no problem. Just open it again as before from within the prrr folder.)

Create a sketch

Great. We now have our local repository on our computer. Now let's create the file where we will develop our program with Arduino. These files use the .ino format and are called sketches. To create the file, simply open Arduino IDE and go to File > New. Then, select the EVB for which the program will be developed. We do this by going to Tools > Board and selecting Nucleo-64. This selects the family to which the EVB belongs. Now, we will choose the model of this EVB by going to Tools > Board part number and selecting Nucleo F401RE. The last thing we need to do is select the method with which we will upload the program to the microcontroller. We do this by going to Tools > Upload method and selecting Mass Storage. Finally, click on Save As... from File and save the sketch in prrr/arduino with the name digital-outputs. A folder named digital-outputs will be created inside the arduino folder, and inside it, a digital-outputs.ino file will be created, which is the Arduino programming file itself. A sketch.

Warning

It is very important that you save all files in the specified paths or directories using the indicated path and name. Automated tests will be executed remotely in some checkpoints (Pull Requests), so if the files are not placed in the correct path, tests will fail and you will not be able to continue with the lab session.

Now we have the following code in front of us:

void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}

We have two functions: setup and loop. Arduino IDE has already added comments indicating the purpose of each function. The setup function is executed once at the beginning of the program and is usually used to initialize variables, peripherals, etc. On the other hand, the loop function, once setup has been executed, will run continuously. This is where the desired behavior for the microcontroller is coded. We are going to create a program that makes the EVB's LED blink every 1 second.

Digital Outputs: Blink the LED

The LED is connected to pin D13 of the Arduino connector. The D denotes that this pin is a digital GPIO that we will use as an output. GPIO stands for General Purpose Input/Output and is a pin on the microcontroller that can perform various functions (e.g., capturing an analog signal, generating a PWM, programming the microcontroller, etc.), both as input (reading) and output (generating a signal). In this case, we will send a digital signal to the LED to turn it on and off. When the digital output signal is 0, the LED will be off. When it's 1, the LED will be on.

Note

It's important to note that in the digital world, we work with a binary system, meaning ones and zeros. But this is at a logical level. At a physical level, these binary values of 0 and 1 are translated to defined voltage levels. These voltage levels are usually 0 V for a 0 and the supply voltage of the microcontroller for a 1. In this case, the EVB powers the microcontroller with 3.3 V, so a binary 1 corresponds to a voltage level of 3.3 V.

So, the first thing we need to do is configure pin D13 as a digital output GPIO. Since the functionality/usage of the pin will not change throughout the program, we only need to configure it once. Therefore, the configuration will be done using the pinMode instruction within the setup function.

void setup() {
  // put your setup code here, to run once:
  pinMode(13, OUTPUT); // we configure pin 13 as a digital output pin.
  digitalWrite(13, LOW); // we configure the LED to be off when the program starts.
}

void loop() {
  // put your main code here, to run repeatedly:

}

In the pinMode function, we configured pin 13 as an OUTPUT or output pin. If we wanted to set it as input (reading a digital value), we would specify INPUT. We also added a second instruction, digitalWrite, which tells us what value we want to output through the specified pin. If we indicate LOW, we are telling it to output a 0. If we specify HIGH, we are telling it to output a 1.

Important

A note for navigators: It is very tempting to copy and paste the code from the document instead of writing it yourself. We warn you in advance that this would be a serious mistake. Not because you can't do it (you can), but because you will not understand or integrate the concepts being studied in the lab sessions, and it will be very difficult for you to tackle the final project on your own.

What you can also do is to enable code suggestions.

And also ensure to proper format your code.

Now, what we are going to do is make the LED blink. This will happen continuously during the execution of the program, so we will code it in the loop function. We have just seen the digitalWrite function to set an output value. We can guess that to make the LED blink, we only need to use this function alternating between LOW and HIGH.

void setup() {
  // put your setup code here, to run once:
  pinMode(13, OUTPUT); // we configure pin 13 as a digital output pin.
  digitalWrite(13, LOW); // we configure the LED to be off when the program starts.
}

void loop() {
  // put your main code here, to run repeatedly:
  digitalWrite(13, HIGH); // LED on
  digitalWrite(13, LOW); // LED off
}

We compile the program by clicking the icon to verify Verify the program and, if everything is correct, the Arduino IDE terminal should not show any errors but should display additional information, such as the space the program occupies within the microcontroller's memory, the maximum space it could occupy, etc.:

Sketch uses 12476 bytes (38%) of program storage space. Maximum is 32768 bytes.
Global variables use 1236 bytes (10%) of dynamic memory, leaving 11052 bytes for local variables. Maximum is 12288 bytes.

We connect the EVB to the computer using the USB cable if we haven't already, and click the icon to upload the program Upload the program

Once uploaded... is the LED blinking?

At first glance, it seems like the LED isn't blinking. In reality, it is, but at such a speed that our eyes can't perceive it. Let's tell the microcontroller to wait 1 second between turning the LED on and off. For this, we will use the delay function provided by Arduino. This function takes the number of milliseconds we want the microcontroller to wait as its argument. While the microcontroller is waiting within the delay function, it doesn't do anything else. Here's how the code looks after adding the delay.

void setup() {
  // Set pin 13 as output pin
  pinMode(13, OUTPUT);
  // Set the LED to be off at the start of the program
  digitalWrite(13, LOW);
}

void loop() {
  // Turn the LED on
  digitalWrite(13, HIGH);
  // Wait for 1 second (1000 milliseconds)
  delay(1000);
  // Turn the LED off
  digitalWrite(13, LOW);
  // Wait for 1 second (1000 milliseconds)
  delay(1000);
}

Now, we compile, upload the program, and we can see how the LED blinks every 1 second.

Commit the version

We have a working program. Let's save this version to ensure that we can always revert to this version of the code if we change something we shouldn't. Let's run the following command:

git add arduino/digital-outputs/digital-outputs.ino

With this command, we add the digital-outputs.ino file to the stage. The stage is simply an area where we place the files whose version we want to save. Once the files whose version we want to save are added to the stage, we will make the commit. And that's what we're going to do now:

git commit -m "make LED blink every 1 second"

The command is simple and you just need to add a descriptive message of the changes made since the last commit. We've just saved our first version of the code!

Project refactor

Now let's make a small change to our Arduino project, and pay attention, because this will be the way to do it in all Arduino projects throughout the course! Basically, if you've noticed, the program runs in a sketch identified by the .ino extension, which is exclusive to Arduino projects. What Arduino IDE does when validating/compiling the sketch is convert it to C++, add the "things" required for a valid C++ file, and that's what ends up being loaded onto the microcontroller. This has two consequences: 1) it hides C++ language peculiarities that we won't know how to handle in a professional environment (and we're here to learn to program microcontrollers in C/C++, not "Arduino"), and 2) it's not impossible, but it makes automated code testing more difficult (those tests that will be run during the course to check your code works correctly, just like in a professional environment). So, let's do our project in C++.

The change is simple. Arduino IDE requires a .ino file as the main file, which can be accompanied by other files with the .cpp extension (the extension for C++ files). So, what we'll do is the following:

  • In Arduino IDE, click the three dots at the top right and select "New Tab."
  • Name it app.cpp.
  • Do the same again, but name it app.h.
  • In the app.cpp file, enter the following code:
#include "Arduino.h"

void app_setup() {
  // Set pin 13 as output pin
  pinMode(13, OUTPUT);
  // Set the LED to be off at the start of the program
  digitalWrite(13, LOW);
}

void app_loop() {
  // Turn the LED on
  digitalWrite(13, HIGH);
  // Wait for 1 second (1000 milliseconds)
  delay(1000);
  // Turn the LED off
  digitalWrite(13, LOW);
  // Wait for 1 second (1000 milliseconds)
  delay(1000);
}

Notice that the content is what we had in the main sketch, but with a couple of extra things:

  1. We've included the Arduino library with the line #include "Arduino.h" (one of the things Arduino IDE does behind the scenes in our sketch and hides from us).
  2. We've added the app_ prefix to the functions app_setup and app_loop so they don't have the same names as the setup and loop functions in the sketch.

The .cpp file is called a source code file and is where variables and functions are defined. That is, where the code for each of them goes.

Let's continue:

  • In the .h file, enter the following code:
#ifndef APP_H__
#define APP_H__

void app_setup(void);
void app_loop(void);

#endif

This file is a header and these are the files where variables and functions are declared. To declare means to state the name of a function, the type of data it returns, and the type of parameters it accepts. It does not include the code of the function itself. That's in the .cpp file.

For now, we won't go into more detail about how declaring/defining works, what those #ifndef are in the header, or any other details. We'll leave things for the rest of the course...😅

Now, the last change. In the main sketch, enter the following code:

#include "app.h"

void setup() {
  app_setup();
}

void loop() {
  app_loop();
}

As you can see, from the setup function we simply call app_setup, and from the loop function we call app_loop. Clearly, our project should do exactly the same as before. Let's try it. Compile/verify, upload the code, and check that the LED indeed blinks every 1 second.

If it works, as before, proceed to make a commit:

git add arduino/digital-outputs/
git commit -m "refactor project structure"

Notice how we've used the folder name to include all files in the stage area instead of adding them one by one.

We've now finished the refactor. Let's request that our project be tested so we can later add it to the main branch.

Warning

Remember, this will be the way to do it in all Arduino projects throughout the course. Never write code directly in the setup and loop functions of the sketch; do it in your app_setup and app_loop. I won't repeat this in every lesson/session, so keep it in mind.

Pull Request

A Pull Request (PR) is a feature in GitHub that allows you to propose changes from one branch (e.g., digital-outputs) into another branch (e.g., main). It enables code review, automated testing, and collaboration before merging your work into the main project.

How to Create a Pull Request

  1. Push your changes to the digital-outputs branch using the following command:
git push digital-outputs

This command uploads the changes from the local repository to the remote repository on GitHub. This way, you can share the changes made with the rest of the team. If a branch is created in the local repository that doesn’t yet exist in the remote repository, when doing a push, Git will notify you and ask you to use a special command. Copy/paste the command that Git provides you when doing the push and run it in the terminal:

 git push --set-upstream origin digital-outputs
  1. Go to the GitHub web interface for your repository.
  2. Click the "Pull request" tab and then "New pull request".
  3. Ensure the base branch is main and the compare branch is digital-outputs.
  4. Add a descriptive title and comment, then click "Create pull request".

Automated Tests

When you create or update a Pull Request (by pushing new commits to the digital-outputs branch), automated tests will be triggered. These tests have been specifically implemented and configured for this course and are executed remotely on a Raspberry Pi (RPi) that is powered on 24/7 and has the same EVB (STM32 Nucleo-F401RE) connected to it. The RPi loads your program into the connected EVB and checks that the defined requirements for the lesson are accomplished (in this case, blinking the LED every 1 second). The status and results of the tests are shown directly in the Pull Request.

Note

There is only one Raspberry Pi available for testing, and it cannot run multiple tests simultaneously. If another student is running a test, you must wait for their test to finish before yours can start.

If your test remains in the "queued" state for a long time (more than 1 hour), please post your issue in the GitHub discussion forum. This could mean the RPi has lost power supply or network connection.

How to Check Test Results

After the tests run, you will see their status in the "Checks" tab of the Pull Request page:

  • If all tests pass, you will see a green checkmark.
  • If any test fails, you will see a red cross and details about the failure.

If a test fails, please refer to the logs provided in the Pull Request to find the problem or reason for the failure and try to solve it. If you are unable to find or fix the issue, please post your issue in the GitHub discussion forum for support.

Merging the Pull Request

Once all tests have passed, you can merge your developments into the main branch by clicking the "Merge pull request" button.

Note

Normally, merged branches should be deleted to keep the repository clean. However, for academic purposes, we will keep them alive.

Next Steps

After merging, go to the root of the project in the GitHub web interface and select the main branch. Wait 20 seconds for AlbertBot to update the main README.md with the next lesson contents. If the new content does not appear, please post your issue in the GitHub discussion forum for assistance.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •