Skip to content

9. Wearables

Research

describe what you see in this image

"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."

weekly assignment

Check out the weekly assignment here or login to your NuEval progress and evaluation page.

about your images..delete the tip!!
  1. Remember to credit/reference all your images to their authors. Open source helps us create change faster together, but we all deserve recognition for what we make, design, think, develop.

  2. remember to resize and optimize all your images. You will run out of space and the more data, the more servers, the more cooling systems and energy wasted :) make a choice at every image :)

This image is optimised in size with resolution 72 and passed through tinypng for final optimisation. Remove tips when you don't need them anymore!

get inspired!

Check out and research alumni pages to betetr understand how to document and get inspired

Add your fav alumni's pages as references

References & Inspiration

The project uses piezos as tap sensors in a glove controlled by FLORA (Adafruit's wearable platform). Touching different parts of the glove generates signals through the piezos, which are then translated into MIDI commands. This allows users to control musical software or hardware, turning the glove into an interactive instrument or controller.

Innovation and Wearables: It combines piezoelectric sensors with wearable technology for a practical and fun application, showcasing how wearables can integrate into performing arts.

MIDI as a Universal Language: MIDI is widely used in electronic music and production. This project is not just an example of creative interactivity but also a potential tool for musicians and producers.

Accessible DIY: Adafruit provides detailed tutorials, making it easy for anyone to replicate the project and experiment with electronics and music.

This project is a perfect example of how technology can be inclusive and foster creativity. It combines skills in programming, design, and music, and could inspire similar projects in other fields, such as interactive fashion or gaming.


Tools

Tools

Process and workflow

My sketches are ...

This schematic 1 was obtained by..

This tutorial 2 was created using..

footnote fabrication files

Fabrication files are a necessary element for evaluation. You can add the fabrication files at the bottom of the page and simply link them as a footnote. This was your work stays organised and files will be all together at the bottom of the page. Footnotes are created using [ ^ 1 ] (without spaces, and referenced as you see at the last chapter of this page) You can reference the fabrication files to multiple places on your page as you see for footnote nr. 2 also present in the Gallery.

Jugando con la oled

#include #include #include

// Definición de pantalla #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_RESET -1 #define SCREEN_ADDRESS 0x3C

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// Función para dibujar el ojo en diferentes estados void drawEye(int state) { display.clearDisplay();

// Contorno del ojo (usando líneas) display.drawLine(24, 32, 104, 32, SSD1306_WHITE); // Línea base display.drawLine(24, 32, 64, 12, SSD1306_WHITE); // Parte superior izquierda display.drawLine(64, 12, 104, 32, SSD1306_WHITE); // Parte superior derecha

// Diferentes estados del ojo if (state == 0) { // Ojo abierto: dibuja un círculo en el centro (iris) display.fillCircle(64, 32, 8, SSD1306_WHITE); // Iris } else if (state == 1) { // Ojo medio cerrado: línea más gruesa display.drawLine(24, 32, 104, 32, SSD1306_WHITE); display.drawLine(24, 33, 104, 33, SSD1306_WHITE); } else { // Ojo cerrado display.drawLine(24, 32, 104, 32, SSD1306_WHITE); }

display.display(); }

void setup() { // Inicialización de la pantalla OLED if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) { // Corregir la inicialización Serial.println(F("No se pudo iniciar la pantalla OLED")); for (;;); // Bucle infinito en caso de error }

display.clearDisplay(); display.display(); }

void loop() { // Ojo abierto drawEye(0); delay(1000);

// Ojo medio cerrado drawEye(1); delay(200);

// Ojo cerrado drawEye(2); delay(300);

// Ojo medio cerrado al abrir drawEye(1); delay(200); }

corazon

include

include

include

define SCREEN_WIDTH 128

define SCREEN_HEIGHT 64

define OLED_RESET -1

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// Dirección del I2C, asegúrate de que esta sea la correcta (0x3C es común para muchos módulos)

define SCREEN_ADDRESS 0x3C

void setup() { // Inicializar pantalla if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) { Serial.println(F("SSD1306 allocation failed")); for (;;); }

display.display(); delay(2000); }

void loop() { for (int i = 0; i < 5; i++) { drawHeart(64, 32, 15 + i*5); // Cambiar el tamaño del corazón delay(200); display.clearDisplay(); delay(200); } }

// Función para dibujar el corazón void drawHeart(int x, int y, int size) { display.fillCircle(x - size / 2, y, size / 2, SSD1306_WHITE); // Lado izquierdo del corazón display.fillCircle(x + size / 2, y, size / 2, SSD1306_WHITE); // Lado derecho del corazón display.fillTriangle(x - size, y, x + size, y, x, y + size, SSD1306_WHITE); // Punta del corazón display.display(); }

Code Rate sensor

To create the "visual wearable", I used an Arduino heart rate sensor as the INPUT and a 2.5" OLED display module with a 128x64 resolution for the MSP430 STM32 series as the OUTPUT. The purpose of this device is to display a real-time animation of a person's heartbeats after exercising, serving as a visual stimulus symbolizing the reward for physical activity. This tool will be very useful for my long working hours hehehe.

How to draw a heart?

The heart in the code is drawn using basic graphic primitives provided by the Adafruit GFX library, specifically circles and a triangle.

  • The pulse sensor reads the analog signal and returns a value corresponding to your heart rate.
  • The signal is smoothed to eliminate sudden fluctuations and provide a more stable output.
  • The smoothed value is used to adjust the size of the heart animation displayed on the OLED screen. A higher heart rate makes the heart larger, while a lower rate makes it smaller.
  • The heart animation is continuously updated to "pulse" based on changes in the heart rate, providing a visual representation of your heartbeat.

Top Circles: - Two circles are used to form the upper curves of the heart. - They are centered to the left and right of the heart's central point. - The radii of the circles are scaled according to the desired size of the heart.

display.fillCircle(x - size / 2, y - size / 2, size / 2, SSD1306_WHITE); display.fillCircle(x + size / 2, y - size / 2, size / 2, SSD1306_WHITE);

Details:

  • x - size / 2 and x + size / 2: Position the circles to the left and right of the x-center.
  • y - size / 2: Places both circles above the central y-point.
  • size / 2: Defines the circle's radius, which depends on the desired size.

Bottom Triangle:

??? A filled triangle is used to connect the bases of the circles and form the pointed lower part of the heart. "

display.fillTriangle(x - size, y, x + size, y, x, y + size * 1.5, SSD1306_WHITE);

Details:

  • (x - size, y): Defines the left vertex of the triangle.
  • (x + size, y): Defines the right vertex of the triangle.
  • (x, y + size * 1.5): Defines the bottom vertex of the triangle, located below the y-center.

Final Structure: By combining the two circles and the triangle:

  • The circles create the two curved upper halves.
  • The triangle forms the pointed lower part.
  • Together, they shape the silhouette of a heart.

Visual representation:

  ****    ****
******  ******

****************
  ************
    ********
      ****
       **

These are the libraries you need to download and add to the code:

Wire.h:

Description: This library is used for I2C (Inter-Integrated Circuit) communication. It allows the microcontroller (like an Arduino) to communicate with other devices (such as displays or sensors) via this two-wire communication protocol.

Adafruit_GFX.h:

Description: This is a general graphic library that provides functions for drawing on displays. It supports basic graphics like lines, circles, text, etc. It is used alongside other libraries that control specific types of displays (in this case, the SSD1306 OLED display).

Adafruit_SSD1306.h:

Description: This library is specifically designed to control OLED displays based on the SSD1306 chip. It provides functions to initialize the display, draw images, text, and other graphics on the OLED screen, making it easy to create visual interfaces.

Definition of Constants

These lines define the size of the OLED screen (128x64 pixels) and initialize the display object using the Adafruit SSD1306 library.

Code

#define SCREEN_HEIGHT 64 #define OLED_RESET -1 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

I2C Address

This is the I2C address of the OLED display. The address 0x3C is common in many SSD1306 displays, but it may vary depending on the hardware.

Code

#define SCREEN_ADDRESS 0x3C

Pulse Sensor Configuration

This is the pin where the pulse sensor is connected. The pulse sensor will generate an analog signal that we can read using analogRead().

Code

const int pulsePin = 26; // Pin A0 en Xiao RP2040

Pulse Sensor Variables
  • pulseValue: Stores the current value read from the pulse sensor.
  • smoothedValue: Used to store a smoothed version of the pulse data to make the heart animation more stable.
  • smoothingFactor: A value between 0 and 1 that controls the level of data smoothing. A higher value results in a smoother signal.
  • pulseRate: Stores the pulse rate, i.e., the number of beats per minute (bpm).

Code int pulseValue = 0; int smoothedValue = 0; float smoothingFactor = 0.1; int pulseRate = 60;

loop()

  • pulseValue = analogRead(pulsePin);: Reads the analog value from the pulse sensor.
  • Updates the smoothed value (smoothedValue) using a simple smoothing algorithm. It adjusts the previous value by a percentage determined by the smoothing factor (0.1 in this case).
  • The pulseRate is calculated by mapping the smoothed value to a range of 60 to 120 beats per minute. This is used to control the size of the pulsing heart.
  • drawPulsingHeart(64, 32, pulseRate);: Calls the function to draw the heart on the screen based on the calculated pulse rate.
  • Serial.println(smoothedValue);: Sends the smoothed value to the serial monitor for debugging or visualizing pulse data.
  • delay(50);: Adds a small delay between readings and screen updates to stabilize the animation and prevent overloading the display.

drawPulsingHeart()

This function is responsible for drawing the pulsing heart on the OLED display.

  • The heart's size is calculated based on the pulse rate, where a higher pulse rate results in a larger heart.
  • display.clearDisplay(): Clears the screen before drawing a new frame.
  • display.fillCircle(): Draws two circles (representing the upper parts of the heart).
  • display.fillTriangle(): Draws a triangle representing the lower part of the heart.
  • display.display(): Updates the screen to show the heart.
Arduino Code

Arduino Code

Below is the Arduino code that you can copy:


#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 12812
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// I2C address
#define SCREEN_ADDRESS 0x3C

// Pulse sensor pin
const int pulsePin = 26; // Pin A0 on Xiao RP2040

// Sensor variables
int pulseValue = 0;
int smoothedValue = 0;
float smoothingFactor = 0.1;
int pulseRate = 60;

void setup() {
  // Initialize serial communication
  Serial.begin(115200);

  // Initialize OLED display
  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;);
  }
  display.display();
  delay(2000);

  // Configure the pulse sensor pin
  pinMode(pulsePin, INPUT);
}

void loop() {
  // Read the analog value from the pulse sensor
  pulseValue = analogRead(pulsePin);

  // Smooth the readings
  smoothedValue = smoothedValue * (1.0 - smoothingFactor) + pulseValue * smoothingFactor;

  // Map the smoothed value to a pulse rate
  pulseRate = map(smoothedValue, 300, 420, 60, 120);
  pulseRate = constrain(pulseRate, 60, 120);

  // Draw the pulsing heart
  drawPulsingHeart(64, 32, pulseRate);

  // Send smoothed value to the Serial Plotter
  Serial.println(smoothedValue);

  delay(50); // Delay to stabilize readings and animation
}

// Function to draw the pulsing heart
void drawPulsingHeart(int x, int y, int rate) {
  int size = map(rate, 60, 120, 10, 30); // Map the pulse rate to heart size
  display.clearDisplay();
  display.fillCircle(x - size / 2, y - size / 2, size / 2, SSD1306_WHITE); // Left circle of the heart
  display.fillCircle(x + size / 2, y - size / 2, size / 2, SSD1306_WHITE); // Right circle of the heart
  display.fillTriangle(x - size, y, x + size, y, x, y + size * 1.5, SSD1306_WHITE); // Bottom triangle of the heart
  display.display(); // Update the display to show the heart
}
    

```

Arduino Heart Pulse Animation Code

Arduino Heart Pulse Animation Code

This page provides the Arduino code for animating a pulsing heart on an OLED screen, using a pulse sensor and a buzzer for feedback.

Code for Heart Animation with Pulse Sensor


#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// I2C address
#define SCREEN_ADDRESS 0x3C

// Pulse sensor pin
const int pulsePin = 26; // A0 pin on Xiao RP2040

// Buzzer pin
const int buzzerPin = 4;

// Sensor variables
int pulseValue = 0;
int smoothedValue = 0;
float smoothingFactor = 0.1;
int pulseRate = 60;

// Buzzer control variables
bool buzzerState = false;
unsigned long lastBuzzerTime = 0;
const unsigned long buzzerInterval = 100; // Buzzer sound duration in milliseconds

void setup() {
  // Initialize Serial
  Serial.begin(115200);

  // Initialize OLED
  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;);
  }
  display.display();
  delay(2000);

  // Configure pulse sensor pin
  pinMode(pulsePin, INPUT);

  // Configure buzzer pin as output
  pinMode(buzzerPin, OUTPUT);
  digitalWrite(buzzerPin, LOW); // Ensure the buzzer is off initially
}

void loop() {
  // Read analog value from the sensor
  pulseValue = analogRead(pulsePin);

  // Smooth the readings
  smoothedValue = smoothedValue * (1.0 - smoothingFactor) + pulseValue * smoothingFactor;

  // Map the value to a pulse rate
  pulseRate = map(smoothedValue, 300, 420, 60, 120);
  pulseRate = constrain(pulseRate, 60, 120);

  // Draw the pulsing heart
  drawPulsingHeart(64, 32, pulseRate);

  // Activate the buzzer when pulse reaches its peak
  if (pulseRate == 120) {
    playBuzzer();
  }

  // Send data to Serial Plotter
  Serial.println(smoothedValue);

  delay(50);
}

// Function to draw the pulsing heart
void drawPulsingHeart(int x, int y, int rate) {
  int size = map(rate, 60, 120, 10, 30);
  display.clearDisplay();
  display.fillCircle(x - size / 2, y - size / 2, size / 2, SSD1306_WHITE);
  display.fillCircle(x + size / 2, y - size / 2, size / 2, SSD1306_WHITE);
  display.fillTriangle(x - size, y, x + size, y, x, y + size * 1.5, SSD1306_WHITE);
  display.display();
}

// Function to activate the buzzer
void playBuzzer() {
  unsigned long currentTime = millis();

  // Emit a short tone only if enough time has passed since the last tone
  if (currentTime - lastBuzzerTime >= buzzerInterval) {
    digitalWrite(buzzerPin, HIGH); // Turn on the buzzer
    delay(100);                    // Keep the buzzer on for 100 ms
    digitalWrite(buzzerPin, LOW);  // Turn off the buzzer
    lastBuzzerTime = currentTime;  // Update the time of the last tone
  }
}
    

otro codigo

#include #include #include

// Definir la dirección I2C de la pantalla OLED (normalmente 0x3C) #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_RESET -1 #define OLED_ADDR 0x3C // Dirección I2C de la pantalla OLED

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// Definir el pin de lectura del sensor de pulso #define PULSE_PIN D0 // Conectar el sensor al pin D0 (GPIO 0) volatile int pulse_count = 0; unsigned long last_pulse_time = 0;

// Configurar interrupción para el sensor de pulso void pulseDetected() { pulse_count++; // Incrementar el número de pulsos last_pulse_time = millis(); // Registrar el tiempo del último pulso }

void setup() { // Inicializar la pantalla OLED if(!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) { // Usamos OLED_ADDR Serial.println(F("Error al iniciar la pantalla OLED")); while(1); // Detener si no se encuentra la pantalla } display.display(); // Mostrar el inicio delay(2000); // Esperar 2 segundos

// Inicializar el pin del sensor de pulso pinMode(PULSE_PIN, INPUT); attachInterrupt(digitalPinToInterrupt(PULSE_PIN), pulseDetected, RISING);

// Inicializar el puerto serial Serial.begin(115200); // Asegúrate de tener el monitor serie abierto }

void loop() { // Calcular el BPM (latidos por minuto) unsigned long current_time = millis(); float bpm = 0;

if (pulse_count > 0 && (current_time - last_pulse_time) > 1000) { // Cada segundo bpm = pulse_count * 60.0; // Pulsos por minuto pulse_count = 0; // Resetear el contador }

// Mostrar la lectura en la pantalla OLED display.clearDisplay(); // Limpiar la pantalla display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);

// Mostrar el número de pulsos detectados display.setCursor(0, 0);
display.print(F("Pulsos detectados:")); display.setCursor(0, 10); display.print(pulse_count); // Mostrar el número de pulsos detectados

// Mostrar el BPM calculado display.setCursor(0, 30); display.print(F("BPM:")); display.setCursor(0, 40); display.print(bpm); // Mostrar el BPM

display.display(); // Actualizar la pantalla

// Imprimir en el monitor serie también Serial.print("Pulsos: "); Serial.print(pulse_count); Serial.print(" BPM: "); Serial.println(bpm);

// Esperar 1 segundo antes de actualizar nuevamente delay(1000); }

El bueno

Arduino OLED Heart Animation

Arduino OLED Heart Animation

This page showcases the latest three codes for animating a heart on an OLED screen using Arduino.

1. Original Code


#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// I2C address
#define SCREEN_ADDRESS 0x3C

// Pin connected to the pulse sensor
const int pulsePin = 26; // Make sure to use an appropriate analog pin

// Variables for reading the pulse sensor
int pulseValue = 0;
int pulseRate = 60;  // Default pulse rate (adjustable)

// For smoothing the values
int smoothedValue = 0; 
float smoothingFactor = 0.1; // Smoothing factor (0.0 to 1.0)

void setup() {
  // Initialize Serial for the Plotter
  Serial.begin(115200);

  // Initialize the OLED screen
  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;);
  }

  display.display();
  delay(2000);
  pinMode(pulsePin, INPUT); // Configure the sensor pin as input
}

void loop() {
  // Read the pulse sensor value
  pulseValue = analogRead(pulsePin);

  // Smooth the readings for more stability
  smoothedValue = smoothedValue * (1.0 - smoothingFactor) + pulseValue * smoothingFactor;

  // Calculate the pulse rate (adjust based on real sensor values)
  pulseRate = map(smoothedValue, 300, 700, 60, 120); 
  pulseRate = constrain(pulseRate, 60, 120); // Constrain the pulse rate to a logical range

  // Draw the pulsing heart animation
  drawPulsingHeart(64, 32, pulseRate);

  // Send data to the Serial Plotter
  Serial.println(smoothedValue);

  delay(50); // Delay for stable readings and animation
}

// Function to draw the pulsing heart
void drawPulsingHeart(int x, int y, int rate) {
  int size = map(rate, 60, 120, 10, 30); // Adjust the heart size based on pulse rate

  display.clearDisplay();  // Clear the screen

  // Draw the two top circles
  display.fillCircle(x - size / 2, y - size / 2, size / 2, SSD1306_WHITE);
  display.fillCircle(x + size / 2, y - size / 2, size / 2, SSD1306_WHITE);

  // Draw the bottom part of the heart
  display.fillTriangle(x - size, y, x + size, y, x, y + size * 1.5, SSD1306_WHITE);

  display.display(); // Update the screen
}
    

2. Smooth Animation Code


[INSERT THE SECOND CODE HERE]
    

3. Adjusted for Maximum Pulse


[INSERT THE THIRD CODE HERE]
    

Results

Video

From Vimeo

Sound Waves from George Gally (Radarboy) on Vimeo.

From Youtube

---

---

Fabrication files


  1. File: xxx 

  2. File: xxx