Arduino Automated Pill Dispenser

Published

Introduction: Arduino Automated Pill Dispenser

According to the World Health Organization (WHO), one out of every two chronic patients does not take the medicine prescribed by the doctor how and when they should.

This poses a serious risk to the patient, and this risk increases in the case of elder people, since they usually must take a considerable number of pills daily and it is very easy to end up forgetting some of them.

That's why, with today's low cost micro-controllers and sensors, we thought it would be a good idea to use Arduino technology and 3D printing to build a pill dispenser that would allow to notify and supply the drugs on schedule. It had to be very simple for the user to program when to take the pills and this is how we did it.

We are two engineering in product design students in ELISAVA (Barcelona) and by doing so we want to help our closest relatives to ensure they don't overmedicate and stay healthy.

Step 1: How to Use It

To schedule the pills you need to take its very simple, the user only has to open the cover to start. The first thing is to rotate the first dial to indicate the interval between each pill, you can choose between 4h, 8h, 12h or 24h. Then rotate the second dial to indicate the starting time. Once both dials are on the right position and the LED strip is already shinning you can start introducing the pills. They have to be introduced one by one, and wait for the LED to shine again between each pill. When they are introduced you only need to close the small cover. Once it's time to take the pill the LED strip will blink to alert the user.

Step 2: How It Works

The operation of the product is relatively simple to understand. When the patient needs to recharge the pill dispenser, he will lift a lid in the upper case. Now, by means of a photoresistor the Arduino detects it's time to schedule. It will check the EEPROM (Arduino internal memory) to see if there's an empty level, as every level corresponds to a different kind of pill. It will activate a motor that will move "the selector" to introduce and organize the pills in the empty level.

Then an LED strip will light to indicate to the user that he can insert the pill. A photoresistor that will be receiving the emission of a laser will detect the inserted tablet and will rotate the specific floor so that the next tablet can be placed in another compartment.

Finally, the user will have defined the frequency with which the drug should be taken and its initial time with the rotation of two potentiometers, and when the lid will be closed, everything will be recorded in the EEPROM memory of the board. An RTC module will also be used to keep track of the current time. When it's time to dispense the medication, the LED strip lights in order to alert the patient. This model consists of two floors of pills storage, although this number can be increased by modifying the 3D model in order to increase the number of pills stored.

Step 3: What You Need to Make It

MATERIAL

  • Arduino Nano or UNO Board.
  • 5x7cm Stripboard
  • 6 AA Cell Holder.
  • 6 AA Batteries2.
  • 2 Photoresistors.
  • 2 Potentiometers (4.7k Ohm each).
  • Mini Laser Dot Diode Module Head.
  • IRF540N Transistor or similar
  • 3 Stepper motors with their own controler boards
  • Tiny RTC I2C Module
  • 4 15k Ohm resistors
  • 12V LED Strip
  • 10m wire
  • Soldering Iron
  • PLA Filament (Although ABS or other rigid filaments can work as well).
  • Translucid plakene A4 Sheet
  • Micro USB to USB Cable
  • Loctite or similar strong glue
  • Self-locking cable tie zips.

TOOLS

  • Solder
  • 3D Printer (In this Instructable we use a Original Prusa i3 MK2 printer). If you don't have one you can use many on-demand 3d printing services such as Fablab.

Step 4: Design and Print the Pill Dispenser Parts

You are lucky, you can skip this step as we have done the work for you, you only need to take the .STL files and print them. The pill dispenser has been printed with PLA, since it is a very easy material to print, and using a fast printing setup it has taken about 25 hours to print, so take your time. You can keep reading if you are interested in how we did it or just skip to next step.

In order to make the product we first had to 3D model it. We used Solidworks to do so, and prepared it to print with Slic3r. Apart from the .STL files we will also attach the Soliworks native files so you can modify them to your needs and .STP files if you want to do it with other modelling software.

While designing the dispenser, the maximum advantatge of the space has been taken into account in order to obtain a product as compact as possible and thus save material, time and costs. Tolerances and clearance between parts need to be taken into consideration while modifying 3d files. Also joints between parts to ensure the are fixed correctly were used and can be modified to adapt them to different electronic components. As Solidworks is a parametric software, modifying the file is easy and fast.

Step 5: Electronics Setup

It's time for Arduino, so get ready and be patient as this is a quite long and complicated process. Probably somethings aren't going to work the first time so check everything is well connected and don't get frustrated.

We decided to use an Arduino Nano to reduce space and make it more efficient, but this means soldering. You can also use an Arduino UNO, a breadboard and jumpers to make it work as Arduino Nano and UNO pins are the same. We have several components, so we will follow the same workflow for every one of them one by one.

Each component is mounted individually, checked with an example code (you can find all example codes in Arduino libraries) to verify connections are right and it works, soldered to the stripboard and finally checked again to ensure all the weldings are right. Once everything works fine we recommend wrapping all the cables with zip ties to ensure a clean setup. We will start by mounting the stepper motors as they are the most complex component.

STEPPERS

Each stepper is connected to it's own control board so, we will start by taking them apart to solder the control board to our arduino. The stepper works by turning ON and OFF four magnets that turn in a loop, making the shaft rotate. For this reason the board has 4 outputs, one for every magnet that needs to be controled. Apart from this, you will also need to supply 5V to the board and GND.

To make it easier for you, don't connect the GND and 5V directly to the board pins, use a dedicated place in the stripboard where you will connect all the GND pins of the different components and another one for the 5V to organize it cleaner.

Note that you can use Stepper knob example to ensure everything is fine (File / Examples / Stepper / MotorKnob). It's posible that the pins indicated on the stepper board aren't well arranged when you buy it. This means you have to change the order of the Arduino code in which you define the pins.

Stepper stepper(STEPS, 8, 9, 10, 11);

The board has four LEDs that light up when the magnet is ON. The only thing you need to do is try MotorKnob example setting turning speed to 1.

<p>void setup() {<br>  // set the speed of the motor to 1 RPMs
  stepper.setSpeed(1);
}</p>

Now it will be slow enough to see in which order LEDs light up, so take note and change the code untill LEDs light in the correct order (1&2, 2&3, 3&4, 4&1,...).

Repeat this process for the three stepper motors.

RTC I2C MODULE

The Real Time Clock module works using the I2C protocol, which means that uses the A4 and A5 pins on the board. Note these can not be changed so it wouldn't work. Here there's the schematic to solder it.

As you see in the schematic only SCL, SDA, VCC and GND pins are used.

If your RTC has two different rows of pins (P1 and P2) it's important to use the first one, if not it isn't going to work and you will get crazy trying to understand what is the problem.

The RTC library it's not installed within the examples so you need to download it. You can use this source (RTC module library) to do so.

LED STRIP

In this cause we are using a 12V LED strip, this means we need external power suply so we use 6AA 1,5V batteries. 5V LED strips are difficult to find but if you can you with avoid the use of the external power source.

To control the strip we will use a transistor following the schematics. The transistor allows to control a bigger voltage by using a small one that works as a switch.

To try the code you can use the blink example changing the pin (File / Examples / Basics / Blink).

POTENTIOMETERS

These potentiometers are going to read an analog value (from 0 to 255) so we need to use an analog pin. Preferably we will use A6 and A7 because these pins only work as input and not as output.

To try the potentiometers you can use the AnalogReadSerial example (File / Examples / Basics / AnalogReadSerial). With the Serial plotter you can check the values you get from the potentiometer are stable and right.

PHOTORESISTORS

This component is very simple, it increases or decreases its resistance value depending on the light amount it recieves. We will need to use two resistors also following the schematics. They need to collect analog values also, so we will use analog pins.

You can use the same AnalogReadSerial code to check the values on the photoresistors.

LASER DOT DIODE MODULE

This is the last component to solder. It works the same way as a LED so it only needs a resistor to work properly. You can follow the schematics to mount it. This laser needs a digital output so either an analog or digital pin is fine.

To try the code you can use the same one as the LED strip (File / Examples / Basics / Blink).

Now we have everything working individually so it's time to assemble everything. The final look of the electronics setup should be something similar to ours. We strongly recommend using three color cables instead of only one (red for the V input, black for the GND and another color for the pins control).

Step 6: Assembling All the Parts

We will start to assemble the parts from the top to the bottom. So here's the procedure.

1.The first thing we will do is to glue the parts in which is divided the top of the dispenser case so it will have enough time to dry.

2. Take the base of the dispenser and put the batteries and stripboard with the arduino on it's place.

3. Put the "first floor" on place. You hace to pass all the elements and sensors through it and put the first two motors in place. Be careful because the base has a joint that needs to be aligned with the one in the first floor.

4. Mount the "selector" on the first stepper and one of the gears in the second one. Note that the stepper with the shaft closer to the center of the dispenser is the one with the selector. Also put the blades on place ensuring they fit with the gear.

5. Repeat the process for the "second floor", pass the elements through it and mount the stepper with its gear and the blades.

6. Mount the laser diode on it's place and the first photoresistor aligned with it. Also mount the second photoresistor. You may need the weld again the photoresistor to fit it in place.

7. Pass the LED strip through the hole in the top of the dispenser and stick it in the place dedicated. Now you can also glue the plakene strip on place to cover the leds.

8. Mount the potentiometers on place and put the printed dials over them.

9. Finally mount the top part over the rest of the dispenser and the small cover on place.

The whole hardware work is done now! The only thing left is coding.

Step 7: The Code

We have all the hardware, we have all the individual codes for every component, now it's time to wrap everything and get the result we want. You can download the code at the bottom of the page and just paste it on your board. However if you are interested in how it works to adapt it to your needs we will explain it to you step by step.

<p>/*<br> * This code is used to make an Arduino Pill Dispenser, you can find all the information about it on Instructables.
 * Made by Arnau Donate and Victor-Marcel Martínez
 * We have used many delays and Serial.print to check the code worked correcty. Most of them can be deleted but please make
 * sure before deleting a delay that it wasn't used to make it work properly. Thanks!
 *</p><p>/ Include the EEPROM library to store values into the internal non-volatile memory of the Arduino Nano
#include 
// Include the Stepper library
#include </p><p>// initialize the stepper library:
int x = 233;
int y = 433;
int z = 433;
Stepper myStepper1(x, 12,9,10,11); //selector
Stepper myStepper2(y, 6,8,7,5); //roda pis1
Stepper myStepper3(z, 13,4,3,2); //roda pis2</p><p>// Setting variables and constants. They're used here to set pin numbers and the values they record.
  int detector1Pin = A1;
  int detector1Value = 0;
  int detector2Pin = A2;
  int detector2Value = 0;
  int detector2Threshold = 0;
  int lightValue = 0;
  
  // Define the EEFROM's adress in which the info will be saved
  int address0 = 0;
  int address1 = 0;
  int address2 = 0;
  
  int counterpills = 0;
  int valknob1 = 0;
  int valknob2 = 0;</p><p>  int ledStrip = A0;                // select the input pin for the LED strip
  int laser = A3;                   // select the input pin for the laser</p><p>  int sensorPin1 = A6;              // select the input pin for the potentiometer 1
  int sensorPin2 = A7;              // select the input pin for the potentiometer 2
  int sensorValue1 = 0;             // variable to store the value coming from the sensor 1
  int sensorValue2 = 0;             // variable to store the value coming from the sensor 2
  
  int i = 0;
  int level = 0;</p><p>void setup() {
  
  // initialize the serial port:
  Serial.begin(9600);
  while (!Serial) {
  ;                                 // wait for serial port to connect. Needed for native USB port only
  }
  myStepper1.setSpeed(60);          //Set rotation speeds of each stepper.
  myStepper2.setSpeed(60);
  myStepper3.setSpeed(60);
  pinMode(ledStrip, OUTPUT);        //Declare led strip and laser as output
  pinMode(laser, OUTPUT);
  detector1Value = analogRead (detector1Pin);       //Read the starting photoresistor value in order to detect when the cover is opened.
}</p><p>void loop() {</p><p>  // Check if the upper cover is opened 
  lightValue = analogRead (detector1Pin);
  detector2Value = analogRead (detector2Pin);
  
  Serial.print ("Cover ");
  Serial.println (lightValue);
  
  if (lightValue >= detector1Value + 100){        //If the cover is opened start the scheduling function and restart the pills counter.
    int counter = 0;
    
    for (int i = 1; i <= 2; i++){                 //Choosing the level that is going to be filled, we have 2 levels so the loop is going to be done twice
      level = i;
      int address0 = (level*10);                  //Adress 0 stores the nuber of pills, every level has it's own (10 for level 1,20 for level 2, 30 for level 3...)
      
      counterpills = EEPROM.read(address0);       //Read the adress for every level to see how many pills are already stored
      
      Serial.print(address0);
      Serial.print("\t");
      Serial.print("pills number ");
      Serial.print(counterpills);
      Serial.print("\t");</p><p>      if (counterpills == 0){                     //If the level checked is empty, we select it as the level we will fill and break the "for loop".
        Serial.print("level choosen ");
        Serial.println(level);
        break;        
      } else {                                    //If there are pills stored we discard it as we can't mix pills.
        Serial.print("Floor ");
        Serial.print(level);
        Serial.println(" is full");
        level = 0;
      }
    }
    if (level != 0) {                             //When one of the levels is empty we proceed to fill it.
      if (level == 1){                            //If the level choosen is the first one we rotate the selector to guide pills to it. 
        myStepper1.step(-2*x);
        delay (500);
        myStepper2.step (y);                      // Every level has 15 compartments so we rotate 24 degreees each time a pill is inserted.
        delay (500);
      }
      if (level == 2){                            //We do the same for level 2
        delay (3000);
        myStepper1.step(-x);
        delay (3000);
        myStepper3.step(z);
        delay (500);
      }
  
      digitalWrite(laser, HIGH);                            //We light the laser and detect the photoresistor value
      delay(2000);
      detector2Threshold = analogRead(detector2Pin);
        
      while (counter <= 15){                                //We repeat the loop 15 times, one for pill.
        detector2Value = analogRead(detector2Pin);          //We read the photoresistor value and light the led strip up to say the user he can introduce the pills
        digitalWrite(ledStrip, HIGH);                       
        
        Serial.print ("        PHTR value ");               
        Serial.print (detector2Value);
        Serial.print ("      counter       ");
        Serial.println (counter);
        
        if (detector2Value <= detector2Threshold - 30){     //If the value is lower than the starting one means a pill has interrupted the laser 
          digitalWrite(ledStrip, LOW);                      //We turn off the led strip and add one pill to the counter
          counter++;
          delay (1500);
          Serial.print ("Rotating level ... please wait");
  
          if (level == 1){
            myStepper2.step (y);
          }
          if (level == 2){            
            myStepper3.step (z);
          }
          delay (1500);
        }
        
        lightValue = analogRead (detector1Pin);              //We check the photorresistor on the cover again to see if the cover was closed.
  
        Serial.print ("lightvalue ");
        Serial.print (lightValue);
        Serial.print ("      threshold ");
        Serial.print (detector1Value + 100);
      
        if (lightValue <= detector1Value + 130){             //If the cover was closed we wait to double check if it was and avoid errors
          delay (5000);
          lightValue = analogRead (detector1Pin);
          if (lightValue <= detector1Value + 130){  
            digitalWrite(ledStrip, LOW);                    //If we confirm it is closed we turn off the led and exit the loop.
            break;
          }
        }
      }
  
      Serial.println ("You have finished inserting pills");
      delay (3000);
      erial.println ("Rotating selector back to it's starting position... please wait");
  
      if (level == 1){                                      //We move back the selector to it's initial position.
        myStepper1.step(2*x);
        delay (1500);
      }
  
      if (level == 2){
        myStepper1.step(x);
        delay (1500);        
      }
  
      sensorValue1 = analogRead(sensorPin1);                  // read the value from the dial 1 and give a value depending on it's position.
      if (0 <= sensorValue1 && sensorValue1 <= 252){
       valknob1 = 6;
      } if (253 <= sensorValue1 && sensorValue1 <= 505){
       valknob1 = 8;
      } if (506 <= sensorValue1 && sensorValue1 <= 757){
       valknob1 = 12;
      } if (758 <= sensorValue1 && sensorValue1 <= 1024){
       valknob1 = 24;
      }
             
      sensorValue2 = analogRead(sensorPin2);                   //We do the same for dial 2
      if (0 <= sensorValue2 && sensorValue2 <= 112){
       valknob2 = 8;
      } if (113 <= sensorValue2 && sensorValue2 <= 224){
       valknob2 = 10;
      } if (225 <= sensorValue2 && sensorValue2 <= 336){
       valknob2 = 12;
      } if (337 <= sensorValue2 && sensorValue2 <= 448){
       valknob2 = 14;
      } if (449 <= sensorValue2 && sensorValue2 <= 561){
       valknob2 = 16;
      } if (562 <= sensorValue2 && sensorValue2 <= 673){
       valknob2 = 18;
      } if (674 <= sensorValue2 && sensorValue2 <= 785){
       valknob2 = 20;
      } if (786 <= sensorValue2 && sensorValue2 <= 897){
       valknob2 = 22;
      } if (898 <= sensorValue2 && sensorValue2 <= 1023){
       valknob2 = 24;
      } 
  
      counterpills = counter;
  
      address0 = (level*10);                                    //We declare wich adress in the EEPROM will be used to store the data.
      address1 = (level*10)+1;
      address2 = (level*10)+2;
     
      Serial.println (valknob1);
      Serial.println (valknob2);
      Serial.println (counterpills);
  
      EEPROM.write(address0, counterpills);                     //And we will write the EEPROM with tha data received from both dials and the pills counter.
      EEPROM.write(address1, valknob1);
      EEPROM.write(address2, valknob2); 
      
      delay (10000);
  
      int k = EEPROM.read(address0);                            //We read the values to check in the serial monitor that they have been recorded right.
      int l = EEPROM.read(address1);
      int m = EEPROM.read(address2);
  
      Serial.println (k);
      Serial.println (l);
      Serial.println (m);   
  
      delay (1000);
    }
  }
  delay (500);
}</p>

if the code isn't working properly and you haven't modified ours ensure all the hardware is right. Try the examples described before for every component.

Step 8: Final Result

Here we are, we hope your brand new pill dispenser is working as desired. This is a university project developed in a few weeks, so deadlines limited our capacity of improving the design and performance.

If you want to step to the next level try adding more levels to the dispenser (which means using another Nano board or a bigger one as a MEGA). Also you can include a speaker to alert the user with light and sound or tune the 3d model to your needs. We hope you enjoyed our project and hope to get your feedback. Really thanks!.

Share

    Recommendations

    • Water Contest

      Water Contest
    • Oil Contest

      Oil Contest
    • Clocks Contest

      Clocks Contest

    2 Discussions

    It's a remarkable project.Can i get the circuit diagram?

    Where can I find the .STP files?