For our Intro to Physical Computing class’s final project, our group, the Guavas, is working with Shaude, an individual from Pittsburgh with cerebral palsy, to develop an assistive device that’s useful and relevant to her experience. To better understand her wants and needs, and get to know Shaude better, we conducted an informational interview with her. It was conducted at Community Living And Support Services (CLASS), a nonprofit organization Shaude spends her time taking classes at during the day, with the members of our group: Sapna, Evie, Dunn and Andres. Our goal for the meeting was to gain a better understanding of aspects of Shaude’s daily routine, tasks or activities she enjoys doing, and spaces for an assistive device during these.
10:00 – Introductions/Ice Breakers. Continue the meeting that started in class the previous week in order to allow a more comfortable interview environment as well as begin to understand her desires and needs
10:20 – Discuss the initial ideas we had that may help her and the initial hopes on what she hoped to gain by participating in this program as well as timeline for project.
10:40 – Discuss how she goes about her day, investigate a walkthrough of normal schedule from wake up to go to sleep in order to find areas in daily life that may need assistance
10:55 – Discuss her likes and frustrations in life. What are some things she really enjoys doing we could make more common, are there any interactions that you have with people we could make easier
11:20 – Spend rest of time discussing takeaways from interview with interviewee as well as see if we can document real life actions of Shaude, i.e. take photos of chair, her range of motion, her doing normal actions.
Rough notes from the meeting.
With Shaude we talked about her daily tasks, what she has the most difficulty with, and how she copes. Shaude has Cerebral Palsy, uses a motorized wheelchair and has the most difficulty with her left foot. In her arms she has the most range of motion, but has struggle gripping with her right hand. She mostly uses her left hand. Besides her mobility issues, Shaude opened up about recently losing her best friend, her great aunt and her troubles coping with grief and mood. She notes that she wishes she could communicate her mood better with her mother, roommate and others helping her. She also wishes to understand them better in turn. She notes that she has the most trouble with her mood in the morning. She says that she is foggy in the mornings, it is harder in the morning for her to communicate her needs to others.
In her daily tasks she noted the reach holding her back from independence. Since she is in a wheelchair she needs someone to help her retrieve anything she drops. She notes that this is most commonly a problem when she is reading a book. She first needs to request a book for someone, and then notes she will often drop a book and need help retrieving it. With her hobby of art and painting we asked her to demonstrate how she goes through this process. She didn’t note any difficulty with her process, but we noted that she needs to bend over in a seemingly uncomfortable way.
Client demonstrating current method of use for paint brush, allow designers to understand range of motion and physical limitations
Shaude holding a paintbrush to show us grip strength and positioning
Lastly we asked about how she gets from place to place. She uses a service called access, but notes she often has difficulty with it because she gets cold while waiting and has difficulty getting warmer. Besides all of these issues we got a good list of her favorite TV shows, games and books. We hope to pursue a feasible solution to one of these problems while making it personal to her and her tastes.
Overall, the interview with Shaude was great, and stayed mostly according to our meeting agenda. The conversation was easy to start and she was very open to communication and chatting with us. There are instances where she brought up ideas that are potentially unachievable, such as those involving dogs, money, and traveling. The team thought it would have been better if the meeting was more physically involved, rather than verbally. For example, we asked her, with respect, to demonstrate her arms’ range of motion, and we should have done more of these where we can understand how she lives her life. She also talked a lot about her passion about art and reading, and we thought it would be very insightful to see the art she makes and the book she reads, so the team can understand more about her and her personality.
]]>A non-destructive attachment to a campus bed that includes a clock, alarm, shelf, and lockable compartment to prevent use of phone in bed.
Demonstration of Alarm/Clock Functionality of Project. Here the alarm would have been set and when the time and alarm where the same, the buzzer would have started.
Demonstration of use of solenoid lock in bottom compartment of project. Here the compartment would be closed and the button far away from bed, forcing user to stand up and walk to press button and unlock compartment in order to access phone.
Clear visual of layout of current time and alarm set point. Also location of potentiometers to set alarm.
Open space to place phone to prevent use, sliding door to access the space and the 5V solenoid lock controlled by button that is separate from main system.
Throughout the design and production process of this project, there were a couple decision points that impacted the final design of my project. The first and most notable was the mode of triggering the solenoid to unlock. Due to wanting to include other subsystems within the final design, as well as manufacturing time requirements, I had to opt for a simpler mode of unlocking the solenoid lock. Originally, I was planning on creating a switch connected to a NRF24L01 wireless connector and a battery source placed in another room that ‘spoke’ to another NRF connector in the main system that told the solenoid lock to open. However, using this to operate the system would have required ordering the part, learning how to get two Arduinos to communicate correctly and I’m sure other issues not considered. Instead, as can be seen in the below image, I used a simple arcade pushbutton connected to the singular Arduino in the product connected through two wires that could be placed at a distance from the bed due to the length of those wires. This decision gave me the time to properly code, wire, and build the other parts of the project instead of struggling with a single subsystem.
Another point that I had to think about and change that significantly impacted the design of my project was the type of speaker to use in the alarm system itself. Originally, I was going to not even use a speaker at all but instead use a vibrator pancake available in the physical computing lab, however, after testing it, I realized that unless I had it physically on my body somehow it would be insufficient to wake me up in the morning. Then I decided to use a 8Ω, 0.2W speaker as that was what I was familiar with from project 1. However, I had a lot of problems with this as I would run 5 V through this speaker when it was not designed for this amount of power. This meant that even though my wiring was correct, the speaker would stop working after a couple of uses of the system. I fixed this issue by using a 8Ω, 3W speaker and a transistor to convey the alarm sound. This speaker could accept the 5V without issue and allowed my alarm to work without issue.
Solidworks design of project to be laser-cut out of wood. Used finger joints and glue to attach after cut.
Initial prototyping of electronics to make sure code and electronics worked together correctly when using temporary connections before everything connecting through use of soldering.
Code slice showing how speaker could be turned on or off. Was an issue at first because in original code alarm would not turn off after it had been triggered. Here, line 124 ensures that alarm only on at appropriate time.
Process of putting together final product. Included soldered together electronics, and Arduino. Later top of box glued down so no wires exposed unnecessarily.
This was a very interesting project to work on, challenging on a technical level while still allowing growth of skills such as soldering, circuits and design. There were a couple of things I would have liked to change or improve on if I had more time to work on the project before submission. In fact, two of those were pointed on in the in-class critique. The first was, “You could add some sort of long piece connected to the bottom that would go under the mattress instead of just attaching it to the side of the bed”. This was an issue I didn’t give sufficient thought to. I had planned to attach the developed system to my bed using command strips as seen in the featured image, however when I attempted that it did not work. Not providing enough support for when I placed my hand on it. I plan on creating a bar to extend from the bed frame that I can attach the bottom of the box to instead of using command strips. Another comment of interest was, “I wish the top was cushioned or padded with fabric in some way. Not sure how the wood texture would feel during sleep.” I want to put some cushioning on the free area of the object to rest my arm on in, to accomplish this I plan to buy a very small pillow and attach it to the wood using hooks.
Overall, I was satisfied with my project. it accomplished the goal I set out with, which was a bed attachment that I could rest my arm on when asleep, and in fact I added functionality to this initial problem such as a clock, alarm and phone lock to ensure I get up when I need to. The only thing I would want to spend more time on if I could is form. This is one thing I learned while working on this project. Don’t be committed to one design too early. Once I made my first CAD of the product, I immediately laser cut it out of the final material. However I think if I would have started making out of cardboard fr simpler faster manner I could have seen a lot of areas of improvement in advance. I also learned a lot about the use of transistor and their use. I think they really helped me refine my final electrical design. Making both the speaker and solenoid work a lot better as I could consistent voltage through them very easily in a very controlled manner that not using them would prevent. Finally, I do not plan on doing another iteration of this product but instead just doing a couple of easy improvements to my existing product to allow for better use. If I were to make another iteration though, there are three major things I would do. The first is wire management. I soldered all my cables in my product, however I often used soldered wires to get them off the protoboard when not necessary. I would be both easier and cleaner to place things directly on the board. Second is attachment mode, I would use an attachment rod on the bottom instead of command strips. Lastly, I would want to use a more complex way to unlock the solenoid lock. Instead of a simple push button I might use a computer generated math problem or something similar.
/* Morning Insurance: Assistive Device for Yourself, Project 2 By: Andres Montemayor Description: The code below does five seperate things. The first would be to set the alarm. By reading two seperate potentiometer inputs, it maps their values onto a 24 hour time schedule and displays that alarm time on an I2C LCD module The second is it reads the current time from an RTC module and also displays that on the I2C Module, The third is it only turns on the backlight of a LCD screen for a predescribed length of time when button 1 is pressed. The fourth is it unlocks a solenoid for a predetermined length of time when button 2 is pressed. The fifth is when the current hour and minute on the clock is equal to the hour and minute set in the alarm it triggers a speaker to make noise until that is no longer true. IE when the alarm changes or the minute changes. Pin Map: pin | mode | description POT1_PIN | input | potentiometer: sets alarm hour POT2_PIN | input | potentiometer: sets alarm minute buttonPin | input | reads when arcade button pressed, triggers backlight on LCD screen lockButton | input | reads when arcade button pressed, unlocks solenoid SPEAKER_PIN1 | output | outputs sound at 400 Hz while alarm is triggered SOLE_PIN | output | unlocks door, high or low to control if open or closed SQL | OUTPUT/INPUT | lcd and rtc go in here SDA | OUTPUT/INPUT | lcd and rtc go in here Credit: Used chatGPT to assist in writing code for controlling wheather or not the backlight should be on IE lines 99 through 111. Used example code from course website for I2C lcd displays available at this website:https://courses.ideate.cmu.edu/60-223/s2023/tutorials/I2C-lcd, and example code from RTC, ds3231, to help write relevent sections Used library from adafruit on RTC_DS3231 available at this website:https://github.com/adafruit/RTClib */ //modules to control different subsystems #include <Wire.h> #include <LiquidCrystal_I2C.h> #include <RTClib.h> //Initialize the LCD library with the I2C address, number of columns and rows. call it lcd LiquidCrystal_I2C lcd(0x27, 16, 2); // Initialize the RTC module object and call it rtc to control from now on RTC_DS3231 rtc; // Initialize the pins for the potentiometers, buttons, speaker, and solenoid const int POT1_PIN = A0; const int POT2_PIN = A1; const int SPEAKER_PIN1 = 9; const int buttonPin = 2; const int lockButton = 5; const int SOLE_PIN =11; //Initialize variables used throughout code for time, timers, and bools bool isButtonPressed = false; bool isLightOn = false; bool isDoorOpen = false; int alarm_hour = 0; int alarm_minute = 0; unsigned long lastOnTime = 0; unsigned long lastUnlockTime = 0; void setup() { // Initialize the LCD display lcd.init(); // Initialize the RTC module Wire.begin(); rtc.begin(); // Set the current time, only do if need to replace battery in RTC module. //rtc.adjust(DateTime(2023, 2, 27, 9, 50, 00)); //year,month,day,hour,min,sec // Set the pins for the potentiometers, vibrator, speaker and solenoid pinMode(buttonPin, INPUT); pinMode(POT1_PIN, INPUT); pinMode(POT2_PIN, INPUT); pinMode(SPEAKER_PIN1, OUTPUT); pinMode(lockButton,INPUT); pinMode(SOLE_PIN,OUTPUT); } void loop() { //if button pressed open solenoid and start a timer if (digitalRead(lockButton) == LOW) { lastUnlockTime = millis(); isDoorOpen = true; digitalWrite(SOLE_PIN,HIGH); } //if 15 seconds have passed close solenoid if (millis()-lastUnlockTime >= 15000) { digitalWrite(SOLE_PIN,LOW); } //if button pressed and backlight off, turn it on and start a timer if (digitalRead(buttonPin) == LOW && !isLightOn) { isButtonPressed = true; lastOnTime = millis(); lcd.backlight(); isLightOn = true; } // Check if the LCD screen is on and the timer is off if (isButtonPressed && (millis() - lastOnTime) >= 20000) { lcd.noBacklight(); isButtonPressed = false; isLightOn = false; } // Print the current time to the LCD display DateTime now = rtc.now(); lcd.setCursor(0, 0); lcd.print(now.hour(), DEC); lcd.print(":"); if (now.minute() < 10) { lcd.print("0"); } lcd.print(now.minute(), DEC); lcd.print(":"); if (now.second() < 10) { lcd.print("0"); } lcd.print(now.second(), DEC); // Read the values of the potentiometers to set the alarm int pot1_value = analogRead(POT1_PIN); int pot2_value = analogRead(POT2_PIN); alarm_hour = map(pot1_value, 0, 1023, 0, 23); alarm_minute = map(pot2_value, 0, 1023, 0, 59); // Print the alarm time to the LCD display lcd.setCursor(0, 1); lcd.print("Alarm: "); if (alarm_hour < 10) { lcd.print("0"); } lcd.print(alarm_hour); lcd.print(":"); if (alarm_minute < 10) { lcd.print("0"); } lcd.print(alarm_minute); // Check if the current time matches the alarm time if (now.hour() == alarm_hour && now.minute() == alarm_minute) { // Activate the speaker tone(SPEAKER_PIN1, 440, 0); } else { //otherwise turn off speaker noTone(SPEAKER_PIN1); } }
]]>
Juhi’s Double Transducer
Andres’s Double Transducer
The Adafruit TCS34725 RGB color sensor is propped up by an inch to align with the output of the other team and receive the input.
Close up of the wiring we did to connect the Arduino to different sub-systems of the double transducer project.
The linear actuator is responsible for extending and retracting the rubber band (i.e. the lever mechanism) dependent on the color read by the RGB sensor.
Close up of the middle step. The force sensor is supported by a wall and is being pushed by the lever pivoted on a stand, which is moved by the linear actuator.
The output i.e. the speaker that varied the sound pitch (from 200Hz to 2000 Hz) according to the amount of force received by the force sensor. (In the color spectrum red being the lowest to purple being the highest)
The machine sees the color emitted by LED, then uses the color value to expand or compress a motor which moves a lever mechanism. The force exerted by the lever mechanism is detected by a senor and is used to change the pitch of a speaker.
At first, we tested out all our inputs and output individually to see whether they were working or not (Juhi)
Once we had all our elements, we were experimenting with the linear actuator and its position in terms of the range we set in relation to the color spectrum (Juhi)
To connect our parts in relation to the other we had to solder a few things (Andres)
To create our middle step we were experimenting with different types of lever mechanisms that would suit our transducer (Andres)
Our double transducer project, while educational, was filled with unexpected challenges. We faced many throughout the project, but the biggest were converting the RGB input signal form into a usable scale, controlling the linear actuator, and coding in general. To start with the RGB adafruit color sensor, depending on the color it ‘sees’ it outputs a RGB value to the arduino; however, we needed to convert this to a linear scale to control the linear actuator. We did this by transforming from the RGB domain to the ‘HSL’ domain where H or hue can be used to put colors on a linear scale from 0 to 360. But, not knowing anything about colors before this project, we had to do research online, speak to the professor and the TA to not only understand how to do this but understand that this was even an option. Moving on to controlling the linear actuator, as it doesn’t have an integrated control, or position controller, we had to figure out how to not only determine position but control that position using time passed and an experimentally determined rate of speed. As neither of us knew a lot about code, we had to once again conduct outside research and learn what and how to use an open loop controller which was extremely helpful in controlling both the actuator, and updates on the I2C screen. Finally, we made bug fixing our code much more challenging than it had to be. This is because we began putting things together before we had debugged each individual piece. Meaning errors propagated throughout the system that could have been fixed piecemeal if we had done more rigorous testing early on. For example, we connected the color sensor to the actuator early on and when the actuator didn’t output the correct distance, I was sure that it was because I mapped the hue incorrectly when actually it was because I was incorrectly controlling the non-feedback actuator.
Being open to change and adapting original ideas was also, in my opinion, one of the most significant and positive parts of our creation process. For instance, when we started, I was sure that a spring was the only way to go in regards to attaching the actuator to the FSR sensor, but through testing we realized a spring added unneeded complexity that just using a weak rubber band would fix. Another thing we had to be open to changing was how to transmit the force to the FSR sensor. Because it only senses compression, at first we weren’t sure of the best way to switch the tension force we were getting from the actuator to compression. We solved this issue by meeting, talking, and listing out ideas before deciding that a simple lever as seen above was the best solution. Finally on things we would have changed if there was more time, two come to mind. The first is changing from a 4 inch extending actuator to a 2 inch as the extra distance only added error to our conversion that a smaller range would have solved. The second is further research into how the Adafruit color sensor works. Because much of the code was based on examples provided by the downloaded library, we were using features and commands that we weren’t 100% certain of their purpose. Because of this, things that we could have changed or adjusted for more ease of use were taken as set in stone. For instance, the sensor has an optional white LED to make colors clearer to the sensor, but since our input was from a LED itself, for us this was unnecessary. However, we weren’t aware it could be turned off and the glare it caused, created problems we had to work around that had an extremely easy fix.
As a group some of the biggest lessons we learned from this project was to avoid unnecessary stress and take things one step at a time. I think we were worried about succeeding 100% in everything we set out to do, which is good, but not to the point of frustration. Every part had value and even if we didn’t succeed completely the learning is more important than success. The other thing we hope to take away from this into project two is while these electronics combine into one system, they are composed of many different individual components. If there is a problem it is most likely in one of these subsystems and the best practice is to start at the beginning and move up when testing.
/* Double transducer: From light color to sound pitch {Andres Montemayor, Juhi Kedia} The code below processes and translates an input RGB reading from LED lights to a speaker pitch (200Hz to 2000Hz). The middle step for the double transducer is a liner actuator that extends and contracts according to the RGB color sensor reading and pushes along a force sensing resistor according to the color spectrum (red being the lowest and violet being the hightest). Pin Map: pin | mode | description FSR_pin | input | LED MOTORCONT1 | output | potentiometer: sets blink rate MOTORCONT2 | output | pushbutton: affect blink rate SPEAKER | output | tone from 200 Hz to 2000 Hz based on FSR reading SQL | OUTPUT/INPUT | SCREEN and ADAFRUIT go in here SDA | OUTPUT/INPUT | SCREEN and ADAFRUIT go in here RGB sensor code sourced from adafruit Color control Used example code from adafuit library 'color view' and code linked below to write this: https://www.geeksforgeeks.org/program-change-rgb-color-model-hsv-color-model/ Conversion from RGB to HSV values makes use of an algorithm sourced from: https://www.rapidtables.com/convert/color/rgb-to-hsv.html */ /* have Working: adafruit color sensor, force sensor, speaker in progress: done test on board */ #include <Wire.h> #include "Adafruit_TCS34725.h" #include <LiquidCrystal_I2C.h> // set to false if using a common cathode LED #define commonAnode true // our RGB -> eye-recognized gamma color byte gammatable[256]; Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS, TCS34725_GAIN_4X); LiquidCrystal_I2C screen(0x27, 16, 2); // rename pins const int FSR_pin = A0; const int MOTORCONT1 = 10; const int MOTORCONT2 = 11; const int SPEAKER = 2; // Set variables for use throughout code float posPast; double travelTime; float stopTime; int swtch = 0; float hPast = 0; int swtch2 = 1; unsigned int timer = 250; void setup() { pinMode(FSR_pin, INPUT); pinMode(MOTORCONT1, OUTPUT); pinMode(MOTORCONT2, OUTPUT); pinMode(SPEAKER, OUTPUT); pinMode(A3, INPUT); screen.init(); screen.backlight(); Serial.begin(9600); // Begin color sensing sensor if (tcs.begin()) { Serial.println("Found sensor"); } else { Serial.println("No sensor"); } extend(); delay(3000); stop(); } // extends the linear actuator void extend() { digitalWrite(MOTORCONT2, LOW); digitalWrite(MOTORCONT1, HIGH); } // returns the linear actuator void retract() { digitalWrite(MOTORCONT2, HIGH); digitalWrite(MOTORCONT1, LOW); } //stops the linear actuator void stop() { digitalWrite(MOTORCONT1, LOW); digitalWrite(MOTORCONT2, LOW); } void loop() { /* //read a pot val was used for testing int potVal = 0; //do the read and store the value into potVal potVal = analogRead(A3); //send potVal's value back to computer */ //FSR control int fsrReading = analogRead(FSR_pin); //Serial.println(fsrReading); // this done input of fsrReading tells force on sensor 0 -> 1023... might need to adjust if too much force being put on // can just change spring as well uint16_t r, g, b, c; double h = 0; // Gather various color data from RGB sensor tcs.getRawData(&r, &g, &b, &c); // RGB to HSV float rNew = r / 65535.0; float gNew = g / 65535.0; float bNew = b / 65535.0; // RGB to HSV algorithm float cmax = max(rNew, max(gNew, bNew)); // maximum of r, g, b float cmin = min(rNew, min(gNew, bNew)); // minimum of r, g, b float diff = cmax - cmin; // diff of cmax and cmin. // if cmax and cmax are equal then h = 0 if (cmax == cmin) { h = 0; } // if cmax equal r then compute h else if (cmax == rNew) { h = fmod(60 * ((gNew - bNew) / diff) + 360, 360); } // if cmax equal g then compute h else if (cmax == gNew) { h = fmod(60 * ((bNew - rNew) / diff) + 120, 360); } // if cmax equal b then compute h else if (cmax == bNew) { h = fmod(60 * ((rNew - gNew) / diff) + 240, 360); } Serial.print("Hue: "); Serial.println(h); //end color control h: 0 -> 360 red -> purple //motor control int travelTime = map(h, 0, 360, 0, 3000); int posNew = map(h, 0, 360, 0, 100); //int posNew = potValMap; if (abs(posNew - posPast) > 5) { if (swtch == 0) { float travelProportion = abs(posNew - posPast) / 100; stopTime = millis() + (travelTime * travelProportion); swtch = 1; } //Serial.println("Need to move"); if (stopTime < millis()) { stop(); posPast = posNew; swtch = 0; } if (posNew < posPast) { retract(); Serial.println("retract"); } if (posNew > posPast) { extend(); Serial.println("extend"); } } /* Serial.print("PosNew: "); Serial.println(posNew); Serial.print("posPast: "); Serial.println(posPast); */ //speaker control int pitch = map(fsrReading, 0, 1023, 200, 2000); //dropped from 1023 to 900 because sensor wasn't reaching max //Serial.println("pitch: "); //Serial.println(pitch); tone(SPEAKER, pitch, 0); //(pin, frequency, delay between tones: should be 0) //lcd screen //only want to update every quarter of a second so made swtch2 to do that if (swtch2 == 1) { Serial.println("screen update"); screen.clear(); screen.home(); screen.print("i:"); int hPrint = map(h, 0, 360, 0, 99); screen.print(hPrint); screen.setCursor(6, 0); screen.print("m:"); screen.print(posNew); screen.setCursor(8, 1); int fsrPrint = map(fsrReading, 0, 1023, 0, 99); screen.print(fsrPrint); screen.setCursor(12, 1); screen.print("o:"); int pitchPrint = map(pitch, 200, 2000, 0, 99); screen.print(pitchPrint); swtch2 = 0; } if (millis() >= timer) { swtch2 = 1; timer += 200; } }
]]>