Skip to content

9. Embedded programming

For the group assignment we decided to compare several kinds of microcontrollers. We decided to take the SAMD11C, the arduino ATmega368 and the rasberry Pi. Here is the comparison table of these components.

Configuration Summary SAMD11C-14 pin SOIC Arduino Uno - ATmega328P Rasberry Pi 3 - Broadcom BCM2837
Number of pins 14 28 40
Number of I/O pins 12 14 Digital I/O Pins; 6 PWM Digital I/O Pins; 6 Analog Input Pins 40
 Flash memory 16 KB 32 KB where 0.5 KB are taken by the bootloader 1GB
 SRAM 4 KB 2 KB N/A
Clock Speed 16 MHz 900 MHz * 4 Cores
Time counter (TC) 2 N/A
Output channels for TC 2 40
Timer Counter for Control (TCC) 1 N/A
Output channels per TCC 8 N/A
Direct memory access channels 6 N/A
USB interface Yes YES
Serial Communication Interface (SERCOM) 2 2
Analog-to-Digital Converter (ADC) channels 5 N/A
Analog Comparators (AC) 2 N/A
Digital-to-Analog Converter (DAC) channels 1 N/A
Real-Time Counter (RTC) Yes YES
RTC Alarms 1 1
RTC compare values 1 32-bit value or 2 16-bit values N/A
External Interrut Lines 8 N/A
Peripheral Touch Controller (PTC) channels for mutual capacitance 12 (4x3) N/A
Peripheral Touch Controller (PTC) channels for self capacitance 7 N/A
Maximum CPU frequency 48MHz 1.2 GHz *4 Cores
Packages SOIC 28P3 Board SoC
Oscillators 32.768kHz crystal oscillator (XOSC32K) 0.4-32MHz crystal oscillator (XOSC) 32.768kHzinternal oscillator (OSC32K)32kHz ultra-low-power internal oscillator (OSCULP32K) 8MHz high-accuracy internal oscillator (OSC8M) 48MHz Digital Frequency Locked Loop (DFLL48M) 96MHz Fractional Digital Phased Locked Loop (FDPLL96M) N/A
Event System channels 6 N/A
SW Debug Interface Yes N/A
Watchdog Timer (WDT) Yes N/A
Temperature range -40 to 85°C -40°C to 85°C -40 to 85 C
Operating voltage 1,62 to 3,63 V 1.8 to 5.5 V 5.1 V
Processor ARM Cortex-M0+ CPU running at up to 48MHz BCM2837 Broadcom system on chip

Raspberry Pi 4 specifications table:

GPIO Pull ALT0 ALT1 ALT2 ALT3 ALT4 ALT5
0 HIGH SDA0 SA5 PCLK SPI3_CE0_N TXD2 SDA6
1 HIGH SCL0 SA4 DE SPI3_MISO RXD2 SCL6
2 HIGH SDA1 SA3 LCD_VSYNC SPI3_MOSI CTS2 SDA3
3 HIGH SCL1 SA2 LCD_HSYNC SPI3_SCLK RTS2 SCL3
4 HIGH GPCLK0 SA1 DPI_D0 SPI4_CE0_N TXD3 SDA3
5 HIGH GPCLK1 SA0 DPI_D1 SPI4_MISO RXD3 SCL3
6 HIGH GPCLK2 SOE_N DPI_D2 SPI4_MOSI CTS3 SDA4
7 HIGH SDA0 SA5 PCLK SPI4_CE0_N RTS3 SCL4
8 HIGH SDA0 SA5 PCLK SPI3_CE0_N TXD2 SDA4
9 LOW SPIO_MISO SD1 DPI_D5 - RXD4 SCL4
10 LOW SDA0 SA5 PCLK SPI3_CE0_N TXD2 SDA6
11 LOW SDA0 SA5 PCLK SPI3_CE0_N TXD2 SDA6
12 LOW SDA0 SA5 PCLK SPI3_CE0_N TXD2 SDA6
13 LOW SDA0 SA5 PCLK SPI3_CE0_N TXD2 SDA6
14 LOW SDA0 SA5 PCLK SPI3_CE0_N TXD2 SDA6
15 LOW SDA0 SA5 PCLK SPI3_CE0_N TXD2 SDA6
16 LOW SDA0 SA5 PCLK SPI3_CE0_N TXD2 SDA6
17 LOW SDA0 SA5 PCLK SPI3_CE0_N TXD2 SDA6
18 LOW SDA0 SA5 PCLK SPI3_CE0_N TXD2 SDA6
19 LOW SDA0 SA5 PCLK SPI3_CE0_N TXD2 SDA6
20 LOW SDA0 SA5 PCLK SPI3_CE0_N TXD2 SDA6
21 LOW SDA0 SA5 PCLK SPI3_CE0_N TXD2 SDA6
22 LOW SDA0 SA5 PCLK SPI3_CE0_N TXD2 SDA6
23 LOW SDA0 SA5 PCLK SPI3_CE0_N TXD2 SDA6
24 LOW SDA0 SA5 PCLK SPI3_CE0_N TXD2 SDA6
25 LOW SDA0 SA5 PCLK SPI3_CE0_N TXD2 SDA6
26 LOW SDA0 SA5 PCLK SPI3_CE0_N TXD2 SDA6
27 LOW SDA0 SA5 PCLK SPI3_CE0_N TXD2 SDA6

Programming of SAMD11C - Code

For this week I programmed my board with LEDs and a button. First to learn how to program, I learnt on an Arduino board, with Serial monitor, to learn how to make function, and fill the paragraph on Arduino software. The programmation of this microcontroller is the first microcontroller programmed for the group assignment.

I will put the files of the most advanced programmed I made, because some codes I worte are the step by step I learnt how to code but doesn’t really do much things.

Here is the kind of basic code I wrote.

I wrote a code to have a counter print on a serial monitor, to try the tool offer by Arduino. Here I just learnt how to fill the setup and the loop function.

void setup (){
  // put your setup code here, to run once:
  Serial.begin(9600); //speed of communication, 9600 baud, mandatory for the serial monitor to work
  delay(1000); //wait a bit at the beginning
  Serial.printIn("start"); //check if the serial monitor is working
}

int toto = 0; //the counter, an integer

void loop(){
  // put your main code here, to run repeatedly:
  delay(1000); //wait 1 sec, to repeat the loop after
  Serial.printIn(toto); //print the coundter
  toto = toto + 1; //every 1 second, the counter is added of 1
}

This is a screenshot of the serial monitor, where the number of the counter is print.

Arduino website has all the references, function we can use to programm.

During the learning of how to code, I make a mistake in my code. I declared a variable 2 times in the code.

And when I upload the code, it broked the board. I wasn’t able to connect the board to my computer. So I had to reflashed it with the bootloader and the programmer.

So now, this is the code I wrote to make the green LED on when I push the button, and switch on the red LED when the button is not pushed. I found the number of the pin on the datasheet, mixed with a picture for the name to put on the code, bellow on this website it is explained.

Don’t forget to open the serial monitor at the beginning.

Here I wrote the code in C++ language, using different functions and variables.

int toto = 0; //a integer variable, a counter
int totoref = 0; // a variable that will help to storage the value of my counter and after do comparison
int pinLEDvert = 14; //LED green linked to the pin 14
int pinLEDrouge = 5; //LED red linked to pin 5

int pushButton = 15; //button linked in pin 15

void setup(){
  Serial.begin(9600); //the initial beginning for the serial monitor to be able to work.
  pinMode(pushButton, INPUT_PULLUP); //setup the button
  pinMode(pinLEDvert, OUTPUT); //setup the LED
  digitalWrite(pinLEDvert, HIGH); //check if the LED is working and if we go well in the function
  delay(1000); //wait 1 sec
  digitalWrite(pinLEDvert, LOW); //switch off the LED
  pinMode(pinLEDrouge, OUTPUT); //setup the red LED, and do the same as the LED before
  digitalWrite(pinLEDrouge, HIGH);
  delay(1000);
  digitalWrite(pinLEDrouge, LOW);
}

bool greenLEDstatus = false; //create a boolean

void loop(){
  int buttonState = digitalRead(pushButton); //a variable that will have the state of the button, and help to do some checking in a if loop
  delay(300);
  if(buttonState == 0){ //if the button is pushed, then toto will change, 1 will be added on the variable integer
    toto = toto+1;
  }
  if(totoref != toto){ //if the reference of toto is different of toto, means taht the button has been pushed, the green LED will be on
    Serial.println(toto); //a check if toto has been changed, on the serial monitor
    setLEDvert(true); // check the function below, turn on the green LED
    greenLEDstatus = true;
    setLEDrouge(false); //turn off the red LED
    totoref = toto; //equalize the two variable, to go out from the if
    delay(300); 
  }
  else{ //else turn off the green LED, and turn on the red LED, the button has not been pushed
  setLEDvert(false);
  greenLEDstatus = false;
  setLEDrouge(true);
  }
}

void setLEDrouge(bool on_offr){ //same as the next function but for the red LED
  if (on_offr == 1){
    digitalWrite(pinLEDrouge, HIGH);
    //Serial.print("LED rouge ");
    //Serial.println(on_offr); 
  }
  else{
    digitalWrite(pinLEDrouge, LOW);
  }

}

void setLEDvert(bool on_offv){ //a function that will turn on or off the LED
  if (on_offv == 1){ //if the boolean is true then the LED will turn on otherwise it will turn off the green LED
    digitalWrite(pinLEDvert, HIGH);
  //Serial.print("LED vert ");
  //Serial.println(on_offv);
  }
  else{
    digitalWrite(pinLEDvert, LOW);
  }

}

The file is available at the end of the page, in all the files.

To upload the code on the board with Arduino, first I selected the right board, and not forget to select the port where the Mattairtech board is plugged. And it is the LEDs turned on and off according to the push button.

Now because I had issues on one pin on one of my board, I fixed it this week. I change with a wire where the LED is linked on the microcontroller. To check which pin is working, I upload this code in the board, and checked how many volts going out the pin I programmed with the multimeter. I took the basic example on Arduino software and just changed some part to be able to change the number pf the pin quickly.

I won’t put the file of this code, it was taken in the example folder of Arduino, a basic blink, I just added 2 variables to be able to do my checks quickly.

int pinLEDvert = 4; //create a varible of which pin is linked to the LED, to change it quickly and make a test on each pin of the board
int pinLEDrouge = 5; // the red LED is working, and linked to the pin 5

void setup() {
  // put your setup code here, to run once:
  pinMode(pinLEDvert, OUTPUT);
  pinMode(pinLEDrouge, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  digitalWrite(pinLEDvert, HIGH); //turn on both LED
  digitalWrite(pinLEDrouge, HIGH);
  delay(1000);
  digitalWrite(pinLEDvert, LOW); //turn off both LED
  digitalWrite(pinLEDrouge, LOW);
  delay(1000);
}

It shows around 3.3 V on the multimeter so I supposed that the pin is working.

I soldered a wire, and cut the trace where the LED is linked with the microcontroller, and when I plugged the board the LED were blinking both, so it worked.

Micro:bit - programming microcontroller Nordic nRF51822

During the bootcamp week, I discovered a little bit about micro:bit, that’s why I reused this board for this week. On micro:bit website, there is an interface, makecode editor to play with code as blocks. I made the programm with blockly language, that bring to a JavaScript code. The micro:bit board is processed by a MCU Nordic nRF51822.

The programmation of this microcontroller is the second microcontroller programmed for the group assignment.

To test the editor, I put the blocks to make the board print “hello” at the end and when we push the A button, it make a heart shape blink two times. The button B clear the LEDs.

We can also check the code in JavaScript:

input.onButtonPressed(Button.A, function () {
    for (let index = 0; index < 2; index++) {
        basic.showIcon(IconNames.Heart)
        basic.pause(1000)
        basic.showLeds(`
            . . . . .
            . . . . .
            . . . . .
            . . . . .
            . . . . .
            `)
    }
})
input.onButtonPressed(Button.B, function () {
    basic.clearScreen()
})
basic.showString("Hello!")
basic.forever(function () {

})

I did not write the code in JavaScript, but I just checked to know what is going on in with this language and blockly I used.

When the code is done, I just need to download the file and then copy it in the micro:bit board, plugged to my computer.

And here is the result:

This way of working is nice to learn quickly some code, and very nice to see, but it is pretty limited, to the micro:bit board.

ESP32

Théo test also the ESP32. Here is his work

During the Interface and application programming week I also programmed an ESP32. This microcontroller is different from the others already mentioned. Here are the different steps to program with an ESP32 on the Arduino software on a Mac.

The ESP 32 in a few words

ESP32 is a series of microcontrollers from Espressif Systeme with integrated support for Wi-Fi and Bluetooth (up to LE 5.0 and 5.11). It is an evolution of the ESP8266.

ESP32 is capable of functioning reliably in industrial environments, with an operating temperature ranging from –40°C to +125°C. Powered by advanced calibration circuitries, ESP32 can dynamically remove external circuit imperfections and adapt to changes in external conditions.

ESP32 is highly-integrated with in-built antenna switches, power amplifier, low-noise receive amplifier, filters, and power management modules. ESP32 adds priceless functionality and versatility to your applications with minimal Printed Circuit Board (PCB) requirements.

ESP32 can perform as a complete standalone system or as a slave device to a host MCU, reducing communication stack overhead on the main application processor. ESP32 can interface with other systems to provide Wi-Fi and Bluetooth functionality through its SPI / SDIO or I2C / UART interfaces.

Engineered for mobile devices, wearable electronics and IoT applications, ESP32 achieves ultra-low power consumption with a combination of several types of proprietary software. ESP32 also includes state-of-the-art features, such as fine-grained clock gating, various power modes and dynamic power scaling.

Credit : Espressif Systeme

Installing the ESP32 on the Arduino IDE

To use the ESP32 with the Arduino software it is necessary to add the board to the software. All the steps are done on a Mac, there may be some inconsistencies with another operating system.

To do this, open the Arduino application and go to Arduino > Preferences then paste this link into this location:

https://dl.espressif.com/dl/package_esp32_index.json

Once you have registered this new link you should also download the boards. To do this you need to open the tools tab > board manager. Type ESP32 in the search bar and download the pack

Installing the CP210x Driver

In order to interface with an ESP32 it is necessary to install a driver to make the link between UART and USB. To do this you need to go to this link and download the appropriate driver for your computer.

https://www.silabs.com/developers/usb-to-uart-bridge-vcp-drivers

When you have downloaded the file you just have to execute it and then your computer has to restart once the driver is installed.

The installation

The goal of the week was to control my little robot with a wireless “remote control”.

For more information click here

Creation of the web page

As previously mentioned I would like to control my wireless robot with a wifi connection. For that I need a web interface that would allow me to control my robot remotely. I followed the tutorials of Tommy des rochers (https://tommydesrochers.com) for how to create an HTML interface compatible with an ESP 32.

In this video he explains very quickly and simply how to create an HTML page (it’s in French). To create a rather nice environment he uses the website W3school.com. This site creates templates, so it is very fast to create an interface with a correct style simply and free. After saving the link in your text file, you can call up the templates already created for you.

Here is the code to recreate a page similar to mine. You can change the styles very easily by going to the W3school website and change the references so that your site corresponds to your expectations.

<!SERVER HTML>

<html lang='fr'>

  <head>
    <title>Server ESP32</title> //Title that your page will have on your browser's tab
    <meta http-equiv='refresh' content='60' name='viewport' content='width=device-width, initial-scale=1' charset='UTF-8' /> // Instruction line for updating your page
    <link rel='stylesheet' href='https://www.w3schools.com/w3css/4/w3.css'> // Line to link the W3school templates to your page
  </head>

   <body>
    <div class='w3-card w3-green w3-padding-small w3-jumbo w3-center'> // Line that indicates that the background of your title will be green, with a Jumbo text in the middle
    <p> THEO ROBOT :</p> // Title on the page
    </div>

    <div class='w3-bar'> // This sets the following objects to be in a horizontal line 
      <a href='/go' class='w3-bar-item w3-button w3-border w3-jumbo' style='width:100%; height:50%;'>GO!</a> // This line means that you have a button with an outline, with "GO" written in the centre in jumbo type. Also when selected it will send to the /go page. It uses all the horizontal space on the line

      <a href='/left' class='w3-bar-item w3-button w3-border w3-jumbo' style='width:50%; height:25%;'>TURN LEFT</a> // This line means that you have a button with an outline, with "TURN LEFT" written in the centre in jumbo type. Also when selected it will send to the /left page. It uses half of the horizontal space on the line

      <a href='/right' class='w3-bar-item w3-button w3-border w3-jumbo' style='width:50%; height:25%;'>TURN RIGHT</a> // This line means that you have a button with an outline, with "TURN RIGHT" written in the centre in jumbo type. Also when selected it will send to the /right page. It uses half of the horizontal space on the line

      <a href='/stop' class='w3-bar-item w3-button w3-border w3-jumbo' style='width:100%; height:50%;'>STOP!</a> // This line means that you have a button with an outline, with "STOP" written in the centre in jumbo type. Also when selected it will send to the /stop page. It uses all the horizontal space on the line
    </div>



    <div class='w3-center w3-padding-16'> // This means that the text that follows will be centred and sparsely spaced.
      <p>This server is hosted on an ESP32</p> // Normal text
      <i>Created by Théo GAUTIER, AgriLab FabAcademy 2021 </i> // Text written in italics
    </div>
   </body>

<html>

This interface has the advantage of working equally well on computer, tablet or smartphone

The code in C++

Now that our web page is functional, we need to insert it into the C++ code to be used by the ESP32. The code being in HTML and the instructions in Arduino in C++ we have to find a way for the server to be read by the microcontroller. To do this, the technique used by Tommy des Rochers is to use the String function. By doing this, the ESP32 can host the server locally and can therefore interact with a web page.

#include <WiFi.h>
#include <WebServer.h>

const char* ssid = "Network name"; // Network name
const char* password = "Network password"; // Network password
WebServer server(80); //Default port for the ESP32 server relationship

const int M1 = 16; //Motor 1 on pin 16
const int M2 = 17; //Motor 2 on pin 17
const int M3 = 18; //Motor 3 on pin 18
const int M4 = 19; //Motor 4 on pin 19

void Homepage() // Function that contains my server and serves as my homepage 
{
  String page = "<!SERVER html>"; // The lines in my HTML server preceded by the string function so that it is readable by the ESP32

    page += "<html lang='fr'>";

    page += "<head>";
    page += "    <title>Server ESP32</title>";
    page += "    <meta http-equiv='refresh' content='60' name='viewport' content='width=device-width, initial-scale=1' charset='UTF-8' />";
    page += "    <link rel='stylesheet' href='https://www.w3schools.com/w3css/4/w3.css'>";
    page += "</head>";

    page += "<body>";
    page += "    <div class='w3-card w3-green w3-padding-small w3-jumbo w3-center'>";
    page += "    <p>THEO ROBOT </p>";
    page += "    </div>";

    page += "    <div class='w3-bar'>";
    page += "        <a href='/go' class='w3-bar-item w3-button w3-border w3-jumbo' style='width:100%; height:50%;'>GO!</a>";
    page += "        <a href='/left' class='w3-bar-item w3-button w3-border w3-jumbo' style='width:50%; height:50%;'>TURN LEFT</a>";
    page += "        <a href='/right' class='w3-bar-item w3-button w3-border w3-jumbo' style='width:50%; height:50%;'>TURN RIGHT</a>";
    page += "        <a href='/stop' class='w3-bar-item w3-button w3-border w3-jumbo' style='width:100%; height:50%;'>STOP</a>";
    page += "    </div>";

    page += "    <div class='w3-center w3-padding-16'>";
    page += "        <p>This server is hosted on an ESP32</p>";
    page += "        <i>Created by Théo GAUTIER, AgriLab FabAcademy 2021</i>";
    page += "    </div>";

    page += "</body>";

    page += "</html>";

    server.setContentLength(page.length()); //This allows the ESP32 to know the length of the website, which allows faster communication
    server.send(200, "text/html", page); // Enables data to be sent
} 

void NotFound() // Function that writes to the user "404 Not found" if a page is unknown
{
    server.send(404, "text/plain", "404: Not found");
}

void go() //Function that allows the robot to move forward, all motors are on
{
    digitalWrite(M1, HIGH);
    digitalWrite(M2, HIGH);
    digitalWrite(M3, HIGH);
    digitalWrite(M4, HIGH);
    server.sendHeader("Location","/"); // This then links to the home page 
    server.send(303); // Command that tells the server it is doing a redirect 
}

void stop() //Function that allows the robot to stop, all motors are off
{
    digitalWrite(M1, LOW);
    digitalWrite(M2, LOW);
    digitalWrite(M3, LOW);
    digitalWrite(M4, LOW);
    server.sendHeader("Location","/"); // This then links to the home page 
    server.send(303); // Command that tells the server it is doing a redirect 
}

void left() //Function that allows the robot to turn left by stopping motors 1 and 2
{
    digitalWrite(M1, LOW);
    digitalWrite(M2, LOW);
    digitalWrite(M3, HIGH);
    digitalWrite(M4, HIGH);
    server.sendHeader("Location","/"); // This then links to the home page 
    server.send(303); // Command that tells the server it is doing a redirect 
}

void right() // Function that allows the robot to turn right by stopping motors 3 and 4
{
    digitalWrite(M1, HIGH);
    digitalWrite(M2, HIGH);
    digitalWrite(M3, LOW);
    digitalWrite(M4, LOW);
    server.sendHeader("Location","/"); // This then links to the home page 
    server.send(303); // Command that tells the server it is doing a redirect 
}

void setup()
{
  Serial.begin(115200); 
  delay(1000); // Delay 1s
  Serial.println("\n"); // Make a line break in the serial monitor

  pinMode(M1,OUTPUT); // Says that M1 is an output
  pinMode(M2,OUTPUT); // Says that M2 is an output
  pinMode(M3,OUTPUT); // Says that M3 is an output
  pinMode(M4,OUTPUT); // Says that M4 is an output
  digitalWrite(M1, LOW); // Set M1 to stop
  digitalWrite(M2, LOW); // Set M2 to stop
  digitalWrite(M3, LOW); // Set M3 to stop
  digitalWrite(M4, LOW); // Set M4 to stop

  WiFi.begin(ssid, password); // Function to start the wifi connection
  Serial.print("Connection in progress..."); // Print on the serial monitor "Connection in progress..."

  while(WiFi.status() != WL_CONNECTED) // As long as the connection to the network has not been established then print a dot every second
  {
    Serial.print(".");
    delay(1000);
  }

  Serial.println("\n");  // Make a line break in the serial monitor
  Serial.println("Connection established!");  // Print on the serial monitor "Connection established!"
  Serial.print("Adresse IP: ");   // Print on the serial monitor "Adresse IP:"
  Serial.println(WiFi.localIP()); // Print on the serial monitor the local IP


  server.on("/", Homepage); // When the server is on "/" then do the homepage function
  server.on("/go", go); // When the server is on "/go" then do the go function
  server.on("/left", left); // When the server is on "/left" then do the left function
  server.on("/right", right); // When the server is on "/right" then do the right function
  server.on("/stop", stop); // When the server is on "/stop" then do the stop function
  server.onNotFound(NotFound); // When the server is not found then do the NotFound function
  server.begin(); // Start the server

  Serial.println("Active web server!"); // Print on the serial monitor "Active web server!"

}

void loop()
{
  server.handleClient(); // Manage the user who is connected to the server
}

For more information click here

The server hosted on the ESP32 allows communication between a web interface and a board. The ESP32 is connected to my own wifi network created by my iPhone. Once on the web page with my Mac or iPhone I can interact with the ESP32 by clicking on the buttons that will then perform the registered functions. This is how I can drive my robot with an ESP32 and a wifi connection.

Video ESP32

  • Musique : Patrick Abrial - Misirlou*
  • A big thank you to Anthonio for having put his talents as a cameraman to good use, it allowed us to have a spectacular result*