ethanl2@andrew.cmu.edu – Intro to Physical Computing: Student Work Fall 2022 https://courses.ideate.cmu.edu/60-223/f2022/work Intro to Physical Computing: Student Work Sun, 18 Dec 2022 12:55:42 +0000 en-US hourly 1 https://wordpress.org/?v=6.0.8 Back-up Alarm by Team Fornax: Final Documentation https://courses.ideate.cmu.edu/60-223/f2022/work/back-up-alarm-by-team-fornax-final-documentation/ Sun, 18 Dec 2022 05:11:51 +0000 https://courses.ideate.cmu.edu/60-223/f2022/work/?p=16847 For this project, we worked in teams of three to design a device that would be useful for a person living with a disability. Each team worked alongside a client from Community Living and Support Services (CLASS) to create something what would be relevant and useful in their lives. Our client was Jeff Owens, an individual with a mobile disability. Through the course of this project we would conduct an interview with Jeff and incorporate his feedback into the final product. To read more about our interview with Jeff, click here.

What We Built

Our end product for Jeff was a device that he could strap onto the bottom of his wheelchair using Velcro strips. This device would help ensure that he would not back up into/onto the objects behind him. Jeff gets in the range of an object behind him the device would beep until he is a reasonable distance away from the object. In additional, the device includes lights that would flash on and off at the same time. Jeff has total control of this device, he has the ability to turn off the device entirely or just the beeping. Similarly, Jeff can adjust the range in which the device starts beeping at.

This is the main photo of the device with all its parts. All the velcro is unstrapped in this photo and there is a loose LED strip in the middle that is connected to the control panel.

This is the control panel close up. It contains a switch that turns off sound (it has sound labeled underneath), and it has a switch that turns off lights and sound (has lights labeled underneath). The switches are like this because we wanted Jeff to have the ability to stop lights and sounds up at the control panel where he can reach. The blue knob is a potentiometer for adjusting the distance the sensor scans for.

This is one of our ultra sonic sensors that is suppose to be strapped to the behind lower part of wheelchair with its one other counterpart. As you can see, you mount this by strapping the velcro tightly around the wheelchair rods.

This is a picture showing what the back of everything looks like, and it’s suppose to show you how you would strap the velcro if it was on the wheelchair.

This is the device on Jeff’s wheelchair at the critique. We didn’t get much time with it but we found it mostly worked except for attaching the underneath box with the Arduino. We must have incorrectly measured on prototype day because the velcro straps were not quite long enough. Otherwise it was kinda successful!

 

Narrative Sketch

After recording another album review for this YouTube, Jeff decides to take a quick nap in his wheelchair. Unknowingly to Jeff at the same time as he begins to drift away his two-year old nephew decided to take out all his toys and begin to play with them all around Jeff. Very quickly Jeff’s nephew gets bored of playing inside and decides to go outside, leaving all his toys still on the ground around Jeff.

After Jeff wakes up from his nap, he realizes that he is surrounded by all his nephew’s toys. Jeff turns on the back-up alarm. Jeff waits and does not hear a beep. He now knows that there is a safe path behind him that he can take to get out of the living room. Jeff has saved himself from getting hurt from accidentally tipping over and has saved himself from hurting his nephew’s feelings by accidentally breaking one of this toys.

How We Got Here

Prototype

The prototype we created was designed to answer the question: How can we help Jeff move safely from Point A to Point B?

Our prototype was more on the simpler side as we wanted to gauge Jeff’s opinion on our approach. The prototype took the shape of a rectangular cardboard box with optical proximity sensors poking out of the frontside. In addition, we mocked up a control panel on paper for Jeff to take a look at. When we showed our prototype, we focused a lot of explaining how device would interact upon certain actions.

This is us testing which sensors to use for our project. We ended up going with the ultrasonic sensor because it had a larger range it detected which would help minimize problems later we suspected. We brought this set up to the prototype critique but the design and wizard of oz prototypes ended up helping us communicate better with Jeff.

This was the underneath box prototype, we talked about how the sensors may end up on the side of this box and be put on the lower half of the wheelchair, however, after looking at Jeff’s wheelchair we decided this wasn’t going to happen.

This is the paper control panel mockups. We had Jeff put his finger on the imaginary buttons to see what was big enough. We also held it next to his arm rest and asked which size was most legible. We found the biggest one was the only viable option after these two tests.

Wizard of Ozzing of the LED Strip

This is what the serial monitor looked like when we were testing the distance sensors before the prototype session.

Here you can see us ideating after Jeff’s interview, trying to get an idea for the prototype critique. We struggled with this because we found Jeff didn’t have any complaints about his daily life. So we tried fleshing out/expanding all three of our ideas and talked to Zach about it. We ended up telling Jeff the problem space we picked but let him decided if he liked this route or not.

The main helpful info we got from the prototype session other than a solid direction for our project was a lot of measurements. This is the main page of notes that documented our measurements through a picture and writing. We ended up referencing this image a lot in the process.

In our mind, our device would mount underneath Jeff’s wheelchair and help detect objects in front of him. From the Prototype Critique, we gained valuable feedback that helped patch up holes from our initial interview with Jeff. Moreover, the Prototype Critique redefined the purpose of our device. Instead of detecting objects in front of Jeff, that he can already see, we learned that it was much more helpful if the device could detect objects behind Jeff as he backs up. This led us to separate the optical proximity sensor from being embedded within the device. We decided to move these sensors to these two metal rods already pointing from the back of Jeff’s wheelchair because these rods were already at an angle.

At the end of the Prototype Critique, we decided to acknowledge and include all the feedback we received from Jeff and the other CLASS clients. As people who do not have much experience with wheelchairs, we believed it was in the best interest to consider all the information we were given as our client knows himself the best. Furthermore, we are making this device for Jeff, hence his opinion would help us finalize our ideas for the final iteration. The main problem we encountered while prototyping was we found that getting the distance sensor accurate was pretty difficult because of angle and the sensor moving around, thus explaining why we wizard of oz the prototype instead.

Process

This is the original code flow chart. This was used to help organize the code initially and figure out how we wanted the information to flow through the device.

This was all our wiring before soldering. This was definitely a lot to tackle and difficult to read when initially soldering.

Results from calibration. This is what we documented when testing the potentiometer. We needed to figure out the highest the calibration should go.

This was the first prototype of the control panel. We ended up deciding the velcro should only strap underneath, because this was extremely unstable and wouldn’t really stay up. We also decided not to do a second potentiometer, and decided to enlarge the hole to a square so the potentiometer was easier to pinch.

This was us testing the ultrasonic sensor holder. We found it to be a little wide and we decided we want a hole to embed the sensor instead of have it sit on top or the wood.

This was us realizing two things. We made a mistake wiring the switches, and the bread board was not fitting in the control panel neatly. This lead us to a lot of re-soldering.

Through this project, we ran into several roadblocks. Firstly, after we had decided on the project, we struggled with deciding exactly how we wanted to go about the user feedback. We had to make some executive decisions on using lights and a buzzer and forgoing vibration. We then had some issues getting our buttons wired, but we then figured out how to get them to work because we found that we accidentally wired the incorrect holes in the soldering board. Afterwards, we then ran into some issues with exactly how we were going to mount the ultrasonic distance sensors on the wheelchair. We realized that the sensors could have easily been bumped, throwing off the distances. We then had to add a potentiometer, though we already had a working setup and working code. After, we ran into several issues with soldering, with the solder on the LEDs easily falling off. This caused several issues, but at the end of the day, we ended up with a working product.

A lot of the issues we ran into were found the night before. This was because we diverged a bit with our projected Gantt chart. We spent the class period before the project’s due date still working, since we had no sense of urgency, and put in little time outside of class. Instead of soldering and assembling the product, which is where we ran into the majority of our problems, we continued trying to refine our code and hardware. If we had dedicated that class period to assembling, we would have had more time to debug, and more time to dedicate to details.

Planned Gantt Chart

Conclusions and Lessons Learned

Our group had a great time with this project and we were happy with the product we produced during the final critique day. That being said, there is always room for improvement, and we received a lot of helpful feedback that we could have implemented, feedback that could have improved our project. 

For example, we received multiple critiques on our non-shrink-wrapped wires, such as “exposed wiring needs shrink wrap,” and “The wires […] would benefit from more protective covering as well”. We thought this was a good critique, as it was one way that our project could have been elevated to the next level. During the final build stage, we were considering adding the shrink wrap to our project, but we ultimately ran out of time. Another critique was that a stable mounting system would have helped a lot with our project, and I am very inclined to agree. The problem that we encountered was that we didn’t have access to Jeff’s wheelchair, and a more complicated mounting system would have taken up a lot of time, and been very difficult to create in the scope of our class. We ended up using velcro for mounting, since it was the simplest option, but I do agree that with a more stable mounting system we would have been able to make the product a lot more effective. 

There was also feedback that complimented our use of the wheelchair, and considering the situation that Jeff himself was in. “[T]he group did a nice job figuring out how to make the device fit on his chair best”. The idea of personalization vs. generalization was a critique that was discussed a lot in person as well. We tried to make it very clear that the goal of this project was not to make a manufacturable product, but to make a project for Jeff himself. That being said, I think some of our guests were excited about the possibility that our product had if we were able to generalize it a bit. I think they appreciated how many people our product might have been able to help, which is a critique that is easy to accept. Another positive critique that we received was that the user feedback options that we had were good choices. We got multiple compliments on the visibility and clarity of the lights, but then one guest commented that for the visually impaired, the idea of the buzzer for sound feedback was also a good option. We appreciated this critique because it took us a while to decide what might be the most effective method of user feedback.  

Working with a client with a disability was a good experience for us. We had to be careful about how we worded interview questions, and it was a bit hard to communicate with Jeff, but we managed to find aspects of his life that we could improve and build our project on. In order to do that, we had to dive fairly deeply into what a day in his life looked like. I don’t think there was anything we would have done differently. We tried to be as open as we could when it came to communication with our client, and I think we did a fairly good job, even though our client was not as responsive as we might have hoped. 

I think all of our group members had a good time with this project. The diversity of backgrounds and skills that we brought into this project helped it run smoothly. We learned how to make things, not just for ourselves or for this class, but for other people. Something that really stuck with me was the impact that our work had on so many people. There were multiple clients talking about how important and life-changing the work we were doing was. Though we’ve only been through one semester of this class, we were able to see the applications of our knowledge in a way that was very fulfilling and meaningful.

Technical Details

Electronic Schematic and Block Diagram

Electronic Schematic

 

Block Diagram

Code

/**
 * @title Back-up Alarm
 * @brief A useful device designed for Jeff
 * 
 * 60-223: Introduction to Physical Computing
 *
 * The following code initializes two optical proximity that serve
 * as eyes of the back of Jeff's wheelchair. If Jeff backs within
 * a certain distance of object, the led strip will light up and
 * the buzzer will buzz. The code also gives Jeff the freedom to
 * adjust the upperbound distance using a potentiometer. 
 *
 * @authors Ethan Lu <ethanl2@andrew.cmu.edu>
 *          Frances Adiwijaya <fda@andrew.cmu.edu>
 *          Gia Marino <gnmarino@andrew.cmu.edu>
 *
 * @mapping
 *  Arduino Pin |   Role   |   Description   
 *  ------------|----------|-----------------
 *      A0         INPUT    Potentiometer
 *      3          INPUT    Buzzer Control Button
 *      4          INPUT    Device Control Button
 *      5          OUTPUT   Buzzer
 *      9          INPUT    ECHO Pin for Right Sensor
 *      10         INPUT    TRIGGER Pin for Right Sensor
 *      11         INPUT    ECHO Pin for Left Sensor
 *      12         INPUT    TRIGGER Pin for Left Sensor
 *      13         OUTPUT   LED Strip
 */

/** @brief Import libraries */
#include <NewPing.h>
#include <PololuLedStrip.h>
#include <assert.h>

/** @brief Declare constants */
#define POTENTIOMETER_PIN         A0

#define BUZZER_CONTROL_PIN        3
#define CONTROL_BUTTON_PIN        4
#define BUZZER_PIN                5
#define RIGHT_ECHO_PIN            9
#define RIGHT_TRIGGER_PIN         10
#define LEFT_ECHO_PIN             11
#define LEFT_TRIGGER_PIN          12

#define LED_COUNT     60
#define MAX_DISTANCE 200
#define MAX_BUZZ       8

/** @brief Debugging macros */
#define requires(expr) assert(expr)
#define ensures(expr)  assert(expr)

PololuLedStrip<13> led_strip;
NewPing sonar_left(LEFT_TRIGGER_PIN, LEFT_ECHO_PIN, MAX_DISTANCE);
NewPing sonar_right(RIGHT_TRIGGER_PIN, RIGHT_ECHO_PIN, MAX_DISTANCE);
rgb_color colors[LED_COUNT];

unsigned lowerbound = 10;
unsigned upperbound =  0;

void fill(uint8_t r, uint8_t g, uint8_t b);

/**
 * @brief Declare pin modes
 */
void setup() {
  pinMode(RIGHT_ECHO_PIN, INPUT);
  pinMode(RIGHT_TRIGGER_PIN, INPUT);
  pinMode(LEFT_ECHO_PIN, INPUT);
  pinMode(LEFT_TRIGGER_PIN, INPUT);

  pinMode(CONTROL_BUTTON_PIN, INPUT);
  pinMode(BUZZER_CONTROL_PIN, INPUT);
  pinMode(POTENTIOMETER_PIN, INPUT);

  pinMode(BUZZER_PIN, OUTPUT);
}

/**
 * @brief Main routine
 */
void loop() {
  delay(100);
  upperbound = map(analogRead(POTENTIOMETER_PIN), 0, 1023, 60, 150);

  cleanup();
  if (digitalRead(CONTROL_BUTTON_PIN) == HIGH) {
    unsigned int left_distance = (sonar_left.ping() / US_ROUNDTRIP_CM);
    unsigned int right_distance = (sonar_right.ping() / US_ROUNDTRIP_CM);

    /** Too close to an object */
    while ((lowerbound < left_distance && left_distance < upperbound) || (lowerbound < right_distance && right_distance < upperbound)) {
      fill(255, 0, 0);
      if (digitalRead(BUZZER_CONTROL_PIN) == HIGH) {
        buzz(min(left_distance, right_distance));
      }
      left_distance  = (sonar_left.ping() / US_ROUNDTRIP_CM);
      right_distance = (sonar_right.ping() / US_ROUNDTRIP_CM);
    }
  }
}

/**
 * @brief     Assigns a new rgb value to every element in the color array
 * @param[in] r Amount of red
 * @param[in] g Amount of green
 * @param[in] b Amount of blue
 */
void fill(uint8_t r, uint8_t g, uint8_t b) {
  for (uint16_t i = 0; i < LED_COUNT; i++) {
     colors[i] = rgb_color(r, g, b);
  }
  led_strip.write(colors, LED_COUNT);
}

/**
 * @brief     Activate the buzzer
 * @param[in] distance
 * @pre       `distance` is non-negative
 * @pre       `distance` is less than `MAX_DISTANCE`
 */
void buzz(unsigned long distance) {
  requires(distance < MAX_DISTANCE);
  int x = MAX_BUZZ - int_log2(distance);

  warn(x);
}

/**
 * @brief     Calculate log2 of an integer
 * @param[in] x
 * @return    log2(`x`)
 * @pre       `x` is non-negative
 */
int int_log2(int x) {
  requires(-1 < x);

  int c = 0;
  if (x == 0) return 1; 
  while ((x >>= 1)) { c++; }
  return c;
}

/**
 * @brief     Run the buzzer a number of times
 * @param[in] x The number of times
 * @pre       `x` is non-negative
 * @pre       `x` is less than or equal to 7
 */
void warn(int x) {
  requires(-1 < x);

  for (int i = 0; i < x; i++) {
    digitalWrite(BUZZER_PIN, HIGH);
    delay(50);
    digitalWrite(BUZZER_PIN, LOW);
    delay(50);
  }
  delay(500);
}

/**
 * @brief Turns the buzzer and led strip off
 */
void cleanup() {
  digitalWrite(BUZZER_PIN, LOW);
  fill(0, 0, 0);
}

Design File

Rhino file that was used to laser cut all the pieces of this device.

]]>
Team Fornax: Interview with Jeff https://courses.ideate.cmu.edu/60-223/f2022/work/team-fornax-interview-with-jeff/ Tue, 08 Nov 2022 13:26:23 +0000 https://courses.ideate.cmu.edu/60-223/f2022/work/?p=16757 Introduction:

This interview was conducted by team Fornax, which includes Ethan, Frances, and Gia. We interviewed Jeff on Tuesday November 1st, at 6pm. Our team went into the meeting with the intention of learning about Jeff’s daily struggles effected by his disability, and what he wants to add in his life. However, we also wanted to let Jeff know our intentions and limitations, and make sure he didn’t have any questions. Our hope was that after the meeting we would have a few ideas on how what kind of assistive gadget we could create to make Jeff’s life better or more convenient.

Agenda:

Before the interview we wrote out a bunch of questions and follow up questions that we planned to run through. We didn’t plan to use it as an exact format where we went down the list. It was more so just to make sure we had enough questions to get a solid interview. I think we went through almost every question.

We also wrote up an outline for an introduction to make things clear with Jeff so he knows where we are coming from. It was mostly based on the outline Zach gave us.

Here were the list of questions:

Say: our names – our backgrounds

Ask client to introduce themselves: name, interest in participating in this

Say project goals:

  • Trying to build prototype useful devices (making a convenience machine/ gadget)
  • Engaging in an iterative design process, including gathering formative feedback around the midpoint of the process
  • Taking about seven weeks to go from this meeting to a reasonably high-fidelity final product (explain timeline)

We are not

  • Professional technologists who are experienced in making polished products
  • Planning to build something that will be sold commercially
  • Constrained by any practicality outside of usefulness to the person we’re designing for
  • Likely to invent a totally novel piece of electronics (say limits of Arduino)

Ask client if they have questions about process

Interview Questions (follow up questions in bullet points)

Are there any Daily life activities that are frustrating/difficult? You can list it or go into detail about a few?

  • Can you group your problems into a couple big categories
  • Can you demonstrate it?
  • What makes it difficult?
  • Is there a product you think that can help mediate this?

Is there something you use to enjoy doing that has become harder over time?

    • Is there any creative ideas you have to help this issue
    • Is there a way to make it somewhat easier again
    • What would encourage you to do this activity again?

Could you narrate or draw your daily life?

      • What’s the typical routine?
      • Common emotions throughout the day?
      • What do you look forward too?
      • What do you not look forward too?

What do you care about?

  • Why is it important to you?
  • How would you want to implement it more into your life?
  • What ways can you think of that would bring this into your life more?

What do you need that maybe you don’t always get?

  • What hinders you from this

How would you improve your resources and tools now?

  • Ways to add on or subtract?
  • Is a completely new device needed? Or add on to what you have now?

Tell us some story about inconveniences that come up in your life?

Meeting Summary and Major Takeaways:

Before we could design a unique device for Jeff, it was important for us to understand Jeff’s hobbies and interests. The meeting started with us asking Jeff about his daily routine. Jeff highlighted that his favorite parts of the day are playing video games with his best friend, recording and watching YouTube, and sitting on back porch. Jeff informed us that he decided to participate in this project because he: “likes the invention of new technology”. After getting to know Jeff a bit more, we then began to explore possible avenues in which a device could assist Jeff in his daily life.

At an earlier point, Jeff mentioned that he works as a receptionist at CLASS for a couple days of a week. We asked if there were any little annoyances that he may experience due to being in a wheelchair. Jeff told us his only pet peeve is wh

en the receptionist working the previous shift doesn’t cleanup after themselves. We decides as a group, that this in an avenue we don’t want to further explore. Naturally we then talked more about Jeff’s life at home. We learned that Jeff has a two-year old nephew, who occasionally leaves their toys out on the floor. We asked Jeff he deals with this situation, he told us that he would always get someone else to clean the toys up. This striked us as a possible avenue that we could explore. We also learned that Jeff sits on his back porch because his front porch is at a slight angle. Jeff emphasized to us that he is always nervous about being on the front porch without someone behind him. He said if he would feel more comfortable if he knew that he would be okay by himself.

Quick sketch of wedges elevating a wheelchair

Towards the end of the hour, we talked to Jeff about his YouTube channel. We learned that Jeff likes to make reviews about music albums. We asked Jeff about how he records his videos. We discovered that his setup was very minimalist, he simply records only using his computer in one take.

 

Quick sketch of the Toy Sweeper

Thinking of ways to create the toy sweeper

Post Interview Thoughts: 

Our interview did not quite go how we expected. Jeff was quite satisfied with how his life functioned and it was a bit difficult for us to ideate some ideas for how to improve his experience. It was difficult to get the conversation started, but slowly but surely, we discovered more and more about Jeff’s life. The agenda we had come up with was definitely not adhered to, as we came up with a lot of follow up questions that we didn’t ever get to. 

I think part of the reason that our interview was not quite as successful as we wanted it to be was that we came into the interview assuming that Jeff would have suggestions on what he thought might be a good gadget. Though he was very receptive with ideas that we suggested, it was difficult to get him to complain about his own life. 

In hindsight, our team wished that we asked a little more about the details of the wheelchair itself, as a lot of our ideas were built on improving the wheelchair. We could have asked about the dimensions or the braking system, which might have been good jumping off points for possible ideas. The ideas that we came up with were quite mechanical, and were grasps on the parts of Jeff’s life that we thought we could ease even more, but not necessarily the most achievable and reasonable ideas. 

That being said, I think our interview served its purpose. We got to learn more about the life of Jeff, and we came up with several possible project ideas that we can build on. 

]]>
Carpel Tunnel Prevention Sleeve https://courses.ideate.cmu.edu/60-223/f2022/work/16342-2/ Thu, 27 Oct 2022 03:42:36 +0000 https://courses.ideate.cmu.edu/60-223/f2022/work/?p=16342 Introducing the Carpel Tunnel Prevention Sleeve, an innovative tool that buzzes the user into “Carpel Tunnel Syndrome”-safe arm positions.

Isometric View

Top View

Bottom View

Process Review

Major Decision 1:

The first major decision of this project was abandoning the Arduino Uno in favor of the Arduino Pro Micro. I wanted the Carpel Tunnel Prevention Sleeve to be a compact device, and with the dimension Arduino Uno I could not accomplish this goal. In addition, the Arduino Pro Micro made for much easier prototyping as the microcontroller could be soldered directly onto the circuit board.

Major Decision 2:

The second major decision of this project was changing the design of the Carpel Tunnel Prevention Sleeve to be more like an arm brace as opposed to the original bracelet idea. This change was a result of me struggling to keep both the VL53L0X Laser Distance Sensor and the ADXL335 3-axis Accelerometer parallel to the surface it was above. With the bracelet design, the sensors shifted around too much. With the new arm brace design, there was another VELCRO strip keeping the sensors in-place.

Process Images:

3-axis Accelerometer ADXL335 and VL53L0X Laser Distance Sensor soldered on a circuit board

Both vibrating motors soldered alongside an Arduino Pro Micro

The Carpal Tunnel Prevention VELCRO arm brace

Discussion

From the in-class critique, I received valuable feedback from my classmates that I would consider in the next iteration of the Carpel Tunnel Prevention Sleeve. One specific comment read: “Maybe figure out what’s up with the smell”. This is an incredibly important piece of feedback, because the smell the commenter is referring to the burning smell from the Arduino Pro Micro. My original plan was to power the Carpel Tunnel Prevention Sleeve using the four rechargeable AA batteries I got from IDEATE Lending. Unfortunately, all four batteries were dead and I was not given the charger. I ended up using a 9V battery for a device that can take up to 3.3V, which was not the best decision on my part.

In addition to this comment, the rest of the other comments talked to visual aspect of the Carpel Tunnel Prevention Sleeve. One such comment read: “I think it would be more usable if it was more comfortable and the wires were more hidden. More like a bracelet type of thing“. I agree with the concerns of this commenter. The Carpel Tunnel Prevention Sleeve is quite fragile and putting on and taking off the device is somewhat difficult. I wished I could have devised a clever way to hide the wires from the both the user and the audience.

On a scale from 1 to 5, where 1 is not satisfied at all and 5 is extremely satisfied, I am at a 4. I believe I was able to capture the functionality I was imagining during the Ideation Stage – a wearable device that buzzes. However, much of the visual design was not what I imagined. As of now, the design for the Carpel Tunnel Prevention Sleeve is a bit sloppy, and not sleek at all. I wish I could have improved the overall wiring of the device as some wires ended up crossing each other. I wish could have improved the soldering on the device as it isn’t too clean throughout the circuit board. Improving these three items would make me extremely satisfied with the Carpel Tunnel Prevention Sleeve.

A key discovery I made on this project was how difficult it is to make a compact device. Soldering, wiring, and designing in such as small scope was incredibly frustrating because there is little to no margin of error. Much of my struggle was a result of poor planning. If I could go back and talk to my past self, I would force him to spend a lot more time on planning out how each component will mesh with each other. On a more happy note, this project made me realize how much fun it was to play with VELCRO. In future project, I will look to include VELCRO at any step possible.

If I had to chance to build another iteration of the Carpel Tunnel Prevention Sleeve. I would investigate eliminating the wires completely. A bluetooth chip from IDEATE Lending maybe a good way to fulfill this desire. Another focus in the next iteration would be to make the arm brace a bit more fashionable. Perhaps, I could investigate making a full-on sleeve with fabric.

Block Diagram

Electrical Schematic

Code

/**
 * @Project Title: Carpal Tunnel Prevention Sleeve
 * @Author: Ethan Lu <ethanl2@andrew.cmu.edu>
 * @Description: 
 * Processes analog readings from a VL53L0X distance Laser Sensor and a ADXL335 analog accelerometer 
 * to calculate distance and angle relative to the table. If the distance and angle results in a
 * "bad position", the two vibrating motors will activate, signaling to the user to change positions.
 *
 * @Mapping:
 * Arduino Pin |  Role | Description
 * ------------|-------|------------
 *      2        INPUT    VL53L0X SDA
 *      3        INPUT    VL53L0X SCL
 *      4        INPUT   ADXL335 XOUT
 *      5        INPUT   ADXL335 YOUT
 *      6        INPUT   ADXL335 ZOUT
 *      8       OUTPUT   Motor OUTPUT
 *      9       OUTPUT   Motor OUTPUT
 */


/**
 * @brief: import header files
 */
#include <VL53L0X.h>
#include <Wire.h>
#include <math.h>

/**
 * @brief: define macros
 */
#define pinX 4
#define pinY 5
#define pinZ 6

#define pinMotorRight 8
#define pinMotorLeft 9

#define adcRef 3.3
#define zeroRef 1.569
#define sensitivityRef 0.3

/**
 * @brief: declare a VL53L0X object
 */
VL53L0X laser_distance;

/**
 * @brief: initialize variables
 */
unsigned x, y, z;
float vecX, vecY, vecZ;
float roll, pitch, yaw;

/**
 * @brief: initialize pinouts
 */
void setup() {
  Wire.begin();

  pinMode(pinX, INPUT);
  pinMode(pinY, INPUT);
  pinMode(pinZ, INPUT);

  pinMode(pinMotorRight, OUTPUT);
  pinMode(pinMotorLeft, OUTPUT);
  
  /**
   * @brief: initialize the VL53L0X object
   */
  laser_distance.init();
  laser_distance.setTimeout(500);
  laser_distance.startContinuous();

  analogReference(DEFAULT);
}

/**
 * @brief: activate the Carpal Tunnel Prevention Sleeve
 */
void loop() {
  int distance = laser_distance.readRangeContinuousMillimeters();
  delay(100);

  x = analogRead(pinX);
  y = analogRead(pinY);
  z = analogRead(pinZ);
  delay(100);

  vecX = vectorize(x);
  vecY = vectorize(y);
  vecZ = vectorize(z);
  delay(100);

  roll = eulerize(vecY, vecZ);
  pitch = eulerize(vecX, vecZ);
  yaw = eulerize(vecY, vecX);
  delay(100);

  roll = fabs(roll);
  pitch = fabs(pitch);
  yaw = fabs(yaw);

  /**
   * @brief: determine if a "bad position"
   */
  if(distance < 55) {
    /*
     * @brief: check if current position is bad
     */
    if(roll < 15.0 || 32.5 < roll || pitch < 19.5 || 32.5 < pitch) {
      activate();
      delay(1000);
    }
  }
  deactivate();
}

/**
 * @brief: determine the vector representation of an acceleration value
 * @param[in] a: acceleration value
 * @return: the predicted vector representation
 */
float vectorize(unsigned a) {
  return (a / 1024.0 * adcRef - zeroRef) / sensitivityRef;
}

/**
 * @brief: calculate the angle between two vectors
 * @param[in] v1: the first vector
 * @param[in] v2: the second vector
 * @return: the predicted angle between v1 and v2
 */
float eulerize(float v1, float v2) {
  return atan2(-v1, -v2) * (180 / PI) + 180;
}

/**
 * @brief: floating point equivalent to abs()
 * @param[in] x: the value to convert
 * @return: |x|
 */
float fabs(float x) {
  if(x < 0) {
    return -1 * x;
  }
  return x;
}

/**
 * @brief: send a 5V signal to the vibrating motors
 */
float activate() {
  digitalWrite(pinMotorRight, HIGH);
  digitalWrite(pinMotorLeft, HIGH);
}

/**
 * @brief: send a 0V signal to the vibrating motors
 */
float deactivate() {
  digitalWrite(pinMotorRight, LOW);
  digitalWrite(pinMotorLeft, LOW);
}

 

 

]]>
Double Transducer: Height to Pitch https://courses.ideate.cmu.edu/60-223/f2022/work/double-transducer-height-to-pitch/ Thu, 29 Sep 2022 01:47:50 +0000 https://courses.ideate.cmu.edu/60-223/f2022/work/?p=16087

Ethan’s final double transducer

Harry’s final double transducer

Process Images:

Our initial layout (Harry)

The LCD screen working (Ethan)

VL53L0X Laser Sensor working (Ethan)

Starting to connect each step together (Harry)

Preparing to shave the hot glue stick (Harry)

Every step wired up together (Ethan)

Detail Photos:

Beautiful soldering job by Harry

The linear actuator is attached to slide potentiometer with a stick of hot glue

Double Transducer in Action:

 

Narrative Description:

    When an object moves within one to four inches of the laser distance sensor, the linear actuator will either push or pull along the slide potentiometer. Based on the location of the slide potentiometer knob, a respective pitch is played.

Discussion:

    We initially struggled with connecting the linear actuator with the other components of the project board. We were successfully able to devise a method to create a temporary connection between the knob of the slide potentiometer and the linear actuator using a slightly melted stick of hot glue. Once we had this connection it was very easy to incorporate the linear actuator with the project board — we simply just masking tape. However, this was only the beginning of our troubles with the linear actuator. Due to the nature of our double transducer, we wanted to be able to control the position of the linear actuator. Unfortunately, there were only two default motions — extend and retract. Luckily, we were cleverly able to implement a type of feedback control. Otherwise, we were going to need to scrape our entire middle step.

 

    There were technically components of this project that came easily to the both of us due to previous experience. For example, soldering the connections for the middle step and breadboard management were both emphasized in our previous coursework. Looking towards the future, a few areas of improvement are wire management and reducing the number of loops. If we were able to implement our double transducer more minimally, it would increase the quality of the project board.

 

    Throughout the project timeline, we need to make important decisions regarding how the double transducer was going to be designed. One noticeable example is how we decided to replace the ultrasonic ranger with a VL53L0X laser distance sensor. This decision was overall made because we desired a more accurate measurement for our middle step. On the software-side, we needed to make decisions regarding how each signal would behave with each other. For example, we had the resistance value of the slide potentiometer relate directly to the pitch of the speaker. This decision was born out of the desire of a more direct relationship between the potentiometer and the pitch.

 

Block Diagram:

 

Electric Schematic:

 

 

Code:

/*
* @Project Title: Double Trasducer: Height to Pitch
* 
* @Authors: Harry Schneider & Ethan Lu
* 
* @Description: 
* - Using a VL53L0X Laser Sensor to measure the height
* of an index card (1''- 4'').
* 
* - The measured height determines how far the linear
* actuator moves, which drags the knob of the slide
* potentiometer.
* 
* - The Ardunio maps the potentiometer signal to [200, 2000]
* and sends a frequency to be played by the speaker.
* 
* @Mapping: 
* Arduino pin | role | description
* ------------|--------|-------------
* A0 INPUT Potentiometer Signal
* A4 INPUT VL53L0X SDA
* A5 INPUT VL53L0X SCL
* SCD INPUT LCD SDA
* SCL INPUT LCD SCL
* 7 OUTPUT Linear Actuator INPUT
* 8 OUTPUT Linear Actuator INPUT
* 9 OUTPUT Speaker Signal
*/


/* import header files */
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <VL53L0X.h>

/* object declaration */
VL53L0X sensor;
LiquidCrystal_I2C screen(0x27, 16, 2);

/* pin-related variables */
const int res_pin = A0;
const int laser_SDA = A4;
const int laser_SCL = A5;
const int act_out1 = 7;
const int act_out2 = 8;
const int pitch_out = 9;

unsigned long prev_distance = 0;

/* VL530X-related varaibles*/
unsigned long lcd_timer;
unsigned long count = 0;

/* unfiltered sensor variables */
unsigned distance_val;
unsigned pot_val;
unsigned pitch_val;

/* filtered sensor variables */
unsigned adjusted_distance_val;
unsigned adjusted_pot_val;

void setup() {
  Wire.begin();

  /* pin setup */
  pinMode(res_pin, INPUT);
  pinMode(laser_SDA, INPUT);
  pinMode(laser_SCL, INPUT);

  pinMode(act_out1, OUTPUT);
  pinMode(act_out2, OUTPUT);
  pinMode(pitch_out, OUTPUT);
  
  /* VL53L0X Sensor */
  sensor.init();
  sensor.setTimeout(500);
  sensor.startContinuous();
  
  /* I2C display */
  screen.init();
  screen.backlight();
  screen.home();
}

/* sends out the linear actuator */
void extend() {
  digitalWrite(act_out1, LOW);
  digitalWrite(act_out2, HIGH);
}

/* returns the linear actuator */
void retract() {
  digitalWrite(act_out1, HIGH);
  digitalWrite(act_out2, LOW);
}

void loop() {
  distance_val = sensor.readRangeContinuousMillimeters();

  if (distance_val < 154) {
    pot_val = analogRead(res_pin);
    pitch_val = map(pot_val, 0, 918, 200, 2000);
  
    /* send signal to speaker */
    tone(pitch_out, pitch_val);
    
    if (prev_distance < distance_val) {
      extend();  
    }
    else if (distance_val < prev_distance) {
      retract();
    }
  
    /* status display */
    if (250 <= millis() - lcd_timer) {
      /* safety clear */
      if (count % 2 == 0){
        screen.clear();
      }
 
      adjusted_distance_val = map(distance_val, 52, 154, 0, 99);
      adjusted_pot_val = map(pot_val, 0, 1050, 0, 99);

      /* update LCD screen*/
      screen.setCursor(0, 0);
      screen.print("i:" + String(adjusted_distance_val));
  
      screen.setCursor(6, 0);
      screen.print("m:" + String(adjusted_distance_val));
  
      screen.setCursor(8, 1);
      screen.print(String(adjusted_pot_val));
  
      screen.setCursor(12, 1);
      screen.print("o:" + String(pitch_val));
  
  
      screen.home();
      lcd_timer = millis();
      count++;
    }
    
    prev_distance = distance_val;
  }
  else {
    /* safety clear */
    if (count % 2 == 0){
        screen.clear();
    }

    /* return to base LCD screen */
    screen.setCursor(0, 0);
    screen.print("i:" + String(99));

    screen.setCursor(6, 0);
    screen.print("m:" + String(99));

    screen.setCursor(8, 1);
    screen.print(String(99));

    screen.setCursor(12, 1);
    screen.print("o:" + String(99));
    noTone(9);
    
    count++;
  }
}

 

]]>