pheo@andrew.cmu.edu – Intro to Physical Computing: Student Work Fall 2021 https://courses.ideate.cmu.edu/60-223/f2021/work Intro to Physical Computing: Student Work Fri, 10 Dec 2021 22:01:03 +0000 en-US hourly 1 https://wordpress.org/?v=5.8.9 Retractable Rain Hood by the Apricots: Final Documentation https://courses.ideate.cmu.edu/60-223/f2021/work/retractable-rain-hood-by-the-apricots-final-documentation/ Fri, 10 Dec 2021 22:01:03 +0000 https://courses.ideate.cmu.edu/60-223/f2021/work/?p=14689 For this project we had a client with a physical disability with whom we had to work with to come up with a solution to a problem they were facing. Our client uses a wheelchair and has little strength in her hands. As a result, she has a really hard time using an umbrella. After meeting with the client, we decided to come up with a solution that would allow for easy control of a product to protect her from the rain while also still being able to control her wheelchair.

 

WHAT WE BUILT

For the solution we designed a hood, inspired by a stroller hood, that is motorized and controlled by the user with two buttons. At least, that was the initial plan. Due to unforeseen circumstances and given our time constraint, we were only able to build the hood, and could not motorize it. The hood goes from the back of the wheelchair and then moves to a position above the client that protects her from the rain.

 

Narrative Sketch

As Cam is about to leave her house it starts to rain. She realizes this and as she is about to leave through the door presses the open button, which is located just below the joystick on her armrest. The hood then opens up covering her body and protecting her from the rain. Once in the vehicle, she then presses the close button to close the hood, moving back to the back of her wheelchair.

 

PROTOTYPE & PROCESS

*confused i think cuz i was writing about the final design instead of the prototype so gonna have to rewrite statements below

This prototype was designed to help answer the design question: “How can [client] keep themselves protected from the rain while still being able to control their wheelchair?”

The prototype shown below is a smaller version of the hood made using plastic ribbing and trash bag material.

Top view of the prototype fully opened.

Side view of opened hood.

Design sketch.

Sketch of hood.

Initial version of prototype

At first, we wanted to create the hood as shown below, with each rib of the hood on their own separate axis. However, we realized that this overcomplicating the device, and that the ribbings could all be placed on the same point of access, so the prototype was simplified in this manner.

Initial prototype laid out with ribbings attached

Initial prototype with ribbings and other components laid out

Whiteboard sketches made during prototype process

Whiteboard sketches made during prototype process(continued)

 

From prototyping the hood portion of the assembly, we were able to figure out how we wanted to construct the moving parts of the device. At first, we unsure on how we wanted the ribbings of the hood to be attached to the device: Did we want them all separate or on one rod? But by prototyping, we were able to come to the conclusion that using one rod mount is simpler. During prototyping, what sort of materials to use was another question we began to address, but never really answered until later in the project, post-prototype. We also wanted to create a motorized version of the prototype, as seen by the servo motors in the pictures above, but due to time constraints, we were unable to make this a reality. In hindsight, this was a good choice, as a motorized version would have been difficult when moving around the hood with the client when making measurements. During prototyping, we were also unable to come up with a solid construction or plan on how to attach the hood onto the wheelchair, a major concern that would be addressed later in the project after we met with the client in person and made measurements.

Overall we received positive feedback on our first prototype, no recommendations were given for us to consider and incorporate into our final design. However, the client did specify, when asked, whether or not she wanted a button-operated device or a joystick-operated device, as well as saying that she wanted the hood to be a large enough size to not make her feel constricted. When it comes to critiques of the prototype, we had thought that a full-shell version of the hood, with a full-180 degree range, would be the final design of the hood. However, after feedback from the client, we moved to a quarter-shell design, with a 90-degree range of protection. What surprised us as well was how large the actual hood would need to be after taking measurements, as the hood’s width alone would be about 32 inches.

 

 

PROCESS

The Retractable Rain Hood attaches to the back of the wheelchair at three places with clamps. These three clamps connect to a box, and at the top of the box is the system that attaches to the hood. The hood is designed to be a quarter of an ellipsoid and so the two wooden strips (reinforcements) in the hood are different lengths. The entire piece is made from wood and then a clear trash bag is what the hood is made from.

At the beginning of this project we were both very concerned and stressed about how and where we would complete this project. One of the things we were worried about was how we would connect the Retractable Rain Hood to the wheelchair in a place that would support the piece and also not cover up anything important on the wheelchair. After meeting with our client and getting to see the wheelchair in person we were able to come up with a solution to our main concern, and this was to clamp the Retractable Rain Hood at three points in the back of the wheelchair. At the end we were able to come up with a design that properly addressed our problem, apart from it being motorized though of course.

When it came to creating the wooden strips in the hood, first we laser cut 3 panels to curve the strips against. Since two of the curved panels were too large for the wooden sheets we had to cut them into four pieces. We also laser cut thin rectangles to turn into the wooden strips. After this, we glued two rectangle pieces together with different lengths and clamped them to the panels, we continued this, while fitting the rectangles into each other, until the wooden strips were complete. The hardest part during this process was the whole thing, but especially so when we got to the part of the panel that was curved. We had a hard time fitting the rectangle pieces together at the right lengths and keeping them flush with the panels. At times the rectangle pieces would pop out or broke from the tension of the curve. Another difficulty we faced was a result of two of the panels being being made from four pieces because it made it harder to keep the rectangle pieces at the right position. However, after creating the first wooden strip we were able to speed up the process for the other two.

One of the things that took longer than expected was deciding on the materials. That along unforeseen circumstances caused our planned materials to not get here on time as expected. Something that we forgot to properly take into consideration is that we had planned to do things during Thanksgiving break and so that definitely did not work out. Also, because of this and other things we changed the project to just focus on building the piece and removed the part that would make it motorized. So our schedule completely changed and we did not refer to it much after a certain point.

CONCLUSION

 

During our final critique, we really enjoyed hearing feedback and critique from others. To start off one of the feedback we received was, “When first hearing of the project, I worried it would make the wheelchair user look like a baby in a stroller. However, the design you came up with showed me that my opinion was unfounded, and it actually looks good.” This was really interesting to hear as this was not something that we thought much of during the design process. This is also probably because we thought that our material choice would take away from that. But overall we were happy with our final design choice. The next feedback that we received was to “Lean in” on boxiness–>provide storage. Use lay-up technique for “bending” wood. Tinted canopy.” We really appreciated this feedback because it makes the most out of our design giving our client another place to store things on her wheelchair. We also love the idea of using a tinted canopy which would still give our client the chance to look out of the hood while maintaining some sort of privacy. Next, someone stated “consider when the rain hood is down, there might be rain on it and get the person in the chair wet when extended.” This is a really good point and something we had not considered much surprisingly, we were hoping that the water would all fall out once the hood was completely closed again. But that is something that we would have to think through more to ensure that the water did not pool up in the hood. Lastly, someone said “Manufacturing limitations severely affected design decisions.” This was definitely the case, and during a conversation with one of the visitors it was really interesting to hear about the other processes to consider.

Working remotely with our client was a bit difficult mainly because our product heavily depended on being able to see the wheelchair in person. This delayed part of our design process as we did not know how we would fit it to her wheelchair until later on. In retrospect, something that we would have done differently is have more meetings with our client to properly update her on the changes made in our project. We also could have sent her more pictures of our process. Working with our client was great for both parties though and we all enjoyed the process.

After working with a person with a disability, we were just really surprised at how many things don’t already exist. We also learned that you can not make direct modifications to a wheelchair as that would void any warranty that came with it. It would have been really great to see the wheelchair in person one more time to make sure the clamps fit properly.

Looking back at our process some things that we would have done differently include doing better research on the materials and better time management in general. Overall, despite the many mechanical problems and our concerns, we successfully designed and built a product that both us and more importantly our client were happy with.

 

 

TECHNICAL PARTS:

We unfortunately did not have any code to supplement our device, as it created as a non-motorized version. However, attached below are the .dxf files, compressed as a .zip file, for the mounting attachments, clasps, riser box, and rod mounts that could be use to laser cut.

RiserDXFFiles

]]>
Team Apricots: Interview with Connie https://courses.ideate.cmu.edu/60-223/f2021/work/team-apricots-interview-with-connie/ Tue, 09 Nov 2021 14:07:38 +0000 https://courses.ideate.cmu.edu/60-223/f2021/work/?p=14544 Introduction:

This project is done with the intent of creating an assistive device for a client who faces certain challenges, and to start it off, an interview was done to help familiarize the team and client. This meeting was conducted in October 2021, with the purpose of Team Apricots, consisting of Peter, Evangeline, and Nathan, learning more about their client, Connie, and what sort of challenges their project could address. The meeting was held online through Zoom, with each individual in their own separate spaces.

Agenda:

In terms of setting up the meeting, a text group chat was created, and from there, the group was able to come up with an appropriate time for said meeting.

Meeting Agenda (follows the suggested agenda on the course website):

  • Group member introductions followed by Connie’s introduction.
    • talk about her disability and what that means for her
    • ask about what she does for a living and her day to day lifestyle
    • share personal stories about interests/hobbies
  • Overview of expectations for the final product that we will be developing
    • Non-professionals, all new to building devices from a hands on approach
    • Not intended to invent something completely new and scalable as a product
    • We are trying to build a useful prototype of an assistive device
    • Ending with a reasonably well done product at the end of the 5 week timeframe
  • Discussion of daily tasks that Connie has trouble with and potential solutions
    • Start with asking her if she has any specific tasks that she struggles with
      • where do these problems come from?
      • what would need to happen for this to be solved?
      • how does she generally work around this problem?
    • Ask about hobbies that she likes doing at home
      • what are some struggles she has with these hobbies?
      • what are workarounds that she has found for any problems she has?
  • Whiteboard initial ideas and drawings
  • Make sure we share contact info, emails, phone numbers, best way to contact each other

Summary:

The interview began with brief introductions, and then, what specific disabilities Connie has. However, in terms of the bulk of the interview, most of the content of the interview involved the team learning more about what challenges Connie and people that have similar disabilities to her face in their day-to-day life, rather than brainstorm specific ideas to address said challenges. As the team learned more about Connie, it was more clear what sort of device we could build in terms of feasibility, as well as what things to look out to help make an assistive device that was not intrusive. For instance, because Connie does not have much hand dexterity or strength, it becomes difficult when it comes to activities such as cutting meat, unlocking her door, and gripping shampoo bottles. Other tasks, such as tying shoes or putting socks were difficult, and even on-market “solutions” such as sock aids were not that comfortable or easy to use. We also learned about more about the wheelchair she uses, and certain limitations that come with her wheelchair. Connie mentioned how her wheelchair has hooks located on the back of her wheelchair, but for Connie, the accessibility of these hooks is not satisfactory, and additional side hooks would also be helpful. In addition to problems specific to Connie herself, Connie also outlined more general issues for other people with disabilities, such as how certain products/services are hard to get or access because these people live in rural areas. If their products or services require external management or maintenance, then this becomes even more difficult and frustrating for people in more rural areas.

Peter drawing out image of an idea that could help with turning door knobs.

Image of some of the notes taken during the interview.

Reflection:

Looking back at how the interview meeting, it went pleasantly well, as some of the team felt a bit nervous going into the interview, but as it progressed, a good pace and ambience was established. We did not experience any sort of long lulls in our interview, and Connie was able to articulate clearly difficulties she had and was eager to answer any questions we had. While the interview did not go exactly as planned, the insights the team was able to obtain was conducive in ideation. If one aspect was lacking, it would have helped for Connie to have shown us her wheelchair and the extent of her physical strength and dexterity, but unfortunately, time ran out before we could get that far. What was perhaps unexpected, was how everyday tasks that we would do without second thought were not as simple for people with certain disabilities, and coming out the interview, this made a strong impression on us. Another point that stood out to the group was how some services and products’ accessibility was not equal across all populations, as rural areas have more difficulty.

]]>
Dental Routine Timer https://courses.ideate.cmu.edu/60-223/f2021/work/dental-routine-timer/ Mon, 01 Nov 2021 14:39:44 +0000 https://courses.ideate.cmu.edu/60-223/f2021/work/?p=14231 Dental Routine Timer:

The assistive device made is a device that times and keeps the user on track with three steps of a typical dental routine: Brushing their teeth, using mouthwash, and flossing.

Images:

Process Images and Review:

One major decision in the process of making my device was whether to include a floss dispenser that could be operated by the user, or not. I had initially thought that the floss dispenser was going to be more straightforward, but as I worked on this component, it proved tougher than expected. The fact that the floss strands were stuck together when on the spool meant that the device would also need some minimum amount of force to pull the floss off the main body of floss on the spool, or alternatively, some sort of separating, sharp edge. However, the prototypes I built and modified were not functioning well, and at this point in the project, I had decided to scrap this component in favor of spending more time on other aspects of the project, such as construction. By doing so, I was able to free up more space on my Arduino boards for other parts, such as RFID readers.

Testing of Sensors Prior to RFID Readers

Setting Up of RFID Sensors

Another decision point in this project was the type of sensors I wanted to use to confirm the presence of the toothbrush, mouthwash, and floss. I had first considered IR break beam sensors and ultrasonic ranger, but I was concerned about how they would fit with the mini-shelves I had planned as well as the ultrasonic ranger not giving consistent readings with the mouthwash cup, as the sides of the cup was slightly slanted. In the end, I decided to go with RFID readers, as I thought the rectangular shape would fit well with the mini-shelves, and it would make the device harder to fool in a sense: with other sensors, you could put in any other object to be detected, but with the RFID readers, you need to use the floss and mouthwash cup with the corresponding sticker labels on them. By using RFID readers, I had to be certain in my final design, as they took up a substantial amount of pins on the Arduino board, and had to create multiple portions of my laser-cut design around the RFID readers, such as the mini-shelves and the overall spacing of components due to wiring.

Device without Front Panel

Discussion:

Overall, I feel satisfied with the outcome with the project, given the time crunch I experienced near the final deadline. However, there are some critiques I would like to address. Firstly, one commentator has said, “The aesthetics are very cool, but don’t seem fit for a bathroom“. I also agree with the comment on the size of the device. While carrying it around, it is not very comfortable to carry around, and is quite bulky to move around, but that is secondary to the main issue that it takes up a lot space for what could be a more compressed device. By making the device smaller, I believe it would make the device more easier to set up and use. Because of the device’s size and weight, it could be broken up into two parts: a hub for the electronics and wiring, and then a secondary hub for the placement and detection of the the brush, wash cup, and floss, as suggested by the people during the in-class critique. I also see this as a very good construction for the device, as it would help address the size issue, as well as improve the accessibility of the object. Another comment posted is on the clear acrylic used for the sides of the device: “Love the black acrylic +1 and the clear side view to check mouthwash levels too!“. Funnily enough, it was not intentional to use clear acrylic in the first place, but only because I had run out of black acrylic to use, which had been all spent for the front and back of the device. In terms of the clear side view, I feel conflicted. On one hand, as the commentator has noted, it makes observing how much mouthwash is left much easier, but on the other hand, it also makes the inner construction (which was done sloppily in my opinion) visible, leaving a clear view of the electronics inside. However, in the grand scheme of what was built, I see the construction and functionality of the device as satisfactory. For my purposes, the device is able perform its function well, and has few, near insignificant, hindrances that stand out. If there was one major complaint I have personally, it is that the side panels were not wide enough to fit into the front panel, and the wiring and tapping together of pieces could have done with better. From this, I learned more on how to improve my modeling skills and how to manage the scope of a project so that it does not become overwhelming. Other skills I developed were working with Fusion 360 and laser-cutting, which were both foreign to me before this project. Reflecting upon these thoughts, if I were to build another iteration of this, I would make the project more compact by creating a custom tank for the liquid, as well as making the housing smaller by making it less tall, and wider horizontally. By doing so, I believe that it will become easier to use and more visually appealing in a restroom.

Block Diagram and Schematic:

Code:

//Assistive Device: Dental Routine Timer
//Peter Heo
//Websites used in learning to implement and use RFID:
//https://www.teachmemicro.com/arduino-rfid-rc522-tutorial/
//https://stackoverflow.com/questions/32839396/how-to-get-the-uid-of-rfid-in-arduino/32842194
//Pin mapping:
//Pin Number          Pin Name            Desc.
//A0                  FSR Round Pin       Input for FSR Round Sensor
//3                   SS Pin Floss        Input for SS Pin for RFID Reader for Floss
//7                   Pump Pin            Output for Relay 
//8                   Switch Pin          Input for Toggle Switch
//9                   RST Pin             Input for RST Pin of Both RFID Readers
//10                  SDA Pin             Input for SDA Pin of Both RFID Readers
//11                  MOSI Pin            Input for MOSI Pin of Both RFID Readers
//12                  MISO Pin            Input for MISO Pin of Both RFID Readers
//13                  SCK Pin             Input for MISO Pin of Both RFID Readers
//SDA                 LCD SDA Pin         Pin for SDA of LCD Display
//SCL                 LCD SCL Pin         Pin for SCL of LCD Display
      

#include <LiquidCrystal_I2C.h>
#include <Servo.h>
#include <NewPing.h>
#include <SPI.h>
#include <MFRC522.h>

//Initialize pins and objects for the RFID readers: one for the floss and one for the moutwash cup.

#define SSCUPPIN 10
#define RSTPIN 9
#define SSFLOSSPIN 3
MFRC522 rfidCup(SSCUPPIN, RSTPIN);
MFRC522 rfidFloss(SSFLOSSPIN, RSTPIN);

//Initialize pins for the switch, peristaltic pump, the round FSR, and, as well as the LCD screen object.
const int TOOTHBRUSHPIN = A0;
const int SWITCHPIN = 8;
const int PUMPPIN = 7;
LiquidCrystal_I2C screen(0x27, 16, 2);

int brushTimer = 2;
int brushTime = 0;
int washTimer = 2;
int washTime = 0;
int flossTimer = 2;
int flossTime = 0;
long prevTime = 0;

boolean setUpFinished = false;
boolean brushStarted = false;
boolean brushFinished = false;
boolean washStarted = false;
boolean washFinished = false;
boolean cupFilled = false;
boolean flossStarted = false;
boolean flossFinished = false;
boolean flossPlaced = false;
boolean routineFinished = false;


void setup() {
  //Set up master toggle switch.
  pinMode(SWITCHPIN, INPUT);
  //Set up FSR sensors (for toothbrush and mouthwash cup).
  pinMode(TOOTHBRUSHPIN, INPUT);
  //Set up pump pin relay.
  pinMode(PUMPPIN, OUTPUT);
  //Set up LCD display.
  screen.init();
  screen.backlight();
  screen.display();
  //Set up RFID readers.
  SPI.begin();
  rfidCup.PCD_Init();
  rfidFloss.PCD_Init();

  Serial.begin(9600);

}

void loop() {


  //Sense if the device is on, if the brush is placed, if the cup is placed, and if the floss is placed.
  boolean deviceOn = (digitalRead(SWITCHPIN) == HIGH);
  boolean brushFound = (analogRead(TOOTHBRUSHPIN) > 15);
  boolean cupFound = false;
  boolean flossFound = false;

  //Sense for cup.
  if (rfidCup.PICC_IsNewCardPresent() && rfidCup.PICC_ReadCardSerial()) {
    if (rfidCup.uid.uidByte[0] == 0xd6  &&
        rfidCup.uid.uidByte[1] == 0xfc &&
        rfidCup.uid.uidByte[2] == 0x5a &&
        rfidCup.uid.uidByte[3] == 0x3e ) {
      cupFound = true;
    }
  }
  else if (rfidCup.PICC_IsNewCardPresent() && rfidCup.PICC_ReadCardSerial()) {
    if (rfidCup.uid.uidByte[0] == 0xd6  &&
        rfidCup.uid.uidByte[1] == 0xfc &&
        rfidCup.uid.uidByte[2] == 0x5a &&
        rfidCup.uid.uidByte[3] == 0x3e ) {
      cupFound = true;
    }
  }

  //Sense for floss.
  if (rfidFloss.PICC_IsNewCardPresent() && rfidFloss.PICC_ReadCardSerial()) {
    flossFound = true;
  }
  else if (rfidFloss.PICC_IsNewCardPresent() && rfidFloss.PICC_ReadCardSerial()) {
    flossFound = true;
  }

  Serial.println(analogRead(TOOTHBRUSHPIN));
  float currTime = millis();

  //Detect for master toggle switch state.
  //If it is on, indicate that device is on with LCD display.
  if (deviceOn) {
    //Display starting text.
    screen.home();
    screen.print("Device is on");
    screen.setCursor(0, 1);

    //Enter set-up stage.
    if (!setUpFinished) {
      //Sense for toothbrush.
      //Indicate for user to place brush if brush is not found.
      if (!brushFound) {
        screen.print("Place brush");
        delay(1000);
        screen.clear();
      }
      //Indicate if brush is found.
      else if (brushFound) {
        screen.print("Found brush");
        delay(1000);
        screen.clear();
        //Indicate for user to place cup if cup is not found.
        if (!cupFound) {
          screen.setCursor(0, 1);
          screen.print("Place cup");
          delay(1000);
          screen.clear();
        }
        //Indicate if cup is found.
        else if (cupFound) {
          screen.setCursor(0, 1);
          screen.print("Cup found");
          delay(1000);
          screen.clear();
          if (flossFound) {
            screen.setCursor(0, 1);
            screen.print("Floss found");
            delay(1000);
            screen.clear();
          }
          else if (!flossFound) {
            screen.setCursor(0, 1);
            screen.print("Place floss");
            delay(1000);
            screen.clear();
          }
          if (cupFound && flossFound && brushFound) {
            //If both cup, floss, and brush are placed, setup is done.
            screen.setCursor(0, 1);
            setUpFinished = true;
            screen.print("Setup done");
            setUpFinished = true;
            delay(3000);
            screen.clear();
          }
        }
      }
    }


    //Enter brush procedure.
    else if (setUpFinished && !brushFinished) {
      //Tell user to start brushing.
      if (!brushStarted && brushFound) {
        screen.print("Take brush");
        delay(2000);
        screen.clear();
      }
      //If brush is taken, begin brush procedure.
      else if (!brushStarted && !brushFound) {
        screen.print("Begin brushing");
        brushStarted = true;
        delay(5000);
        screen.clear();
      }
      //Begin timing user for brushing.
      else if (brushStarted && !brushFinished) {
        //If time is up, exit procedure.
        if (brushTimer - brushTime <= 0) {
          brushFinished = true;
          screen.print("Brushing done");
          delay(5000);
          screen.clear();
        }
        //Otherwise, display timer for brushing.
        else if (!brushFinished) {
          screen.print("Brush time: ");
          //
          if (currTime - prevTime >= 1000) {
            prevTime = currTime;
            brushTime += 1;
          }
          screen.print(brushTimer - brushTime);
          delay(250);
          screen.clear();
        }
      }
    }

    //Enter mouthwash stage once brush is finished.
    else if (brushFinished && !washFinished) {

      //If the cup is placed and washing has not yet started, wait for pump to fill the cup.
      if (!washStarted && cupFound && !cupFilled) {
        //Indicate to user that cup is being filled with mouthwash.
        screen.print("Found cup.");
        delay(1000);
        screen.clear();
        screen.print("Fill cup");
        delay(2000);
        //Activate pump for enough time so that cup is filled.
        digitalWrite(PUMPPIN, HIGH);
        delay(30000);
        digitalWrite(PUMPPIN, LOW);
        screen.clear();
        screen.print("Cup filled");
        cupFilled = true;
        delay(2000);
        screen.clear();
      }
      if (!washStarted && !cupFound && !cupFilled) {
        screen.print("Place cup...");
        delay(1000);
        screen.clear();
      }
      //If the cup is placed and filled, wait for user to take the cup.
      else if (!washStarted && cupFound && cupFilled) {
        screen.print("Take cup");
        delay(1000);
        screen.clear();
      }
      //If cup is taken, begin wash procedure.
      else if (!washStarted && !cupFound && cupFilled) {
        screen.print("Begin rinse");
        washStarted = true;
        delay(2000);
        screen.clear();
      }
      //If the cup has taken the cup, begin timing user for moutwashing.
      else if (washStarted && !washFinished && cupFilled) {
        //If time is up, exit procedure.
        if (washTimer - washTime <= 0) {
          washFinished = true;
          screen.print("Rinsing done");
          delay(2000);
          screen.clear();
        }
        //Otherwise, display timer for washing.
        else if (!washFinished) {
          screen.print("Rinse time: ");
          //
          if (currTime - prevTime >= 1000) {
            prevTime = currTime;
            washTime += 1;
          }
          screen.print(washTimer - washTime);
          delay(250);
          screen.clear();
        }
      }
    }

    //Enter mouthwash stage once brush is finished.
    else if (washFinished && !flossFinished) {

      //Look for floss.
      if (!flossStarted && flossFound && !flossPlaced) {
        //Indicate to user that floss was found by device.
        screen.print("Found floss.");
        flossPlaced = true;
        delay(1000);
        screen.clear();
      }
      //If floss was not found, indicate for user to place floss.
      if (!flossStarted && !flossFound && !flossPlaced) {
        screen.print("Place floss...");
        delay(1000);
        screen.clear();
      }
      //If the flossed is placed, wait for user to take the floss.
      else if (!flossStarted && flossFound && flossPlaced) {
        screen.print("Take floss");
        delay(1000);
        screen.clear();
      }
      //If floss is taken, begin floss timer.
      else if (!flossStarted && !flossFound && flossPlaced) {
        screen.print("Begin flossing");
        flossStarted = true;
        delay(2000);
        screen.clear();
      }
      //If the cup has taken the floss, begin timing user for flossing.
      else if (flossStarted && !flossFinished) {
        //If time is up, exit procedure.
        if (flossTimer - flossTime <= 0) {
          flossFinished = true;
          screen.print("Flossing done");
          delay(5000);
          screen.clear();
        }
        //Otherwise, display timer for flossing.
        else if (!flossFinished) {
          screen.print("Floss time: ");
          //
          if (currTime - prevTime >= 1000) {
            prevTime = currTime;
            flossTime += 1;
          }
          screen.print(flossTimer - flossTime);
          delay(200);
          screen.clear();
        }
      }
    }

    //If the user has finished the entire routine, indicate so and wait for the user to turn the device off.
    else if (flossFinished && brushFinished && washFinished && !routineFinished) {
      routineFinished = true;
    }
    else if (routineFinished) {
      screen.print("You're done!");
      delay(1000);
      screen.clear();
      screen.print("Turn device off");
      delay(1000);
      screen.clear();
    }
  }


  //If device is off, reset fields.
  else if (!deviceOn) {
    screen.home();
    screen.print("Device is off");
    screen.setCursor(0, 1);
    brushTime = 0;
    washTime = 0;
    flossTime = 0;
    prevTime = 0;

    setUpFinished = false;
    brushStarted = false;
    brushFinished = false;
    washStarted = false;
    washFinished = false;
    cupFilled = false;
    flossStarted = false;
    flossFinished = false;
    flossPlaced = false;
    routineFinished = false;
    delay(2000);
    screen.clear();
  }
}

 

 

]]>
Double Transducer: Position to Brightness https://courses.ideate.cmu.edu/60-223/f2021/work/double-transducer-position-to-brightness/ Tue, 05 Oct 2021 19:06:34 +0000 https://courses.ideate.cmu.edu/60-223/f2021/work/?p=13850 Project 1: A Double Transducer: Position to Brightness

Peter Heo, John Hewitt, Evangeline Mensah-Agyekum

Gallery

View of Completed Project

View of Servo Motor Arm and Round FSR

 

 

Progress Images

Initial design for pressure actuation onto round FSR. Use of a shorter arm compared to final project.

Second version of pressure actuation using servo motor. Used a sort of piston to press down on the round FSR; however, it was finicky and not very stable.

I had everything ready to be soldered, but I didn’t realize the wires weren’t going to be long enough

my broken FSR

Discussion

In terms of difficulty, the brainstorming was one of the more easier parts, as we were able to quickly come up with what we wanted for our middle step to be. However, what was more difficult were the more specific mechanics of the middle step, as we were initially unsure of how to convert slide position into pressure. We started with a couple of ideas but we were able to narrow it down to an arm that would press down on the sensor. Peter tried to come up with a piston that would press and lift a weight onto the round FSR, and a sort of linear actuator that would press against a vertically placed FSR sensor, but both of these proved to be unwieldy and unreliable. We eventually settled on using a straw attached to a lever (servo arm) with enough flexibility to bend when pressed against the FSR.

There were also a couple of challenges along the way, as the code proved to be one source of difficulty. The motor would jitter and stutter periodically, making the servo arm unreliable in pressing down on the FSR sensor. The initial approach to this problem was try to smooth out the values, as we thought it was the potentiometer sending jumpy values, but we learned that it was actually timer collisions between the servo motor and the Neopixel LED ring causing the servo motor to jitter. From this, we learned that sometimes it is not the main user code that is unreliable, but the type of libraries and mechanical components we use.

It was also interesting to calibrate the sensors to not only work with each other, but fit into a 1-100 range on the lcd. It took some finessing, but as we messed around with the values it began to feel more intuitive.

Both Evangeline and Peter experienced a specific wiring issue with the potentiometer, where they switched up input with ground/5V wiring, causing a short circuit. However, after learning that the wiring was fixed, this problem was easily addressed. Soldering also proved an interesting step for Peter, as he was unfamiliar with it, and learning how to solder was something he enjoyed learning, albeit a bit nervously. John preemptively soldered up the different parts of the project without realizing the wires were not long enough to reach the opposite ends of the board, and had to re-solder things. John also snapped a round FSR when trying to reposition it, it was interesting to use such a delicate piece. John also learned to what a heatsink was, and would have probably damaged the FSR if he hadn’t been warned ahead of time.

This project also made us think more spatially, as organization and how components would be physically laid out on the board were also part of the project near the end of putting the whole thing together. However, the straightforwardness of the setup and its processes made it easier to assemble.

Block Diagram and Schematic

Code

//Project: Double Transducer (Position to Brightness)
//Peter Heo
//John Hewitt
//Evangeline Mensah-Agyekum

//The code below allows for the user to control a slide potentiometer, which then controls a servo motor.
//The slide potentiometer readings are converted to a servo motor angle.
//Said servo motor exerts pressure onto a round FSR through the use a physical arm.
//The round FSR readings are then converted to a certain degree of brightness for an Neopixel LED ring.
//All the input and output values of the mechanisms aforementioned are displayed onto an LCD screen...
//...all mapped to a range of 0-99.

//Pins                    Mode                    Description
//A0                      Input                   Slide potentiometer readings
//A3                      Input                   Round FSR readings
//6                       Output                  LED Ring
//10                      Output                  Servo motor

//Library and implementation for the Neopixel servo motor object:
//https://learn.adafruit.com/neopixels-and-servos/the-ticoservo-library

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Adafruit_TiCoServo.h>
#include <Adafruit_NeoPixel.h>

//Intitialize pin for LED ring and the number of lights on said LED ring, as well as the LED object.
#define PIN  6
#define NUMPIXELS  16
Adafruit_NeoPixel light = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

//Initialize pins for the slide potentiometer, the round FSR, and the servo motor, as well as the LCD screen object.
LiquidCrystal_I2C screen(0x27, 16, 2);
const int SLIDEPIN = A0;
const int PRESSUREPIN = A3;
const int SERVOPIN = 10;

//Initialize the time between display updates, and the timer itself.
const int LCDUPDATETIME = 250;
long prevDisplayTime = 0;

Adafruit_TiCoServo servoMotor;

void setup() {
  //Set up pins for inputs and outputs:
  //Slide potentiometer...
  //...Servo motor...
  //...and Round FSR sensor.
  pinMode(SLIDEPIN, INPUT);
  servoMotor.attach(SERVOPIN);
  pinMode(PRESSUREPIN, INPUT);

  //Set up LCD display.
  screen.init();
  screen.backlight();
  screen.display();

  //Set up light.
  light.begin();
  light.setBrightness(0);
  light.show();

  //Open the serial communication port to talk back to the computer.
  Serial.begin(9600);
}

void loop() {

  //Look at current time.
  long currentTime = millis();

  //Initialize slide potentiometer value.
  int slideVal = analogRead(SLIDEPIN);

  //Range should be about 11 degrees.

  //Set servo motor angle proportional to slide pot value.
  int servoVal = map(slideVal, 0, 1023, 142, 156);
  servoMotor.write(servoVal);


  //Read pressure value from FSR sensor.
  int pressureVal = analogRead(PRESSUREPIN);

  //Set brightness of LED ring proportional to pressure value.
  int brightnessVal = map(pressureVal, 0, 410, 0, 255);
  light.setBrightness(brightnessVal);

  //Set color of all LEDs on the LED ring to green.
  for (int i  = 0; i < NUMPIXELS; i++) {
    //Set color of all LEDs on the LED ring to green.
    light.setPixelColor(i, light.Color(128, 150, 128));
  }
  light.show();

  //Update LCD display every 250 milliseconds.
  if (currentTime - prevDisplayTime >= LCDUPDATETIME) {
    screen.clear();

    //Print slide values on a range of 0-99 on LCD display.
    int slideDisplayVal = map(slideVal, 1023, 0, 0, 99);
    screen.home();
    screen.print("i:");
    screen.print(slideDisplayVal);

    //Print servo motor value on a range of 0-99 on LCD display.
    int servoDisplayVal = map(servoVal, 142, 156, 99, 0);
    screen.setCursor(6, 0);
    screen.print("m:");
    screen.print(servoDisplayVal);

    //Print pressure values on a range of 0-99 on LCD display.
    int pressureDisplayVal = map(pressureVal, 0, 410, 0, 99);
    screen.setCursor(8, 1);
    screen.print(pressureDisplayVal);

    //Print brightness values on a range of 0-99 on LCD display.
    int brightnessDisplayVal = map(brightnessVal, 0, 255, 0, 99);
    screen.setCursor(12, 1);
    screen.print("o:");
    screen.print(brightnessDisplayVal);

    prevDisplayTime = currentTime;

  }



}

 

]]>