Considering the Fab Lab criteria for the final project, here is is my idea and the sketch.
The AquaSense Smart Swim Coach elevates your swim with real-time feedback, lap count, and time tracking. It alerts for pace and breathing, offers personalized coaching, and sets goals. With a waterproof design, it's your all-in-one companion for a smarter and more effective swimming experience.
Here are few more ideas for my final project.
A fan-powered wall climbing robot employs airflow for adhesion, combining suction and thrust to climb vertical surfaces. Ideal for inspection and maintenance, this innovative design ensures stability and controlled movement, making it a versatile solution for navigating and accessing hard-to-reach areas on walls and structures.
A soft robotics-based massaging robot for feet leverages gentle, customizable pressure on specific points to provide a targeted and relaxing massage experience. Mimicking the principles of reflexology, this innovative robot adapts soft robotic technology to enhance comfort, relieve tension, and promote well-being through precise pressure point stimulation.
An LED cube matrix as an art installation is a visually captivating and dynamic creation. Comprising a three-dimensional array of programmable LED lights, the cube matrix illuminates and morphs into intricate patterns, colors, and animations. This interactive and versatile piece of art engages viewers, transforming spaces with its luminous, ever-changing displays.
Develop a tactile musical instrument for the deaf, translating sound into vibrations and visual cues. Utilize sensors to detect musical nuances, converting them into vibrations or light patterns. Ensure a versatile and inclusive interface, allowing deaf individuals to experience and create music through touch and visual feedback.
After trying out all tools, I've designed the watch using Fusion 360.
I've used Fusion 360 for the rendering. So I opened Render Studio and played around with the environment settings to get these renders.
I used Fusion 360 to animate my design.
I watched a tutorial on animations and tried to implement it on my design. So here, I selected a frame and used transform to components to choose each component and moved. I've also used view to make assembly of the components shown from different directions. So here's the animated video:
The 1.28" Round LCD Display Module features an embedded GC9A01 driver and utilizes the SPI bus for communication. It is a 240x240 Round RGB LCD Display featuring a four-wire SPI communication interface. By utilizing SPI, it efficiently utilizes GPIO ports and enables faster communication speeds. Similar in size to the 240x240 square LCD, it distinguishes itself with rounded edges. This LCD employs the GC9A01 driver, offering a resolution of 240RGB×240 dots.
Pin | Description |
---|---|
VCC | Power (3.3V / 5V input) |
GND | Ground |
DIN | SPI data input |
CLK | SPI clock input |
CS | Chip selection, low active |
DC | Data/Command selection (high for data, low for command) |
RST | Reset, low active |
BL | Backlight |
After refering the documentation of the display module, I thought of testing it out with ESP 32 Module.
So I referred this documentation and documentation for the testing.
Here's the pin connections
ESP 32 Pin | Display Pin |
---|---|
3V3 | VCC |
GND | GND |
G23 | DIN |
G18 | CLK |
G22 | CS |
G16 | DC |
G4 | RST |
3V3 | BL |
Now I need to set up the library.
I searched for “TFT_eSPI” and installed it.
I need to make a couple of modifications in order to get the library working, as it was meant for several types of displays and processors.
Here is what I did:
Using your File explorer, I navigated to Arduino Libraries folder, which is inside my Arduino folder in Documents.
Look for the TFT_eSPI folder and
Inside the folder, I found several files so I looked for the User_Setup.h file.
I opened the file using visual code studio and made the following edits:
Comment out the line defining the ILI9341 driver.
Uncomment the line defining the GC9A01 driver.
Comment out all the SPI definitions for the ILI9341.
For ESP 32, set MOSI to 23.
set SCLK to 18.
set CS to 22.
set DC to 16.
set RST to 4.
Then I saved the file.
A great demo code sample is the Animated_dial sketch, which is found inside the Sprites menu item from File>Examples>TFT_eSPI. This demonstration code will produce a “dial” indicator on the display, along with some simulated “data” (really just a random number generator). In order to run this sketch, I need to install another library. After installation, the code is uploaded and I get this output.
Next example is called Boing Ball Demo and it can be found in Example>TFT_eSPI> DMA Test>Boing Ball Demo
Next Sketch is this Scrolling Sprite Message which can be found in Example> TFT_eSPI> Sprite> ScrollingSprite 16 Bit. I made a few edits to the code to get this.
Since my final project is a swimming watch make a board with esp 32 module will make the watch size really big. So I found out a suitable board for my final project to interface with the display.
So I referred this documentation to understand the board and followed the steps of board installation. I implemented blink program and additionally, I tried to test the inbuilt sensor which is an accelerometer.
So I referred this documentation and used the code there to test the sensor. That documentation is about using tinyml to sense the human acitivity by one of the instructors Salman Farris.
// XIAO BLE Sense LSM6DS3 Data Forwarder #include "LSM6DS3.h" #include "Wire.h" //Create a instance of class LSM6DS3 LSM6DS3 myIMU(I2C_MODE, 0x6A); //I2C device address 0x6A #define CONVERT_G_TO_MS2 9.80665f #define FREQUENCY_HZ 50 #define INTERVAL_MS (1000 / (FREQUENCY_HZ + 1)) static unsigned long last_interval_ms = 0; void setup() { Serial.begin(115200); while (!Serial) ; if (myIMU.begin() != 0) { Serial.println("Device error"); } else { Serial.println("Device OK!"); } } void loop() { if (millis() > last_interval_ms + INTERVAL_MS) { last_interval_ms = millis(); Serial.print(myIMU.readFloatAccelX() * CONVERT_G_TO_MS2, 4); Serial.print('\t'); Serial.print(myIMU.readFloatAccelY() * CONVERT_G_TO_MS2, 4); Serial.print('\t'); Serial.println(myIMU.readFloatAccelZ() * CONVERT_G_TO_MS2, 4); } }
So I tried to keep the microcontroller with my watch and tried to immitate the swimming movements with my hands. The values are getting displayed accordingly.
So for my final project, I'm thinking of using tinyml to train the movements of somersault to count the number of laps. I am a little bit familiarised with tinyml since I had attended a workshop about it by one of the instructor Salman Farris before Fab Academy. So the workshop was about using tinyml to sense the movements of the microcontroller. A similar implementation is available in this documentation about using tinyml for sensing human activity.
So here is the library generated during the workshop>
Magic Wand
Next, I uploaded this code to the board
/* Includes ---------------------------------------------------------------- */ #include < Xiao-nRF-MagicWand-LightControl_inferencing.h > //replace the library name with yours #include "LSM6DS3.h" /* Constant defines -------------------------------------------------------- */ #define CONVERT_G_TO_MS2 9.80665f #define MAX_ACCEPTED_RANGE 2.0f // starting 03/2022, models are generated setting range to +-2, but this example use Arudino library which set range to +-4g. If you are using an older model, ignore this value and use 4.0f instead #define INTERVAL_MS (1000 / (FREQUENCY_HZ + 1)) static unsigned long last_interval_ms = 0; LSM6DS3 myIMU(I2C_MODE, 0x6A); //I2C device address 0x6A static bool debug_nn = false; // Set this to true to see e.g. features generated from the raw signal /** * @brief Arduino setup function */ void setup() { // put your setup code here, to run once: Serial.begin(115200); // comment out the below line to cancel the wait for USB connection (needed for native USB) while (!Serial); Serial.println("Edge Impulse Inferencing Demo"); if (!myIMU.begin()) { ei_printf("Failed to initialize IMU!\r\n"); } else { ei_printf("IMU initialized\r\n"); } if (EI_CLASSIFIER_RAW_SAMPLES_PER_FRAME != 3) { ei_printf("ERR: EI_CLASSIFIER_RAW_SAMPLES_PER_FRAME should be equal to 3 (the 3 sensor axes)\n"); return; } } /** * @brief Return the sign of the number * * @param number * @return int 1 if positive (or 0) -1 if negative */ float ei_get_sign(float number) { return (number >= 0.0) ? 1.0 : -1.0; } /** * @brief Get data and run inferencing * * @param[in] debug Get debug info if true */ void loop() { //ei_printf("\nStarting inferencing in 2 seconds...\n"); delay(2000); //ei_printf("Sampling...\n"); // Allocate a buffer here for the values we'll read from the IMU float buffer[EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE] = { 0 }; for (size_t ix = 0; ix < EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE; ix += 3) { // Determine the next tick (and then sleep later) uint64_t next_tick = micros() + (EI_CLASSIFIER_INTERVAL_MS * 1000); //IMU.readAcceleration(buffer[ix], buffer[ix + 1], buffer[ix + 2]); buffer[ix+0] = myIMU.readFloatAccelX(); buffer[ix+1] = myIMU.readFloatAccelY(); buffer[ix+2] = myIMU.readFloatAccelZ(); for (int i = 0; i < 3; i++) { if (fabs(buffer[ix + i]) > MAX_ACCEPTED_RANGE) { buffer[ix + i] = ei_get_sign(buffer[ix + i]) * MAX_ACCEPTED_RANGE; } } buffer[ix + 0] *= CONVERT_G_TO_MS2; buffer[ix + 1] *= CONVERT_G_TO_MS2; buffer[ix + 2] *= CONVERT_G_TO_MS2; delayMicroseconds(next_tick - micros()); } // Turn the raw buffer in a signal which we can the classify signal_t signal; int err = numpy::signal_from_buffer(buffer, EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE, &signal); if (err != 0) { ei_printf("Failed to create signal from buffer (%d)\n", err); return; } // Run the classifier ei_impulse_result_t result = { 0 }; err = run_classifier(&signal, &result, debug_nn); if (err != EI_IMPULSE_OK) { ei_printf("ERR: Failed to run classifier (%d)\n", err); return; } // print the predictions // ei_printf("Predictions "); // ei_printf("(DSP: %d ms., Classification: %d ms., Anomaly: %d ms.)", // result.timing.dsp, result.timing.classification, result.timing.anomaly); //ei_printf("\n"); for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) { // ei_printf(" %s: %.5f\n", result.classification[ix].label, result.classification[ix].value); if (result.classification[ix].value > .5) { ei_printf("%s \n", result.classification[ix]); } } // if (result.classification[ix].value > .5) { // ei_printf(" %s: %.5f\n", result.classification[ix].label, result.classification[ix].value); // } // } #if EI_CLASSIFIER_HAS_ANOMALY == 1 ei_printf("anomaly score: %.3f\n", result.anomaly); #endif } #if !defined(EI_CLASSIFIER_SENSOR) || EI_CLASSIFIER_SENSOR != EI_CLASSIFIER_SENSOR_ACCELEROMETER #error "Invalid model for current sensor" #endif
So this code will sense the motion of the microcontroller and identify if it is circle, idle or swish.
SL No | Material | Amount |
---|---|---|
1 | Seeed XIAO nRF52840 Sense | ₹1,899.00 |
2 | Seeed Studio 1.28-inch Round Touch Display for XIAO | ₹1,899.00 |
3 | 400 mAh 3.7V single cell Rechargeable LiPo Battery | ₹189.00 |
4 | TP4056 1A Li-ion lithium Battery Charging Module With Current Protection – Type C | ₹11.00 |
5 | NeoPixel WS2812 RGB Addressable LED | ₹359.00 |
6 | 3*6*2.5 mm SMD Tactile Switch | ₹80.00 |
7 | 3V 6*14MM Vibration Hollow Cup Motor | ₹49.00 |
8 | Smart Watch Belt Steel Button | ₹20.00 |
9 | SeSun eTPU-95A 3D Printing Filament-Transparent Purple | ₹2,149.00 |
10 | Aditya Silicone Rubber RTV – 3915 – 1 Kg. – German Materials Silicone | ₹1,395.00 |
Total | ₹8,050.00 |