Project tutorial
NoPro

NoPro

A counterproductive suite of office products

  • 3,398 views
  • 12 comments
  • 5 respects

Components and supplies

Sneakers
×1
Office Chair
×1
09590 01
LED (generic)
×5
Motor
×1
Off-Center Weight
×1
Electricimp
Electric Imp
×2
A000066 iso both
Arduino UNO & Genuino UNO
×2
Force Sensitive Resistor
×1
08377 02 l
Resistor 330 ohm
×5
Wood Boards
×2
Transistor
×1
Screws
×10
Tens70
9V battery (generic)
×3

Necessary tools and machines

3drag
3D Printer (generic)
Lasercutter
Laser cutter (generic)

About this project

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.

The Team

Presentation

Process Images

Schematics

3D Print File

3d Print File

Laser Cut File

NoPro Demo Video

A video demonstrating a use case for our design.

Chair Arduino Code

chair_code.c
Chair Arduino Code

Warning: Embedding code files within the project story has been deprecated. To edit this file or add more files, go to the "Software" tab. To remove this file from the story, click on it to trigger the context menu, then click the trash can button (this won't delete it from the "Software" tab).

// 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);

}

Chair Imp Agent

chair_imp_agent.c
Chair Imp Agent

Warning: Embedding code files within the project story has been deprecated. To edit this file or add more files, go to the "Software" tab. To remove this file from the story, click on it to trigger the context menu, then click the trash can button (this won't delete it from the "Software" tab).

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);

Chair Imp Device

chair_imp_device.c
Chair Imp Device

Warning: Embedding code files within the project story has been deprecated. To edit this file or add more files, go to the "Software" tab. To remove this file from the story, click on it to trigger the context menu, then click the trash can button (this won't delete it from the "Software" tab).

// 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);

Shoe Imp Agent

shoe_imp_agent.c
Shoe Imp Agent

Warning: Embedding code files within the project story has been deprecated. To edit this file or add more files, go to the "Software" tab. To remove this file from the story, click on it to trigger the context menu, then click the trash can button (this won't delete it from the "Software" tab).

//*************************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);

Shoe Imp Device

shoe_imp_device.c
Shoe Imp Device

Warning: Embedding code files within the project story has been deprecated. To edit this file or add more files, go to the "Software" tab. To remove this file from the story, click on it to trigger the context menu, then click the trash can button (this won't delete it from the "Software" tab).

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();

Code

chair_code.cC/C++
chair_code.c
// 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);

}
chair_imp_agent.cC/C++
chair_imp_agent.c
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);
chair_imp_device.cC/C++
chair_imp_device.c
// 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);
shoe_imp_agent.cC/C++
shoe_imp_agent.c
//*************************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);
shoe_imp_device.cC/C++
shoe_imp_device.c
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();

Custom parts and enclosures

enclosure_for_shoe.stl
3d Print File

Sketchfab still processing.

Comments

Similar projects you might like

2WD Voice Controlled Robot with Arduino and BitVoicer Server

Project tutorial by Marcio Tamagushi

  • 10,213 views
  • 11 comments
  • 32 respects

Use the Force... Or your Brainwaves?

Project tutorial by Tamas Imets

  • 29,213 views
  • 18 comments
  • 101 respects

The Annoy-O-Bug: A Chirping Light-Up Throwie

Project tutorial by Alex Wulff

  • 12,026 views
  • 15 comments
  • 39 respects

Electroplating with Copper

Project tutorial by Ryan Gill

  • 8,172 views
  • 8 comments
  • 18 respects

AirLock with Artik Cloud

Project tutorial by Akash Ravichandran and Prabhakaran Senthilnathan

  • 2,830 views
  • 0 comments
  • 9 respects

BE∆ST: Bluetooth Vehicle Final Designed Chassis

Project showcase by Matthew Chiang

  • 2,702 views
  • 0 comments
  • 15 respects
Add projectSign up / Login