Jennie Wei
Top view of the posture proctor: This is the interface the user sees when the device is in use. The bad posture indicator lights are on and look like eyes :)
Side view of posture proctor with on/off switch and the clamp screw in view
This project monitors my posture as I sit at a desk, indicating with lights when I am not sitting straight (too far from the table). It also tracks how long I've been sitting and reminds me to take a break at 20-minute intervals of sitting.
3/4 view
3/4 view showing a bit of the clamp screw in use
Led lights in the eyes of the rabbit on the top side; infrared temperature sensor (left) and laser distance sensor (right) in the upside down rabbit's eyes on the front side.
Device interface when "take a break" light is on.
All of the sensors and LEDs are soldered to a portoboard screwed into the inside panel. The Arduino sits atop the battery pack.
This video shows how the device flashes when I slouch and stops when it sit up straight. Near the end of the video you can see that after 20 seconds passes, the break indicator light and signal goes off. The signal stops when I stand up but the break light continues.
This view shows a top view of the device in use. I change my posture a few times in the video and the bunny eyes on the top interface light up when I'm slouching. At the end the 20 seconds of sitting time has passed so the break light in the top left corner turns on.
Prototype sketch/plans for a plush-wrapped device.
Initial prototype to get the sensors working and a red LED for feed back.
First box design. I had an obnoxious amount of fingerjoints and it was too big.
Initially, I didn't have concrete measurements because I wasn't sure how small I could get my electronic components to be, so I ended up with 4 versions to make my final box size/design as compact as possible (had weird issues with measurement constraints so it was easier for me to restart than change all measurements).
Final box design! I also spent multiple iterations refining the finger joints to be less noticeable. I had a difficult experience with finger joints since I had so many surfaces and if I wanted to undo something specific I would have to also undo everything after it.
First lasercut
First lasercut pieces
Somewhat ugly & too large, but it worked!
Laser-cutting my second smaller box iteration with graphics that I made in Illustrator! It was challenging to remember all the settings for the rastering and vectoring but the monitor helped me
Lasercut pieces of the final box. You can see the tee nut I used on the panel for the clamp screw on the right.
Planning how I was going attach my portoboard to my device with screws and nuts.
Soldered all the input and output elements to a protoboard and screwed it to the panel. Lots of wire management going on here.
"The use of a temperature sensor to detect whether a person is sitting or it’s just a chair is really cool"/ "Everyone likes the implementation of the temp and distance together" is the most common positive feedback I got, which I appreciate since it speaks to the functionality of my final device and not just the aesthetics (which is a big reason why I like this class!). I have to thank Zach for initially bringing up the issue of detecting a person's presence vs an object's presence as it was a possible issue I didn't think of before and I'm proud of myself for coming up with the idea of using temperature since it seems like the most portable implementation.
"Lights might be tweaked; brightness and/or different colors" was a negative crit I got while "I really like the difference between the break light and the bad posture light" was a positive crit I got. During the actual crit, it was interesting to see how some people really liked the bright flashing lights for the posture indication because it is attention-grabbing, while others disliked it for the same reason. I appreciated people voicing their differing opinions since it gave insight into how different people would approach the same problem based on their mental model of what the device should do (such as be more disruptive/urgent or be more minimal/less distracting). I chose the jarring flashing lights for a stronger visual warning to myself about my posture since I could ignore it otherwise, but if I were designing this for a broader population and had more time I would love to test with more people to find the most suitable setting for the indicator lights! Someone also mentioned the idea of ramping up the visual intensity (unfortunately a lot of my crit was not written) of the indicator lights as more time passes with the bad posture, which is an intriguing idea that I would also love to explore with more time.
I'm quite satisfied with my project! I put a lot of effort into keeping it as compact as possible and I made 4 different fusion models to reach my final resolution and ideal size. I regret being so perfectionist with the fingerjoints, since I refingerjointed my model multiple times since there were so many surfaces and I wanted symmetry and aesthetic fingerjoint placement (also the fingerjoint library was messing up the joints and making them not fit the notches?). I'm not sure if working so hard on appearance was worth it for this project, but it forced me to have very good wire management (much retrimming wires) and lots of soldering practice! Since all my pieces had to be soldered together, I took a big risk by soldering everything before I wrote any code, so I feel very proud (and lucky) that nothing went wrong in soldering everything to the protoboard. I would definitely put more time into making sure my code worked before putting the project together next time, even if it meant having a less aesthetically pleasing resolution. Overall, this project was looking quite rough at 1 am 2 nights before, but I'm grateful and proud that everything worked out!
For the next steps, I hope to recut one of the sides to have a hole for the Arduino cord so I can actually glue the box together and still edit the code! I also want to find a lidded battery holder so they can be changed easier but Zach said those are quite elusive at the moment, so I'm not sure if that will happen. I think I will be permanently dropping the idea of wrapping the device in a plush, considering how large it is already.
// Posture Device
// Reads an infrared temperature sensor and laser distance as input and lights up 3 LEDS as output: 2 leds based on temp & distance values,
// 1 based on millis timer
//pin mapping :
// Arduino pin | role | description
// ___________________________________________________________________
// 4 OUTPUT drives LED
// 5 OUTPUT drives LED
// 6 OUTPUT drives LED
#include <Wire.h>
#include <DFRobot_VL53L0X.h>
#include <Adafruit_MLX90614.h>
Adafruit_MLX90614 mlx = Adafruit_MLX90614();
DFRobot_VL53L0X sensor;
int leftLEDPin = 4;
int rightLEDPin = 5;
int farLEDPin = 6;
unsigned long workStartTime = 0;
unsigned long breakStartTime = 0;
int seatedMaxDist = 400; //distance threshold for person to be seated
int bodyMinTemp = 75; //person temp threshold
int postureVal = 200; //distance threshold for acceptable posture
unsigned int sitTime = 20000; //20 s for demo
unsigned long sitTimeStart = 0;
unsigned long breakTimeStart = 0;
unsigned long sitTimer = 0;
//break and sitting states
bool isBreakReminder = false;
bool sitTimerStarted = false;
void setup() {
// distance sensor setup
Serial.begin(9600);
Wire.begin();
sensor.begin(0x50);
sensor.setMode(sensor.eContinuous, sensor.eHigh);
sensor.start();
// temp sensor setup
mlx.begin();
// LED setup
pinMode(leftLEDPin, OUTPUT);
pinMode(rightLEDPin, OUTPUT);
pinMode(farLEDPin, OUTPUT);
}
void loop() {
//read temp and distance sensor values
int dist = sensor.getDistance();
int temp = mlx.readObjectTempF();
//set states for if user is sitting and if posture is bad
bool isSitting = dist < seatedMaxDist && temp > bodyMinTemp;
bool postureBad = dist > postureVal;
if (isSitting) {
//posture check
if (postureBad) {
flashLights();
}
if (sitTimerStarted) {
sitTimer = millis() - sitTimeStart;
Serial.println((String) "SIT TIME: " + sitTimer);
if (sitTimer > 500 && !postureBad) { //turn off timer started indicator lights after .5 s
digitalWrite(leftLEDPin, LOW);
digitalWrite(rightLEDPin, LOW);
}
if (sitTimer >= sitTime) {
isBreakReminder = true;
Serial.println("BREAK REMINDER");
}
} else if (!sitTimerStarted) {
sitTimeStart = millis();
sitTimerStarted = true;
digitalWrite(leftLEDPin, HIGH); //timer started indicator lights
digitalWrite(rightLEDPin, HIGH);
digitalWrite(farLEDPin, LOW); //turn off break indicator light
}
}
if (isBreakReminder) { //break indicators
alternateFlash(); //flash left & right lights
digitalWrite(farLEDPin, HIGH); //break light
}
if (!isSitting) {
digitalWrite(leftLEDPin, LOW); //turn left & right lights off
digitalWrite(rightLEDPin, LOW);
isBreakReminder = false; //update reminder state
sitTimer = 0; //reset sit timer
sitTimerStarted = false; //reset sit timer state
}
}
//flashing lights function for fast flashing lights, uses millis so other code is not delayed
void flashLights() {
static bool ledState = false;
static unsigned long lastBlinkTime = 0;
if (millis() - lastBlinkTime >= 50) { // Blink every 500ms
ledState = !ledState; //updates current state for blink
digitalWrite(leftLEDPin, ledState);
digitalWrite(rightLEDPin, ledState);
lastBlinkTime = millis();
}
}
//alternating lights function for the break light, uses millis so other code is not delayed
void alternateFlash() {
static bool ledState = false;
static unsigned long lastBlinkTime = 0;
if (millis() - lastBlinkTime >= 500) { // Blink every 500ms
ledState = !ledState; //updates current state for blink
digitalWrite(leftLEDPin, !ledState);
digitalWrite(rightLEDPin, ledState); //left and right opposite states for alternating flash
lastBlinkTime = millis();
}
}