Engineering

Outreach

Resources

Enrichment

Green Engineers

Mechatronics Studio

Contact Us

Mechatronics Learning Studio

Automated Pill Dispenser

Eleanor Gerson, Rachelle Bernier, Aarti Singla and Stefanie Cheung

 

Idea and Motivation

Today in society there is a growing need to assist seniors. One very important task is taking prescription medication. There are issues concerning seniors’ ability to remember to take and handle their medicine on their own. Many seniors who suffer from dementia or Alzheimer’s may not remember when to take their medication or what medication to take. In addition, seniors often have difficulty handling their medication, as pills can be small and their containers difficult to open. 

In order to provide a solution to these problems, our group of biomedical mechanical engineering students decided to design an automated pill dispenser. This would reminded the client when to take their medication and it dispense the necessary medication at specific times during the day. This would prevent the client from forgetting to take their medication, or accidentally taking the wrong medication, while giving seniors increased independence and a better quality of life.

Logic Sequence of Events

Below is the sequence of events that would occur once the timer has gone off. The time period between dispensing is preset in the code.

Project Components

Role of Major Components

Stepper Motor

The compartment tray holding the pills requires a stepper motor to divide the motion into small equal steps. We used a 5V brushless unipolar DC stepper motor to ensure the tray only rotates 25.7 degrees each turn, as there are 14 compartments.

Servo Motor

A servomotor attached to a 4 bar linkage is used to open and close the door, through which the user collects their medication. The motor was set to rotate 90 degrees, allowing a suitable range of motion for the door.

Serial LCD

The LCD screen is placed on the outside of the pill dispenser to let the user know how many pills they must take. The photo interrupter will count how many pills have passed through the exit shoot, and this number is displayed on the LCD screen as a confirmation for the user of how many pills they should be taking at that time point. When the pill dispenser is not in dispensing mode, its default setting is to display the ambient temperature and humidity, informing the user of the storage conditions of their medication.

DHT11 Sensor

The DHT11 sensor is a temperature and humidity sensor, which displays these values on the Serial LCD. This function is to ensure that the user is aware of the storage conditions of their medication.

LDR

A light dependent resistor circuit is used to signal the opening and closing of the door (via servo motor). When the pills are ready for the user and the buzzer is sounding, the user will come to the dispenser and place their finger over the LDR sensor. When the LDR is placed in light as it usually is (as there is a blue LED constantly on above the LDR), there is no voltage outputted. However when the LDR senses no light due to the user covering the sensor, the variable resistance allows a voltage to be sent to the servo motor to open the door. Once the user has taken their medication, they may place their hand over the sensor once more to close the door and reset the program.

Photointerrupter

The photointerrupter is what counts the number of pills that have been dispensed. The photointerrupter consists of an IR LED emitter and IR phototransistor detector, which are aligned and face each other. If something obstructs the emitter and detector, then the IR beam will be broken. Thus, for every pill that passes in between the emitter and detector, the IR beam is broken and this is counted through the Arduino program. This value is displayed on the LCD as seen below.

 

System Overview Block Diagram

The below diagram shows all the inputs and outputs to the microcontroller (Arduino Uno).

Possible Improvements

 

Texting Function: In order to inform the caregiver or family member that the user has taken their medication, a GSM Shield can be used with the Arduino which will automatically send a text message to a specified cell phone, when the pills have been dispensed.

 

Voice Instruction: It was realized that although there is a buzzer to remind the user to take their medication, those with dementia or Alzheimer’s may have difficulty recognizing the reason for the buzzer. A voice instruction would allow the user to know exactly when the pills are ready for them, and create a more comfortable setting, making the product more user friendly. 

Strength of Photointerrupter: Because a weak photointerrupter was chosen, some errors in counting were made while testing. This occurred because although emitter and detector were aligned, a slight misalignment while moving the dispenser can misalign the signal, and create an error when counting the pills. This can be easily resolved by using a stronger photointerrupter.

 

CODE

 

/********************************

      Pill-Dispenser Code

********************************/

 

//Declaration of libraries required

#include <Servo.h>

#include <Stepper.h>

#include <SoftwareSerial.h>

#include <dht.h>

 

//Determine the number of steps per revolution of the motor

const int stepsPerRevolution = 200;

 

/**************************************************

Initialize the stepper motor with pins 8 through 11.

This tells the arduino which pins are responsible

for the stepper motor

***************************************************/

Stepper myStepper(stepsPerRevolution, 8,9,10,11);   

 

#define dht_dpin A0 //Set humidity sensor to analog pin 0

#define lcdscreen 6

 

dht DHT;

SoftwareSerial LCD = SoftwareSerial(0, lcdscreen);

 

const int LCDdelay = 6;

 

/***Initialization of the LCD screen:***/

 

// Indicate the intial position of the cursor

void lcdPosition(int row, int col) {

  LCD.write(0xFE);   //command flag

  LCD.write((col + row*64 + 128));    //position

  delay(LCDdelay);

}

void clearLCD(){

  LCD.write(0xFE);   //command flag

  LCD.write(0x01);   //clear command.

  delay(LCDdelay);

}

void backlightOn() { //turns on the backlight

  LCD.write(0x7C);   //command flag

  LCD.write(157);    //light intesity of screen indicating 'ON'

  delay(LCDdelay);

}

void backlightOff(){  //turns off the backlight

  LCD.write(0x7C);    //command flag

  LCD.write(128);     //light intesity of screen representing 'OFF'

   delay(LCDdelay);

}

 

// Call the command flag to issue orders to other commands

void serCommand(){ 

  LCD.write(0xFE);

}

/*********************************************************/

 

// create servo object to control a servo

Servo myservo;           

 

//Indicate which pin a component connects to:

int rled = 13;

int gled = 12;

int buzz = 3;

int pinLB = A3; // LightBarrier, Photointerrupter

const int buttonPin = A1;     // Set phototransistor to analog pin 1

const int servoPin = 5;

 

//Declare sub-programs that appear within the main program

int beep();

int signalon();

int signaloff();

int weather();

int stepper();

int myservoloop1();

int myservoloop2();

 

//Initialize required variables 

int pos = 0;

int counter = 0;

String stringOne;

String stringTwo;

int sum;

boolean lastLbStatus;

int loopcount = 0;

unsigned int buttonState = 0;  // 0 state indicates button as 'OFF'

 

/**********************************

***       COMPONENT SETUP       ***

***********************************/

void setup()

{

  // Initialize the servo, buzzer, and LED pins as an output:

  pinMode(servoPin, OUTPUT);         

  pinMode(rled, OUTPUT);

  pinMode(gled, OUTPUT);

  pinMode(buzz, OUTPUT);

 

  // Set Phototransistor and Humidity sensor as an input

  pinMode(pinLB,INPUT);

  pinMode(dht_dpin, INPUT);

 

  // Setup of the LCD screen 

  pinMode(lcdscreen, OUTPUT);

  LCD.begin(9600);

  delay(300);//Let the system settle

  clearLCD();

  lcdPosition(0,0);

 

  // Attach the servo on pin 5 to the servo object

  myservo.attach(5);

 

  // Set the speed at 10 rpm:

  myStepper.setSpeed(10);

 

}

 

void loop()

{

  /*************************************

  *******     MAIN PROGRAM       *******

  *************************************/

 

  // Turn the red LED to ON state

  digitalWrite(rled, HIGH);

 

  // Run the weather sub-program while the red light is ON

  do

  {

    weather();

  }

    while (rled == HIGH);

 

  // Turn off the LED

  digitalWrite(rled, LOW);

  // Wait 500ms

  delay(500);          

 

  // Turn green LED to ON state

  digitalWrite(gled, HIGH);

 

  //Run the following sub-programs while the green LED is on

  do

  {

     beep();

     stepper();    

     pillcounter();

     signaloff();

  }

    while (gled == HIGH);

}

 

/************************************************

** The following sections are the sub-programs **

**  that were called during the main program   **

************************************************/

 

/************************************

  This function controls the buzzer

************************************/

int beep()

{

  void loop();

  {

    //Indicate the pin that is connected with the buzzer

    //and the frequency which determines the tone heard

    tone(3,50); 

  }

}

 

/************************************************

  Read the humidity and temperature of the room

  and display it on the LCD screen

************************************************/

int weather()

{

void loop();

{

  DHT.read11(dht_dpin);

 

    LCD.print("Humidity =");

    LCD.print(DHT.humidity);

    LCD.print("%");

   

    LCD.print("Temp = ");

    LCD.print(DHT.temperature);

    LCD.println("C");

 

   //The delay is representative of the time between pill taking

  delay(5000);

  clearLCD();

  }

}

 

int stepper()

{

  void loop();

  {

  // Move the stepper to one direction by one step

  myStepper.step(25);

  }

}

 

/*************************************

  Count the number of pills that fall

*************************************/

int pillcounter()

{

  int newLbStatus;

   

  // read the value of the phototransistor

  buttonState = analogRead(buttonPin);

 

  //Check if phototransistor value is above 100

  while(buttonState > 100)

  {

        newLbStatus = analogRead(pinLB);

       

        //Create conditional statement to compare photoresistor value       

        if(newLbStatus > 70)

        {

          counter = counter + 1;

          stringOne = "Number of pills: ";

          stringTwo = stringOne + counter;

          LCD.print(stringTwo);

          delay(500);

          clearLCD();

          sum = counter;

        }

       

  buttonState = analogRead(buttonPin);

  continue;

}   

      //After exiting "while" loop, display number of pills

      LCD.print("Number of pills: ");

      LCD.print(sum);   

     

      //Reset the counter and sum variables so that the next

      //iteration of the program begins counting from 0

      counter = 0;

      sum = counter;

   

    //Turn off the buzzer  

    noTone(3);

   

    // Run the sub-function myservoloop1   

      myservoloop1();

}

 

/***********************************************

    The function opens the door to allow

    access to the pills that need to be taken

***********************************************/

int myservoloop1()

{

  void loop();

  {

    //Move the servo from 0 to 90 degrees in 1 degree steps

    for(pos = 0; pos < 90; pos += 1)

    {                               

      myservo.write(pos);      // servo goes to specified position

      delay(15);              // waits 15ms for the servo to reach the position

    }

  }

}

 

/****************************************

  Turn off green LED and reset program

*****************************************/

int signaloff()

{

  void loop();

  {

  // read the state of the phototransistor value:

  buttonState = analogRead(buttonPin);

 

  /******************************************************

      The phototransistor reads the light intensity

      as values. This transistor views values above 100

      as an equivalent to the OFF state of a pushbutton.

      As such, the phototransistor is continually read

      until the value falls below 100 indicating an ON

      state.

  *******************************************************/

  while(buttonState > 100)

  {

  buttonState = analogRead(buttonPin);

  continue;

  }}

 

   clearLCD(); 

  

   //turn the green LED off

   digitalWrite(gled,LOW);

      delay(500);

   // start sub-program myservoloop2   

      myservoloop2();

}

 

/**********************************************

  Controls the servo in order to close the

  door initially opened by a previous function

**********************************************/

int myservoloop2()

{

  void loop();

  {

      for(pos = 90; pos>=1; pos-=1)     // goes from 180 degrees to 0 degrees

  {                               

    myservo.write(pos);              // tell servo to go to position in variable 'pos'

    delay(15);                       // waits 15ms for the servo to reach the position

  }

}

}