Sie sind auf Seite 1von 55

Medicine Dispenser

Authored By:

Jordyn Marshall

MaryAnne Laxamana

Jennifer Xie

Liberty High School

Oregon MESA

5/4/2018
1

Table of Contents

Problem Statement…. ...2-3

Design Process…. ...3-9

Results….. ...9-11

Next Steps/Recommendations……. ...11-12

Data…… ...12-15

Appendix……. ...16-52

Bibliography……. ...53-54
2

Project Statement

Everyday, elderly people face difficulties handling day-to-day life, and these challenges

only get worse as they age. These problems include, but aren’t limited to, balance, lack of

stamina, loss of strength, arthritis, and fading memory. The goal of this project is to use

human-centered design to improve the life of an elderly person by addressing an issue a client

may have. To do so, a team consisting of three high school seniors would interview a client and

design a device specifically for their needs.

Several elderly people were interviewed, but one was selected to be the team’s client.

This ends up being MaryAnne’s grandmother, Debbie. Debbie has to take at least five different

kinds of medication per day, and she is not the only one. 32 million Americans use three or more

medications daily. (“Patient Compliance + Medication Adherence Statistics”) However, a huge

problem when it comes to elderly people and people in general seems to be forgetting to take

their medication. 75% of all adults fail to take their medication correctly. When it comes to

elderly people, 57% admit to forgetting to take their medication. It seems that this is more

prevalent among those who have to take five or more medication, as 63% say they forget to take

medication, compared to the 51% percent who have to take fewer medications. (“Patient

Compliance + Medication Adherence Statistics”)

In order to solve this issue of forgetting to take medication, the team has interviewed

Debbie on criteria and expectations for the device. In general, the medicine dispenser should be

able to store medication in separate containers and dispense the correct amount when it is time

for the user to take them. The 12-hour am-pm clock was used to provide information to the client

and makes the machine more user-friendly. SInce there is a limited budget, the team purchased
3

conservatively to reduce cost as much as possible. The medicine dispenser also includes a history

of when medication was last dispensed for the user, and it is able to count the number of tablets

contained through special methods. In other words, the machine will be able to notify the user

when they need to refill the the container at least ten days in advance. The design should also be

applicable to hold around ten different types of medications, and hold at least two weeks of it.

The team would take this criteria into mind and design a medicine dispenser which would best

suit Debbie’s needs.

Design Process

The team began their interviews in October, but was unable to find their client until

November, who ended up being MaryAnne’s grandmother, Debbie. The team asked various

questions and notes were taken throughout the interview (Figure 1). Criteria and constraints were

created for the team to follow, as they are listed in the problem statement. The team had also

asked about information about her daily interactions with medications to gain background

knowledge in her struggles and preferences.

Prior to starting the project, the team researched briefly on the problem itself. They also

did some research on struggles elderly face in general. Arduino is best described as a

“programmable logic controller”, which essentially means that it can be programmed to interact

with the world based on inputs, such as buttons, and outputs like motors (Bruce). The team had

prior experience working with Arduino when they were tasked with building a robotic prosthetic

arm from the year before. They had applied those knowledge as well as the ones learned from

engineering classes to build the medicine dispenser. The team also researched on how to use the
4

components required to allow the medicine dispenser to function, and such research is detailed

throughout the report.

Eventually, the team started brainstorming a design and composed rough sketches within

the team’s notebook (Figures 2 and 3). The main design for the medicine dispenser was a box

with holes for an LCD and four buttons. The user would be able to input information to the

Arduino through them, such as when they need to take medication, what size the medication is,

and how many pills are being put into the container. The user would also be able to view when

the last type of medication was dispensed and which medication is in each container on the LCD.

Medication would be stored within containers on the top of the medicine dispenser. When it is

time for the medication to dispense, a small gate would move and allow the pills to fall into a

carousel, which would then be taken to a hole on the platform below the carousel, leading them

down a track where they will land into a container outside of the box. A servo would control the

carousel and four gates, which open​ ​to allow the pills within the bottles to fall into the carousel

when it is time for it to dispense. Meanwhile, the Arduino would also be connected to a

RealTimeClock module to ensure that it can keep track of the time and date, as well as a

buzzer,that will go off when it is time to take their medication.

After brainstorming, the team started gathering materials to construct the dispenser. The

first materials include the Arduino itself as well as a few components, namely the LCD, buttons,

buzzer, and RealTimeClock module. Since many elderly have bad vision, the team purchased the

biggest LCD screen within our budget availability, which was 2.5cm × 7cm. In order for them

to work, the team researched information on how each component would work. An example for

a schematic and code for the LCD(Figures 4 and 5). The exact circuit for the LCD, as well as the
5

LiquidCrystal library on Arduino, was used in the final design. The team learned how to code the

buttons from a manual that came with the Arduino (SparkFun Electronics). The RealTimeClock

module is specifically known as a DS1302, and it has three pins which connect to the Arduino.

The module was originally controlled by code on Arduino Playground (“DS1302 Real Time

Clock”), but the team eventually switched to using a library. This helps the time information

easier to program (“DS1302RTC library”). The buzzer was simply turned on and off by the

Arduino using the function digitalWrite().

Later, the team was able to get four servos, one continuous rotation servo, the bluetooth

module and an expansion module. The four servos and continuous rotation servo were connected

and programmed easily using the servo library on the Arduino (“Servo Library”). The bluetooth

module was briefly connected and tested using information online (Stan) (Mathavan, Hariharan).

Finally, an extension module was purchased because there would not be enough pins for

everything to be connected, with the total I/O pins required being 20 and only 19 are on the

Arduino board. As such, the extension module was connected and programmed using a library

found on Github to control the buzzer (skywodd). Once each component was tested working

individually, they were all connected together in one circuit(Figure 6). Also created a code to test

this circuit (Figure 7). The only component that was not connected was the Bluetooth module,

which was hard to test for due to the lack of an app. All of the components had worked together

in a circuit, minus two of the servos. The issues with the servos involves being connected to two

I/O pins that didn’t work with them, and they eventually worked when connected to two other

pins.
6

While the circuit was being worked on, the base of the medicine dispenser was being

constructed. The team purchased plywood in order to build the base. After measuring height and

length, a miter saw was used to cut it into the necessary pieces (Figure 8). Holes were then cut

out in the front to allow for room for the LCD and buttons using a scroll saw, and holes were

also drilled out on the top to fit the containers. According to observation within the client’s

household, the most common pill sizes were between 0.7cm to 2.3cm wide. The team then

designed four different sized holes that were in diameter of 1cm, 1.3cm, 1.5cm, and 2.3cm. The

pill containers ended up being water bottles, which were cut in half then flipped over for the neck

of the bottle was face down into the drilled holes with the height of 11cm. The bottom of the

bottles was also used as lids (Figure 9). Eventually, the entire device was put together using

wood glue. However, the top was left unattached so the team would be able to access the circuit

and for maintenance. The back was attached with a hinge. The team took in consideration in the

space available in households and tried to make the final product as small as possible. A

rectangular bottom was used for easy fitting on top of counters, tables, etc. The final

measurement of the outer box is 15cm × 15.5cm and the height was 29.5cm, the addition box

attached for catching the pills was 5.5cm × 9.5cm × 3cm.

Meanwhile, the team was also working on the gates and carousel to be 3D-printed. These

parts were modeled in Autodesk Fusion 360 (Figures 10, 11, and 12). They were eventually

3D-printed at our school and attached to their servos. The diameter of the carousel was around

13cm with the thickness of around 1.3cm. The gates were connected to a metal rod then to the

servo and the diameter of the gate was slightly larger than the opening of the water bottles to
7

ensure full coverage, which was 2.7cm. However, the glue would not hold the rods to the servos

so the team replaced them with plastic lego sticks which was easily connected with hot glue.

The circuit was then put into the box created for each component(Figure 13). The

carousel was attached to the continuous rotation servo with hot glue, and was being programmed

so that its position could be controlled. A continuous rotation servo has no position control,

unlike a normal servo, and only the speed and the direction of the servo could be programmed.

As such, a method in the code was planned to be created so that one could give it a degree, and

the continuous rotation servo would turn to that degree. In order for this to work, the code

needed to know the angular velocity of the servo. This exact equation and programmed method

used are contained within the Data section of this report. The servos and gates were connected at

each corner.foam was used to create more stability. In the beginning the box wasn't tall enough

for the carousel and gates. The team solved this issue by adding strips of wood to make it taller.

Eventually, everything was put together and the first iteration of the project was

completed. However there were some issues with the gates not being long or big enough to cover

the holes, and the fixed part needing a hole in the middle, so cardstock was used to make up for

these shortcomings. The project was shown to be able to dispense some of the team’s test

medication, or candies. The demo code (Figure 14), while two videos of the device are linked to

in Figure 15 and 16. However, the final code itself could not be completed as there was an issue

with the continuous rotation servo. The method written for it required for the servo to work at a

constant speed. However, the servo would not move at a constant speed, and there were even

small issues such as the angle which would be written to the servo to stop it changing, so that it

would be moving when it should be stopped.


8

After the first iteration of the medicine dispenser, everything was taken out to be

reorganized. Two holes were drilled into the base, one for a hypothetical power cord for the

Arduino, and another for the buzzer. The carousel and gates were 3D-printed once more to fix

any measurements issues, and the fixed part having a hole in the middle for the servo to go

through. The circuit was then put back in and the machine became more organized and

clean-looking than before(Figure 17).

In order to make the speed of the servo more consistent, the team got a more expensive

continuous rotation servo. However, upon receiving it, the servo would not respond well to the

commands passed to it on Arduino. It was supposed to respond to commands from the servo

library, but there was a communication issue between the Arduino and the servo. Due to the lack

of time to troubleshoot, the team was forced to get a motor. It could still work to control the

carousel, but a motor could only move in one direction. This would be addressed in the code, by

having everything move 360 degrees during a full rotation, but it would not be the most ideal for

this application.

Despite the team getting a new motor, they still had issues with attaching the moving part

of the carousel to the motor. This was caused by the glue the team tested. It would either attach

to the plastic or the metal, but not both efficiently enough that it would stay on after a few

seconds of use, this is what also happened to the metal rods connected to the gates and servos.

About five different types of glue was tested to connect the carousel and the motor directly, but

all methods did not work. In order to fix this problem, the team had added foam and glued it onto

the motor and carousel to act as an in between so that the motor and carousel would glue together

enough to work.
9

While everything was being constructed, the final code was being slowly worked on over

time. It works through a class which would create objects used to keep track of all information

regarding the medication, such as when it should be dispensed, how much of it should be

dispensed, what container is is in, and what size the medication is in reference to the carousel.

The final code would also include menus, so that the user would be able to input all information

without needing to code. Specifically, the interface should allow for the user to set up any

medication, add information regarding refills, and check when it was last dispensed. The final

code remains incomplete, however, as issues with the motor for the carousel both not working or

not attaching forced the testing of the device to be delayed. Nonetheless, the work in progress of

the final code is seen in the Appendix (Figure 19).

Results

The medicine dispenser is somewhat functioning. Most of the components work as they

are supposed to. The gates can move easily if the right angles are put in. Meanwhile, the buzzer

can work through being turned on and off easily, and the buttons and LCD are all functioning

very well. The clock, while not completely accurate, can still tell the time, and the team can

easily program it to easily follow the time using the Arduino Time library (“Arduino Time

Library”). The only component which is not working well is the motor. It is hard to program as it

is not moving at a consistent speed. This motor ends up being more consistent than the servos,

but it is still inconsistent enough that it is hard to program. A data table and a histogram have

been created in the data section for values used in the code for the total amount of time it took for

the motor to go one full rotation. They show that the speed of the motor was indeed changing, as
10

the distribution of the histogram is bimodal (Table 1)(Chart 1). The carousel can take the

medication to where it needs to go, but some last minute testing has shown that sometimes the

medication gets stuck. There were also issues with the glue coming off last minute as well.

Because the motor cannot be programmed to be consistent, the medicine dispenser cannot

be properly automated. All of the dispensing mechanisms work, and the medicine dispenser does

work should the motor bring the carousel to the right place at the right time. Because this is

constantly changing, the medicine dispenser does not work properly. There is code to demo the

medication dispenser by dispensing through all four containers, as well as keep track of the time

to dispense every five minutes, but it again does not work due to inconsistencies in the motor

(Figure 18).

The code itself is not complete, as the programmer was waiting to be able to use a

consistent motor to do so. Nonetheless, the work in progress is seen in the Appendix. The code is

not tested due to the lack of consistent dispensing mechanism, but the code should be able to

keep track of medication which is taken once a day, twice a day, and at several intervals

throughout the day. The amount of medication in the container is also taken into account, which

the user enters, and the Arduino uses this information accordingly to keep track of when it

should tell the user they need a refill. The main menu system has been started, but not

completely finished. Nonetheless, it is complete enough to see what the final iteration of the code

might look like (Figure 19).

The team had complied a budget sheet of the components used for the medicine

dispenser. They are trying to add a stepper motor to the circuit, but have yet to be successful.
11

Nonetheless, the budget sheet includes the components bought for the stepper motor as opposed

to the motor used in the last iteration of the project (Figure 20).

Next Steps/Recommendations

One of the main recommendations for this project is to not use a motor or a continuous

rotation servo. It is very hard to say that the speed of either would be consistent, unless it

potentially has a high torque. As such, the best kind of motor for this application may be a

stepper motor. The main issue with a stepper motor is that it requires more pins on the Arduino.

In order to fix this, a larger Arduino would have to be used for the more input/output pins it

could provide. The solution the team is trying to use in order to get the stepper motor working is

to use a shield, which would allow for more pins on the Arduino to be used, as well as remove

the hassle of trying to put together a circuit for the stepper motor. Furthermore, more consistent

glue could be used on the 3D-printed parts to make sure that they stick on, or the parts could be

printed again to fit where they need to go, and the team would need more time to ensure each

component is working correctly.

One all of the components are working together correctly, the team had an idea to

connect the device to the user’s phone through an app. The main reason the team could not do

this is due to the lack of an app to work connect to the Arduino with. They did have a Bluetooth

module, and it was functioning, but the team could not construct an app in a timely manner that

would also ensure that the sorter itself is functioning. Nonetheless, the team feels that an app

would allow for an easier interface for the user, especially since more information could be

printed out when compared to the LCD, and buttons could be larger and easily distinguishable.

In general, a better interface for the Arduino would improve how easy it is to use, because the
12

LCD cannot print a lot of information out to the user, and the buttons limit the amount of inputs

the user could give to it, potentially making the programmer have to make unintuitive design

designs to ensure that the buttons are being used efficiently.

Data

Trial Time to Go One Full Trial Time to Go One Full


Rotation (In Rotation (In
Milliseconds) Milliseconds)

1 11610 17 11700

2 11590 18 11710

3 11570 19 11760

4 11560 20 11770

5 11530 21 11800

6 11520 22 11780

7 11500 23 11770

8 11485 24 11760

9 11495 25 11740

10 11520 26 11750

11 11530 27 11760

12 11540 28 11780

13 11560 29 11740

14 11570 30 11720

15 11650 31 11730

16 11750
Table 1. This is a table of all the values the programmer of the team put into the code to try to
control the position of the carousel. This information was recorded to try and hone in on a
specific value which would work to control the position. It was compiled into a histogram
(below) which ends up being a visual representation that the speed was changing, and thus
position control with the motor proved to be almost impossible.
13

Chart 1. This is a histogram of the values put into the code for the time to do one full rotation.
The programmer of the team was recording these values in the notebook to keep track of what
numbers were originally put in the code, in order to find the true time to do one full rotation so
that the position of the carousel could be possibly controlled. The distribution is bimodal, which
means that there are two different times the programmer was trying to hone in on, and thus the
speed of the motor was changing. This means that the motor cannot be programmed in order to
accurately control the position of the carousel, which is what the team needs.

Calculations:

In order to program the carousel to have position control when it physically did not have

position control, the team observed the following equation:

This equation finds the position of an object, in angles, by using the initial angle, initial

angular velocity, and the angular acceleration over a certain amount of time in order to find the

final position. This is actually the angular version of a popular physics equation for tangential

position:
14

In which the position is a function of time, and the initial position, velocity, and

acceleration are used to find the final position. However, for this project, the team had only

observed the angular version. Because the team assumes that the acceleration of the motor is

negligible, they rewrote the angular position function to the following:

The Arduino needs to figure out the time for which the motor should be turned on. As

such, the equation should be written to solve for time. The equation becomes the following:

For this equation to work, the team needs to find the angular velocity of the motor that

they are using. This involves finding the time it took for the carousel to go around in a full circle,

and using that time to calculate the angular velocity. The equation to do this was the following:

This served as a starting point to experiment with the values for what the angular velocity

should be in the above equation for the Arduino.

Later, instead of a servo, the team got a motor. A motor can only move in one direction,

so the team would need to figure how the angular velocity as well as the amount of time it takes

to go one full circle. The above equation would be used again, but instead of the motor being

turned on for that certain amount of time, the motor would be turned on for that time, turned off

for the medicine to fall into it, and then turned on for the rest of the time to go a full circle. In
15

order to make this work, the time calculated would be subtracted from the total time it would

take to go one full circle. This again, however, works only if there’s a consistent speed for the

motor, which the team ran into issues with doing so.
16

Appendix

How old are you?


- 63

Do you find yourself forgetting things?


- Sometimes

Do you take medication?


- Yes - and vitamins

When?
- Morning and Evening

How many?
- 5 different medications and about five different vitamins

How good are you with technology?


- Can send pictures
- Can download apps
- Owns a Google Pixel
- If taught, then can easily do something

How easy to learn medicine sorter?


- Able to manage ATMs/Debit Card slider

What about others?


- Sometimes confusing for others, icons may need to be big, difficulty sliding things

Would you want to use an app or buttons?


- Would be easier on phone, but may need failsafe if phone out of batteries

Notes:
- Maybe portable idea with phone app?
- With antibiotic, [Debbie] would set timer as a reminder to remind
- Touch screen or buttons?
- Touch screen would be easier to use than buttons
- Money may be limited, phone may be more useful than machine, phone app could be
optional with machine.
- Would refill through provider
- AM + PM notification
- Know how to tell 24 hour, but can translate
- Tablets look alike, may be an issue
- May need a history to make sure when medication is taken
17

- Cound tablets, manually put in tablets, need some way to know if need refill.
- Hours to get refill, unless doctor permission if controlled
- State if need renewal 10 days in advance
- Should hold at least 10 different types, hold at least a week or two weeks
- Favorite color - black
Figure 1. This is a transcript of the questions asked, responses, and notes took during an
interview session with the team’s client, Debbie. The interview was conducted on November
29th, and laid out the main criteria and constraints for the team from the client.

Figure 2. This is a sketch of one of the team’s initial designs for the medicine dispenser. It
consists of several containers on top of a box, with an LCD and buttons which allow for the user
18

to interact with the dispenser. There is also a slide and place for the medication to dispense into.
There are several handwritten notes detailing several ideas on how the medicine dispenser should
be constructed.

Figure 3. This is another sketch of ideas for the medicine dispenser. This details information on
the slide, how several of the components should work, and an early sketch for the carousel, very
similar to one seen in a Skittles dispenser (The Atmel Team).
19

Figure 4. This is the “HelloWorld” circuit, which functions through the use of a Liquid Crystal
Display (LCD). A potentiometer and a resistor can also be seen in this circuit. This circuit,
combined with the code below, can be used to print “Hello World” and the amount of seconds
since the code started on the LCD screen. This circuit was retrieved from Arduino’s website
(“Hello World”).

/*
LiquidCrystal Library - Hello World

Demonstrates the use a 16x2 LCD display. The LiquidCrystal


library works with all LCD displays that are compatible with the
Hitachi HD44780 driver. There are many of them out there, and you
can usually tell them by the 16-pin interface.

This sketch prints "Hello World!" to the LCD


and shows the time.

The circuit:
* LCD RS pin to digital pin 12
* LCD Enable pin to digital pin 11
* LCD D4 pin to digital pin 5
* LCD D5 pin to digital pin 4
* LCD D6 pin to digital pin 3
* LCD D7 pin to digital pin 2
* LCD R/W pin to ground
* LCD VSS pin to ground
* LCD VCC pin to 5V
* 10K resistor:
* ends to +5V and ground
* wiper to LCD VO pin (pin 3)
20

Library originally added 18 Apr 2008


by David A. Mellis
library modified 5 Jul 2009
by Limor Fried (http://www.ladyada.net)
example added 9 Jul 2009
by Tom Igoe
modified 22 Nov 2010
by Tom Igoe
modified 7 Nov 2016
by Arturo Guadalupi

This example code is in the public domain.

http://www.arduino.cc/en/Tutorial/LiquidCrystalHelloWorld

*/

// include the library code:


#include <LiquidCrystal.h>

// initialize the library by associating any needed LCD interface pin


// with the arduino pin number it is connected to
const ​int​ rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

void​ ​setup​() {
​// set up the LCD's number of columns and rows:
lcd.​begin​(16, 2);
​// Print a message to the LCD.
lcd.​print​(​"hello, world!"​);
}

void​ ​loop​() {
​// set the cursor to column 0, line 1
​// (note: line 1 is the second row, since counting begins with 0):
lcd.​setCursor​(0, 1);
​// print the number of seconds since reset:
lcd.​print​(​millis​() / 1000);
}
Figure 5. This is the code for the “HelloWorld” circuit. The LiquidCrystal library is used here in
order to operate the LCD, and the functions used to do so are shown through the creation of a
LiquidCrystal object. In order words, the user can use simple functions to print information, such
as “Hello World”, to the LCD without having to be concerned about what is going on when it
comes to the machine level. This code was from Arduino’s site. (“Hello World”).
21

Figure 6. This is a picture of the complete circuit for the medicine dispenser. This circuit may
change as it is being troubleshooted, but otherwise it is the final circuit which would be used
with the medicine dispenser. In this circuit, the LCD, buttons, extension module and buzzer,
RTC module, servos, and Bluetooth module are all connected to the Arduino.

//imports all necessary libraries.


#include <LiquidCrystal.h>
#include <Servo.h>
#include <Wire.h>
#include "PCF8574.h"
#include <DS1302RTC.h>
#include <Time.h>
#include <TimeLib.h>

//Sets up the pins and the LiquidCrystal object, to be


//used with the LCD
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 1, d7 = 0;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

//Sets up the object to be used for the expansion module,


//and thus the buzzer.
PCF8574 expander;
22

//Creates objects for all of the 180 degree servos


Servo servo1;
Servo servo2;
Servo servo3;
Servo servo4;

//Defines the pins for all of the 180 degree servos


int servo1pin = 10;
int servo2pin = 17;
int servo3pin = 2;
int servo4pin = 3;

//Creates an object for the continuous rotation servo


Servo servo360;

//Defines the pin for the continuous rotation servo


int servo360pin = 13;

//Defines the pins for all of the buttons


const int blackButton = 9;
const int redButton = 8;
const int blueButton = 6;
const int yellowButton = 7;

//defines the pin for the buzzer


const int buzzer = 0;

//defines the variables for all of the states of the buttons


int blackState, redState, blueState, yellowState;

//Sets up pins for RTC: CE, IO, CLK


DS1302RTC RTC(16, 15, 14);

//Bluetooth setup - not complete

//Variable to keep track if the menu needs to be printed out


//to the LCD or not.
int menu = 0;

void setup() {
//Sets up the LCD object so it could now be used
lcd.begin(16, 2);

//Sets up the extension module and buzzer so they


//could be used.
expander.begin(0x20);
expander.pinMode(buzzer, OUTPUT);

//Sets up the 180 degree servos so that they could be used.


servo1.attach(servo1pin);
servo2.attach(servo2pin);
servo3.attach(servo3pin);
servo4.attach(servo4pin);
23

//Sets up the 360 degree servos so that it could be used.


servo360.attach(servo360pin);

//Sets up all the buttons to be used as inputs.


pinMode(blackButton, INPUT);
pinMode(redButton, INPUT);
pinMode(blueButton, INPUT);
pinMode(yellowButton, INPUT);
}

void loop() {
//Sets up the LCD to display all of the options to the user
//if loop designed to check if the menu has already been
//printed or not
if (menu == 0)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Circuit Test");
lcd.setCursor(0,1);
lcd.print("[sr][bz][ti][bl]");
menu = 1;
}

//Checks the states of all of the buttons


blackState = digitalRead(blackButton);
redState = digitalRead(redButton);
blueState = digitalRead(blueButton);
yellowState = digitalRead(yellowButton);

//If the black button is pressed, test all of the serovs


//Each servo goes one direction for a second, then the
//other, and then stops
//The LCD prints values out based on what servo is being
//tested.
if (blueState == LOW)
{
//The first 180 degree servo is tested
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Servo 1 Test");
servo1.write(180);
delay(1000);
servo1.write(0);
delay(1000);
//The second 180 degree servo is tested
lcd.clear();
lcd.print("Servo 2 Test");
servo2.write(180);
delay(1000);
servo2.write(0);
delay(1000);
//The third 180 degree servo is tested
lcd.clear();
24

lcd.print("Servo 3 Test");
servo3.write(180);
delay(1000);
servo3.write(0);
delay(1000);
//The fourth 180 degree servo is tested
lcd.clear();
lcd.print("Servo 4 Test");
servo4.write(180);
delay(1000);
servo4.write(0);
delay(1000);
//The 360 degree servo is tested
lcd.clear();
lcd.print("360 Servo Test");
servo360.write(180);
delay(1000);
servo360.write(0);
delay(1000);
servo360.write(90);
menu = 0;
}
//If the red button is pushed, test the buzzer
//The buzzer is turned on for a little bit,
//and then turned off.
if (redState == LOW)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Buzzer Test");
expander.digitalWrite(buzzer, HIGH);
delay(1000);
expander.digitalWrite(buzzer, LOW);
delay(1000);
menu = 0;
}
//If the blue button is pushed, test the RTC module
//This uses the code from “DS1302RTC library”,
//and checks to see if the clock is working
//fine, before printing values out from the
//clock.
if (yellowState == LOW)
{
//Checks clock oscillation
lcd.clear();
if (RTC.haltRTC())
lcd.print("Clock stopped!");
else
lcd.print("Clock working.");

// Check write-protection
lcd.setCursor(0,1);
if (RTC.writeEN())
lcd.print("Write allowed.");
25

else
lcd.print("Write protected.");

delay ( 2000 );

// Setup Time library


lcd.clear();
lcd.print("RTC Sync");
setSyncProvider(RTC.get); // the function to get the time from the RTC
if(timeStatus() == timeSet)
lcd.print(" Ok!");
else
lcd.print(" FAIL!");

delay ( 2000 );

lcd.clear();

int t = 0;
while (t != 5)
{
// Display time centered on the upper line
lcd.setCursor(3, 0);
print2digits(hour());
lcd.print(" ");
print2digits(minute());
lcd.print(" ");
print2digits(second());

// Display abbreviated Day-of-Week in the lower left corner


lcd.setCursor(0, 1);
lcd.print(dayShortStr(weekday()));

// Display date in the lower right corner


lcd.setCursor(5, 1);
lcd.print(" ");
print2digits(day());
lcd.print("/");
print2digits(month());
lcd.print("/");
lcd.print(year());

// Warning!
if(timeStatus() != timeSet) {
lcd.setCursor(0, 1);
lcd.print(F("RTC ERROR: SYNC!"));
}

delay ( 1000 ); // Wait approx 1 sec


t += 1;
}
menu = 0;
}
//If the yellow button is pressed, tests out the
26

//Bluetooth module.
//Because the test function for the Bluetooth
//module has not yet been decided, this test is incomplete.
if (blackState == LOW)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Sorry! No Blue");
lcd.setCursor(0,1);
lcd.print("Tooth Test");
delay(2000);
menu = 0;
}
}

//Function for printing out two digits


//Used when printing out time for the
//RealTimeClock. From “DS1302RTC library”
void print2digits(int number) {
// Output leading zero
if (number >= 0 && number < 10) {
lcd.write('0');
}
lcd.print(number);
}
Figure 7. This is the code which would be used to test all of the components for the medicine
dispenser. It is mostly complete, save for the lack of a test for the Bluetooth module, due to the
lack of a phone. Nonetheless, it serves as a way to test if all of the components would be able to
work with each other.
27

Figure 8. This is the box for the base of the medicine dispenser. It has been taped together, and
would be used to store all of the components of the circuit, as well as the dispensing mechanism.
The containers for the dispenser would be stored on top.

Figure 9. This is the four containers which would be used to store medicine in the medicine
dispenser. They are made out of water bottles, which have been cut in half and glued together.
The bottom of each water bottle was kept intact to be used as a lid. In the final design, the lids of
each water bottle would be removed, and instead a gate controlled by a servo would control the
process of dispensing medication, alongside the carousel.
28

Figure 10. This is the 3D model of the gate which would be used with servos to allow medicine
to fall from the containers to the carousel. Four instances of this piece would be 3D-printed, and
would work as apart of the dispensing mechanism.

Figure 11. This is the 3D model of the moving part of the carousel. It would be used in
combination with the gate as apart of the dispensing mechanism, so that only one tablet of
medication would fall into it at a time. There are four different sizes of holes, which accounts for
four different sizes of medication.

Figure 12. This is the fixed part of the carousel. It works as apart of the dispensing mechanism. It
would not be moving, and allows for a hole for the moving part of the carousel to drag the tablet
over to, so that the tablet could leave the medicine dispenser and head to a spot where the user
would easily be able to get ahold of it and take their medication.
29

Figure 13. This is the first iteration of the circuit inside of the medicine dispenser. It is rather
messy, with little attention to organization. The main goal was to get the circuit inside of the box,
which explains the lack of clear organization.

//imports all necessary libraries


#include <LiquidCrystal.h>
#include <Servo.h>
#include <Wire.h>
#include "PCF8574.h"
#include <DS1302RTC.h>
#include <Time.h>
#include <TimeLib.h>

//Sets up the pins and the LiquidCrystal object, to be


//used with the LCD
30

const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 1, d7 = 0;


LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

//Sets up the object to be used for the expansion module,


//and thus the buzzer.
PCF8574 expander;

//Creates objects for all of the 180 degree servos


Servo servo1;
Servo servo2;
Servo servo3;
Servo servo4;

//Defines the pins for all of the 180 degree servos


int servo1pin = 10;
int servo2pin = 17;
int servo3pin = 2;
int servo4pin = 3;

//Creates an object for the continous rotation servo


Servo carousel;

//Defines the pin for the continous rotation servo


int carouselPin = 13;

//Defines the pins for all of the buttons


const int blackButton = 9;
const int redButton = 8;
const int blueButton = 6;
const int yellowButton = 7;

//defines the pin for the buzzer


const int buzzer = 4;

//defines the variables for all of the states of the buttons


int blackState, redState, blueState, yellowState;

//variable to control if the main menu


//should be printed out on the LCD
//or not
int menu = 0;

//integer to contain the previous degree the servo was at.


int previousDegree;

void setup() {
//Sets up the LCD object so it could now be used
lcd.begin(16, 2);

//Sets up the extension module and buzzer so they


//could be used.
expander.begin(0x20);
expander.pinMode(buzzer, OUTPUT);
31

//Sets up the 180 degree servos so that they could be used.


servo1.attach(servo1pin);
servo2.attach(servo2pin);
servo3.attach(servo3pin);
servo4.attach(servo4pin);

//Sets up the 360 degree servos so that it could be used.


carousel.attach(carouselPin);

//Sets up all the buttons to be used as inputs.


pinMode(blackButton, INPUT);
pinMode(redButton, INPUT);
pinMode(blueButton, INPUT);
pinMode(yellowButton, INPUT);

//Sometimes the buzzer likes to turn on


//randomly. This method is to turn off
//the buzzer should it randomly start
//making noise
expander.digitalWrite(buzzer, LOW);

void loop() {
//Prints out the main menu to the user, which
//just says to press any button for the demo
//to activate
if (menu == 0)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Demo");
lcd.setCursor(0,1);
lcd.print("Press any button");
menu = 1;
}
//Checks the states of all of the buttons
blackState = digitalRead(blackButton);
redState = digitalRead(redButton);
blueState = digitalRead(blueButton);
yellowState = digitalRead(yellowButton);

//method to hopefully stop the continuous rotation


//servo and set the gate servo to its default positon
carousel.write(88);
servo2.write(50);

//if any of the buttons are pressed


if (blueState == LOW || redState == LOW || blackState == LOW || yellowState
== LOW)
{
//indicates to the user that there is a dispensing test
//and dispenses by telling the continuous rotation
32

//servo to go to a certain degree as well as telling


//the gate to open for a select amount of time.
//delay functions are there to make sure everything
//executes in the right amount of time
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Dispensing Test");
continousDegree(-45);
servo2.write(15);
delay(500);
servo2.write(50);
continousDegree(60);
delay(1000);
menu = 0;
}

//function to tell the continous rotation servo to move a


//certain amount of time, should the angular velocity
//be constant. Based on the equation in which
//time = (degree - initial degree) / angular velocity
void continousDegree(int degree)
{
int onTime = (degree - previousDegree) / 0.13;
//if the time is positive, go counterclockwise
if (onTime < 0)
{
onTime = -onTime;
carousel.write(94);
delay(onTime);
}
//if the time is negative, go clockwise
else if (onTime > 0)
{
carousel.write(84);
delay(onTime);
}
//stops the servo
carousel.write(88);
//unused code to
// previousDegree = degree;
}
Figure 14. This is the demo code that ran on the first iteration of the medicine dispenser. It is a
little messy, due to it being programmed in a short amount of time, but worked nonetheless. The
main reason that it doesn’t work very well, however, is that it assumed the speed of the
continuous rotation servo is constant. The speed, however, is not constant.

https://drive.google.com/file/d/1pJTqnjajRR_viJ7kPYRCPR-ys3-EDMcf/view?usp=sharing
Figure 15. This is the first video of the first iteration of the medicine dispenser. It is the front
view of the medicine dispenser as the demo code from Figure 14 is being ran. The video is five
33

seconds long, and shows that, after the button is pushed, one of the test candies fall out of the
.slide.

https://drive.google.com/file/d/1P1ZttHtqayg9VdI4s-b-dzLHlrFoII1T/view?usp=sharing
Figure 16. This is the second video of the first iteration of the medicine dispenser. It is a top view
of the medicine dispenser as the demo code from Figure 14 is being ran. The video is five
seconds long, and shows the carousel and gate moving to dispense medication after the button is
pushed.

Figure 17. This is the inside of the medicine dispenser after everything has been pulled apart and
put back together. While the wires are not the cleanest, it is much cleaner than the first iteration
of it. A motor is also used, instead of the servo which was used in the first iteration.

/*
* Imports all needed libraries. There is a library for the extension
* module, the servo, the liquid crystal display, the real time clock
* and libraries to help keep track of the time. These are all imported
* to help control certain items easier without having to code
* the more machine-specific items.
34

*/
#include "PCF8574.h"
#include <Servo.h>
#include <LiquidCrystal.h>
#include <DS1302RTC.h>
#include <Time.h>
#include <TimeLib.h>

//This is the object to control the


//extension module
PCF8574 expander;

//This is all of the servo objects for each gate


Servo gate1;
Servo gate2;
Servo gate3;
Servo gate4;

//Defines the pins for all of the gate servos


int gate1pin = 10;
int gate2pin = 17;
int gate3pin = 13;
int gate4pin = 3;

//Defines the pin for the motor


int carouselPin = 2;

//Defines the pins for the LCD and creates


//an object to control it.
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 1, d7 = 0;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

//Defines the pins for all of the buttons


const int blackButton = 9;
const int redButton = 8;
const int blueButton = 6;
const int yellowButton = 7;

//defines the pin for the buzzer


const int buzzer = 0;

//defines the variables for all of the states of the buttons


int blackState, redState, blueState, yellowState;

//Sets up pins for RTC: CE, IO, CLK


DS1302RTC RTC(16, 15, 14);

//This is a variable to tell the user whether


//the menu should be printed or not
int menu = 0;

//These are all boolean variables to tell the


//program what container needs to dispense.
boolean container1 = true;
35

boolean container2 = false;


boolean container3 = false;
boolean container4 = false;

//This is a variable to tell the program


//what time, in minutes, that the device
//needs to dispense next
int timeToDispense;

void setup() {
//This sets up the pin for the motor as an output
pinMode(carouselPin, OUTPUT);

//This sets up the expander so the buzzer could be controlled.


//The buzzer is not used in this program, and this is only
//to turn off the buzzer if it randomly turns on.
expander.begin(0x20);
expander.pinMode(0, OUTPUT);
expander.digitalWrite(0, LOW);

//Sets up the LCD object so it could now be used


lcd.begin(16, 2);

//Sets up the 180 degree servos so that they could be used.


gate1.attach(gate1pin);
gate2.attach(gate2pin);
gate3.attach(gate3pin);
gate4.attach(gate4pin);

//The servos ensure that the gates are at the right angles,
//so they would be covering the hole so medication does
//not fall in when it shouldn’t.
gate1.write(0);
gate2.write(110);
gate3.write(90);
gate4.write(160);

//Sets up all the buttons to be used as inputs.


pinMode(blackButton, INPUT);
pinMode(redButton, INPUT);
pinMode(blueButton, INPUT);
pinMode(yellowButton, INPUT);

//Calls the function to ensure that the clock is working.


setupClock();

//This sets the time for the first medication to dispense,


//which is five minutes from the current time.
timeToDispense = minute() + 5;
}

void loop() {
//calls a function to update buttons
updateButtons();
36

//Sets a loop to tell if the menu needs to


//be printed. This is so it does not flash.
if (menu == 0)
{
//The LCD is cleared so that no extra information
//is put on it.
lcd.clear();
//Sets the cursor to the first letter on the top row.
lcd.setCursor(0,0);
//Prints information out to the user
lcd.print("Demo-every 5 min");
//Sets the cursor to the first letter on the second row.
lcd.setCursor(0,1);
//Prints information out to the user
lcd.print("Push to auto");
//The menu is set to not reprint itself.
menu = 1;
}
//Sets the following code to be executed if it is time to dispense,
//or if any of the buttons have been pushed.
if (minute() == timeToDispense || blueState == LOW || redState == LOW ||
blackState == LOW || yellowState == LOW)
{
//if the first container is set to dispense
if (container1)
{
//Sets it to go to a certain angle to the first gate,
//so that the medication could fall in
toAngle(325 ,1);
//Sets it so that it would dispense medication from the next container
container1 = false;
container2 = true;
//Sets the next time to dispense in five minutes.
timeToDispense = minute() + 5;
delay(1000);
}
else if (container2)
{
//Sets it to go to a certain angle to the first gate,
//so that the medication could fall in
toAngle(310, 2);
delay(1000);
//Sets it to go to the angle for it to dispense
toAngle(260, 0);
//Sets it so that it would dispense medication from the next container
container2 = false;
container3 = true;
//Sets the next time to dispense in five minutes.
timeToDispense = minute() + 5;
delay(1000);
}
else if (container3)
{
//Sets it to go to a certain angle to the first gate,
37

//so that the medication could fall in


toAngle(300, 3);
delay(1000);
//Sets it to go to the angle for it to dispense
toAngle(80, 0);
//Sets it so that it would dispense medication from the next container
container3 = false;
container4 = true;
//Sets the next time to dispense in five minutes.
timeToDispense = minute() + 5;
delay(1000);
}
else if (container4)
{
//Sets it to go to a certain angle to the first gate,
//so that the medication could fall in
toAngle(320, 4);
delay(1000);
//Sets it to go to the angle for it to dispense
toAngle(180, 0);
//Sets it so that it would dispense medication from the next container
container4 = false;
container1 = true;
//Sets the next time to dispense in five minutes.
timeToDispense = minute() + 5;
delay(1000);
}
}

//This is a function to setup the clock to be used with the Time Library
//The team got this code online. (“DS1302RTC library”)
void setupClock() {
boolean resync;
lcd.clear();
do {
if (RTC.haltRTC()) {
lcd.print("Clock stopped!"); }
else {
lcd.print("Clock working."); }

delay ( 2000 );

// Setup Time library


lcd.clear();
lcd.print("RTC Sync");
setSyncProvider(RTC.get); // the function to get the time from the RTC
if(timeStatus() == timeSet) {
lcd.print(" Ok!");
resync = false;}
else {
lcd.print(" FAIL!");
resync = true;
38

lcd.setCursor(0,1);
lcd.print("Trying Again");
lcd.setCursor(0,0);
}

delay ( 2000 );
} while (resync);
}

//This is a function to update the buttons


void updateButtons()
{
//Checks the states of all of the buttons and updates it
blackState = digitalRead(blackButton);
redState = digitalRead(redButton);
blueState = digitalRead(blueButton);
yellowState = digitalRead(yellowButton);
}

//Function which allows the motor to go to an angle, and


//back to the start position
void toAngle(int degree, int servo)
{
//calculates the amount of time the motor should
//be on, from the degree and angular velocity
int onTime = degree / 0.0324;
//Turns the motor on for this amount of time.
digitalWrite(carouselPin, HIGH);
delay(onTime);
digitalWrite(carouselPin, LOW);
//If the servo passed is the first gate, open it.
if (servo == 1)
{
gate1.write(40);
delay(1000);
gate1.write(0);
}
//If the servo passed is the second gate, open it.
if (servo == 2)
{
gate2.write(150);
delay(1000);
gate2.write(110);
}
//If the servo passed is the third gate, open it.
if (servo == 3)
{
gate3.write(50);
delay(1000);
gate3.write(90);
}
//If the servo passed is the fourth gate, open it.
if (servo == 4)
{
39

gate4.write(120);
delay(1000);
gate4.write(160);
}
//The motor is then turned on for the remaining amount
//of time for it to go in a full circle.
digitalWrite(carouselPin, HIGH);
delay(11725 - onTime);
digitalWrite(carouselPin, LOW);
}
Figure 18. This is the most recent demo code for the medicine dispenser. It is designed to
dispense from one container every five minutes, but can dispense early if the user presses the
button. Here, the toAngle() function is created, in which it is designed to work with the motor by
passing the method an angle. The method would then calculate the amount of time it would take
to get to that angle, and then back to the original position.

/* Imports all external libraries for each component to function. For example,
Liquid Crystal
* Imports all external libraries for each component:
* LiquidCrystal - Helps control the Liquid Crystal Display (LCD)
* Servo - Controls the servos, in which there are five in total in this
circuit
* PCF8574 - Controls the extension module, so that the button could be
controlled
* DS1302RTC - Controls the Real Time Clock, can work with the Time library
* Time - Library to help easily display time
*/
#include <LiquidCrystal.h>
#include <Servo.h>
#include <Wire.h>
#include "PCF8574.h"
#include <DS1302RTC.h>
#include <Time.h>
#include <TimeLib.h>

/*
* Sets up pins which the LCD are connected to.
* Initiates a Liquid Crystal object, which allows for information
* to be printed to the LCD.
*/
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 1, d7 = 0;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

/*
* Sets up an object to be used with the expansion module.
* This allows it so that the buzzer could be connected
* to the expansion module, but could still be controlled
* by it through the Arduino
*/
PCF8574 expander;

/*
40

* Sets up four servo objects. These servo objects


* control the gate, and thus have position control
*/
Servo servo1;
Servo servo2;
Servo servo3;
Servo servo4;

/*
* Defines all the pins for the servos defined about.
* The servos would be attached to these pins in the
* setup function. Allows for user to easily change.
*/
int servo1pin = 10;
int servo2pin = 17;
int servo3pin = 2;
int servo4pin = 3;

/*
* Creates an object which would control the servo
* which controls the carousel. This is a continuous
* rotation servo, so, while degrees could still be
* written to it, it does not have position control
*/
Servo carousel;

/*
* Defines the carousel pin, which the carousel
* servo would attach to in the setup function
*/
int carouselPin = 13;

/*
* Defines the pins for which the buttons would
* be attached to. Also defines the color
* of each button
*/
const int blackButton = 9;
const int redButton = 8;
const int blueButton = 6;
const int yellowButton = 7;

/*
* Defines the pin for the buzzer. This pin
* is technically on the expansion module
*/
const int buzzer = 4;

/*
* Defines the state of each button, which is
* used to define the state of each button:
* on or off
*/
int blackState, redState, blueState, yellowState;
41

/*
* Initiates the real time clock object.
* The pins are, in order, CE, IO, and CLK
*/
DS1302RTC RTC(16, 15, 14);

/*
* This would be where the setup for any objects
* or primitive types involving the bluetooth
* module. As the bluetooth module is not
* connected, there is no bluetooth yet.
*/

/*
* Stores the information for all of the angles
* at which the carousel would need to go to.
*/
int smallToDispense;
int mediumToDispense;
int largeToDispense;
int xLargeToDispense;

int smallToOne;
int smallToTwo;
int smallToThree;
int smallToFour;
int mediumToOne;
int mediumToTwo;
int mediumToThree;
int mediumToFour;
int largeToOne;
int largeToTwo;
int largeToThree;
int largeToFour;
int xLargeToOne;
int xLargeToTwo;
int xLargeToThree;
int xLargeToFour;

int menu = 0;
boolean mainMenu = true;
boolean containerMenu = false;

/*
* This is a class to keep track of the medicine. In this project,
* four Medicine classes would be created to reflect the four
* containers which contain the medicine
*/
class Medicine {

//Contains information regarding the container for which


//the medicine is stored in, as well as the size the
42

//medication is.
int container;
int medSize;

//Contains the information for the hour and minute the medicine
//should be dispensed at, if one takes their medication
//at a specifc time of day.
int hr;
int m;

//Contains the information for the second hour and minute


//the medicine should be dispensed at, if one takes their
//medication twice a day.
int hr2;
int m2;

//Contains information regarding if the medication


//should be taken hourly, and if so, what interval
//it should be dispensed at, and when the medication
//should start and stop being dispensed based on
//when the user goes to sleep or get up.
int interval;
int morning;
int night;

//Identifies the gate servo which would open


//when it is time to dispense
Servo servo;

//Contains information on how much medication is contained


//in the container.
int medNumber;
int medRefill;

//Contains number on how much medication needs to be dispensed.


int numDispense;

public:
/*
* Medicine Constructor for when there is only one
* specific time for the medication to dispense.
* Adds all information inputted to the class
* contain - container which medication is located
* mSize - the size of the medication (0 is small, 1 is medium, 2 is large,
3 is extra large
* medNum - initial number of medication in container
* dispenseNum - how much medication would need to be dispensed at a time
* medHour - the hour the medication needs to be dispensed at
* medMinute - the minute the medication needs to be dispensed at
*/
Medicine (int contain, int mSize, int medNum, int dispenseNum, int medHour,
int medMinute){
container = contain;
medSize = mSize;
43

medNumber = medNum;
numDispense = dispenseNum;
//Calculates need for refill, if need to get refill two weeks in advance
medRefill = 14 * dispenseNum;
hr = medHour;
m = medMinute;
if (container == 1) {
servo = servo1;
}
else if(container == 2) {
servo = servo2;
}
else if(container == 3){
servo = servo3;
}
else if(container == 4){
servo = servo4;
}
}

/*
* Medicine Constructor for when there is are two
* specific times for the medication to dispense.
* Adds all information inputted to the class
* contain - container which medication is located
* mSize - the size of the medication (0 is small, 1 is medium, 2 is large,
3 is extra large
* medNum - initial number of medication in container
* dispenseNum - how much medication would need to be dispensed at a time
* medHour - the first hour the medication needs to be dispensed at
* medMinute - the first minute the medication needs to be dispensed at
* medHour2 - the second hour the medication needs to be dispensed at
* medMinute2 - the second minute the medication needs to be dispensed at
*/
Medicine (int contain, int mSize, int medNum, int dispenseNum, int medHour,
int medMinute, int medHour2, int medMinute2){
hourly = false;
container = contain;
medSize = mSize;
medNumber = medNum;
numDispense = dispenseNum;
//Calculates need for refill, if need to get refill two weeks in advance
medRefill = 14 * 2 * dispenseNum;
hr = medHour;
m = medMinute;
hr2 = medHour2;
m2 = medMinute2;
if (container == 1) {
servo = servo1;
}
else if(container == 2) {
servo = servo2;
}
else if(container == 3){
44

servo = servo3;
}
else if(container == 4){
servo = servo4;
}
}

/*
* Medicine Constructor for when the medication
* must be dispensed throughout the day. Adds all
* inputs to their corresponding outputs.
* contain - container which medication is located
* inter - the interval at which medication should dispense
* morn - the time at which the first medicine in the morning
* even - the time the last medication should be dispensed, or when one goes
to bed
* inter - the interval at which medication should dispense
* morn - the time at which the first medicine in the morning
* even - the time the last medication should be dispensed, or when one goes
to bed
* medNum - initial number of medication in container
* dispenseNum - how much medication would need to be dispensed at a time
*/
Medicine(int contain, int mSize, int inter, int morn, int evening, int
medNum, int dispenseNum)
{
hr = hour();
m = 0;
container = contain;
medSize = mSize;
interval = inter;
morning = morn;
night = evening;
medNumber = medNum;
numDispense = dispenseNum;
//Calculates need for refill, if need to get refill two weeks in advance
medRefill = ((evening - morn)/interval) * 14 * numDispense;
if (container == 1) {
servo = servo1;
}
else if(container == 2) {
servo = servo2;
}
else if(container == 3){
servo = servo3;
}
else if(container == 4){
servo = servo4;
}
}

/*
* Function to check if there is a need for a refill
* Returns: True if refill is needed, false if not
45

*/
boolean checkRefill()
{
if (medNumber < medRefill)
{
return true;
}
else {
return false;
}
}

/*
* Function which checks the time. If the time aligns
* with the time the medication needs to dispense,
* dispense it.
*/
void checkTime()
{
// Checks to see if the medication dispenses at an interval.
if (interval)
{
//Checks the hour and minute the medication needs to dispense.
if (hour() == hr) {
if (minute() == m) {
for (numDispense; numDispense > 0; numDispense--)
{
//If conditions are met, dispenses the medication
dispenseMed();
}
//Changes the time the medication needs to dispense next.
//This time is based on the interval
hr += interval;
//If the next time would be during the night
//Changes the time to the morning time.
if (hr > night)
{
hr = morning;
}
}
}
}
}
//Otherwise, just checks the time the medication
//needs to dispense at.
else {
if (hour() == hr) {
if (minute() == m) {
for (numDispense; numDispense > 0; numDispense--) {
//Dispenses the medication at the right time.
dispenseMed();
}
//If there is a second dispensing time, changes
//the current time with it so that it would
46

//dispense at the next time


if (hr2)
{
int tempHr = hr2;
int tempM = m2;
hr2 = hr;
m2 = m;
hr = tempHr;
m = tempM;
}
}
}
}
}

private:
void dispenseMed() {
if (medSize == 1)
{
if (container == 1) {
dispense(smallToOne, smallToDispense);
}
if (container == 2) {
dispense(smallToTwo, smallToDispense);
}
if (container == 3) {
dispense(smallToThree, smallToDispense);
}
if (container == 4) {
dispense(smallToFour, smallToDispense);
}
}
if (medSize == 2) {
if (container == 1) {
dispense(mediumToOne, mediumToDispense);
}
if (container == 2) {
dispense(mediumToTwo, mediumToDispense);
}
if (container == 3) {
dispense(mediumToThree, mediumToDispense);
}
if (container == 4) {
dispense(mediumToFour, mediumToDispense);
}
}
if (medSize == 3) {
if (container == 1) {
dispense(largeToOne, largeToDispense);
}
if (container == 2) {
dispense(largeToTwo, largeToDispense);
}
47

if (container == 3) {
dispense(largeToThree, largeToDispense);
}
if (container == 4) {
dispense(largeToFour, largeToDispense);
}
}
if (medSize == 4) {
if (container == 1) {
dispense(xLargeToOne, xLargeToDispense);
}
if (container == 2) {
dispense(xLargeToTwo, xLargeToDispense);
}
if (container == 3) {
dispense(xLargeToThree, xLargeToDispense);
}
if (container == 4) {
dispense(xLargeToFour, xLargeToDispense);
}
}
}

void dispense(int toPosition, int toDispense)


{
carousel.write(toPosition);
servo.write(10);
delay(100);
servo.write(0);
carousel.write(toDispense);
}
};

void setup() {
//Sets up the LCD object so it could now be used
lcd.begin(16, 2);

//Sets up the extension module and buzzer so they


//could be used.
expander.begin(0x20);
expander.pinMode(buzzer, OUTPUT);

//Sets up the 180 degree servos so that they could be used.


servo1.attach(servo1pin);
servo2.attach(servo2pin);
servo3.attach(servo3pin);
servo4.attach(servo4pin);

//Sets up the 360 degree servos so that it could be used.


carousel.attach(carouselPin);

//Sets up all the buttons to be used as inputs.


pinMode(blackButton, INPUT);
pinMode(redButton, INPUT);
48

pinMode(blueButton, INPUT);
pinMode(yellowButton, INPUT);

setupClock();
}

void loop() {
updateButtons();
if (mainMenu)
{
if (menu == 0)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Dispenser Menu")
lcd.setCursor(0,1);
//1 is set, 2 is check, 3 is log, 4 is bluetooth
lcd.print("[st][ch][lg][bl]")
menu = 1;
if(redState == LOW)
{
mainMenu = false;
containerMenu = true;
menu = 0;
}
if(blackState == LOW)
{
mainMenu = false;
checkMenu = true;
menu = 0;
}
if(blueState == LOW)
{
mainMenu = false;
logMenu = true;
menu = 0;
}
if(yellowState == LOW)
{
mainMenu = false;
bluetoothMenu = true;
menu = 0;
}
}
}
if (containerMenu)
{
if(menu == 0)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print("What Container")
lcd.setCursor(0,1);
//1 is set, 2 is check, 3 is log, 4 is bluetooth
49

lcd.print("[1][2][3][4]")
menu = 1;
}
if(redState == LOW)
{
containerMenu = false;
sizeMenu = true;
menu = 0;
tempContainer = 1;
}
if(blackState == LOW)
{
containerMenu = false;
sizeMenu = true;
menu = 0;
tempContainer = 2;
}
if(blueState == LOW)
{
containerMenu = false;
sizeMenu = true;
menu = 0;
tempContainer = 3;
}
if(yellowState == LOW)
{
containerMenu = false;
sizeMenu = true;
menu = 0;
tempContrainer = 4;
}
}
if (sizeMenu)
{
if(menu == 0)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print("What Size")
lcd.setCursor(0,1);
//1 is set, 2 is check, 3 is log, 4 is bluetooth
lcd.print("[sm][md][la][xl]")
menu = 1;
}
if(redState == LOW)
{
sizeMenu = false;
numMenu = true;
menu = 0;
tempSize = 1;
}
if(blackState == LOW)
{
containerMenu = false;
50

numMenu = true;
menu = 0;
tempSize = 2;
}
if(blueState == LOW)
{
containerMenu = false;
numMenu = true;
menu = 0;
tempSize = 3;
}
if(yellowState == LOW)
{
containerMenu = false;
numMenu = true;
menu = 0;
tempSize = 4;
}
}
if (checkMenu)
{
if(menu == 0)
{

}
}
}

void setupClock() {
boolean resync;
lcd.clear();
do {
if (RTC.haltRTC()) {
lcd.print("Clock stopped!"); }
else {
lcd.print("Clock working."); }

delay ( 2000 );

// Setup Time library


lcd.clear();
lcd.print("RTC Sync");
setSyncProvider(RTC.get); // the function to get the time from the RTC
if(timeStatus() == timeSet) {
lcd.print(" Ok!");
resync = false;}
else {
lcd.print(" FAIL!");
resync = true;
lcd.setCursor(0,1);
lcd.print("Trying Again");
lcd.setCursor(0,0);
}
51

delay ( 2000 );
} while (resync);
}

void updateButtons()
{
//Checks the states of all of the buttons
blackState = digitalRead(blackButton);
redState = digitalRead(redButton);
blueState = digitalRead(blueButton);
yellowState = digitalRead(yellowButton);
}
Figure 19. This is a work in progress of the final code for the medicine dispenser. The user
should be able to input information into the LCD, and then the Arduino should be able to keep
track of when it needs to dispense. There is also an option for the user to check the information
for the medication in each container, and check a log for when medication was last dispensed.
There is also a button allocated to bluetooth, in which it would, in theory, allow the user to sync
the device with their phone. As stated before, this code is a work in progress and thus is not
complete, and has not been tested.

Part Retail Price per Quantity Total Cost Retail Source


Price Unit Used

Arduino $19.95 $19.95 1 $19.95 Sparkfun


https://www.sparkfun.com/prod
ucts/13975

LCD Screen $15.95 $15.95 1 $15.95 Sparkfun


https://www.sparkfun.com/prod
ucts/709

Button $1.50 $0.38 4 $1.50 Sparkfun


https://www.sparkfun.com/prod
ucts/14460

RTC $6.75 $6.75 1 $6.75 Surplus Gizmos

Buzzer $0.75 $0.75 1 $0.75 Surplus Gizmos

Extension $9.99 $9.99 1 $9.99 Amazon


Module https://www.amazon.com/Expa
nsion-Expander-Evaluation-De
velopment-XYGStudy/dp/B00
DUO17J6

Servos $9.95 $9.95 4 $39.80 Sparkfun


https://www.sparkfun.com/prod
52

ucts/11884

Stepper Motor $4.95 $4.95 1 $4.95 Adafruit


https://www.adafruit.com/produ
ct/918

Stepper Motor $19.95 $19.95 1 $19.95 Adafruit


Shield https://www.adafruit.com/produ
ct/1438

Breadboard $4.95 $4.95 2 $9.90 Sparkfun


https://www.sparkfun.com/prod
ucts/12002

Plywood $5.49 $5.49 1 $5.49 JoAnns

Water Bottles ? ? 4 ? Reused

Female pin $0.85 $0.85 3 $2.55 Surplus Gizmos


headers (40 pins)

Hinges $6.00 $6.00 1 $6.00 Fred Meyer

Bubble tea $0.50 $0.50 1 $0.50 Yogurt Munch


straw

Total $144.03
Figure 20. This is the team’s itemized budget sheet. It includes all everything used to build the
device, including the stepper motor and the stepper motor shield the team plans to add to the
final iteration.
53

Bibliography

“Arduino Time Library.” Arduino. Arduino. N.d. Web. Accessed 28 November 2017.

<​http://playground.arduino.cc/Code/Time​>

Atmel Team, The. “ATmega328 is under the hood of this sweet candy sorting machine”. ​Atmel |

Bits and Pieces. ​WordPress.com. 3 November 2014. Web. Accessed 19 March 2018

<​https://atmelcorporation.wordpress.com/2014/11/03/atmega328-is-under-the-hood-of-th

is-candy-sorting-machine%E2%80%A8%E2%80%A8/​>

Bruce, James. “What is Arduino & What Can You Do With It?”. ​Make Use Of. ​Make Use Of. 25

September 2011. Web. Accessed 30 November 2017.

<​http://www.makeuseof.com/tag/arduino-technology-explained/​>

“DS1302 Real Time Clock”. ​Arduino Playground. ​Arduino. N.d. Web. Accessed 19 March

2018.

<​https://playground.arduino.cc/Main/DS1302​>

“DS1302RTC library”. ​Arduino Playground. ​Arduino. N.d. Web. Accessed 19 March 2018.

<​https://playground.arduino.cc/Main/DS1302RTC​>

“Hello World”. ​Arduino.​ Arduino. N.d. Web. Accessed 30 November 2017.

<​https://www.arduino.cc/en/Tutorial/HelloWorld​>

Mathavan, Hariharan. “Control an Arduino Using Bluetooth.” ​All About Circuits. ​EETech

Media,

LLC. 26 November 2015. Web. Accessed 30 November 2017.

<​https://www.allaboutcircuits.com/projects/control-an-arduino-using-your-phone/​>

“Patient Compliance + Medication Adherence Statistics”. ​E-pill. ​E-pill. N.d. Web. Accessed 19
54

March 2018. <​https://www.epill.com/statistics.html​>

“Servo Library”. ​Arduino. ​Arduino. N.d. Web. Accessed 19 March 2018.

<​https://www.arduino.cc/en/Reference/Servo​>

skywodd. “pcf8574_arduino_library”. ​Github. ​Github, Inc. N.d. Web. Accessed 19 March 2018.

<​https://github.com/skywodd/pcf8574_arduino_library​>

SparkFun Electronics, inc. Sik Guide ver. 3.2. SparkFun Electronics, inc. N.d. Print.

Stan. “HC-06 Bluetooth module datasheet and configuration with Arduino”. ​42 Bots. ​Wordpress.

25 May 2014. Accessed 19 March 2018.

<​http://42bots.com/tutorials/hc-06-bluetooth-module-datasheet-and-configuration-with-ar

duino/​>

Das könnte Ihnen auch gefallen