Pill dispenser robot

An intelligent robot that manages my medication regimen.

Similar projects worth following
I have to take one tablet in the morning and two in the evening. If I forget to take the tablet in the morning, I have a horrible day, if I forget to take it in the evening, I have a horrible night. It doesn't help if I take them late. Since I suffer from bipolar disorder, I will have to take the tablets for the rest of my life. A robot could support me and others in that. Bipolar disorder is one of the most serious mental illnesses. I hope the jury knows how difficult it is to realize such a complex project with this disease.


The heart of the robot is a drum divided into 14 chambers. A Hitec HS-785 HB winch servo turns the drum. The servo is completely overkill in terms of torque, but it supports a true 360-degree rotation via the PWM signal. A second servo opens a flap so that the corresponding pills fall into a small catch basin. A touch sensor is integrated into the catch basin so that the robot recognizes whether the patient has taken the pills. The robot will also be able to speak, and the head of the robot will be equipped with a TFT display. For more details, see the Speech Synthesis and PCBs log.

Building the robot

The first batch of parts have been printed in ABS with a 50 to 80% infill and came out ok.

First, the touch sensor and push button PCB were installed, then the micro servo to operate the slider for pill dispensing.

The HS-785 HB servo for rotating the drum was screwed to the bracket with four M4 X 12 mm screws, then fitted into the robot housing. The four slotted holes in the housing to mount the bracket make it easy to align the servo precisely.

In the next step, the servo horn was screwed to the drum using four M2 x 12mm screws, then placed on the main axis of the servo and secured using the screw supplied with the servo. Finally, the laser-cut acrylic disk was attached using two M2.2 x 8mm self-tapping screws.

The HS-785 HB servo rotates 2826° at a pulse width of 600-2400µs and 630° at a pulse width of 1500-1900µs. This gives us a maximum resolution of 1.57°. Not very precise, but precise enough for our purpose.

Using the kit seen on the left, I made custom cable connectors for the OLED. You don't need any special tool for this, just a small pair of pliers. I don't just clamp the wire to the insert, but solder the wire to the insert, which gives a much more reliable connection.

After I made some adjustments, the second batch came out of the printer quite nicely.

THE OLED was screwed into the head of the robot using four M1.7 x 6mm self-tapping stainless steel screws.

The head was then attached to the upper body with two M3 x 25 mm stainless steel screws and nuts.

After wiring the OLED, the cover was attached to the back of the head with four M1.7 x 8mm self-tapping stainless steel screws.

The robot has exactly the 80s look I wanted.

Next, the back panel, the VISATON K28.40, and the Adafruit PAM8302 breakout were needed. The speaker was screwed to the back panel with four M3 x 8mm stainless steel screws and nuts, and the breakout with two self-tapping stainless steel screws M1.7 x 6mm. Afterward, the speaker was wired. For the breakout, I again made a custom connector.

In the meantime, the last two parts needed were 3D printed.

The Arduino Due was screwed to the base plate using four 6mm spacer sleeves and four M2 X 16mm stainless steel screws and nuts. The reason for not integrating the spacers into the base plate is to better align the Arduino Due so that the two USB connectors are aligned with the corresponding holes in the box.

Next, all the cables were fed through the opening in the box, then the upper body of the robot was bolted to the box. Four M3 x 10 mm stainless steel screws and nuts were used for this.

The cables of the back panel were also led through the opening and the cables were tightened with cable ties so that the mini servo can move freely.

In the next step, the back panel was screwed to the upper body using four self-tapping M1.7 x 8mm stainless steel screws.

The two remaining holes in the box are for the 5.5mm x 2.1mm power jack and the on/off switch, a latching push button in stainless steel.

All cables were shortened accordingly and fitted with connectors.

Then the power jack and the on/off switch were mounted and wired.

On the Arduino Due mounted on the base plate, the shield PCB was plugged on, then the TTS module.

The CR1220 coin cell powers the DS3231...

Read more »

ino - 32.68 kB - 05/29/2023 at 19:21


x-zip-compressed - 257.03 kB - 05/25/2023 at 10:52


x-zip-compressed - 297.93 kB - 05/17/2023 at 16:42


x-zip-compressed - 79.34 kB - 05/17/2023 at 16:42


Standard Tesselated Geometry - 265.90 kB - 05/16/2023 at 09:18


View all 17 files

  • 1 × HS-785 HB servo
  • 1 × EMAX ES08MA II servo
  • 1 × Adafruit PAM8302 breakout
  • 1 × VISATON K28.40 speaker
  • 1 × XFS5152 speech synthesis module

View all 27 components

  • My robot made in the news

    M. Bindhammer08/15/2023 at 14:56 0 comments

    Heise Online, a German IT news magazine reported today about my robot.

    An article in the German Make Magazine will probably follow in October.

  • Hackaday Prize 2023

    M. Bindhammer07/20/2023 at 16:00 0 comments

    A big thank you goes out to the judges. I've been participating in the Hackaday Prize since 2015, and this is the first time I've made it to the finals. It makes me happy and means a lot to me.

  • Initial code and field testing

    M. Bindhammer05/28/2023 at 11:28 0 comments

    In an initial code (see FILES section), I modeled my current medication. I take 100 mg of sertraline at 10:00 in the morning and 600 mg of quetiapine at 20:00 in the evening. Each Sunday evening after taking quetiapine, I refill the pill organizer for the next week.

    At the moment I am doing a field test to identify possible bugs and improve the source code.

    Meanwhile I have been using the robot for two months and it has fundamentally changed my medication and thus my everyday life. And if it helps me, it can also help many others.

  • Daylight saving time and standard time

    M. Bindhammer05/16/2023 at 08:46 0 comments

    Since I live in Europe, we have daylight saving time and standard time. The clocks are mostly synchronized by the longwave time signal DCF77. Since we use the high-precision RTC DS3231 and a microcontroller, this is not necessary. For daylight saving time, the time change takes place on the last Sunday in March. Thereby at 2:00 a.m., the clock is advanced by one hour. For the winter time (standard time) the time change takes place on the last Sunday in October. At 3:00 a.m. the clock is set back by one hour.

  • Speech synthesis

    M. Bindhammer05/03/2023 at 09:42 8 comments

    I bought the Chinese XFS5152CE Speech Synthesis Module on eBay. It supports TTS in Chinese and English language and has some sound effects. Also, speech recognition of up to 30 commands should be possible. The module supports UART, I2C, and SPI communication. There is no datasheet for the module itself, only for the processor XFS5152CEA. A translation can be found under FILES. The DFRobot Gravity - Speech Synthesis Module uses the same processor. Fortunately, user iforce2d on youtube has already done some preliminary work:  XFS5152 speech synthesis module.

    I have also collected some useful information in advance:

    As expected, only the RX pin on the XFS5152CE Speech Synthesis Module works with hardware serial. This is the same for the EMIC-2 module. Since I want to use an Arduino Due, software serial is out of the question. We actually only need RX and the status indicator output of the speech Synthesis Module, which we can monitor with an interrupt routine. I used the following wiring and components for testing:

    Test code:

    const byte ledPin = 13;
    const byte interruptPin = 2;
    volatile byte state = LOW;
    void speak(char* msg) {
      Serial1.write(2 + strlen(msg));
    void busy() {
      state = !state;
      digitalWrite(ledPin, state);
    void setup() {
      pinMode(ledPin, OUTPUT);
      pinMode(interruptPin, INPUT_PULLUP);
      attachInterrupt(digitalPinToInterrupt(interruptPin), busy, CHANGE);
    void loop() {
      speak("[x0][t6][v5][s6][m51][g2][h2][n1]Please take your medicine now.");
      while(state == HIGH);

    Video (the first one in my new youtube channel):

  • PCBs

    M. Bindhammer05/02/2023 at 16:34 0 comments

    The first PCB I had to design is the one for the touch sensor. I use an AT42QT1011, which is a capacitive sensor. The wiring is very simple.

    The board design is just as simple. To not interfere with the touch sensor, I did not use a ground plane. The datasheet states in this regard: Metal areas near the electrodes will reduce the field strength and increase Cx loading and should be avoided, if possible. Keep ground away from the electrodes and traces.

    The only component that is a bit difficult to solder by hand is the AT42QT1011. You need a magnifying glass and backlight to find the pin 1 ID.

    The second PCB for the robot that I designed is the one for the three push buttons.

    The touch sensor is very sensitive. When I get closer than 2cm with my finger, the circuit already reacts. I also put my pills on the touchpad. Fortunately, they contain too little water to react. By decreasing the value for C1 we can make the sensor less sensitive if need to. In my case, I had to change the value of C1 to 4.7nF.

    The third and last PCB we need is a shield for the Arduino Due. All connections are broken out, it supplies 5V with up to 1.5A for the servos and has a DS3231 Precision RTC and a backup battery on board.

    For the shield, the LDO was first soldered using solder paste and a hot air gun, since the GND solder area of the LDO in the D2P package is not accessible in any other way. The remaining components were soldered by hand.

    On the bottom side, you can see the female pin header for the SPI connection. There is no other way to make the SPI pins accessible on the Arduino Due.

    Finally, the PCB was cleaned of flux residues using isopropanol and a discarded toothbrush.

  • Minimizing redraw flicker

    M. Bindhammer05/01/2023 at 16:55 0 comments

    Redraw flicker is mostly an issue with color LCD or OLED screens, where graphics are rendered with every function call. To minimize the effect I had to use an offscreen canvas, respectively the 1-bit canvas type for the animated robot face. You can think of it as all the graphics primitives or text that are on the canvas are converted to a bitmap and then drawn on the OLED.

    // Screen dimensions
    #define SCREEN_WIDTH  128
    #define SCREEN_HEIGHT 128 
    // Use HW SPI (MOSI, SCK, MISO) and those pins
    #define DC_PIN   4
    #define CS_PIN   5
    #define RST_PIN  6
    // Color definitions
    #define    BLACK        0x0000
    #define    BLUE         0x001F
    #define    RED          0xF800
    #define    GREEN        0x07E0
    #define CYAN            0x07FF
    #define MAGENTA         0xF81F
    #define YELLOW          0xFFE0  
    #define WHITE           0xFFFF
    #include <Adafruit_GFX.h>
    #include <Adafruit_SSD1351.h>
    #include <SPI.h>
    Adafruit_SSD1351 tft = Adafruit_SSD1351(SCREEN_WIDTH, SCREEN_HEIGHT, &SPI, CS_PIN, DC_PIN, RST_PIN);
    GFXcanvas1 canvas(126, 58);
    bool MAGENTA_prim = true;
    void setup(void) {
    void loop() {
      // Only draw once and not on the canvas
      if(MAGENTA_prim == true) {
        tft.fillRoundRect(10, 59, 22, 10, 5, MAGENTA); 
        tft.fillRoundRect(98, 59, 22, 10, 5, MAGENTA);
        MAGENTA_prim = false;
      canvas.fillScreen(0);    // Clear canvas (not display)
      int randmouth1 = random(-4, 4);
      canvas.fillCircle(20, 27, 18, WHITE);
      canvas.fillCircle(17 + randmouth1, 24 + randmouth1, 4, BLACK);
      canvas.fillCircle(107, 27, 18, WHITE); 
      canvas.fillCircle(104 + randmouth1, 24 + randmouth1, 4, BLACK);
      // Talking
      int randmouth2 = random(7, 22);
      canvas.fillCircle(64, 41, 16, WHITE);
      canvas.fillRect(48, randmouth2, 33, 32, BLACK);
      tft.drawBitmap(0, 0, canvas.getBuffer(),
      canvas.width(), canvas.height(), BLACK, WHITE);

  • Laser cutting and engraving

    M. Bindhammer04/28/2023 at 15:54 1 comment

    Since I wanted the front of the tablet drum to be transparent, I had a corresponding disc laser cut from 3mm acrylic glass. I also had the symbols for the day and evening laser engraved.

View all 8 project logs

  • 1
    Step 1

    Detailed build instructions can be found under Details.

View all instructions

Enjoy this project?



estepsandra881 wrote 08/12/2023 at 18:44 point

Wow, it's impressive! Appreciate you sharing the project.

  Are you sure? yes | no

Ben wrote 05/25/2023 at 15:31 point

This is cool. Hopefully  we can see future iterations ( bigger capacity (perhaps touch screen instead of voice). I have a hero device- it is great but $35 per month. It is quite complicated inside and break s every year or 2 . An opensource DIY option would be amazing. It could allow those who can't afford something like the hero to take care if it's advantages- better mediation adherence- one of the major contributors to bad outcomes in patients. 


  Are you sure? yes | no

M. Bindhammer wrote 05/25/2023 at 16:27 point

Thanks! I've also thought about a larger drum driven by some sort of planetary gear. I chose the voice because I want the robot to remind me acoustically until I have taken my medication. Unfortunately, that's all I can get out of this $15 Chinese text-to-speech module. The touch screen is no problem, small TFT displays with touch functions have been around for many years. Daily use will show what needs to be improved as well.

  Are you sure? yes | no

mrpendent wrote 05/19/2023 at 14:39 point

Is it loaded manually, or can it load from a hopper? I've considered something like this, but I want to be able to dump the pills in and let it dole them out. I just haven't been able to figure out how to load the cell without potentially crushing a pill that lands wrong.

  Are you sure? yes | no

M. Bindhammer wrote 05/19/2023 at 16:21 point

The drum is loaded manually, then at the push of a button the drum moves one chamber at a time, either clockwise, or if you prefer, counterclockwise.

  Are you sure? yes | no

mrpendent wrote 05/19/2023 at 16:59 point

Well it looks great! Thanks for posting the project.

  Are you sure? yes | no

craig wrote 05/11/2023 at 05:09 point

You wouldn't want the tablets to dispense until prompted by the person taking them. To do otherwise risks the tablet being taken by child or pet.

Ideally the cover for the tablet tray should be easy to open, but child proof, and could only be opened when horizontal. Not sure how this could be done.

I wonder if there is enough room for a tablet tray with four spaces per day?

I wouldn't bother with the speech synthesis. I think there are cheap I2C mp3 player modules, which would provide a better quality of output.

  Are you sure? yes | no

M. Bindhammer wrote 05/11/2023 at 05:49 point

The tablets are dispensed only at a certain time. The robot was designed specifically for my disease. I take 100mg in the morning, 600 mg in the evening. Also, I think TTS is better than an mp3 player, so the robot is highly configurable. I thought about using a fingerprint sensor instead of the touch sensor, but my daughter is old enough and our cat would never eat the medicine.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates