Embedded Programming

Programming Microcontroller Development Boards

This page includes documentation of work completed during Fab Academy Academic Overlay 2023 at Aalto University New Media MA Program. Due to the academic overlay's structure, embedded programming week was preceding electronics production week. Programming of the microcontroller dev board from electronics production week was included in this week for the sake of continuity.

Group Assignment Page

This week’s group assignment covers programming Xiao RP2040 and D11C and ATtiny412 based programmers and hello boards.

Seeed Studio XIAO RP2040

For the embedded programming week, I first experimented with programming the XIAO RP2040. Here is a good guide for getting started with the board.

Soldering Pins

The first thing I had to do was to solder pins to the XAIO board. After soldering, I found out that one pin was not soldered properly. I went back and fixed the solder.

solder-setup solder error final solders

Adding the Board to Arduino IDE

In order to be able to program the XIAO board through Arduino IDE, we have to add it manually. We can do this by following the instructions in the Seeed Studio Wiki.

After we set it up, we must select it from the menu below:

menu

The first example we did was the blink test. However, there was an issue connecting the XAIO board, Arduino IDE was not registering it as connected.

To fix this we have to “check” the correct port from Tools > Port > COM6. It was COM6 for my case, but it can change.

After this, I conducted the blink test with the code below.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
}

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

Blinking the Green LED

Then, I tried to blink only the green LED, instead of the default LED.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
int greenLed = PIN_LED_G;

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

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

Green LED blink test

Using All the RGB Leds

I tried to use functions to make the LED’s blink in a specific order. I created a “blink” function.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
int ledG = PIN_LED_G;
int ledR = PIN_LED_R;
int ledB = PIN_LED_B;

void setup() {
  // put your setup code here, to run once:
  pinMode(ledG, OUTPUT);
  pinMode(ledR, OUTPUT);
  pinMode(ledB, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  blink(ledG);
  blink(ledR);
  blink(ledG);
  blink(ledB);
}

void blink(int led){
  digitalWrite(led, LOW);
  delay(1000);
  digitalWrite(led, HIGH);
  delay(1000);
}

Blinking the LED's in order

After this, I experimented with using “for loops” to create a flashing effect.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
int ledG = PIN_LED_G;
int ledR = PIN_LED_R;
int ledB = PIN_LED_B;
int dur=20;

void setup() {
  // put your setup code here, to run once:
  pinMode(ledG, OUTPUT);
  pinMode(ledR, OUTPUT);
  pinMode(ledB, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  blink(ledG);
  blink(ledR);
  flash(ledB);
}

void flash(int led){
  for (int i=0; i<dur; i++){
    digitalWrite(led, LOW);
    delay(100);
    digitalWrite(led, HIGH);
    delay(100);
  }
}

void blink(int led){
  digitalWrite(led, LOW);
  delay(1000);
  digitalWrite(led, HIGH);
  delay(1000);
}

Using "for loop"s to create flashing

Using the Neopixel LED (Kris’ Example)

To use the Neopixel LED built into the XIAO board, we first have to load it’s library. We just search for “neopixel adafruit” in Arduino IDE, and install the one made by Adafruit.

In this example, we also learned how to detect a button press. We basically designate a pin for the button, and watch if it is OFF or ON.

In XIAO boards, in contrast to Arduino’s, “HIGH” or “1” means there is no current. “LOW” or “0” means there is current.

Here is Kris’ working example code for the changing the color of the Neopixel LED to a random RGB value, when detecting a button press.

Kris’ Example Code for Neopixels
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <Adafruit_NeoPixel.h>

int powPin = NEOPIXEL_POWER;
int neoPin = PIN_NEOPIXEL;
int btnPin = D10;

#define NUM_PIXELS 1

Adafruit_NeoPixel pix(NUM_PIXELS, neoPin, NEO_GRB + NEO_KHZ800);

void setup() {
  pix.begin();
  pinMode(powPin, OUTPUT);
  pinMode(btnPin, INPUT_PULLUP);
  digitalWrite(powPin, HIGH);
}

void loop() {
  int btnState = digitalRead(btnPin);

  if(btnState == LOW){
      int r=random(0,255);
      int g=random(0,255);
      int b=random(0,255);
      pix.clear();
      pix.setPixelColor(0, pix.Color(r,g,b)); //setting an rgb color
      pix.show();
      delay(200);
  }
}

Working example for button and neopixel

Communicating Between the Board and Computer

The TX and RX pins on the XIAO are used for communicating with other devices.

We can use the Serial connection to send and receive messages to the XIAO from our computer.

In the tutorial example below, when we write a letter to the serial monitor, it returns “received: letter”. And the led blinks the amount of letters we type +1.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
void setup() {
  Serial.begin(19200);
  pinMode(LED_BUILTIN,OUTPUT);

}

void loop() {
  while(Serial.available()>0){
    char message= Serial.read();
    Serial.print("Received: ");
    Serial.println(message);

    digitalWrite(LED_BUILTIN, LOW);
    delay(100);
    digitalWrite(LED_BUILTIN, HIGH);
    delay(100);
  }
}

Working example for serial communication

Turn On Random LED After Button Press

After going through the tutorials, I wanted to combine them and play around with them.

In this example, when I press the button, a random LED will go off. Holding the button down will not do anything.

For a previous Physical Computing course, we had learned how to code a single button press. I first tested this code.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
int btnPin = D10;
int btnState = 1; //btnState 1 means not pressed
int prevBtnState = 1;

void setup() {
  //beginning serial communication
  Serial.begin(19200);

  //defining the button pin
  pinMode(btnPin, INPUT_PULLUP); 
}

void loop() {

  btnState = digitalRead(btnPin);

  if (btnState != prevBtnState){
    if (btnState==0){
      Serial.println("button pressed!!");
    }
  }

  prevBtnState = btnState;
  
  delay(10);
}

After I got it working, what I wanted to do was when I press the button, either the red, green or blue LED will blink randomly. The code below was my first attempt on testing it, but the switch function didn’t work because it was not choosing between integers.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
    if (btnState != prevBtnState){
    if (btnState==0){
      Serial.print("button pressed!!");
      
      switch(random(1,3)){
        case 1: 
          Serial.println("1");
          break;
        case 2:
          Serial.println("2");
          break;
        case 3:
          Serial.println("2");
          break;
      }
    }
  }

Then, I got some help from ChatGPT on why this wasn’t working. I learned that this is how I generate a random integer.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
int chooser = random(1,4); //generate random integer 1, 2 or 3.
      switch(chooser){
        case 1:
          Serial.println("red");
          blink(ledR);
          break;
        case 2:
          Serial.println("green");
          blink(ledG);
          break;
        case 3:
          Serial.println("blue");
          blink(ledB);
          break;
      }

But this had an issue as well, as one of the LED’s was always turned ON in the beginning. After a while, it turns off when the randomizer chooses it. To solve this, I added the following code in void setup():

1
2
3
4
//turn off all LEDs in the beginning
  digitalWrite(ledR, HIGH);
  digitalWrite(ledG, HIGH);
  digitalWrite(ledB, HIGH);

After this, it was working as intended. Here is the final code:

Turning on Random LED with Button Press
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
int ledR = PIN_LED_R;
int ledG = PIN_LED_G;
int ledB = PIN_LED_B;

int btnPin = D10;
int btnState = 1; //btnState 1 means not pressed
int prevBtnState = 1;

void setup() {
  //beginning serial communication
  Serial.begin(19200);

  //defining the LED pins
  pinMode(ledR, OUTPUT);
  pinMode(ledG, OUTPUT);  
  pinMode(ledB, OUTPUT);

  //defining the button pin
  pinMode(btnPin, INPUT_PULLUP);

  //turn off all LEDs in the beginning
  digitalWrite(ledR, HIGH);
  digitalWrite(ledG, HIGH);
  digitalWrite(ledB, HIGH);
}

void loop() {
    
  btnState = digitalRead(btnPin);
  
  if (btnState != prevBtnState){
    if (btnState==0){
      Serial.print("turning on LED: ");
      
      int chooser = random(1,4); //generate random integer 1, 2 or 3.
      switch(chooser){
        case 1:
          Serial.println("red");
          blink(ledR);
          break;
        case 2:
          Serial.println("green");
          blink(ledG);
          break;
        case 3:
          Serial.println("blue");
          blink(ledB);
          break;
      }
    }
  }

  prevBtnState = btnState;
  delay(10);
}

void blink(int led){
  digitalWrite(led,LOW);
  delay(1000);
  digitalWrite(led,HIGH);
  delay(10);
}

Blinking a random LED after a single button press

Controlling Neo-Pixel by Typing

After this, I moved onto the NeoPixel. I wanted to type certain colors in the serial, and the neopixel will produce those colors.

I was trying to make the program read the things I write in the serial monitor. I tried this code first:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <Adafruit_NeoPixel.h>

int powPin = NEOPIXEL_POWER;
int neoPin = PIN_NEOPIXEL;

#define NUM_PIXELS 1

Adafruit_NeoPixel pix(NUM_PIXELS, neoPin, NEO_GRB + NEO_KHZ800);

void setup() {
  Serial.begin(19200);
  
  pix.begin();
  pinMode(powPin, OUTPUT);
  digitalWrite(powPin, HIGH); //turning off neopixel
}

void loop() {
  while(Serial.available()>0){
  char message= Serial.read();
  if(message == "a"){
    Serial.println("yes");
  }
  }
}

But there was a problem with the if statement. I asked ChatGPT and apparently we need to use single quotes(‘a’) instead of double quotes when comparing characters with a character literal. This fixed the issue.

But still, I was not able to type whole words and get the code to recognize them, I only could work with characters. I could not figure out how to use words, that is for an other time.

I changed the if statement to a switch statement for better readability. Here is the final code:

Controlling Neo-Pixel LED by Typing
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <Adafruit_NeoPixel.h>

int powPin = NEOPIXEL_POWER;
int neoPin = PIN_NEOPIXEL;

#define NUM_PIXELS 1

Adafruit_NeoPixel pix(NUM_PIXELS, neoPin, NEO_GRB + NEO_KHZ800);

void setup() {
  Serial.begin(19200);
  
  pix.begin();
  pinMode(powPin, OUTPUT);
  digitalWrite(powPin, HIGH); //turning off neopixel
}

void loop() {
  
  while(Serial.available()>0){
    char message= Serial.read();
    switch(message){
      case 'a':
        Serial.println("purple");
        changeColor(255,0,255);
        break;
      case 'b':
        Serial.println("green");
        changeColor(0,128,0);
        break;      
      case 'c':
        Serial.println("yellow");
        changeColor(255,255,0);
        break;
      case 'd':
        Serial.println("off");
        digitalWrite(powPin, HIGH);
        delay(1000);
        break;      
    }
  }
}

void changeColor(int r, int g, int b){
  pix.clear();      
  pix.setPixelColor(0,r,g,b);
  pix.show();
  delay(200);
}

Typing on serial monitor to control neopixel color

With this, I can change the color of the neopixel by typing “a”, “b”, or “c”.

I also tried to add a switch case where I can turn off power completely, but that did not seem to work. I could not find out why yet.

Further Programming My Microcontroller Board from the Electronics Production Week

Controlling LED Brightness with Potentiometer

Now was the time to try to program the potentiometer. I was not sure if I should write a pinMode(potPin, INPUT_PULLUP) statement for it like the button, so I asked ChatGPT. It said that it would be wrong to write PULLUP, because potentiometers don’t have internal resistors. Also, it was not needed to write this statement at all, since analog pins are read as inputs by default.

chatgpt answer

I tried the code below with the pinMode(potPin, INPUT) and without it. Both worked well and I got a reading.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
int potPin = D3;
int potVal = 0;

void setup() {
  Serial.begin(19200);
}

void loop() {

  // detecting potentiometer input for brightness
    
  potVal = analogRead(potPin);
  Serial.println(potVal);

  delay(10);
}

Controlling brightness of one LED

To bring it all together, I first tried the code below. However, the digitalWrite and analogWrite did not work at the same time.

Not Working Code
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
int btnPin = D4;
int btnState = 1; //1 means not pressed
int prevBtnState = 1;
int counter = 1;

int ledPinA = D0;
int ledPinB = D1;
int ledBrightness = 255;

int potPin = D3;
int potVal = 0;

void setup() {
  Serial.begin(19200);

  pinMode(btnPin, INPUT_PULLUP); 

  pinMode(ledPinA, OUTPUT);
  pinMode(ledPinB, OUTPUT);

  digitalWrite(ledPinA, LOW);
  digitalWrite(ledPinB, LOW);
}

void loop() {

  //detecting button press to turn on/off LEDs

  btnState = digitalRead(btnPin);

  if (btnState != prevBtnState){
    if(btnState == 0){
      counter ++; //with every press of the button, counter goes up by one
      switch(counter % 2){ //checks if counter is even or odd
        case 0:
          Serial.println("LED ON");
          digitalWrite(ledPinA, HIGH);
          digitalWrite(ledPinB, HIGH);
          break;
        case 1:
          Serial.println("LED OFF");
          digitalWrite(ledPinA, LOW);
          digitalWrite(ledPinB, LOW);
          break;
      }
    }
  }
  prevBtnState = btnState;
  
  // detecting potentiometer input for brightness
    
  potVal = analogRead(potPin);
  Serial.println(potVal);

  ledBrightness = map(potVal, 0, 1000, 0, 255);
  analogWrite(ledPinA, ledBrightness);

  delay(10);
}

I tried putting the potentiometer code inside case 0: to only execute it when the LED’s were on. But this did not work either. The brightness stayed the same.

Can't control brightness

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
switch (counter % 2) {  //checks if counter is even or odd
        case 0:
          Serial.println("LED ON");
          digitalWrite(ledPinA, HIGH);
          digitalWrite(ledPinB, HIGH);

          // detecting potentiometer input for brightness
          potVal = analogRead(potPin);
          Serial.println(potVal);
          ledBrightness = map(potVal, 0, 1000, 0, 255);
          analogWrite(ledPinA, ledBrightness);
          break;
        case 1:
          Serial.println("LED OFF");
          digitalWrite(ledPinA, LOW);
          digitalWrite(ledPinB, LOW);
          break;
      }

This led me to remove the digitalWrite(ledPinA, HIGH) statement because it was setting it to a high from the beginning. After this, I could control the brightness of the LED with the potentiometer, but not in real time. The change in brightness registered only when I turned it on and off again.

Most probably, the reason for this was that once the button is pressed, btnState=prevBtnState gets executed. This causes the switch statement to not be read on a loop, but only when the button is pressed. Therefore I cannot get the brightness control in real-time.

Can't control brightness in real time

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void loop() {
  //detecting button press to turn on/off LEDs
  btnState = digitalRead(btnPin);
  if (btnState != prevBtnState) {
    if (btnState == 0) {
      counter++;              //with every press of the button, counter goes up by one
      switch (counter % 2) {  //checks if counter is even or odd
        case 0:
          Serial.println("LED ON");
          /* digitalWrite(ledPinA, HIGH); */
          digitalWrite(ledPinB, HIGH);
          // detecting potentiometer input for brightness
          potVal = analogRead(potPin);
          Serial.println(potVal);
          ledBrightness = map(potVal, 0, 1000, 0, 255);
          analogWrite(ledPinA, ledBrightness);
          break;
        case 1:
          Serial.println("LED OFF");
          digitalWrite(ledPinA, LOW);
          digitalWrite(ledPinB, LOW);
          break;
      }
    }
  }
  prevBtnState = btnState;
  delay(10);
}

In order to get it to work, I created a turnOn variable that would be either true or false. When the button is pressed and the LED’s are on, turnOn is true. When this happens, the potentiometer brightness control code is allowed to execute. When the button is pressed again, turnOn becomes false. LED’s are turned off by digitalWrite, and the potentiometer code cannot be executed.

This way, I can turn the LED’s on and off with the button, and control their brightness with the potentiometer in real time. Below is the code and video.

Controlling LED Properties with Push Button and Potentiometer
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
int btnPin = D4;
int btnState = 1;  //1 means not pressed
int prevBtnState = 1;
int counter = 1;

int ledPinA = D0;
int ledPinB = D1;
int ledBrightness=255;

int potPin = D3;
int potVal = 0;

int turnOn = false; 

void setup() {
  Serial.begin(19200);

  pinMode(btnPin, INPUT_PULLUP);

  pinMode(ledPinA, OUTPUT);
  pinMode(ledPinB, OUTPUT);

  digitalWrite(ledPinA, LOW);
  digitalWrite(ledPinB, LOW);
}

void loop() {

  //detecting button press to turn on/off LEDs
  btnState = digitalRead(btnPin);

  if (btnState != prevBtnState) {
    if (btnState == 0) {
      counter++;              //with every press of the button, counter goes up by one
      switch (counter % 2) {  //checks if counter is even or odd
        case 0:
          Serial.println("LED ON");
          analogWrite(ledPinA, ledBrightness); 
          analogWrite(ledPinB, ledBrightness);
          turnOn = true;
          break;
        case 1:
          Serial.println("LED OFF");
          digitalWrite(ledPinA, LOW);
          digitalWrite(ledPinB, LOW);
          turnOn = false;
          break;
      }
    }
  }

  prevBtnState = btnState;

  if (turnOn == true){
       // detecting potentiometer input for brightness
          potVal = analogRead(potPin);
          Serial.println(potVal);
          ledBrightness = map(potVal, 0, 1000, 0, 255);
          analogWrite(ledPinA, ledBrightness);
          analogWrite(ledPinB, ledBrightness);
  }

  delay(10);
}

Final working example

Programmer SWD D11C

As a part of our group project, we also looked into programming SAM D11C and Attiny 412 chips.

My task was to explore programming the SAM D11C chip using an SWD D11C programmer board. I followed the tutorial written by Kris, which can be found here.

SAM D11C is a low-power microcontroller with 14 pins, 12 of which are general purpose I/O pins. It supports both digital and analog pins. D11-series microcontrollers also support USB connectivity, therefore boards using the D11 can be manufactured in a way that allows direct USB connection with a computer.

swd d11c

The D11C board I was working with is the Hello D11C. It’s a hello board, so we can program it and use it control input or output devices connected through I/O pins. The board is designed so that it can connect to a programmer through SWD. Programmer SWD D11C is what I used to program the Hello Board. It also uses a D11C microcontroller.

The steps are documented in detail both in this weeks group assignment page and in the tutorial.

Previously, I only worked with programming development boards such as Arduino or Xiao boards. After this assignment, I also got an introduction to progamming D11C and Attiny chips as well. It is a much more complicated process, but it allows us to build much smaller and much cheaper boards, and make them fit our needs better. I will explore this process more in the future.

programming swd d11c programmings swd d11c