Vision Voice Development
Week01
Visualize
To clearly visualize my final project, I have used canva to jot down the ideas and features of my project.

Here is the link to my canva for reference
Circuit
Using Canva I have also made a Draft of the circuit.( The circuit is not finilized and I need to rework on it. ^o^)

Here is the link to detailed connection.
Week02 - Cardboard Prototyping.
Today, our local instructor guided us through the process of cardboard prototyping, which was both fun and interesting. Afterward, we were given two hours to complete our first prototype for our final projects.
Hero Shot

I started by making the glove and attaching the flex sensors.

Next, I researched every component to find their specific dimensions, such as thickness and height. I carefully drew these dimensions onto the cardboard and cut them out using blades and scissors.

After that I estimated the size of the casing and drew on the cardboard.

Once the pieces were ready, I assembled everything to create the final structure.

Key Takeaways( Things I need to work on here after.)
Cloth Glove Fabrication: Figuring out how to transition the design from cardboard to actual fabric.
Sensor Integration: Determining the best method to securely attach the flex sensors to the cloth glove.
Casing Design & Wire Management: Planning the internal layout of the casing to fit the PCB and organize wires neatly.
Accessibility Mechanism: Designing a lid system (likely using screws) that allows you to easily open the casing for maintenance.
Material Constraints: Accounting for the specific thickness of your final materials and hardware (like screw sizes) in your design
Future Plans
Here after I plan to make a working prototype with the cardboard and test my programs and connections.
*Thank You
Week04
Simulations and Prototyping
I wanted to make something for my final project. I wanted to use the XIAO ESP32C3 board and display text when a certain value is reached from the flex sensor. This will help me understand the flex sensor values better, which is a really important component for my final project.
I gathered all the components and made the circuit. The main purpose of this was to test the components and be fimilar with the circuit. In the comming weeks I plan to test all the compoents.


After that I downloaded the following libraries for the OLED display:
Adafruit_GFX.h Adafruit_SSD1306.h

I then added the XIAO ESP32C3 board to the Arduino IDE. This is the link: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_dev_index.json
I added the link to the preference URL tab. Then I downloaded the ESP32 from the Board Manager.


After carefully installing all the libraries and components, I uploaded the code to the XIAO ESP32C3 board.


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);
#define FLEX_PIN D0
// Your exact ranges
#define IDLE_MIN 350 // 350-360 = Bend sensor (idle)
#define HELLO_MIN 280 // 280-345 = Hello World
#define VISION_MIN 200 // 200-275 = I Am Vision Voice
#define THANKS_MIN 110 // 110-195 = Thank You
const char* words[] = {
"HELLO WORLD",
"I AM VISION VOICE",
"THANK YOU"
};
int lastState = -1;
void displayWord(const char* word) {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setTextWrap(true);
int textSize = (strlen(word) > 9) ? 1 : 2;
display.setTextSize(textSize);
int16_t x1, y1;
uint16_t w, h;
display.getTextBounds(word, 0, 0, &x1, &y1, &w, &h);
int yPos = (SCREEN_HEIGHT - h) / 2;
int xPos = (SCREEN_WIDTH - w) / 2;
if (xPos < 0) xPos = 0;
display.setCursor(xPos, yPos);
display.println(word);
display.display();
}
void displayIdle() {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(20, 28);
display.println("Bend the sensor...");
display.display();
}
void setup() {
Serial.begin(115200);
pinMode(FLEX_PIN, INPUT);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("SSD1306 allocation failed");
while (true);
}
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(10, 20);
display.println("VISION");
display.setCursor(30, 42);
display.println("VOICE");
display.display();
delay(2000);
displayIdle();
}
void loop() {
int flexValue = analogRead(FLEX_PIN);
Serial.print("Flex Value: ");
Serial.println(flexValue);
int currentState = -1;
if (flexValue >= IDLE_MIN) {
currentState = -1;
} else if (flexValue >= HELLO_MIN) {
currentState = 0;
} else if (flexValue >= VISION_MIN) {
currentState = 1;
} else if (flexValue >= THANKS_MIN) {
currentState = 2;
}
if (currentState != lastState) {
if (currentState == -1) {
displayIdle();
} else {
displayWord(words[currentState]);
}
lastState = currentState;
}
delay(100);
}
Code Explanation
After that I wrote the code. Note that the code wasn't entirely written by me. It was written with the help of Claude AI.
Libraries Used
I used three libraries for this project:
- Wire.h — this handles the I2C communication between the microcontroller and the OLED display
- Adafruit_GFX.h — this is a base graphics library that lets you draw text and shapes on a display
- Adafruit_SSD1306.h — this one is specifically for controlling the SSD1306 OLED display
How the Code Works
1. Defining the Screen and Pin
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define FLEX_PIN D0
This part basically sets up the OLED display size, which is 128×64 pixels, and tells the code which pin the flex sensor is connected to — in this case, D0.
The OLED_RESET -1 just means I'm not using a separate reset pin for the display.
2. Setting the Flex Sensor Ranges
This was honestly the most important and tricky part I had to figure out. The flex sensor gives out different analog values depending on how much it's being bent. So I had to test it a bunch of times using the Serial Monitor and note down what values came out at different bend positions.
Here are the ranges I ended up with:
| Flex Value Range | What it Shows |
|---|---|
| 350 – 360 | Idle (not bent) |
| 280 – 345 | "HELLO WORLD" |
| 200 – 275 | "I AM VISION VOICE" |
| 110 – 195 | "THANK YOU" |
I also stored all the phrases in an array so I can just call them by their index number instead of retyping them every time:
3. Tracking the State
I used a variable called lastState to keep track of what's currently being shown on the display. This way, the display only updates when the state actually changes — so it's not constantly refreshing for no reason. -1 means the display is in idle mode.
4. The displayWord() Function
void displayWord(const char* word) {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setTextWrap(true);
int textSize = (strlen(word) > 9) ? 1 : 2;
display.setTextSize(textSize);
int16_t x1, y1;
uint16_t w, h;
display.getTextBounds(word, 0, 0, &x1, &y1, &w, &h);
int yPos = (SCREEN_HEIGHT - h) / 2;
int xPos = (SCREEN_WIDTH - w) / 2;
if (xPos < 0) xPos = 0;
display.setCursor(xPos, yPos);
display.println(word);
display.display();
}
This is the function that actually puts the text on the OLED screen. I added a small bit of logic here to handle text sizing:
- If the phrase is longer than 9 characters, it uses a smaller text size (1) so everything fits on the screen
- If it's shorter, it uses size 2, which looks bigger and easier to read
I also made the text centered on the screen using getTextBounds(). What this does is calculate the width and height of the text first, and then figure out the exact x and y position to place it right in the middle:
5. The displayIdle() Function
void displayIdle() {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(20, 28);
display.println("Bend the sensor...");
display.display();
}
This is a simple function that shows the idle message "Bend the sensor..." whenever the flex sensor is in its resting position (not bent). It just lets the user know that the device is ready and waiting.
6. The Setup Function
void setup() {
Serial.begin(115200);
pinMode(FLEX_PIN, INPUT);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("SSD1306 allocation failed");
while (true);
}
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(10, 20);
display.println("VISION");
display.setCursor(30, 42);
display.println("VOICE");
display.display();
delay(2000);
displayIdle();
}
When the board first powers on, here's what happens step by step:
- The Serial Monitor starts at a baud rate of
115200(useful for debugging) - The flex sensor pin is set as an input
- The code checks if the OLED display started successfully — if it didn't, it prints an error and just stops
- It then shows a startup screen saying "VISION VOICE" for 2 seconds
- After that, it switches over to the idle screen
7. The Main Loop
void loop() {
int flexValue = analogRead(FLEX_PIN);
Serial.print("Flex Value: ");
Serial.println(flexValue);
int currentState = -1;
if (flexValue >= IDLE_MIN) {
currentState = -1;
} else if (flexValue >= HELLO_MIN) {
currentState = 0;
} else if (flexValue >= VISION_MIN) {
currentState = 1;
} else if (flexValue >= THANKS_MIN) {
currentState = 2;
}
if (currentState != lastState) {
if (currentState == -1) {
displayIdle();
} else {
displayWord(words[currentState]);
}
lastState = currentState;
}
delay(100);
}
This is the main loop that keeps running over and over. Here's what it does:
- It reads the analog value from the flex sensor every 100 milliseconds
- It also prints the value to the Serial Monitor — this was super helpful when I was testing and figuring out the ranges
- It then checks which range the value falls into and sets the
currentStateaccordingly - If the
currentStateis different from thelastState, it updates the display — either showing the idle message or the matching phrase lastStategets updated so the display doesn't keep refreshing unnecessarily
Important Improvement
I made the display update only when the state changes:
- Prevents flickering
- Makes the output much smoother
Results

Here when I bend the flex sensor the text changes to the corresponding phrase that I setup in the Code. Yayyy! :D