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.
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:
Blink Test
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.
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.
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.
#include <Adafruit_NeoPixel.h>
int powPin = NEOPIXEL_POWER;
int neoPin = PIN_NEOPIXEL;
int btnPin = D10;
#define NUM_PIXELS 1Adafruit_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.
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.
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){
case1:
Serial.println("red");
blink(ledR);
break;
case2:
Serial.println("green");
blink(ledG);
break;
case3:
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:
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:
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.
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.
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
case0:
Serial.println("LED ON");
digitalWrite(ledPinA, HIGH);
digitalWrite(ledPinB, HIGH);
break;
case1:
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
case0:
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;
case1:
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.
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
case0:
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;
case1:
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
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
case0:
Serial.println("LED ON");
analogWrite(ledPinA, ledBrightness);
analogWrite(ledPinB, ledBrightness);
turnOn = true;
break;
case1:
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.
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.
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.