Week 4
Week assignments
Embedded programming
- Group assignment:
- demonstrate and compare the toolchains and development workflows for available embedded architectures.✔
- Individual assignment:
- browse through the data sheet for your microcontroller.✔
- write a program for a microcontroller, and simulate its operation, to interact (with local input &/or output devices) and communicate (with remote wired or wireless connections)✔
- extra credit: test it on a development board. ✔
- extra credit: try different languages &/or development environments.
Group assignment
On Thursday, February 13th, Luis spent the whole day with us, starting first thing in the morning. We kicked things off by checking out the packs Luis had prepared for each of us. They’re super well-organized, with all the components labeled for easy access. Honestly, a fantastic gift!
To complement Neil’s class explanation, Luis broke down the differences between various microcontrollers and programming languages. He also shared some great tips on the best ways to work with them.
Link to week 4 group assignment
To collaborate on the group work, we decided to split the analysis of these designs:
Later, Luis walked us through the basics of using a multimeter — how to check for continuity, voltage, and resistance. We also learned that some components, like LEDs and diodes, can only be placed in one direction.
Individual assignment
On Luis’ recommendation, I installed Arduino IDE to program a microcontroller. In our group work, we analyzed different microcontrollers, but for our first learning practices, I’ll be using the Arduino UNO. Later on, I’ll decide which microcontroller is best for my final project, where I’ll be using load cells and an LED matrix that will communicate wirelessly.
He also recommended a link to Luis Llamas’ website, with a large number of examples related to this week’s topic Embedded programming.
Arduino UNO
Before getting started with this board, it’s important to know the key features of the Arduino Uno. As a test, I decided to ask FabAcademy about its main specs, and here’s what it came up with:
- Microcontroller: ATmega328P
- Architecture: Harvard-style with a RISC instruction set (basically, it’s efficient and fast).
- Clock speed: 16 MHz
- Memory:
- Flash: 32 KB (0.5 KB is used by the bootloader)
- SRAM: 2 KB
- EEPROM: 1 KB
- Operating voltage: 5V
- Input/Output pins:
- 14 digital pins (6 support PWM output)
- 6 analog input pins
- Communication interfaces:
- UART (serial)
- I2C
- SPI
- Power options:
- USB port (5V)
- DC power jack (7-12V)
- VIN pin (external voltage input)
- ICSP connector for direct microcontroller programming
- Standard Arduino form factor, meaning it’s compatible with tons of shields and accessories
Datasheet Arduino UNO (pdf)
Pinout Definition
First the basics
After installing the Arduino IDE, I started to analyse very basic cases to understand how it works. At the same time I was playing the program with the WOKWI simulator and then I did the same on a breadboard.
Obviously, the first step was to connect the Arduino Uno to the computer and then using Arduino IDE, I did the following:
Tools: select Board > check port > Load sketch and modify or write code from scratch > Verify > Upload to Arduino Uno.
Blink Load examples> 01.Basic. Blink > Modifing OUTPUT and changing BUILTIN to pin 11.
/*
Blink
*/
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin LED_BUILTIN as an output. LED on/off only works once.
pinMode(11, OUTPUT);
digitalWrite(11, HIGH); // turn the LED on (HIGH is the voltage level)
delay(2000); // wait for two second
digitalWrite(11, LOW); // turn the LED off by making the voltage LOW
}
// the loop function runs over and over again forever
void loop() {
/* digitalWrite(11, HIGH); // turn the LED on (HIGH is the voltage level)
delay(2000); // wait for two second
digitalWrite(11, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
*/
}
Wokwi: simple blink simulation.
Simple blink Arduino
After this, I generated a code for a traffic light sequence by declaring integer type variables.
// declaring integer type variables
const int ledR = 12; //* Red LED connected to pin 12
const int ledA = 10; //* Yellow LED connected to pin 10
const int ledV = 8; //* BLue (I have not a Green LEDs I use a Blue LED ) LED connected to pin 8
//the function is executed only once
void setup() {
// initialises the led pins as digital outputs
pinMode(ledR, OUTPUT);
pinMode(ledA, OUTPUT);
pinMode(ledV, OUTPUT);
}
// The loop function runs infinitely
void loop() {
// red light ON
digitalWrite(ledR, HIGH);
digitalWrite(ledA, LOW);
digitalWrite(ledV, LOW);
delay(1000);
// yellow light ON
digitalWrite(ledR, LOW);
digitalWrite(ledA, HIGH);
digitalWrite(ledV, LOW);
delay(1000);
// Green/Blue light ON
digitalWrite(ledR, LOW);
digitalWrite(ledA, LOW);
digitalWrite(ledV, HIGH);
delay(1000);
}
Wokwi: traffic light simulation.
Next steps were done in order to practise a “for” sequence with and analogue output.
int led=3;
void setup() {
pinMode(3, OUTPUT);
}
void loop() {
for (int i=1; i <=255; i++){
analogWrite (led, i);
delay (10);
}
}
Wokwi: “for” sequence simulation.
The following code was used to practise modifying the delay time through a digital output.
int led = 2;
int time = 100;
void setup() {
pinMode(led, OUTPUT);
}
void loop() {
for (int i = 1; i <= 5; i++) {
digitalWrite(led, HIGH);
delay(time);
digitalWrite(led, LOW);
delay(time * 10);
}
}
Wokwi: digital output sequence simulation
Arduino IDE extensions
As part of this week’s learning, I need to interact with input and output devices. To do this, I must expand the capabilities of the Arduino IDE by installing, on one hand, the ability to manage boards other than the Arduino Uno and, on the other hand, libraries that allow working with LEDs, humidity sensors, temperature sensors, or load cells.
Once the group task was completed, I was able to prepare this comparison between the four processors, and it seems that the one that best fits the needs of my final project is the XIAO ESP32-C3 due to its processing speed and integration of Wi-Fi and Bluetooth communication.
These are the steps:
Arduino IDE: File > Preferences > Aditional boards manager > Add URL: https://espressif.github.io/arduino-esp32/package_esp32_index.json\
After pressing the OK button twice, the installation will start and after a few minutes the Arduinno ESP32 Board will be available.
Them I copied & pasted this URL: https://descartes.net/package_drazzy.com_index.json
to be able to use MegaTiny Core boards with the program.
I also needed to use the library manager to extend the Arduino IDE’s element handling capability. Luis provided us with some NeoPixel strips; I needed to implement the Adafruit NeoPixel library to handle it.
In Wokwi I also had to install the library to be able to simulate the operation of the LEDs.
// NeoPixel Ring simple sketch (c) 2013 Shae Erisson
// Released under the GPLv3 license to match the rest of the
// Adafruit NeoPixel library
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
// Which pin on the Arduino is connected to the NeoPixels?
#define PIN 6 // On Trinket or Gemma, suggest changing this to 1
// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS 10
// When setting up the NeoPixel library, we tell it how many pixels,
// and which pin to use to send signals. Note that for older NeoPixel
// strips you might need to change the third parameter -- see the
// strandtest example for more information on possible values.
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
#define DELAYVAL 500 // Time (in milliseconds) to pause between pixels
void setup() {
// These lines are specifically to support the Adafruit Trinket 5V 16 MHz.
// Any other board, you can remove this part (but no harm leaving it):
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
clock_prescale_set(clock_div_1);
#endif
// END of Trinket-specific code.
pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
}
void loop() {
pixels.clear(); // Set all pixel colors to 'off'
// The first NeoPixel in a strand is #0, second is 1, all the way up
// to the count of pixels minus one.
for(int i=0; i<NUMPIXELS; i++) { // For each pixel...
// pixels.Color() takes RGB values, from 0,0,0 up to 255,255,255
// Here we're using a moderately bright green color:
pixels.setPixelColor(i, pixels.Color(random(50), random(50), random(50)));
pixels.setPixelColor(9, pixels.Color(150, 0, 0)); //Last LED ever RED
pixels.show(); // Send the updated pixel colors to the hardware.
delay(DELAYVAL); // Pause before next pass through loop
}
}
Wokwi: last LED in red simulation.
To go from the digital world to the real world, I had to learn how to solder the connections on the LED strip. So first, I had to check and figure out the data, power, and ground connections.
Arduino IDE Last LED in red, the rest in random colours.
For my final project, I need to learn how to simulate the following situations:
- Figuring out how much load the load cells at the base of each seat can handle.
- Collecting the data from each of the load cells.
- Using this data to calculate the bending stress on the beam. I’ll determine the values at 14 points for each section.
- Once I have the key values, I’ll map them so they can be displayed on the LED matrix.
- Sending the organized data to the microprocessor, which will visualize the stress diagrams.
As a preliminary step I have to learn how to simulate and assemble a load cell and an LED matrix. Initially, I will approach it with Arduino UNO and then adjust the design to a XIAO ESP32 C3.
XIAO ESP32 C3
Load cell
Arduino UNO
For this first simulation, I used a beam-shaped load cell with a permissible load of 1 kg. To ensure its operation, the applied load must not exceed 80 per cent of its maximum capacity.
I had to use the HX711 signal amplifier and to simulate it in the Arduino IDE I loaded the HX711 Roob Tillaart library.
I adjusted the calibration scale with a half-litre bottle of water. I had to calibrate the scale; for that I determined the average value of the values of
load.read()
to determine the tare, in my case it reached a value of -182600. I had to adjust this value so that the value of the unloaded scale is zero. Next, I place an object of known weight, in this case a bottle of water, and determined the scale between what the scale should read and the value displayed. After these adjustments, the scale displayed the correct value.
HX711
Datatypes (KEYWORD1) | |
---|---|
HX711 | KEYWORD1 |
Methods and Functions | (KEYWORD2) |
---|---|
is_ready | KEYWORD2 |
set_gain | KEYWORD2 |
read_average | KEYWORD2 |
get_value | KEYWORD2 |
get_units | KEYWORD2 |
tare | KEYWORD2 |
set_scale | KEYWORD2 |
get_scale | KEYWORD2 |
set_offset | KEYWORD2 |
get_offset | KEYWORD2 |
power_down | KEYWORD2 |
power_up | KEYWORD2 |
#include "HX711.h"
// HX711 circuit wiring
const int LOADCELL_DOUT_PIN = A1;
const int LOADCELL_SCK_PIN = A0;
HX711 load;
void setup()
{
Serial.begin(115200);
load.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
delay(250);
load.tare(-182600); // Hacer 20 lecturas, el promedio es la tara
load.set_scale(950); //The default scale is 1
}
void loop() {
if (load.is_ready())
{
//long reading = load.read(); // Reading without taring and scaling
//long reading = load.get_value( ); // Value read minus tare, (do 10 times)
long reading = load.get_units(10); //Unweighed and corrected weight
Serial.println(reading);
}
else
Serial.println("HX711 not found.");
delay(500);
}
Wokwi I uploaded the same program to the Wokwi platform, this time with a 5 kg load cell. I adjusted the scale values so that the reading corresponds to the setpoint value. The tare value, in this case, is meaningless as the strain gauges of the load cell start from a zero value.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "HX711.h"
HX711 load;
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
float weight =0;
void setup() {
Serial.begin(115200);
// Serial.println("Initializing the scale");
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 10);
// Display static text
display.println("Hello, world!");
display.println("Fab Academy 2025");
load.begin(D8, D7);
//load.set_scale(); //The default scale is 1
// load.tare(); // Take 20 readings, the average is the tare weight.
load.set_scale(420);
delay (2000);
}
void loop() {
// Serial.println(load.get_units(), 1);
// delay(1000);
weight = load.get_units();
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 10);
display.println("Fab Academy 2025");
// Display static text
display.setCursor(0, 30);
display.setTextSize(2);
display.println(weight);
display.display();
}
Programming ATtiny412
For the group assignment, I was in charge of reviewing and documenting the ATtiny412 microprocessor. On Thursday, February 14th, Luis provided us with the materials to build a Serial UPDI-3 pin, and with his help, I was able to get a functional programmer working.
I consulted the information about this electronic board here:
Using this programmer, I uploaded a simple program to the Hello World Luis Díaz-Faes board. This board was designed by Luis during Week 6 of his FabAcademy training in 2022 and features a Megatiny412.
Up until now, I had been uploading code to an Arduino Uno via USB. To send it to the development board through the programmer, I needed to select the correct settings in the Arduino IDE.
First: File > Preferences > Aditional boards manager > Add URL: https://drazzy.com/packkage_drazzy.com_index.json
and click twice but this url did not work.
After checking the web for alternative URLs I found this reference https://descartes.net/package_drazzy.com_index.json
I then copied & pasted this URL and I was able to install it.
Later, I selected the Attiny412 board and the PORT and press ok.
Then, under Tools > Programmer, I chose serialUPDI - SLOW: 57000 baud.
After picking the right programmer, I uploaded using programmer, and as you can see in the video, the programming went smoothly.
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(7, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(7, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(7, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}