Hardware components | ||||||
| × | 1 | ||||
| × | 1 | ||||
| × | 5 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 2 | ||||
| × | 2 | ||||
| × | 1 | ||||
| × | 5 | ||||
| × | 2 | ||||
| × | 1 | ||||
| × | 10 | ||||
| × | 3 | ||||
Hand tools and fabrication machines | ||||||
| ||||||
|
About
This version of the NoPro features a wifi-enabled chair and accompanying shoe attachment that work together to get you up and keep you moving. Pressure sensors, timing mechanisms, LEDs and vibrating motor in the chair are used in tandem to alert the user that they should stand up. The chair then remains in this "unsettled" state until the activity sensor in the shoe signals back that an adequate amount of distraction has occurred. Active users also receive text messages during active times. These messages can be tailored to your needs, including being substituted with twitter feeds, and have the potential to drive an entirely new level of anti-productivity.
Product Gallery
The Team
Presentation
Process Images
Schematics
3D Print File
Laser Cut File
NoPro Demo Video
A video demonstrating a use case for our design.
Chair Arduino Code
Chair Imp Agent
Chair Imp Device
Shoe Imp Agent
Shoe Imp Device
// We'll be controlling the motor from pin 9. This must be one of the PWM-capable pins.
const int motorPin = 9;
/// This pin brings the pressure data back to the computer
const int pressureSensorPin = A0;
//LED Pins
const int led1 = 2;
const int led2 = 3;
const int led3 = 4;
const int led4 = 5;
const int led5 = 6;
// Electir Imp pin
const int electricImpPin = 7;
// Project constants
const int maxTimeSitting = .5 * 1000; // This is how many loop cycles the user can be sitting down
const int pressureCutOff = 800;
/// Projects Changing Variables
int currentTimeSitting = 0; /// How long the user has been sitting. Right now it resets when the motor turns on
void setup()
{
pinMode(motorPin, OUTPUT);
pinMode(led1,OUTPUT);
pinMode(led2,OUTPUT);
pinMode(led3,OUTPUT);
pinMode(led4,OUTPUT);
pinMode(led5,OUTPUT);
pinMode(electricImpPin,INPUT);
Serial.begin(9600);
}
void loop()
{
int isSitting = isSittingFunction();
if (isSitting == 1) {
handleSitting();
} else {
handleStanding();
}
}
/// Checks if the user it sitting by reading in the pressure sensor
int isSittingFunction(){
int pressureSensorReading = analogRead(pressureSensorPin);
if (pressureSensorReading < pressureCutOff){
return 1;
}
return 0;
}
/// Handles the user sitting down. Increments the currentTimeSitting and if need be starts the process of making the user stand up
void handleSitting() {
int impVal = digitalRead(electricImpPin);
if (currentTimeSitting >= maxTimeSitting && impVal == 0) { /// Sat and used all time, have not taken enough steps, sat back down.
turnAllOn();
return;
}
if (currentTimeSitting >= maxTimeSitting && impVal == 1) { /// Sat and used all time, have taken enough steps, sat back down. Will reset
resetState();
return;
}
if (currentTimeSitting < maxTimeSitting){
currentTimeSitting = currentTimeSitting + 1;
}
if (currentTimeSitting > maxTimeSitting/5) { /// if statement needed for integer overflow
digitalWrite(led1, HIGH);
}
if (currentTimeSitting > 2*maxTimeSitting/5) {
digitalWrite(led2, HIGH);
}
if (currentTimeSitting > 3*maxTimeSitting/5) {
digitalWrite(led3, HIGH);
}
if (currentTimeSitting > 4*maxTimeSitting/5) {
digitalWrite(led4, HIGH);
}
if (currentTimeSitting >= maxTimeSitting) {
/// COULD SET OUT TO HOT TO SIGNAL START STEPS
digitalWrite(led5, HIGH);
digitalWrite(motorPin, HIGH);
}
}
void resetState(){
currentTimeSitting = 0;
turnAllOn();
}
/// Function that handles the user not being in the chair
void handleStanding(){
turnAllOff();
}
void turnAllOn(){
digitalWrite(led1, HIGH);
digitalWrite(led2, HIGH);
digitalWrite(led3, HIGH);
digitalWrite(led4, HIGH);
digitalWrite(led5, HIGH);
digitalWrite(motorPin, HIGH);
}
void turnAllOff(){
digitalWrite(led1, LOW);
digitalWrite(led2, LOW);
digitalWrite(led3, LOW);
digitalWrite(led4, LOW);
digitalWrite(led5, LOW);
digitalWrite(motorPin, LOW);
}
function requestHandler(request, response) {
try {
server.log("In request");
// check if the user sent led as a query parameter
if ("flag" in request.query) {
if (request.query.flag == "1" || request.query.flag == "0") {
// convert the led query parameter to an integer
local flagState = request.query.flag.tointeger();
device.send("signalStopMotor", flagState);
}
}
// send a response back saying everything was OK.
response.send(200, "OK");
} catch (ex) {
response.send(500, "Internal Server Error: " + ex);
}
}
// register the HTTP handler
http.onrequest(requestHandler);
// create a global variabled called led,
// and assign pin9 to it
led <- hardware.pin9;
// configure led to be a digital output
led.configure(DIGITAL_OUT);
// function to turn LED on or off
function stopMotor(flagState) {
server.log("Set Flag: " + flagState);
local temp = 0 + flagState; // Cast issue
led.write(temp);
}
// register a handler for "led" messages from the agent
agent.on("signalStopMotor", stopMotor);
//*************************TWILIO***********************************************
const TWILIO_ACCOUNT_SID = "AC04fd8b43060c1717212c0f8d3f6de1f8" // your SID goes here
const TWILIO_AUTH_TOKEN = "135257d098e1ac2dd4a01fd9266f938c" // your token goes here
const TWILIO_FROM_NUMBER = "+16179345601" // your phone no goes here
const TWILIO_TO_NUMBER = "+14089210322" // destination phone no
function send_sms(number, message) {
local twilio_url = format("https://api.twilio.com/2010-04-01/Accounts/%s/SMS/Messages.json", TWILIO_ACCOUNT_SID);
local auth = "Basic " + http.base64encode(TWILIO_ACCOUNT_SID+":"+TWILIO_AUTH_TOKEN);
local body = http.urlencode({From=TWILIO_FROM_NUMBER, To=number, Body=message});
local req = http.post(twilio_url, {Authorization=auth}, body);
local res = req.sendsync();
if(res.statuscode != 201) {
server.log("error sending message: "+res.body);
}
}
device.on("sms", function(v) {
send_sms(TWILIO_TO_NUMBER, v)
});
//*****************************END TWILIO***************************************
//https://github.com/joel-wehr/electric_imp_security_system/blob/master/agent.nut
//(617) 934-5601
// Other electric imps urls
local urlServerFlagOn = "https://agent.electricimp.com/qvXhYcL2vsj-?flag=1";
local urlServerFlagOff = "https://agent.electricimp.com/qvXhYcL2vsj-?flag=0";
////////FOR TALKING TO THE OTHER ELECTRIC IMP////
function tempCallBack(resp){
server.log("We are in temp call back");
}
function mimcHTTPRequest(flag){
local temp = flag + 0;
local request;
if (flag == 0){
request = http.get(urlServerFlagOff, {});
} else if (flag == 1){
request = http.get(urlServerFlagOn, {});
} else {
server.log("ERROR: FLAG NOT 1 or 0");
}
request.sendasync(tempCallBack);
}
function signalChairImp(flag) {
mimcHTTPRequest(flag);
}
device.on("enoughStepsTaken", signalChairImp);
cs <- hardware.pin8;
miso <- hardware.pin7;
mosi <- hardware.pin5; //self test probably
sck <- hardware.pin2;
// configure pin
cs.configure(ANALOG_IN);
miso.configure(ANALOG_IN);
mosi.configure(ANALOG_IN);
sck.configure(ANALOG_IN);
led.configure(DIGITAL_OUT);
led2.configure(DIGITAL_OUT);
local x = 0;
local y = 0;
local z = 0;
local xo = 0;
local yo = 0;
local zo = 0;
local t = 80;
local counter = 0;
local smssent = 0;
local stepLimit = 20;
function poll() {
// read pin and log
x = cs.read();
y = miso.read();
z = sck.read();
if ((math.abs(x - xo) > 900) || (math.abs(y - yo) > 900) || (math.abs(z - zo) > 900)) {
counter++;
}
if (counter == stepLimit && (smssent == 0)) {
smssent = 1;
agent.send("sms", "food truck outside, $1 hotdogs for the next 20 minutes");
}
//reset acceleometer data
xo = x;
yo = y;
zo = z;
// wake up in 0.1 seconds and do it again
imp.wakeup(1, poll);
}
// start the loop
poll();
Kevin Simons
3 projects • 0 followers
Senior studying Electrical Engineering and Computer Science at UC: Berkeley
Comments