"Dr. Pablo" Smart Medication Dispenser
by Massimo De Bock in Circuits > Raspberry Pi
166 Views, 1 Favorites, 0 Comments
"Dr. Pablo" Smart Medication Dispenser
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
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)
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)
While also being part of components this one deserves its own section.
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)
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
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
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
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
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
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.