sjying@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 21:57:17 +0000 en-US hourly 1 https://wordpress.org/?v=5.8.9 Automated Umbrella by Team Pomegranates: Final Documentation https://courses.ideate.cmu.edu/60-223/f2021/work/automated-umbrella-by-team-pomegranates-final-documentation/ Fri, 10 Dec 2021 21:57:17 +0000 https://courses.ideate.cmu.edu/60-223/f2021/work/?p=14614 Matthew Wagner, Serena Ying, Yuqi (Alice) Zhou for Brenda

 

1. Introduction

For our final project, we were tasked to work with a client to develop a personal assistive device which would help improve an aspect of their lives. Our client, Brenda, uses a power chair and spends the majority of her time with it due to limited mobility. One problem she was very enthusiastic about solving was using an umbrella that would cover the electronics on her power chair if it was raining, and which could also be used as a sunshade when she participates in protests in the summer. So, for our project, we decided to realize the idea that Brenda proposed– an automated umbrella opener and closer which could be mounted on the back of her chair and activated easily without having to hold the actual umbrella. For more details and interview documentation with Brenda, please see here:

Interview Documentation Team Pomegranates

2. What We Built

Our project works very simply. The umbrella and the control boxes are to be mounted to a power chair, utilizing the existing interface of the back of the chair. The device has three buttons the user operates to control the umbrella. The power button allows the other buttons to be activated, so the umbrella isn’t accidentally raised or lowered when not desired. The device plays a little jingle to alert the user that the device is on. From there the user uses the other two buttons to raise and lower the umbrella respectively. The buttons activate a motor which pulls a string attached to the top of the umbrella, to pull it to the open position.

Since Brenda wasn’t able to make it to our final critique, we weren’t able to mount the device on her wheelchair. However, we look forward to connecting in the future.

Final working video – button presses engage motor either CW or CCW to pull rope through pulleys mounted in the base box and at the umbrella apex and tension or release the umbrella

The Control Box houses the buttons that Brenda uses to power on/off (green) the device as well as raise and lower the umbrella. The box is mounted such that the two white buttons are aligned vertically, where “raise” is on top of “lower”.

The box hosting the wiring, motor and pulley system.

The box as well as the umbrella itself are mounted to an aluminum extrusion beam.

The aluminum extrusion beam attaches to Brenda’s chair using the black clips that pin to cylindrical components of the chair. The pole of the umbrella is also connected similarly to where Brenda’s headrest is, to prevent the umbrella from wanting to rotate.

An inside look at the box shows the orientation of the motor amidst the wires and battery pack used to power the device. The motor spins the pully to wind and release the string used to raise and lower the umbrella. The worm gear inside the motor, prevents rotation of the axel when the motor is shut off or when the umbrella is raised so that it stays raised during use.

The string goes up the pole of the umbrella and around another pully fixed at a bearing at the top of the umbrella. This bearing is bolted into the umbrella pole allowing the string to pull up the “runner” which slides up the pole to open the umbrella. Typically, the runner is moved manually, but our device automates this procedure.

Umbrella at a open position

Umbrella at a close position

Brenda spends most of her waking hours sitting in her wheelchair, so accessibility is super important. On a given rainy or very sunny day, Brenda would decide to use our assistive device to protect her from the elements. With some help attaching the mount to the back of her power chair, Brenda is ready to be outside and go about her journey without any additional assistance. With the press of a button that is easily in reach on her left arm rest, Brenda powers the device, allowing her to control raising and lowering the umbrella by pressing and holding the adjacent buttons. The umbrella is able raise and lower while not obstructing Brenda’s vision in front of her and protects the entirety of the power chair due to the large diameter when raised.

On a particular rainy day, Brenda doesn’t worry about driving her chair through the rain because the umbrella will protect the controls and electrical components of the chair that are susceptible to water damage. The umbrella will protect her from the rain, and she is able to raise and lower the umbrella freely to accommodate her busy work schedule.

In the summer, Brenda chooses to attend a protest but is worried her chair’s stature will cause her to get lost in the crowds. To both protect her from the sun and help the people she is with to identify her in a crowd, Brenda uses our device to stay safe and be independent while fighting for what she believes in.

3. Prototypes and Process

This prototype was designed to help answer one question: does the motor we decided to use to pull the umbrella open have enough torque to lift the runner of the umbrella due to the umbrella’s size and weight.

For our prototype, we only utilized the top half the umbrella pole and attached the motor, pulley assembly to the pole using duct-tape. Using a borrowed motor driver and a lever switch, we were able to control up, then down of the umbrella using a single press for each. At this stage the switch activated the motor to rotate for a fixed amount of time. We had to hold the umbrella upright as no mount was created at this point. Additionally, we designed and 3-D printed a bearing for the top of the umbrella which held a pully, allowing the string to raise the umbrella. The motor wounds the string in tension to pull up, and releases that tension, relying on gravity to bring the umbrella back to the lowered position.

We grounded the motor to the base of the umbrella pole using duct-tape. This ensured consistency in the raising and lowering as the motor was only set to rotate for a specific amount of time.

The first iteration of the bearing we made was too big for the width of the pole. This happened because we had to send the part to the 3D printers before the umbrella was delivered. We were able to use a piece meant to lock the runner in place to rest the bearing on during the prototyping phase. The same design was updated with a smaller diameter for the final product.

Figuring out the wirings for the motor

Prototype of motor with bottom pulley attached responding to up and down button presses

Findings from the Prototyping Process

The answer is: the motor we decided to use does have enough torque to lift the runner of the umbrella and pull the umbrella open despite the size and weight of the umbrella. 

Feedback from the Critiques

One feedback we received from the critique was on the power of the system. For the prototype, to supply power, we had to plug in a 12v power supply. That is not ideal because Brenda would need to find power supplies. Thus, we decided to change it so that the whole system is powered by a battery pack; changing batteries once in a while is comparably easier.  

Another feedback we received was concerning the accidental activation of the system. Based on the feedback, we added an on/off button to act as the safety switch. The up/down control buttons would not work unless this on/off button is pressed; this adds another layer of protection to accidental activation.  

One feedback we didn’t quite address in our final design was designing for different umbrellas. Brenda mentioned umbrellas are consumables, so she would like the system to be usable by other umbrellas as well. We tried to address this feedback, however, ended up focusing on making the system work for the specific umbrella we had. If we had more time, we would love to make it work with other umbrellas as well.  

Surprises

One surprise knowledge we learned during the prototype process was that humans can act as resistors. We were wiring the motor and at one point, the motor only ran when a person was holding the wires. We tried adding in a resistor, and it sort of worked. So, we learned humans can have resistance of as high as 100,000 ohms. However, in the end, it turned out that we didn’t have a ground for the wiring which was the real problem. So, now we know humans can act as both resistors and ground.

Process

A lot of planning, drafting, redrafting, and revisions went into designing this project. Here is a (mostly) chronological record of our work sessions throughout the weeks.

Initial schematic drawn for clarity after scrapping the gear track idea and confirming that the beach umbrella was gravity tensioned

After we received the umbrella, work sessions got a lot more crowded but way more tangible. We made a ton of design choices and swapped out parts from IDeATe Lending out for ordered components– sometimes requiring rewiring and redesigning.

Umbrella is usable in midst of figuring out how to attach runner to pulleys!

Fitting the lever switches with arcade buttons for ease of use

An angle of the motor, motor driver (old Pololu), and Arduino (which would go into the control box) and the control interface (small box), with the external 12V power source connecter still attached

Process update for the control interface box, with old H-Bridge chip, with switches working and assembled

Progress photo of new H-Bridge motor driver connected and operational with new 12V battery pack– temporary connectors still attached and system not soldered yet

Then it came down to fitting all the components into the control box. One big issue we had was attaching the crossbar to the back of the control box and also securing it to the worm motor. This process took a lot of elbow grease (and literal machine grease), soldering, resoldering, and sawing screws and the metal stem of the umbrella.

Drafting work being done to design how the motor and pulley would fit inside the control box and how the control box would be mounted to the back of Brenda’s chair

Progress photo of figuring out how to fit all the components into the control box

Sawing the screws to the right length in order to slide into the crossbar

View of screw joints used to hold together control box

Inside view of control box while the motor was being screwed into the backing bar that attached to the back of the control box– copious amounts of motor oil for sliding the screws in not pictured

Throughout the process, we made and learned from our mistakes, discovered new techniques, and encountered many instances of components not working. Some mistakes we made included accidentally soldering all the wires with their extensions without passing them through the slots cut into the bottom of the acrylic control box, which caused a little bit of despair. Other mistakes included not making the tolerance of the 3D printed parts correct. The base that would slide onto the bottom of the umbrella stem and hold the control box wasn’t large enough and got stuck before sliding up all the way and we ended up having to saw off the plastic from the base of the umbrella and reprint the part. Additionally, the parts comprising the pulley at the apex of the umbrella were printed too large and did not secure onto the diameter of the pole as snugly as we would have hoped, so that was another part we had to remeasure and reprint. In addition to our components being ill-fitting, we also had issues with wire connections and soldering– at points the soldering in the wire extensions was not electrically connected and we had to spot check each wire to isolate which connection was not secure and thus causing the motor to continue rotating past the fully extended distance and nearly breaking our pulley system.

Some discoveries made included managing the H-Bridge motor driver. At first, using the one from IDeATe Lending was a little complicated as we had to figure out how to wire the motor to the chip, and at one point our entire group plus Catherine and Zach experimented with being human resistors. Once we finally sorted out the wiring, Zach simplified our code more by having us just drive one signal high and the other low and vice versa to switch the motor direction, and both low to stop the motor rather than using library functions which would be only applicable to the specific type of chip we had. Then, we had to figure out if a cheaper alternative to the H-Bridge motor driver from IDeATe Lending that we were using could be feasibly constructed from a series of transistors. Although we experimented with using MOSFETS as current switchers, in the end the homemade H-Bridge had to be scrapped since resources online which outlined such DIY H-Bridges utilized BJTs rather than MOSFETS, which is all the Physical Computing lab had. Although the components are similar, their electronic behavior was just different enough to be too complicated to transfer the wiring from one transistor type to another. We ended up ordering a cheaper high current H-Bridge, which then still took some trial and error to re-figure out the wiring for.

In terms of following schedules, we planned out a Gantt chart which may have been a little too ambitious:

A snippet of our Gantt Chart

Although we tried our best to stay on schedule, we encountered setbacks from having to wait for 3D printers to be available, different replacement components to come in, and for delays with 3D prints not being started as scheduled or TechSpark being closed unexpectedly. In this way, our work ramped up as the deadline approached and included a few long work sessions the nights before, as well as one particularly late night the night before presentations. Overall though, other than delays caused by materials not being usable in time, we kept on track for our designing benchmarks and were able to put everything together in time once we had our hands on the right materials.

4. Conclusions and Lessons Learned

Responding to Some Feedback

“The buttons are a little bit confusing some way of differentiating between them would be helpful” We were planning to position the box in a way that would have one button on the top and one on the bottom, so then the direction of control would align with the position of the button. However, we agree that it would be even better to distinguish the buttons with differently shaped buttons. That way the user can instantly know which button is for which direction, instead of fumbling around to see where the button is located. 

“The box attached to the umbrella is a little too big, but again it’s a prototype; the size of the black rotating rod limited the compactness…” Yes, the size of the box is indeed on the bigger side. We actually had to adjust where it’s located due to the size. It was originally going to be located toward the top of the chair near the headrest. This suggestion of using a smaller rotating rod would definitely help reduce the size of the box.

“The hardest part of robotic umbrellas (surprisingly I have experience here) is with making them close again. This team was able to figure out a way to deal with that, and it impresses me.” Thank you! Figuring out how we make the umbrella closes was definitely a big part of our initial discussions. We were originally going for a rack and pinion mechanism, however we realized, with the help of our professor, that we can use the help of gravity. So, we went ahead and found an umbrella that closes with gravity which simplified our design. 

“Auto stopping–>needs to count rotations or measure stall voltage on motor” This was definitely something we were planning to do but did not get the chance to. The next step, for safety reasons, would be implementing some sort of stop/limit switch, so the motor will only be activated for enough time to just open up and close the umbrella. The stall voltage suggestion is an interesting idea to try implementing. 

“The team has a problem I’ve had for years- overdesigning. By being as strict in designs to Brenda’s chair specifically, it can only ever work for HER chair. By having a looser design, more people could potentially use it.” Like mentioned above in our prototype feedback, this is something we are aware of. The current design might be hard even for Brenda to change the umbrella to a different one. One suggestion we got from the final critique was to reconsider how we attach the system to the chair by using a tripod-like mechanism: have one side always fit for our umbrella holder and the other adjustable for different kinds of chairs.

Experience of Working Remotely

Fortunately, the working experience is mostly hybrid for this project. We were able to meet in person and only went remote when needed. The most challenging aspect was communicating effectively when not in person. There were times when we needed Brenda’s input, and it took many text messages to sort it out. It was also frustrating at the beginning of the project when we were unable to get hold of Brenda. Despite all these, we were able to find compromises and move forward with the project. In retrospect, it is really important to plan for the in person opportunities we do have. If we have thought more about questions to ask her and measurements to take, we might have been able to minimize the need to communicate virtually.     

Working with a Person with a Disability

One takeaway is that when designing for people with disabilities, designers need to keep in mind the clearance issue. Power chairs are already bulky enough, it would be ideal to avoid making them bigger, especially horizontally. We had to carefully think about the placement of the control because of this. Nevertheless, I have to say, although designing for disability has its own special things, it is also really not that different from just designing for people. What surprised me is how this project can appeal to a broader audience. There was one comment from our critique saying “I needed this walking to class when I was in school” and I personally would love to have this umbrella retraction system for the porch umbrella my family has. Universal design is really the golden standard all designers should follow. 

Concluding Thoughts

To conclude, one last lesson we would like to mention is how iteration is an essential part of the design. People shouldn’t rely on things working out the first time they try, and we should plan for failures and redesigns. Our reprint of parts, reconnecting the wires, redesign of the box and more taught us too well of this lesson.

5. Technical Details

Block and Schematic Diagrams

Block Diagram

Schematic

Code

/*
   Automated Umbrella

   This code drives a motor CW or CCW by sensing up and down button presses. The up
   and down button presses are only registered when an overall on switch has been
   engaged. While the overall on switch is engaged and the motor is not running,
   a buzzer will sound an arpeggio as an alert tone to warn the user that the up
   and down buttons are active and can be engaged. The motor is driven CW or CCW by
   driving its IN_A and IN_B pins either high or low-- IN_A being high and IN_B
   being low or vice versa indicate the motor being driven in one direction, or
   both pins driven as low indicates the motor is stopped. The pins will never be
   both driven as high (illegal).
*/

/*
   ------------------------------------------------------------------------------
   Pin Mapping
   ------------------------------------------------------------------------------

   Name             Pin             In/Out
   IN_A              3               OUT
   IN_B              4               OUT
   PWM               5               OUT
   BUTTON_UP         2               IN
   BUTTON_DOWN       7               IN
   BUTTON_ON         8               IN
   BUZZER_PIN        9               OUT
*/

/*
   Credits:
   
   https://arduinogetstarted.com/faq/how-to-use-buzzer-without-blocking-other-code
*/

#include <ezBuzzer.h>


// motor pins
#define IN_A 3    // pwm pin motor (digital output)
#define IN_B 4    // control pin INA (digital output)
#define PWM 5    // control pin INB (digital output)

#define BUTTON_UP 2
#define BUTTON_DOWN 7
#define BUTTON_ON 8

#define BUZZER_PIN 9

ezBuzzer buzzer(BUZZER_PIN); // create ezBuzzer object

// notes in the buzzer melody
int melody[] = {
  NOTE_C4, NOTE_E4, NOTE_G4, NOTE_C5
};

// note durations: 4 = quarter note, 2 = half note
int noteDurations[] = {
  4, 4, 4, 2
};

//Variables representing state
bool up_state = 0;
bool down_state = 0;
bool on_state = 0;
unsigned long timer = 0; // used for speaker delay


// Helper functions for driving motor
void motor_stop() {
  digitalWrite(IN_A, LOW);
  digitalWrite(IN_B, LOW);
  analogWrite(PWM, 0);
}

void motor_cw() {
  digitalWrite(IN_A, HIGH);
  digitalWrite(IN_B, LOW);
  analogWrite(PWM, 255);
}

void motor_ccw() {
  digitalWrite(IN_A, LOW);
  digitalWrite(IN_B, HIGH);
  analogWrite(PWM, 255);
}

void setup() {
  pinMode(BUTTON_UP, OUTPUT);
  pinMode(BUTTON_DOWN, OUTPUT);
  pinMode(BUTTON_ON, OUTPUT);
  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(IN_A, OUTPUT);
  pinMode(IN_B, OUTPUT);
  pinMode(PWM, OUTPUT);
  //Initial state of motor
  motor_stop();
}

void loop() {
  up_state = digitalRead(BUTTON_UP);
  down_state = digitalRead(BUTTON_DOWN);
  on_state = digitalRead(BUTTON_ON);
  // If overall on switch is activated (button will latch)
  if (on_state) {
    // If up button is registered, stop motor and then turn CW
    if (up_state) {
      buzzer.stop();
      motor_cw();
      delay(500); // delay for motor
    }
    // If down button is registered, stop motor and then turn CCW
    else if (down_state) {
      buzzer.stop();
      Serial.println("down");
      motor_ccw();
      delay(500); // delay for motor
    }
    // If neither button is registered, stop motor and loop buzzer alert
    else if (!up_state && !down_state) {
      buzzer.loop(); // called to play in the background
      motor_stop();
      delay(500); // delay for motor
      // if buzzer isn't currently playing anymore and 0.5 second has passed, repeat
      if (buzzer.getState() == BUZZER_IDLE && (millis() - timer) > 500) {
        int length = sizeof(noteDurations) / sizeof(int);
        buzzer.playMelody(melody, noteDurations, length); // playing
        timer = millis();
      }
    }
  }
}

 

]]>
Interview Documentation Team Pomegranates with Brenda https://courses.ideate.cmu.edu/60-223/f2021/work/interview-documentation-team-pomegranates-with-brenda/ Tue, 09 Nov 2021 04:11:01 +0000 https://courses.ideate.cmu.edu/60-223/f2021/work/?p=14555 Introduction

We are Team Pomegranates (Matt, Serena, and Alice) taking Intro to Physical Computing. For our final project, we are working with our client Brenda, a person with disability, to create a device that would be relevant and useful for her daily life. To start off, we scheduled an interview with Brenda to get to know her. The main purpose of the meeting was to learn about what her daily lives are like, and from there, to be able to generate ideas and directions for the project. All team members met with Brenda on Tuesday Nov. 2nd at 9:45. 

Meeting Agenda

Introduction

  • acknowledge the atypical circumstance of conducting this meeting remotely
  • How are you
  • Names (“fun fact”) + years / majors
  • Their name, “fun fact”, what drew them to want to participate

 

Ask for permission to record

 

Explanation and Clarification about Project Goals

  • Time frame: 5 weeks; 18th prototype due; 
  • We are:
    • Trying to build prototype useful devices
    • Engaging in an iterative design process, including gathering formative feedback around the midpoint of the process
    • Taking about five weeks to go from this meeting to a reasonably high-fidelity final product
    • Documenting our process
  • 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 (we combine many existing available components in new ways, but don’t make components)
  • Any questions?

Understanding Needs

  • Any activities in their daily life that are difficult, frustrating, or otherwise seem like they could use an intervention?
    • Willing to demonstrate a daily task or a series of tasks to you on the call? 
    • Anything used to enjoy doing, which has become harder over time for any reason? Are there creative ways to make that thing easier to do now?
    • narrate the action and do the drawing yourself in a way that’s visible to the group. (map, a sequence of cartoon panels, more abstract form)
    • Ask if she’s comfortable using a shared drawing-surface tool? → ask the client to draw a map or cartoon of their daily life

https://jamboard.google.com/d/1s5Rxv3rxq0p4oE7c4sLhxYmTp92bzYberSlI7clN7xU/edit?usp=sharing

  • Ask ethnographic questions: “why is this important to you?”
  • Once you’ve asked some of these guiding questions, use materials you might have on hand (play dough, household building materials like toothpicks, tongue depressors, tape, etc.) to mock up solutions to the story you’re telling, and show these to the camera
  • Make sure they are a part of the process as much as possible
  • Discuss and establish some categories for “problems” to narrow and refine the conversation
  • Think of this as making a “convenience machine”, one that reduces one of the little annoyances we all have, maybe call it a “gadget”? Language is important.
  • Conclude
  • Thank your client for their time
  • take any final documentation images/drawings/notes you may need to wrap up before you sign off.
  • Reiterate the overall project schedule if you feel it would be necessary to clarify before leaving.

Meeting Summary and Major Takeaways

Brenda came into the interview with her main idea already in mind. Before we could even introduce ourselves, she explained how she wanted us to develop an automatic retracting device for her umbrella that would be attachable to her power chair. While it excited us that she had already found an idea she was passionate about, we slowed the conversation to dig a little deeper and learn more about Brenda. 

First thing first, Brenda was adamant about changing our team name from the raisins. Instead of the dried up fruit, we decided to change our team name to the pomegranates, a much more exotic fruit.

Next, we wanted to learn a little bit more about Brenda’s disability. She told us that she has trouble using her left hand and uses her right hand to drive her power wheelchair. While she is able to do simple functions with her left hand, such as pushing a button or flipping a switch, it is hard for Brenda to juggle multiple tasks while in her power chair. Some examples she gave were carrying her coffee from meeting to meeting, making a phone call on the go or simply holding an umbrella in the rain, which was the basis for her idea. Brenda even expressed difficulties taking her shoes on and off without having to wait for someone to help her with the task. Since Brenda spends “90 percent of [her] day” in the power wheelchair, it is frustrating for her not to be able to multitask during her busy schedule at work. 

This conversation really motivated us as a group. By taking us through different things she finds difficult, Brenda was able to convey just how important her idea of an umbrella holder and retractor would be to her. As a result, we were excited to know more about what exactly she was looking for and what would best suit her needs. She would like our design to: 

  • Mount on the back, left side of the power chair
  • Be able to open and close automatically with the flip of a switch or
  • via connection to the Bluetooth module in her power chair
  • Retract at least 4-5 inches above her head
  • Cover her whole power chair
  • Utilize an umbrella that is colorful so she is easily seen in crowds
  • Be easy to dismount from her power chair when not needed. 

Based on this information, we came up with the following sketches and used our Jambord link to show Brenda what we were thinking to confirm that we were on the same page as her. 

Early sketches developed from Brenda’s description of the chair and what she was looking for.

With these specifications, we needed to learn a little more about her wheelchair and the beach umbrella she likes to use. While she attempted to show us how her wheelchair could put her in a standing position, she wasn’t able to manipulate the camera angle so we couldn’t really get a clear picture of what was going on. Brenda assured us that she would give us pictures of what it looks like raised and lowered, as well as general pictures of the chair that we can use to see what area on the chair we have to work with. Unfortunately, Brenda has not gotten back to us since our interview, and we were unable to get any pictures to include here showing the power chair, its design or how it works. We had to make educated guesses when performing ideation and sketches. Furthermore, Brenda has not gotten back to us about which umbrella she uses or how it works specifically. We are eagerly waiting for her response and plan to look into purchasing a similar umbrella to test and construct on. 

Thoughts and Discussion

The meeting did not follow our agenda, but that’s not to say it wasn’t productive. Before we even had a chance to introduce ourselves or begin our icebreaker, Brenda started off with explaining her idea, and why she wanted it. Since this removed the need to probe for aspects of her life which could benefit from an assistive device, it allowed us to further explore the idea of her automated umbrella retractor during our meeting. This was a benefit, as we were able to ask clarification questions about her chair, as well as learn more about how we could possibly integrate Bluetooth functionality into this project. Conversation flowed really naturally throughout the entire meeting as we brainstormed and asked questions. Next time, we would opt to ask her more directly if she could point out other ideas we could fall back on, or just adjacently consider if her primary idea doesn’t seem feasible as we start to draft our solution. 

 

After our meeting, we realized that we didn’t get a good description of the umbrella she uses in detail, which made it a little challenging to begin the brainstorming process, but we’ve opted to just purchase an umbrella for testing and prototyping purposes. In addition, we realized we each had different understandings of what Brenda wanted from our project— either it being just an umbrella opener/closer, or just an umbrella elevator/retractor, or both. However, after discussing it within the group we were able to come to the conclusion that it was likely Brenda meant for the combination of features. Overall, we all though that the meeting went well, but wished we were able to obtain details about her umbrella as well as the power chair more quickly— Brenda has yet to reach out with her follow-up information. 

]]>
RFID Phone Lock https://courses.ideate.cmu.edu/60-223/f2021/work/rfid-phone-lock/ Sun, 31 Oct 2021 18:55:07 +0000 https://courses.ideate.cmu.edu/60-223/f2021/work/?p=14153 Overview

This device reminds a user to not use their phone as frequently by allowing the user to set a timer for how long they’d like to put their phone down for, and if it senses that the phone has been removed before the allotted time is up, the device will flash lights.

 

 

 

Process Images and Review

The first decision point I encountered was the selection of what kind of button I wanted to use to set the timer. Initially, I envisioned the button being behind a finger sized acrylic panel on the top of the device which the user could depress, and it would push on a small lever pushbutton to set the timer. Instead, I realized that making the acrylic stay on the lever pushbutton would be pretty difficult given the small surface area on the lever. In prototyping, I used a small black pushbutton as it was the most basic sort of button I could use for testing, and I also considered using the panel to depress the small black pushbutton but that would require sufficient support for the breadboard underneath in order for the user to depress the button safely in the z axis (from on top). Both of these button ideas would require some sort of internal scaffolding within the acrylic box and in the end, there wasn’t enough room and time to design these. Hence, I opted for a red exposed pushbutton for which I laser cut a small opening for on the side of the box with the potentiometer also sticking out. Thus, with both of these components being manipulated directly from the external source (my hand), there was enough cohesiveness to allow both to remain on the side panel of the box.

Circuit during the process– originally had a small black pushbutton that I intended on switching out for a lever pushbutton so that I could mount a piece of acrylic on top.

The new pushbutton I selected would peek through the acrylic rather than being hidden.

The second large decision point in my process regarded the alarms that would notify the user that the phone had been removed before the timer went off. In the beginning, I had imagined two sources of alerts– having a light blinking, and also a little buzzer going off. The buzzer would obviously be annoying, but in particular I wanted the blinking of the LED to peek through the smokey black acrylic I intended on using. This would give the effect that the acrylic was glowing and would allow the LED light to pierce through and annoy the user more than it does now. However, after some though while laser cutting, I knew that the smokey acrylic would show all the wiring underneath, which I though would be too exposed and messy. So, I opted to keep the sticky backing of the acrylic intact on one side such that it provided a more opaque wall that would hide the wiring and electronics. Unfortunately, this fix caused the entire box to look very much like it was made of just black acrylic, rather than the sleek, translucent panels I was going for. So I tried to make the most of this by cutting slits along the bottoms of the panels so that you could see the glow of the LEDs when they were on or flashing, in order to sort of emulate a strip of LEDs going across the bottom of the box, akin to my initial sketches. Despite my best efforts, my desire to hide the wiring also hid the light of the LEDs which were already diffused panels and thus not bright enough, so they do not shine through the sticky backing on the acrylic.

Side of the acrylic box, with panels made of smokey gray acrylic with sticky backing attached, with bottom slits to allow for LED lighting to peek through as much as possible.

Additional Process Images

I wanted to make the top as sleek as possible with a plate of green-edged clear acrylic that would cover the LCD display so that it wasn’t exposed. The etched circle indicates where the RFID sensor lies, and faces inwards so that the surface is completely smooth.

The underside of the device was quite messy. This required me to add an additional bottom panel to add support and structure (seen in second last image).

External design with clear acrylic top and smokey grey acrylic sides, with RFID sensor laying underneath top panel.

 

Discussion

Overall, this project showed me a lot about my own working process as well as allowed me to follow a task from start to finish, all while managing expectations and finding compromises. In the design process, I was very ambitious, putting features that made sense in a design aspect but were not that simple to implement or would be more time consuming to implement. Such is the fallacy of not heeding my own limitations on the time I could spend on this project. During in-class crit, I was granted great criticism from my fellow Paw Paws. Two pieces of criticism I received involved comments on the design:

“I like the etching on the acrylic for where to put your phone! I think that’s a clean solution and the whole thing feels like a scale which fits the interaction of placing your phone down”

I love the shape and design, but it looks a little big for you to regularly have on your desk”

I agree with both of these sentiments– I tried to make the box as sleek and modernistic as possible with the rounded edges and the etched acrylic for the placement of the RFID sensor. However I also agree that the box became much larger than I intended and more obtrusive that initially planned. If I had scaled the base of the box down a bit and had it be shallower, but still had the acrylic plate on top the same size, it would be a bit more compact for a desk accessory.

Another piece of valuable feedback I received was this:

I think that it could have a better sort of deterrent system besides LEDs.”

This comment resonates very much– I see this as a major drawback in my project that I wasn’t able to implement more types of deterrents in this device. As I mentioned previously, I intended on having a buzzer be angry at me if the tag was removed before the timer was up, but I wasn’t able to implement this in time. The other IDEATE professor also mentioned this fact, including implementing a more robust system with the LEDs where the flashing rate would increase in intensity as the period of time where the phone was lifted off extended longer and longer, as even more of deterrent.  I think these suggestions are ingenious and wish I had thought of them earlier too.

Elaborating on the previous statement, my reflections on this project are mixed. On one hand I like how I was able to use the green-edged clear acrylic and the etched center circle for the RFID placement, as well as how I was able to use a technology that I really like and have learned about– RFID as the foundation of the project as I enjoyed working with it. However, in many ways I did not satisfy all my goals. In my initial planning I listed many features which I was not able to realize, and which would have made this project a more reasonable level of complexity. However I am still reasonably satisfied with how I was able to pull together the basic functionality of the device as I had envisioned it, with the timer and the RFID tag working.

In general, my most relevant reflection is that I learned about my limitations on time management and overcomplicating simple tasks. Firstly, I wasn’t able to put as much time as I had wanted to into the project due to other deadlines. However I think that if I could go back to change things I would definitely continue tinkering with the project more frequently over the weeks rather than doing work large chunks at a time, infrequently. Secondly, I overcomplicated the code, which was one of the first steps I tackled in the project which became a problematic roadblock since I spent so much time on making the code work by adding more and more lines, which just became patchwork to try to make things work off a an ineffective base assumption I made. There was a much simpler solution that I could have seen earlier if I had just taken a step back and though about it a bit, and which would have allowed me to allocate more time towards the design and implementation of more features. I was able to arrive at this solution very late in the process of the project timeline, but since I knew I had to fix the code, I had to factor that time in which limited my ability to work on the hardware.

So, if I were to make another iteration of the project, I would improve on the following points: definitely think critically about the code first and don’t overcomplicate things by continuing to brute force the logic. There’s always an easier way to do things even if that solution isn’t obvious at first. Next, would implement the LED flashing by using NeoPixels as a strip around the bottom of the device as I know that they would be much brighter and I could program them to blink more rapidly as the time the phone was removed in the middle of a timer increased. I would also probably add a buzzer to increase the annoying factor of the deterrent, as it would increase incentive to place the phone back on the plate. Lastly, I would figure out a way to place the RFID tag on the phone in a way such that I could place my phone face down on the top plate, so that I don’t get distracted by the notifications.

 

Technical Information

Electronic Schematic

Functional Block Diagram

Code:

/*
 * RFID Phone Lock
 * Serena Ying 60-223 Fall 2021
 * This code utilizes the MFRC522 Library to detect RFID signals from an MFRC522 Reader and 
 * compatible RFID Tag. The code will detect when an RFID tag is present on the sensor, and
 * set a flag to avoid disturbances where the RFID readings do not stay high.
 * 
 * Description:
 * While the user has not yet set a timer on the device, the LCD Display
 * will dynamically show the current value of time which the user can manipulate using the 
 * potentiometer on the device. Once the user presses the button, this code will save the analog 
 * reading of the potentiometer signal as the timer value. The LCD display will indicate 
 * "Phone Down..." to tell the user to place their phone down so that the RFID sensor can be detected, 
 * which starts the period of phone lock. Then, once the RFID tag has been detected, the LEDs 
 * will turn on and a counter will begin to count up from 0 to the timer value. The LCD display 
 * shows a progress bar for how much time out of the timer has elapsed, and indicates "Focus Time...". 
 * If the RFID tag is ever not detected on the reader, this code will stop the counter and display 
 * a LCD message to notify the user that the time is not up yet. In addition, the LEDs will begin flashing.
 * Once the RFID tag is once again detected, the LEDs will be constantly on once more and the counter resumes.
 * The LCD display will show "Focus Time..." until the count has reached the timer, at which point it
 * displays "Done!" for a short duration before returning to the state in which the user can 
 * manipulate the potentiometer and read the amount of minutes to set the timer for.
 * 
 * Pin Mapping:
 *  RFID Pin         Arduino Pin
 * ----------       -------------
 *    SDA                 10 (input)
 *    SCL                 13 (input)
 *    MOSI                11 (input)
 *    MISO                12 (input)
 *    IRQ                 --
 *    GND                 GND (output)
 *    RST                 5 (output)
 *    3.3V                3.3V (ouput)
 *    
 *   Signal          Arduino Pin
 * ----------       -------------
 *    LED_PIN              2 (output)
 *    RED_LED              7 (output)
 *    POT_PIN              A0 (input)
 *    BUTTON_PIN           4 (input)
 *    
 * Credits:
 * phenoxyethanol on instructables.com for the Arduino Progress Bar
 * lastminuteengineers.com for the RFID starter code
*/

#include <SPI.h>
#include <MFRC522.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

/* Creates an LCD display object called "screen" with I2C address 0x27
   which is 16 columns wide and 2 rows tall. */
LiquidCrystal_I2C lcd(0x27, 16, 2);

// RFID Reader pins
#define RST_PIN           9          
#define SS_PIN            10   

// External Circuit Pins
#define LED_PIN           2
#define RED_PIN           7
#define POT_PIN           A0
#define BUTTON_PIN        4   

// Consts used for operation of timer loop
const int DELAY_DURATION = 500;
unsigned long time_counter = 0;
unsigned long timer = 0;
unsigned long lcdcounter = 0;
unsigned long ledcounter = 0;
bool ledState = LOW;
int flag = 0;
int shortFlag = 0;
bool done = 0;
int buttonState = 0;         // variable for reading the pushbutton status
unsigned long delay_timer = 0;
int runnin = 0; // indicates that the button has been pressed


MFRC522 mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance

// Arrays for progress bar display
byte zero[] = {
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000
};
byte one[] = {
  B10000,
  B10000,
  B10000,
  B10000,
  B10000,
  B10000,
  B10000,
  B10000
};
byte two[] = {
  B11000,
  B11000,
  B11000,
  B11000,
  B11000,
  B11000,
  B11000,
  B11000
};
byte three[] = {
  B11100,
  B11100,
  B11100,
  B11100,
  B11100,
  B11100,
  B11100,
  B11100
};
byte four[] = {
  B11110,
  B11110,
  B11110,
  B11110,
  B11110,
  B11110,
  B11110,
  B11110
};
byte five[] = {
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111
};

// Print formatter helper function used for debugging
void formatPrint( char *leftStr, unsigned long MyVar1, char *sepStr, unsigned long MyVar2, char *rightStr, unsigned long MyVar3) {
  Serial.print (leftStr);
  Serial.print (MyVar1);
  Serial.print (sepStr);
  Serial.print (MyVar2);
  Serial.print (rightStr);
  Serial.println (MyVar3);

}


// Setting up RFID reader, button, LEDs, and potentiometer
void setup() {
  Serial.begin(9600);    // Initialize serial communications with the PC
  SPI.begin();      // Init SPI bus
  mfrc522.PCD_Init();   // Init MFRC522
  delay(4);       // Optional delay. Some board do need more time after init to be ready, see Readme
  mfrc522.PCD_DumpVersionToSerial();  // Show details of PCD - MFRC522 Card Reader details
  pinMode(LED_PIN, OUTPUT);
  pinMode(RED_PIN, OUTPUT);
  pinMode(BUTTON_PIN, INPUT);
  pinMode(POT_PIN, INPUT);
  // for setting up the lcd:
  lcd.init();
  lcd.backlight();
  lcd.home();
  lcd.createChar(0, zero);
  lcd.createChar(1, one);
  lcd.createChar(2, two);
  lcd.createChar(3, three);
  lcd.createChar(4, four);
  lcd.createChar(5, five);
}

// Function to update progress bar as the count increases until the set timer, causes lcd to animate blocks going across the screen
void updateProgressBar(unsigned long count, unsigned long totalCount, int lineToPrintOn) {
  double factor = totalCount / 80.0;
  int percent = (count + 1) / factor;
  int number = percent / 5;
  int remainder = percent % 5;
  if (number > 0)
  {
    lcd.setCursor(number - 1, lineToPrintOn);
    lcd.write(5);
  }

  lcd.setCursor(number, lineToPrintOn);
  lcd.write(remainder);
}


// Main loop for operation, waits for button press to begin the counter and other functionality
void loop() {
  // for lcd:
  if (millis() - lcdcounter >= 500) {
    lcd.clear();
    lcd.home();
    lcd.print("Set timer for :");
    lcd.setCursor(0,1);
    lcd.print(timer);
    lcd.print(" minutes");

    lcdcounter = millis();
  }
  // check button, if pressed, stop updating the timer to pot_pin (sets the timer) and resets counter to 0, done to 0, and 
  // updates runnin to 1
  buttonState = digitalRead(BUTTON_PIN);
  if (buttonState == HIGH) {
    Serial.println("BUTTON PRESSED");
    runnin = 1;
    done = 0;
    time_counter = 0;
  }
  else if (buttonState == LOW) {
    timer = map(analogRead(POT_PIN), 0, 1023, 60, 0);
    Serial.println(timer);
  }
  // Runnin indicates that the button has been pressed and that the next thing to check for is the RFID tag state
  while (runnin) {
    buttonState = digitalRead(BUTTON_PIN);
    if (buttonState == HIGH) {
      Serial.println("BUTTON PRESSED");
      digitalWrite(LED_PIN, LOW);

      Serial.println("DONE!");
      if (millis() - lcdcounter >= 500) {
        lcd.clear();
        lcd.home();
        lcd.print("Are you sure???");
        delay(3000);
        done = 0;
        lcdcounter = millis();
        runnin = 0;
        return;
      }
    }
    // for lcd to print out three options of messages
    if (millis() - lcdcounter >= 500) {
      lcd.clear();
      lcd.home();
      if (time_counter == 0) {
        lcd.print("Phone Down...");
      }
      else if (shortFlag) {
        lcd.print("Time's not up!!");
      }
      else {
        lcd.print("Focus Time...");
      }
      updateProgressBar(time_counter, timer, 1);
      lcdcounter = millis();
    }
    // if time has been reached, we can exit
    if (time_counter >= timer) {
      done = 1;
      Serial.println("Done!");
    }
    // if time has not been reached, enter the operation function which maintains the counter on a delay loop
    if ((millis() - delay_timer) >= DELAY_DURATION) {
      operation();
      delay_timer = millis();
    }
    // if we have indicated that the RFID tag has been removed prematurely, set the shortFlag and blink the LED
    if (shortFlag) {
      if (millis() - ledcounter >= 500) {
        ledState = !ledState;
        ledcounter = millis();
      }
      digitalWrite(LED_PIN, ledState);
      digitalWrite(RED_PIN, ledState);


    }
    // if the done flag has been set from within the operation function, turn off the LED and update the LCD display
    if (done) {
            digitalWrite(LED_PIN, LOW);

      Serial.println("DONE!");
      if (millis() - lcdcounter >= 500) {
        lcd.clear();
        lcd.home();
        lcd.print("Done!");
        delay(3000);
        done = 0;
        lcdcounter = millis();
        runnin = 0;
        return;

      }

    }
  }
}

// Operation function begins once the button has been pressed, which set the timer, and sets flags which indicate if the
// tag is present or not
void operation() {
  if (!done) {
    flag = 0;
    if (mfrc522.PICC_IsNewCardPresent())
    {
      flag = 1; // card present
    }
    else  //try again to catch the toggle effect
    {
      if (mfrc522.PICC_IsNewCardPresent()) flag = 1; // card present
    }
    // if present, increment the counter
    if (flag) {
      Serial.println("Flag!");
      time_counter = time_counter + 1;
      Serial.println("Timecounter:");
      Serial.println(time_counter);
      digitalWrite(LED_PIN, HIGH);
      digitalWrite(RED_PIN, LOW);
      if (shortFlag) {
        shortFlag = 0;
        Serial.println("Resetting shortFlag");
      }
    }
    // if not present, do not increment the counter and check if the time is premature or not
    else {
      Serial.println("No Flag!");
      Serial.println(time_counter);

      if (time_counter != 0 && time_counter < timer) {
        Serial.println("Nope");
        shortFlag = 1;
      }
    }
  }
}

 

]]>
Double Transducer: Rotational Position to Frequency of Tapping https://courses.ideate.cmu.edu/60-223/f2021/work/double-transducer-rotational-position-to-frequency-of-tapping/ Tue, 05 Oct 2021 06:17:05 +0000 https://courses.ideate.cmu.edu/60-223/f2021/work/?p=13965 Description

This project is a double transducer that takes a rotational position (0-90) as input and produces a frequency of tapping (20-60 taps per min) as output. The double transducer takes in the rotational degree and adjusts the rotation of the stepper motor accordingly. The stepper motor then drives the pulley to change the position of the obstacle. The ultrasonic ranger detects the distance between the obstacle and itself to adjust the frequency of tapping in accordance.

Overall Logic:

Rotational Position (Potentiometer) –> Stepper Motor Rotation –> Pulley System Movement –> Obstacle Movement –> Distance Detection by Ultrasonic Ranger –> Frequency of Tapping (Solenoid)

Overall Photos

Serena’s Overall

Bella’s Overall

Detailed Photos

Stepper Motor

Stepper Motor Pulley System

Stepper Motor Driver Closeup

Solenoid Driver Circuit

Stepper Motor (left) and Solenoid (right) Driver Circuits

Movies

Serena’s video:

 

Bella’s video:

 

Progress Images

Figuring out the solenoid voltage problem

Figuring out how to use a solenoid

Initial prototype for pulley system with stepper motor and potentiometer

Added LCD display and solenoid to the mix after switching to a stepper motor for a more hefty rotational force

Discussion

The project taught us that implementing a fun idea could present so many challenges, ones that we anticipate and ones that come out of nowhere. For this project, some parts we were prepared to tackle with patience from the beginning, such as the pulley system controlled by the stepper motor. We spent a long time brainstorming on how to use a stepper motor, how to make the pulley work, how to move the obstacle attached to the pulley, etc. But the real frustration came from the parts that we thought would be as easy as a breeze, such as a solenoid. The solenoid seemed to be simpler than most of the things we’ve seen in class. However, it was unexpected that adding the solenoid would cause a disruption for the voltage for the entire project. The solenoid causes the 5V to drop to around 3V whenever it is activated, causing the LCD display to dim and the stepper motor to shake. After an hour of tinkering in the OH on the night before the due, we still could not find the problem. Since we left the solenoid to be the last to do, it was too late to find an alternative to solve the issue. This experience shows that every part of the project should be tested out in the beginning stage, even the ones that appear to be easy to implement.

This project also showed the importance and efficiency of the “divide and conquer” strategy. During the early stages, we experimented with different sections of the project. While one of us attempts to figure out how to use a stepper motor, the other one would fiddle with the LCD display. Being responsible for different tasks and piecing them together in the end allowed us to work efficiently and effectively within a limited time.

Functional Block Diagram

Schematic Diagram

Code

/*
 * Double Transducer: Rotational Position -> Frequency of Tapping
 * 
 * Team Members: Bella Liu, Serena Ying
 * 
 * Description:
 *   The program is designed to receive input from the potentiometer and convert
 *   the value to appropriate rotatoin for the stepper motor in order to control
 *   the pulley and therefore move the obstacle. The ultrasonic ranger then detects 
 *   the distance between itself and the obstacle, and converts it to a frequency for
 *   the solenoid tapping accordingly.
 *  
 * Pin Mapping Table:
 * 
 *   Arduino pin | description
 *   ------------|-------------
 *   A0            Potentiometer
 *   
 *   11            Echo pin, ultrasonic ranger
 *   12            Trigger pin, ultrasonic ranger
 *   
 *    2            Step pin, A4988 driver chip for stepper motor
 *    3            Direction pin, A4988 driver chip for stepper motor
 *    
 *   SDA           SDA pin, LCD display
 *   SCL           SCL pin, LCD display
 *
 *
 * References: 
 *  https://courses.ideate.cmu.edu/60-223/f2021/tutorials/ultrasonic-ranger
 *  https://courses.ideate.cmu.edu/60-223/f2021/tutorials/stepper
 *  https://courses.ideate.cmu.edu/60-223/f2021/tutorials/I2C-lcd
 */

// Libraries
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <AccelStepper.h>
#include <NewPing.h>

//Pin for potentiometer
const int POTEN = A0;

//Pins for ultrasonic ranger
const int TRIGGER_PIN = 12;
const int ECHO_PIN = 11;
const int MAX_DISTANCE = 200;

//Pins for A4988 diver chip
const int STEP_PIN = 2; // A4988 "STEP" pin wired to Arduino pin 2 (you can change this)
const int DIR_PIN = 3; // A4988 "DIRECTION" pin wired to Arduino pin 3 (you can change this)

//Variables for LCD display
unsigned long LCDtimer = 0;
const int LCDwait = 500;
bool LCDstate = LOW;

//Pin and variables for solenoid
const int SOLENOID = 5;//This is the output pin on the Arduino
unsigned long SOLEtimer = 0;
int SOLEwait = 0;
bool SOLEstate = LOW;

//Setups
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); 
LiquidCrystal_I2C screen(0x27, 16, 2);
AccelStepper motor(1, STEP_PIN, DIR_PIN);

void setup() {

  //Pin setup
  pinMode(POTEN, INPUT);
  pinMode(SOLENOID, OUTPUT);

  Serial.begin(9600);
  Serial.begin(115200);

  //LCD screen initialization
  screen.init();
  screen.backlight();

  // set cursor to home position, i.e. the upper left corner
  screen.home();

  //Stepper motor initialization
  motor.setMaxSpeed(6000); // measured in steps per second
  motor.setAcceleration(8000); // measured in steps per second squared

}

void loop() {

  //Variables to store values for potentiometer and ultrasonic ranger
  int potVal = analogRead(A0);
  int ranger = sonar.ping_cm();

  //Printing potentiometer and ultrasonic ranger values in the monitor for debugging
  Serial.println(potVal);
  Serial.print("ping:");
  Serial.print(sonar.ping_cm());
  Serial.println("cm");

  //Adjust the stepper motor rotation according to the rotational degree
  int motorPos = map(potVal, 0, 1023, 0, 400);
  motor.moveTo(motorPos);
  motor.run();  

  //Adjust the frequency of tapping based on the distance detected by the ranger
  SOLEwait = map(ranger, 19, 0, 800, 300);
  if ( (millis() - SOLEtimer) >= SOLEwait ) { 
    SOLEstate = !SOLEstate; 
    SOLEtimer = millis(); 
  }
  digitalWrite(SOLENOID, SOLEstate);

  //display on the LCD
  if ( (millis() - LCDtimer) >= LCDwait ) { // millis() is always the number of milliseconds since the Arduino powered up
    LCDstate = !LCDstate; // this will "toggle" the value of "quarterStateLight" to its opposite
    LCDtimer = millis(); // reset the timer before exiting the function.
  }

  //display values for the LCD
  int input = map(potVal, 0, 1023, 0, 99);
  int mid = map(motorPos, 0, 400, 0, 99);
  int mid2 = map(ranger, 20, 0, 0, 99);
  int output = map(SOLEwait, 300, 100, 0, 99);  
  
  if (LCDstate == HIGH) {
      screen.clear();
      screen.print("i:");
      screen.setCursor(6,0);
      screen.print("m:");
      screen.setCursor(6,1);
      screen.print("m:");
      screen.setCursor(12,1);
      screen.print("o:");
      screen.setCursor(2, 0);
      screen.print(input);
      screen.setCursor(8, 0);
      screen.print(mid);
      screen.setCursor(8, 1);
      screen.print(mid);
      screen.setCursor(14,1);
      screen.print(output);
  } 

}

 

]]>