"Dr. Pablo" Smart Medication Dispenser

by Massimo De Bock in Circuits > Raspberry Pi

166 Views, 1 Favorites, 0 Comments

"Dr. Pablo" Smart Medication Dispenser

back.png

Dr Pablo is your companion for a better life, helping you remember to take your medication.

It's specially designed to work for multiple patients, primarily thinking of a retirement home.

Supplies

  • Raspberry Pi
  • Keypad | Membraan 4x4 Matrix keypad switch (OT2023-B116)
  • Rfid reader | RFID-RC522 NFC Kit MFRC522 S50 Mifare incl. RFID Fudan Card en Key Tag (OT705-D81)
  • Touch sensor
  • Servo SG90
  • LCD display
  • Raspberry Pi power supply
  • Breadboard
  • Breadboard power supply
  • Jumper cables
  • led
  • Active buzzer
  • Stepmotor and controller
  • 12V Power Transformer

Wire It All Up

These pds should show how to wire up everything.

Database

EERD.png

Here you can see the Enhanced Entity-Relationship (EER) diagram, I'll go over some that might need clarification

Creating it in this order should also cause no issues with foreign keys.


MedicationType:

Name: holds the name of the medication

Description: holds a description of the medication

UserInfo:

PhoneNumberResponsible: the phonenumber that should be called in case of emergencies.

RFID: holds the id of the badge of the person, if it is empty the touchsensor can be used instead.

MedicationIntake:

Time: the time that the medication should be taken on

Patient: links to a UserInfo id, holds the person that should take the medication

TypeId: link to a MedicationType id, hold what medication linked to this intake

Status: tells you if it was taken, in the process of being taken or is scheduled to be taken in the future

Delay: the delay a person had till they took the medication in minutes

RelatedDoctorId: links to DoctorInfo, tells you which doctor prescribed the medication.

Dosage: holds the dosage for each intake

ComponentType:

This is needed if more components of the same type get added, for now it doesn't add much purpose, does make future expansion possible

Name: the name of the component type, like: Stepmotor, Servomotor,..

Category: Is it an actuator or a sensor?

Unit: the measurement it uses

ComponentValue:

Logs all actions with components, both actuators and sensors.

SettingsProfile:

This was here for loging in purposes, however it fell out of the scope so it has no purpose for now.

Setup

Before we can get started with coding we might have to do some preparations

Repository

First make sure we close a repository from github, or any other you might like.

Virtual Environment

Create a new virtual environment by first opening a python file (not needed but can help)

go to the console and execute

on windows

py -m venv venv_fswd

or on mac

python3 -m venv venv_fswd

close the current terminal and open a new one, this should tell you that it's using the venv.

Install the necessary packages

on windows

pip install -r ./requirements.txt

or on mac

pip install -r requirements.txt


Database

There should be a config_example.py, copy this one and call it config.py and change it to your needs.

Happy Coding Time (Components)

image_2023-06-18_182159170.png

Take a look

Class_StepMotor.py

Just initiate it with with the address that the linked pcf is on, they should be connected to pin 4-7

on turn you can tell it how much it has to turn 1 direction, you can change the direction by using negative numbers.

Class_ServoMotor.py

Decide what PWM pin you use in the init, after that just use set_angle(angle) to set an angle.

Class_TimedFunction.py

Don't want to keep adding a manual timer for every function that should only be run at certain intervals? just set the frequency here and the function that should be used and it's taken care off.

Class_TimeOutableFunction.py

With this you can disable a function for a certain amount of time.

Class_TouchSensor.py

This should be self-explanatory and works like a regular button, CheckJustPressed and CheckJustReleased can be used to check if they were just changed. the moment you call 1 of these the next time they won't be justpressed or released. Save the output don't keep requesting it.

Class_RFID.py

This is just a wrapper around SimpleMFRC522, every id will only be output once, a constant scan wont be shown.

Class_PCF.py

Handles the use of a PCF

Class_Keypad.py

The keypad uses the pcf to lower the amount of pins being used. all columns are active untill it notices any button is being pressed, once that happens check all columns individually till the exact button is idintified.

Happy Coding Time (LCD)

image_2023-06-18_180247632.png

While also being part of components this one deserves its own section.

take a look

Class_LCD.py

LCDinstructions: All instructions that can be send to the lcd that are well supported for this class, you can still execute others if you need them.

LCDFormatting: all the formatting options currently available.

LCDScrollOptions: Used for choosing in which way you want to move things, you can '|' to concatenate options.

LCD_Monitor(): The init method, give it the rsPin and pulsePin, and a formatSetting incase you want it to wrap to the next line

SendInstruction(): used to send commands

AddText(): concatenates to the text on chosen line

ChangeText(): Clears the text that's currently there and inserts new text without automatically rewriting and resetting the scroll index

RewriteMessage(): The same as ChangeText() but with the option to adjust the data instantly.

WriteMessage(): The same as AddText() but always rewrites() without the scroll index reset.

DoubleWrite(): Change both lines at once.

PromptInput(): asks a question on the command line and put that on the screen, great for testing.

SetScrollSpeed(): changes how fast it will scroll.

SetScrollSpacing(): The amount of spaces that should be done when wrapping back to the beginning on a scrolling line.

RewriteDisplay(): sends all lines again to update changes.

UpdateDisplay(): Mainly handles the scrolling parts, and calls RewriteDisplay if needed.

Happy Coding Time (MedicationHandler)

Take a look

MedicationHandler.py


LCDModes: tells you which mode the LCD is in, since you can change it between 4 different ones, each showing different info.

Region LCD: Initiates my lcd and sets some settings, which ill go over in the lcd section.

Cleanup: Cleans the pins on delete, keeping the pins on isn't a good practice.

Update: the main code getting called over and over again, it calls all other updates that need to happen

HandleTouchSensor: when the touch sensor just went from unpressed to pressed look if the next medication is due, if so and it doesn't have an id assigned to it drop the medication

HandleCodeRequests: if the code that is requested is valid execute it.

HandleKeyPad: handles the keypad, incase a code was entered execute it if it is linked to something, or if A-D is pressed change the LCDMode

HandleReader: Runs ReadRFID()

ReadRFID: if the rfid reads anything look if the id is that of the medication that should currently be taken, if so drop it.

CodeInput: stores the most recent requested code from the frontend, (not instantly checked to avoid data being send at the same time.

CheckCodes: execute the actions linked to a certain code

...

Set...Return: saves the functions of app.py so they can be used later, this is needed to communicate with the frontend on its own terms

SetScanReturnId: tells you where the next rfid id should be send to.

HandleNextMedication: does all logic to see when the next medication is, if it's now let the user now,...

DepositeMedication: execute all that is needed for the medication to be rolled out.

RecheckMedication: Empty all data related to the next medication so they will be requested automatically.

ChangeLCDMode: changes the mode the lcd is in

Log...: Put info here that that happens.

Happy Coding Time (Backend)

Now we go over the backend

Take a look

app.py

This is where all of the code starts, it holds all routes, socketio and also thread that holds the actual code.

First we initiate SocketIO

isBreadboardPowered(): Keeps checking if we can find the PCF, if we can't the breadboard isn't connected and check again later till we find it. This prevents us from having the need that the breadboard gets powered before the RPI

Then we initiate a medicationhandler and stop it. This is done in an if True to have its scope controlled. Why this gets done is to ensure we have a clean shutdown, since when we stop the service this isn't guaranteed.

After that we initialize the actual MedicationHandler object

In the end we then start a thread that keeps forcing the MedicationHandler to update till it gets told to stop.


Note:

change the flask secret.

Frontend

image_2023-06-18_182609414.png
image_2023-06-18_182625236.png

Having an interface might be nice, so let's do that now. We mainly want to make sure we can easily add new medication reminders, adding new medication would also be nice.

There was a boilerplate provided to us which allowed for quicker creation of a decent looking site, I can heavily recommend using one of you want to do all steps yourself.

Encase you also want the titles of text fields to move, follow these instructions

Making Pablo Some Clothes

image_2023-06-18_184421701.png
image_2023-06-18_184437526.png
image_2023-06-18_184517111.png
image_2023-06-18_184229550.png
image_2023-06-18_184246479.png

Now we will give the project some nice housing. I ended up shifting from my original plans of 3d printing one due to the size of the model, however the files are still included to do so if you want to.

Dress Pablo Up

image_2023-06-18_185528162.png
image_2023-06-18_185547755.png
image_2023-06-18_185514339.png
image_2023-06-18_185252470.png
image_2023-06-18_185319801.png
image_2023-06-18_185452939.png
image_2023-06-18_185329005.png
image_2023-06-18_185339142.png

After finishing step 6 you should now be ready to wire everything up in the new housing. Before you do this make sure all the wiring works the way it should, also add some tape to ensure the wires don't suddenly get messed up.

Enjoy Your New Companion

Front.png
back.png

Hopefully you made it to the end successfully,

if not you can always leave down comments and I will do my best to clear problems up.


Thanks for taking this journey with me.