Bowel Monitor

 

Description:

The Bowel Monitor is a device built to ease the pain of waiting for the bathroom by giving information about who’s using the bathroom, their purpose inside, and how long they have been using the bathroom.

 

The Bowel Monitor in its natural habitat (Command stripped to the door)

 

Magnet holder to trip the magnetic field sensor when  the door is closed

 

Magnetic field sensor taped to wall for easy positioning and configuration to any bathroom door

 

Small potentiometer so that the brightness of the display can be changed to adapt to different lighting conditions

 

User selecting the type of business they will be engaging in during their bathroom experience

 

Build Process:

The build process for this device required lots of thought about user interaction. A key moment in the designing the functionality of the device arose in deciding where the device would actually be placed. Initially, the device was going to be placed inside the bathroom and the LCD display would be placed outside the bathroom. This method of communication would require communication through the door complicating the electronic physical build of the device. In order to cut down on complexity and reduce points of failure, I instead focused on minimizing the amount of separate components communicating with each other. I decided to have one device placed on the outside of the bathroom that the user could interact with before entering the bathroom. This type of device both cut down on the points of failure within the device by reducing both electrical complexity and simplified the user interaction by giving the immediate feedback about the information they are choosing to display.

Initial ideation sketch of the two module system with the display outside the bathroom and the keypad inside the bathroom

Initial ideation sketch of the single display module mounted outside on the bathroom door

 

 

 

 

Final build of single display module device

Another major consideration was the process for determining whether or not the door has been closed. The device could either use a proximity sensor or magnetic field sensor to detect when the door closes and display the appropriate information. The proximity sensor would have required less components as it could be placed within the physical housing of the device and rely on proximity to a reference near the door; however, physically holding the proximity sensor inside the housing would reduce versatility as it could only be placed where there is a hole in the side of the box. In contrast, the magnetic field sensor required both the sensor inside the display module and a separate set of magnets on the outside of the box to trip the sensor when the door closes. While this design is physically more complex because of the extra component, electrically it is much simpler because the magnetic field sensor acts as a switch as opposed to the analog output from the proximity sensor. The magnetic field sensor could also be taped anywhere inside the housing making the Bowel Monitor more versatile in where it can be placed outside the bathroom. In order to simplify the electronics and increase versatility of the Bowel Monitor, I decided to use the magnetic field sensor to detect when the door has closed.

Visualization of display module and magnet module

 

Discussion:

I am extremely pleased with the outcome of this project. I think the overall design and look of the Bowel Monitor came out clean and elegant as intended. I agree with the comments on cleanliness and humor of the device: “Everything about the display is so clean! I like the humor incorporated into the project and the timer is a nice feature.” Part of this cleanliness came from the laser cut look of the device. As noted by peers, “the laser cut look” and “plate with the LCD and the numbers [are] really clean and give a really nice user interface.” I believe the laser cut housing organized the display and user interaction creating a more cohesive and clean design. As for the design of the box itself, I agree that “adding more to the design of the box would add to the comedic feel of the overall project.” I think designing the box in the shape of something like a poop emoji would add more comedic effect to the device and consequently enhance its light-hearted nature. Similarly, adding emojis to the display could enhance the user experience with more comedy about the types of bathroom uses.

While the overall design and interaction succeeded in providing both comedic effect and useful information, I think some of the sensing mechanisms could have been enhanced to improve versatility of the Bowel Monitor. Replacing the magnetic sensor for a proximity sensor could decrease the physical complexity of the device by reducing the amount of components needed for the device to function. As for the user interaction with the device, adding a selection menu while the door is open would allow the user to select their business in the bathroom while the door is open instead of just while the door is closed. This would reduce the strain on the user by giving them more options on how to interact with the Bowel Monitor. They could either close the door, enter their information, and then go into the bathroom as before, or they could keep the door open while they select their information, and then use the bathroom as indicated.

As for my own experience designing and building the Bowel Monitor, I learned a lot about my design and manufacturing capabilities. I learned how to both design and manufacture electronic housing using a laser cutter as opposed to a 3D printer. I also thoroughly enjoyed applying technical knowledge in such a silly manner.

 

Technical Information:

Functional block diagram of Bowel Monitor

 

Electrical Schematic of Bowel Monitor

 

/*
   60-223, Project 2: Bowel Monitor
   James Kyle (jkyle1)
   time spent: Too much

   Collaboration and sources:
   1) I watched the canvas course modules
   2) Keypad tutorial: https://www.circuitbasics.com/how-to-set-up-a-keypad-on-an-arduino/

   Challenge(s): I had lots of trouble coming up with the logical 
   variables I needed to update the display properly. I also struggled 
   with writing the function to determine how to update the display 
   based on the key pressed on the key pad. I ended up using the serial 
   monitor to display the value returned by each key press and then used 
   that value to distinguish keys.

   Next time: I'll start by thinking at a higher level about the user interaction 
   before diving into the details of coding the device behavior. I will also 
   research the components I am using more thoroughly to ensure I understand 
   how they work.

   Description: This device determines whether the bathroom door is open or 
   closed. When the door is closed, the user is able to press keys on a keypad 
   to indicate who they are and what they are doing in the bathroom. 
   The device then displays that information along with the time they have been 
   in the bathroom to give others an indication of how much longer they can 
   expect to wait to use the bathroom.


   Pin mapping:

   Arduino pin | type   | description
   ------------|--------|-------------
   A0            input     R4 [Keypad]
   A1            input     R3 [Keypad]
   A2            input     R2 [Keypad]
   A3            input     R1 [Keypad]
   A4            input     Reed Switch
   2             output    D7 LCD
   3             output    D6 LCD
   4             output    D5 LCD
   5             output    D4 LCD
   6             output    E pin LCD
   7             output    RS pin LCD
   10            output    C4 [Keypad]
   11            output    C3 [Keypad]
   12            output    C2 [Keypad]
   13            output    C1 [Keypad]

*/

//Importing necessary libraries
#include <Keypad.h>
#include <LiquidCrystal.h>


/***************
   KEYPAD SETUP
 ***************/

//Setting up pins for key pad
const int R1 = A3;
const int R2 = A2;
const int R3 = A1;
const int R4 = A0;
const int C1 = 13;
const int C2 = 12;
const int C3 = 11;
const int C4 = 10;

//Setting up key pad logic
const byte ROWS = 4;
const byte COLS = 4;

//Creating key pad matrix
char hexaKeys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

byte rowPins[ROWS] = {R4, R3, R2, R1};
byte colPins[COLS] = {C4, C3, C2, C1};

//Creating key pad variable
Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);

char customKey; //variable to store key pressed



/**************
   LCD DISPLAY
 **************/

//Setting up LCD
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);



/**************
   Reed Switch
 **************/

const int REEDPIN = A4;



/*************
   Variables
 *************/

//Variables for timing
unsigned long timer = 0; //overall time
unsigned int timerSec = 0; //time in seconds
unsigned int timerMin = 0; //time in minutes
unsigned long prevTime = 0; //previous time in miliseconds
unsigned long prevTimer = 0; //previous time in seconds

//Message variables for LCD display
String useMessage; //Bathroom use type
String user = ""; //Person using the bathroom
String timerMessage; //For displaying time in bathroom
String openMessage = "The Porcelain Throne Awaits Your Return"; //Idling message

//Logical variables for updating LCD display and timer
bool updateUseMessage = false;
bool updateTime = false;
bool resetDisplay = false;
bool doorOpen = false;
bool lcdClearClosed = false;
bool lcdClearOpen = false;

//Variables for timing LCD and scroll updates
int displayCounter = 0;
int scrollCounter = 0;



void setup() {

  //Initializing reed pin using pull-up
  pinMode(REEDPIN, INPUT_PULLUP);

  //Debugging
  Serial.begin(9600);

  //Start communicating with LCD
  lcd.begin(16, 2);

}


void loop() {

  //Read Key Pad using Keypad.h
  customKey = customKeypad.getKey();

  //Check if door is open or closed
  int doorState = digitalRead(REEDPIN);



  /***********************
   ***Door Open Squence***
   ***********************/

  //If door is open, dislay idling message
  if (doorState == 1) {

    //Clear LCD only if door was just opened and LCD hasn't been cleared yet
    if (lcdClearOpen == false) {
      lcd.clear(); //clear LCD
      delay(100);
      lcd.setCursor(0, 0);
      lcd.print(openMessage); //Display idling message
      delay(1000); //Wait 1 second
      
      //Update LCD cleared variables
      lcdClearOpen = true; //LCD cleared after door was opened
      lcdClearClosed = false; //LCD needs to be cleared when door opens

      //Update timers and counters for LCD
      scrollCounter = 0;
      
      //Reset displayed time
      timerSec = 0;
      timerMin = 0;
    }

    //Scroll idling message until it reaches end of message,
    //then wait for 1 second and return to beginning of 
    //idling message 
    if (scrollCounter < openMessage.length() - 16) {
      lcd.scrollDisplayLeft();
      scrollCounter = scrollCounter + 1; //increment scroll counter
      delay(500);
    } else {                  //If message reaches end point
      scrollCounter = 0;      //clear LCD and reset counters
      lcdClearOpen = false;
      delay(1000);
    }
  }


  /*************************
   ***Door Closed Squence***
   *************************/

  //If door closes, display user inputs and time on LCD
  else if (doorState == 0) {

    //Starting timer
    timer = millis() / 1000 - prevTimer;

    //Clearing LCD if door was just closed
    if (lcdClearClosed == false) {
      lcd.clear();
      lcdClearClosed = true;
      lcdClearOpen = false;
      prevTime = millis(); //resetting relative time 
      prevTimer = millis() / 1000; //Conversion to seconds
    }

    //only update time if one second has passed
    if (millis() - prevTime > 1000) {
      updateTime = true;
      prevTime = millis();

      //Converting time from seconds to minutes and seconds
      timerSec += 1; //incrementing seconds counter
      if (timerSec >= 60) {
        timerSec = 0;
        timerMin += 1; //incrementing minutes counter
      }
    }

    //update time on lcd
    if (updateTime == true) {
      lcd.setCursor(0, 1);
      lcd.print((String) timerMin + " min " + timerSec + " sec");
      lcd.setCursor(14,1);
      lcd.print(user);
      updateTime = false; //resetting update variable for time
    }

    //If keypad pressed, do something based on the key pressed
    if (customKey) {
      updateUseMessageFunction(customKey);
    }

    //Update lcd if it needs to be updated
    if (updateUseMessage == true) {
      lcd.setCursor(0, 0);
      lcd.print("                 "); //Clearing current use message
      lcd.setCursor(0, 0);
      lcd.print(useMessage); //Display new use message
      Serial.println(useMessage); //debugging line for lcd screen
      updateUseMessage = false; //resetting update variable so screen is updated only if there is a change
    }

  }

}



//This function determines how to update the display based on the keys 
//pressed on the key pad

void updateUseMessageFunction(char key) {
 
/****************************
 ** Types of Bathroom Uses **
 ****************************/

//Peeing
  if (int(key) == 49) {
    useMessage = "Pee Pee Time!  "; //Changing use message
    updateUseMessage = true; //Indicating LCD needs to be updated
  }

//Pooping
  if (int(key) == 50) {
    useMessage = "Poopy Time!  ";
    updateUseMessage = true;
  }

//Diarrhea or equivalent destructive act
  if (int(key) == 51) {
    useMessage = "Uh-oh! ;)   ";
    updateUseMessage = true;
  }

//Washing face
  if (int(key) == 52) {
    useMessage = "Washing Face";
    updateUseMessage = true;
  }

//Brushing Teeth
  if (int(key) == 53) {
    useMessage = "Brushing Teeth";
    updateUseMessage = true;
  }

//Showering
  if (int(key) == 54) {
    useMessage = "Showering";
    updateUseMessage = true;
  }

//Clear use type on screen
  if (int(key) == 42) {
    useMessage = "                ";
    updateUseMessage = true;
  }



/***************************
 ** People Using Bathroom **
 ***************************/

//James Kyle
  if (int(key) == 65) {
    user = "JK";
    updateTime = true;
  }

//Judson Kyle
  if (int(key) == 66) {
    user = "JK";
    updateTime = true;
  }

//Roommate 1
  if (int(key) == 67) {
    user = "MR";
    updateTime = true;
  }

//Roommate 2
  if (int(key) == 68) {
    user = "LW";
    updateTime = true;
  }

}