Final Project

The inspiration for this project comes from my personal experience. I was diagnosed with hearing loss at the age of seven, and since then, one of my biggest challenges has been identifying the source of sounds—especially while walking or moving around. Often, I found it so difficult to determine when someone is speaking to me and from which direction.

Driven by this need, I am developing a wearable device designed to restore the user's sense of auditory orientation. The system detects the source of loud sounds and uses strategic haptic feedback (vibration patterns) to indicate exactly where they are coming from.

Furthermore, this project aims to go beyond safety and assistance; it integrates a feature that transforms music into vibrations. This enriches the sensory experience, allowing people with profound hearing loss or deafness to 'feel' the music and reconnect with their environment in a new way.

link Fig 1. Project sketch

Initial Project Systems

🎤

Sound Input System

The project will use basic microphones placed on different sides of the wearable to detect surrounding sounds. By comparing the signals, the system will estimate from which side the sound is coming.

🧠

Processing & Control

A small microcontroller, such as a XIAO series board, will be used to read the microphone data and make simple decisions based on sound intensity and direction.

📳

Haptic Feedback System

Small vibration motors will provide feedback to the user. Each vibration pattern will represent a direction, helping the user understand where the sound is coming from through touch.

🔋

Power System

The device will be powered by a compact battery, allowing it to be wearable and portable. Basic voltage regulation will be included to safely power the electronics.

👕

Physical / Wearable

The structure will be designed as a wearable object (like a clip or band) and fabricated using 3D printing or flexible materials to comfortably hold the electronic components.

Plan for the next weeks

To achieve the final result, I have mapped the development of the device to the weekly assignments:

  • • Computer-Aided Design: Design the 3D model of the wearable casing, focusing on ergonomics so it fits comfortably on clothes or as a wristband.
  • • Electronics Design & Production: Design a custom PCB for the XIAO microcontroller that connects the microphones and vibration motors without loose wires.
  • • 3D Printing: Fabricate the final housing of the device to hold all components securely using PLA or PETG.
  • • Molding and Casting: Create a soft silicone cover or button interface for a better tactile experience and user comfort.
  • • Input Devices: Program the microphones to read ambient sound levels and implement the logic to detect the direction of the noise source.
  • • Output Devices: Control the vibration motors to provide haptic feedback (left or right vibration) corresponding to the detected sound direction.
  • • Interface and Application Programming: Build a simple visual interface to monitor the microphone values in real-time and calibrate the sensitivity.

Final project progress

First, it was essential to design a board that included all the necessary outputs to test the components required for the final project, such as the vibration motor and the microphone.

This board was designed during the Electronics Design week.

Folder structure
Folder structure

Microphone

During the Input Devices week, I used an analog microphone module based on the MAX4466. I connected the module’s output to an ADC pin on my board, which uses a XIAO RP2350 microcontroller. The microcontroller samples these continuous voltage fluctuations and converts them into digital values, allowing the system to measure real-time sound intensity.

Code

 
                    const int micPin = D0;  // Pin of the microphone
                    const float volt = 3.3; // Voltage power of the XIAO 

                    void setup() {
                    analogReadResolution(12);      // Reading precision
                    Serial.begin(115200);          // Serial communication
                    while(!Serial);               
                    }

                    void loop() {
                    unsigned int sampleWindow = 50; // Use 50 milliseconds to listen for sound
                    unsigned int signalMax = 0;     // Variable to store the highest sound level
                    unsigned int signalMin = 4095;  // Variable to store the lowest sound level

                    unsigned long startMillis = millis(); // Record the exact time we start listening

                    // Collect sound data for 50 milliseconds
                    while (millis() - startMillis < sampleWindow) {
                        int sample = analogRead(micPin);  // Read the current value from the microphone
                        if (sample > signalMax) {         // If current value is higher than our max
                        signalMax = sample;             // Update signalMax
                        }
                        if (sample < signalMin) {         // If current value is lower than our min
                        signalMin = sample;             // Update signalMin
                        }
                    }

                    // Calculate the difference between the loudest and quietest moments
                    int peakToPeak = signalMax - signalMin; 
                    
                    // Convert the digital intensity into real Voltage
                    float volts = (peakToPeak * volt) / 4095.0;


                    Serial.print("Intensity: ");       // Intensity
                    Serial.print(peakToPeak);          // Digital value
                    Serial.print(" | Voltage: ");      // Voltage
                    Serial.println(volts);             // Print the voltage
                    Serial.print(" V | ");

                    int numR = map(peakToPeak, 0, 2000, 0, 30); 
                    for (int i = 0; i < numR; i++) {
                        Serial.print(">");
                    }
                    
                    Serial.println();

                    delay(50);                         
                    }
                

Results

During week 9, I also tested a different microphone, the MP34DT01, a high-performance digital MEMS microphone. This will be the one used in my final project, since unlike analog modules, this digital approach eliminates the need for an external amplifier, improving signal quality.

I connected it to the digital pins of the XIAO RP2350, which uses its internal PIO or PDM interface to decode the bitstream into usable audio data.

Code

 
                    const int micPin = D0;  // Pin of the microphone
                    const float volt = 3.3; // Voltage power of the XIAO 

                    void setup() {
                    analogReadResolution(12);      // Reading precision
                    Serial.begin(115200);          // Serial communication
                    while(!Serial);               
                    }

                    void loop() {
                    unsigned int sampleWindow = 50; // Use 50 milliseconds to listen for sound
                    unsigned int signalMax = 0;     // Variable to store the highest sound level
                    unsigned int signalMin = 4095;  // Variable to store the lowest sound level

                    unsigned long startMillis = millis(); // Record the exact time we start listening

                    // Collect sound data for 50 milliseconds
                    while (millis() - startMillis < sampleWindow) {
                        int sample = analogRead(micPin);  // Read the current value from the microphone
                        if (sample > signalMax) {         // If current value is higher than our max
                        signalMax = sample;             // Update signalMax
                        }
                        if (sample < signalMin) {         // If current value is lower than our min
                        signalMin = sample;             // Update signalMin
                        }
                    }

                    // Calculate the difference between the loudest and quietest moments
                    int peakToPeak = signalMax - signalMin; 
                    
                    // Convert the digital intensity into real Voltage
                    float volts = (peakToPeak * volt) / 4095.0;


                    Serial.print("Intensity: ");       // Intensity
                    Serial.print(peakToPeak);          // Digital value
                    Serial.print(" | Voltage: ");      // Voltage
                    Serial.println(volts);             // Print the voltage
                    Serial.print(" V | ");

                    int numR = map(peakToPeak, 0, 2000, 0, 30); 
                    for (int i = 0; i < numR; i++) {
                        Serial.print(">");
                    }
                    
                    Serial.println();

                    delay(50);                         
                    }
                

Results

Vibration motor

During the Outputs week, I designed a custom module to control the vibration motor that I will use in my final project, using two essential components: a MOSFET and a diode. This setup is necessary because the motor requires more current than a microcontroller pin can safely provide.

Folder structure
Folder structure

Code

 
                    // Pin definitions
                    const int micPin = D0;           // Microphone OUT connected to A0
                    const int modulePin = D5;        // Motor Module connected to D5
+
                    // Settings
                    const float threshold = 2.5;     // Noise limit (Voltage) to trigger the motor
                    const float voltiosReferencia = 3.3; 

                    void setup() {
                    analogReadResolution(12);      // 12-bit resolution for RP2350
                    pinMode(modulePin, OUTPUT);    // Set module pin as output
                    
                    digitalWrite(modulePin, LOW);  // Start with motor OFF
                    
                    Serial.begin(115200);
                    while(!Serial);
                    }

                    void loop() {
                    unsigned int sampleWindow = 50; // 50ms window to catch sound waves
                    unsigned int signalMax = 0;
                    unsigned int signalMin = 4095;

                    unsigned long startMillis = millis();

                    // Step 1: Record sound to find Peak-to-Peak amplitude
                    while (millis() - startMillis < sampleWindow) {
                        int sample = analogRead(micPin);
                        if (sample > signalMax) signalMax = sample;
                        if (sample < signalMin) signalMin = sample;
                    }

                    // Step 2: Calculate intensity and real voltage
                    int peakToPeak = signalMax - signalMin;
                    float volts = (peakToPeak * voltiosReferencia) / 4095.0;

                    Serial.print("Intensity: ");
                    Serial.print(peakToPeak);
                    Serial.print(" | Voltage: ");
                    Serial.println(volts);

                    // Step 3: Logic to activate the External Module
                    if (volts >= threshold) {
                        // If sound is LOUD: Turn ON the module
                        digitalWrite(ledPin, HIGH);
                        digitalWrite(modulePin, HIGH);
                        
                        Serial.println(">>> MOTOR MODULE ACTIVATED <<<");
                        delay(400); // Keep vibrating for 400ms
                    } 
                    else {
                        // If sound is QUIET: Turn OFF everything
                        digitalWrite(ledPin, LOW);
                        digitalWrite(modulePin, LOW);
                    }

                    delay(10); 
                    }
                    

Results