3D printed medicine vial rack

giik 3D printed medicine vial rack
🏥
We present a practical and economical solution for creating a custom-made medicine vial rack with the help of 3D printing technology. In the article, you will find a programming script to create your own medicine vial rack.

In healthcare settings like primary care surgeries or hospital wards, medical personnel use medicines in vials on a daily basis. Vials are small glass or plastic containers with medication in liquid or powder form. Depending on the scope of work and protocols, each workplace must always have a sufficient amount of specific medicine vials.

Usual storage and use of medicine vials

A large number of medicines come in vials. Vials are produced in several different sizes (diameter and height), and have diverse labels with basic information about the drug. Furthermore, identical drugs are sometimes made by various manufacturers. Medicine is usually packed in cardboard boxes with different number of vials, most often 5 or 10.

Example of a drug in vials in a cardboard package
Example of a drug in vials in a cardboard package

Vials are often stored in their original boxes in the hospital pharmacy or another designated area. However, a smaller amount of vials is also stored where the drugs are administered, such as the doctor's office or the intensive care unit, to allow immediate access. Even in this case, medicines are often stored in their original packaging, for example in cupboards with glass doors or closed containers.

Such practice has numerous disadvantages, and sometimes can contribute to mistakes endangering patients' health. Some of the problems that arise due to a non-functional storage of vials are:

  • difficulty in searching for a specific medicine,
  • poor stock insight,
  • variable position of a specific medicine,
  • susceptibility of choosing the wrong medicine, etc.

This can result in unreliable stock (too many or too few vials in stock, expiration date, etc.), loss of time when looking for medicine, greater risk of drug shortages, use of the wrong vial or the one which is out of date.

Example of a dysfunctional organisation of vials on a cabinet shelf in doctor's office
Example of dysfunctional organisation of vials on a cabinet shelf in doctor's office

There are solutions on the market to organise vials in the form of containers or cabinets, and even robotic systems for automatic handling. Such solutions have many advantages, but also disadvantages - they are expensive, and thus inaccessible to most surgeries, and as a rule are not portable, at least not for field work.

Challenge: design and 3D print a custom made medicine vial rack for a doctor's office

Motivation to develop our vial storage solution came from the need to organise medication in Fiumed clinic from Croatia. Fiumed incorporates a family medicine practice, which needs vials of various medication in different quantities.  

Our primary goal was to create a simple, affordable and reliable mode of organising medicine vials in Fiumed clinic. In addition, we wanted to offer an open-source solution for creating tailor-made vial racks, which can be adapted to different stations, furniture and users.

Theoretical and scientific basis

Although this problem might appear trivial at first glance, a lot of scientific papers have been published dealing with medication organisation to improve workflow and avoid errors. There are different approaches based on the environment and use cases (e.g.  intensive care unit vs emergency department vs family medicine practice). Their common goal is to propose medication storage solutions which meet the following requirements:

  • vials should be clearly visible, including medication names, easily accessible, and allow quick assessment of stock,
  • vials should not be stored in closed boxes, which saves time needed to open the packaging,
  • individual medication should ideally always be in the same place,
  • should be impossible to store individual vials in the wrong place.

Requirements of Fiumed clinic

Fiumed staff decided to place their medicine vials in two lockable drawers. The drawers are located inside a cabinet in the nurse's room and are easily accessible during regular work, but also in case of an emergency.

The type and quantity of medicine vials has been determined by analysing:

  • local requirements and protocols for mandatory medication in every family medicine practice,
  • additional drugs used by trained personnel for specific treatments,
  • the number of patients served by the clinic, and the dynamics of consumption of individual drugs.

Methods

3D modelling and prototyping

After gathering information about the dimensions of the drawers and the number, type and dimensions of the vials, we started creating our first 3D models and prototypes. In order to provide a better user experience and usability, and because of the particularity of 3D printing technology, we decided on a modular rack instead of making it in one piece.

We divided our vial storage solution into 24 modules of identical external dimensions and shape. Each module stores a particular number of vials of one medication. When combined, modules fit perfectly into drawers.

We perfected the design of our base module through a series of iterations with corrections and practical tests of 3D printed prototypes. After defining the basic design of our vial module, i.e. its external appearance and dimensions, we further shaped individual modules by adapting them to the vials of each drug. For this task, we used the OpenSCAD app.

OpenSCAD

3D model of our vial rack can be drawn in almost any 3D modeling software. However, in our case we had over 20 medicines with vials of different dimensions and required quantities. This means that we had to draw many different modules, with a preferably regular and visually logical arrangement of the slots. At the same time, any change in the basic characteristics of the module, i.e. its dimensions or individual details (shape, inscriptions, slanted sides, etc.) is reflected differently on individual modules.

Modeling of each module with many variants would be laborious and time-consuming in a typical 3D modeling software. This is why we decided on OpenSCAD, which is slightly different. It is a free, open-source application available for all computer platforms. Apps key feature is that you do not draw 3D models by using the mouse (or a similar device) or ready-made predefined basic geometric shapes, as with most such programs, but by programming, i.e. mathematical creation of 2D and 3D shapes, their modification, translation, merging, subtraction, multiplication and similar operations, which is why OpenSCAD is called "The Programmers Solid 3D CAD Modeller".

Prior knowledge of programming is not necessary to use OpenSCAD, but it is desirable and advantageous. We think that it is even more important to have a slightly better knowledge of spatial geometry and a mathematical "feel" for 3D drawing.

Using this tool comes down to writing code, that is, scripts with commands. Its scripting language contains a series of commands for creating basic 2D and 3D shapes, for their "drawing", moving and similar geometric operations, and classic programming commands such as repeating loops, branching, variables and arrays, mathematical operations and operations on character strings. A short list of all commands and functions can be found on the CheatSheet page, and their use is described in detail with examples in the user manual.

Here, we will not explain in detail the use of OpenSCAD. We will only explain how we "programmed" our medicine vial rack, that is, how the script written in OpenSCAD works to generate all of its modules. We published our script as open source under the GPLv3 license. This means it can be freely studied, used and modified, with reference to the source and author.

Script for creating 3D models of a medicine vial rack

You can copy the script below and run it in the OpenSCAD application. By running the script, i.e. starting the rendering, you will get a complete model with all modules used to store vials in Fiumed clinic. It can be saved in a standard STL format for printing on any 3D printer, including popular home printers.

We used Prusa Mini and Creality Ender-3 printers for 3D printing. Printing one module took about 5.5 hours, but we printed two modules in one go. Since the complete rendering takes about 5 minutes (depending on your computer) and takes up about 1.2 GB of RAM, the Preview option can be used for a quick preview of the model, and works almost instantly.

You can easily modify the script by changing its parameters such as the dimensions of the module itself and the number and dimensions of the vial slots. There are short comments in the script with explanations, and here are the important bits:

  • line 8 to 32 - array containing a list of vials, their quantity in the corresponding module, diameter and height, and any corrections of the slot depth; by updating this list, it is possible to generate modules for almost any vials;
  • line 34 to 65 - the basic dimensions of one module, its inscription slot, module holder and other features are defined, whereby certain dimensions are calculated relative to the primary ones; these parameters can be changed to match different dimensions of drawers, cabinets or boxes for placement of vial racks;
  • line 69 to 121 - loop which draws one module for each medication from the list, where the basic module is always the same, only different slots are made, which are automatically calculated depending on the quantity and dimensions of the vials so that the layout is always symmetrical and optimal;
  • line 125 to 195 - a hollow module is made based on the basic module for holding suppositories and similar medication, with a suitable cover.
💡
With the same code, an arbitrary amount of modules with different vial slots can be quickly created by simply modifying the list of medication and the basic parameters of the module (with certain restrictions such as the largest vial size or quantity).
// Medicine vial rack
// GIIK for Fiumed
// V3.2 October 2022
// info@fiumed.hr
// Released under GPLv3 licence

// vials list: name, qty, diameter in cm, height in cm, hole depth correction
vials_list = [
    ["Adrenalin",5,1.2,5.1,0],
    ["Amiodaron",4,1.6,6.9,0],
    ["Atropin",5,1.2,4.7,0],
    ["Aminophylline",4,1.9,8.5,0],
    ["Calcium glukonat",3,2.3,8.5,0],
    ["Dexamethason",10,1.2,4.7,0],
    ["Diazepam",10,1.2,5.7,0],
    ["Diklofenak",10,1.4,6.2,0],
    ["Furesemid",6,1.2,5.8,0],
    ["Flumazenil",2,1.6,6.8,0],
    ["Haloperidol",5,1.2,4.7,0],
    ["Hiosicin butilbromid",10,1.2,6,0],
    ["Ketoprofen",10,1.2,5.7,0],
    ["Kloropiramin",10,1.2,5.4,0],
    ["Lidokain",5,1.6,6.9,0],
    ["Metoklopramid",8,1.2,5.9,0],
    ["Morfin klorid",2,1.2,6,0],
    ["Nalokson",5,1.2,6,0],
    ["Promazin",3,1.2,6,0],
    ["Propafenon",2,2.4,10.1,-3],
    ["Tietilperazin",6,1.2,4.7,0],
    ["Tramadol",6,1.2,5.6,0],
    ["Solu-medrol",4,2.4,6.4,7]
];

// vials params in mm
vial_max = 101;
vial_min = 47;

// box params in mm
box_width = 130;
box_length = 60;
box_height = 40;
bottom_width = box_width*0.85;
bottom_length = box_length*0.85;

// label area
label_width = box_width*0.5;
label_length = box_length*0.24;
label_hole = 2;
label_distance = 2;
text_distance = 9.5;
text_height = 0.5;

// handles - dimensions and base distance
handle_radius = 15;
handle_thickness = 2.5;
handle_offset = 9;

// holes area
holes_width = box_width*0.8;
holes_length = box_length*0.75;

// container box params
container_dist = 4;
cover_height = 3;
cover_clearance = 0.5;

// drawing code
// loop for each vials box in the list
for(v=[0:len(vials_list)-1]) {

    // vials calculations
    vial_diameter = vials_list[v][2]*10;
    vial_height = vials_list[v][3]*10;
    vial_qty = vials_list[v][1];
    vial_rows = vial_diameter*1.3*vial_qty < holes_width ? 1 : 2;
    vial_in = vial_max/3+vials_list[v][4];
    hole_area = holes_width/(vial_qty/vial_rows);

    // move away each drawn box
    translate([0,(box_length+10)*v,0]) {
        difference() {
            // one box
            union() {
                // bootom part of the box
                linear_extrude(2*box_height/3,scale=[box_width/bottom_width,box_length/bottom_length])
                    square([bottom_width,bottom_length],center=true);
                // upper part of the box
                translate([0,0,2*box_height/3])
                    linear_extrude(box_height/3)
                        square([box_width,box_length],center=true);
                // handles
                translate([0,-box_length/2+handle_offset/2,box_height])
                    rotate([90,0,0])
                        linear_extrude(handle_thickness)
                            circle(d=handle_radius,$fn=100);
                translate([0,box_length/2-label_length-label_distance,box_height])
                    rotate([90,0,0])
                        linear_extrude(handle_thickness)
                            circle(d=handle_radius,$fn=100);
            }
            
            // label hole
            translate([0,box_length/2-label_length/2-label_distance,box_height-label_hole])
                linear_extrude(label_hole,scale=[1,0.8])
                    square([label_width,label_length],true);
            
            // label hole vial identification number
            translate([0,box_length/2-text_distance,box_height-label_hole-text_height])
                linear_extrude(0.5)
                    text(str(v+1),halign="center",valign="center",$fn=100);
            
            // vial holes
            for(n=[0:vial_qty-1]) {
                r = n < round(vial_qty/vial_rows) ? 0 : 1;
                i = n % ceil(vial_qty/vial_rows);
                translate([i*hole_area+hole_area/2-holes_width/2+(vial_rows-1)*(r*2-1)*(hole_area/4),(holes_length/(1+vial_rows))*(r+1)-box_length/2,box_height-vial_in])
                    cylinder(vial_in,d=vial_diameter,true,$fn=100);
            }
        }
    }
}

// empty container box with cover

translate([0,-(box_length+10),0]) {
    
    // container box
    
    difference() {
        // box
        union() {
            // bootom part of the box
            linear_extrude(2*box_height/3,scale=[box_width/bottom_width,box_length/bottom_length])
                square([bottom_width,bottom_length],center=true);
            // upper part of the box
            translate([0,0,2*box_height/3])
                linear_extrude(box_height/3)
                    square([box_width,box_length],center=true);
        }
        
        // label hole
        translate([0,box_length/2-label_length/2-label_distance,box_height-label_hole])
            linear_extrude(label_hole,scale=[1,0.8])
                square([label_width,label_length],true);

        // container hole
        translate([0,0,container_dist]) {
            difference() {
                union() {
                    // hole bottom part
                    linear_extrude(2*box_height/3-container_dist,scale=[(box_width-2*container_dist)/(bottom_width-2*container_dist),(box_length-2*container_dist)/(bottom_length-2*container_dist)])
                        square([bottom_width-2*container_dist,bottom_length-2*container_dist],center=true);
                    // hole upper part
                    translate([0,0,2*box_height/3-container_dist])
                        linear_extrude(box_height/3)
                            square([box_width-2*container_dist,box_length-2*container_dist],center=true);
                }
                translate([0,box_length/2-label_length/2-label_distance,0])
                    linear_extrude(box_height)
                        square([box_width,label_length+label_distance*2],center=true);
            }
        }

        // cover hole
        translate([-(box_width-container_dist)/2,-(box_length/2-(handle_offset/2-handle_thickness)/2),box_height-cover_height])
            linear_extrude(cover_height)
                square([box_width-container_dist,box_length-(handle_offset/2-handle_thickness)/2-(label_length+label_distance)-cover_clearance]);
    }

    // cover with handles

    translate([0,-cover_clearance/2,10]) { // move cover above box
        difference() {
            union() {
                // cover plate
                translate([-(box_width-container_dist)/2+cover_clearance/2,-(box_length/2-(handle_offset/2-handle_thickness)/2)+cover_clearance,box_height-cover_height])
                    linear_extrude(cover_height)
                        square([box_width-container_dist-cover_clearance,box_length-(handle_offset/2-handle_thickness)/2-(label_length+label_distance)-2*cover_clearance]);
                // handles
                translate([0,-box_length/2+handle_offset/2-cover_clearance,box_height])
                    rotate([90,0,0])
                        linear_extrude(handle_thickness)
                            circle(d=handle_radius,$fn=100);
                translate([0,box_length/2-label_length-label_distance-cover_clearance,box_height])
                    rotate([90,0,0])
                        linear_extrude(handle_thickness)
                            circle(d=handle_radius,$fn=100);
            }
            // cut handle bottoms
            translate([-(box_width-container_dist-cover_clearance)/2,-(box_length/2-(handle_offset/2-handle_thickness)/2)+cover_clearance,box_height-cover_height-(handle_radius/2-cover_height)])
                linear_extrude(handle_radius/2-cover_height)
                    square([box_width-container_dist-cover_clearance,box_length-(handle_offset/2-handle_thickness)/2-(label_length+label_distance)-2*cover_clearance]);
        }
    }
}
OpenSCAD script for generating a 3D model of the complete medicine vial rack

A few images of rendered modules in OpenSCAD:

Fiumed medicine vial rack

Fiumed uses a total of 24 modules to store medication. In 23 modules, different medicine vials are stored. We made the 24th module later in the process. It has a larger container with a lid for storing medicines in the form of suppositories.

In Fiumed clinic, they arranged the medication in alphabetical order according to generic names. Drugs used in emergencies were additionally highlighted with red background on the name card.

The layout of the modules can be easily changed due to their uniformity. It is also possible to print the entire module in different colors than white. Modules are easily removed from the drawer, allowing for easy transport of medication.

Limitations

Dimensions of the slots on our modules are adapted to the respective vials. Larger vial cannot fit into a smaller slot. Smaller vial can fit into a larger slot, but the remaining free space around it signals that it does not belong there. The only real risk of wrong placement is with vials of the same dimensions but different medication. This problem is not solved by our approach, but risk is reduced to a minimum because there are few such vials. Risk is significantly lower compared to generic vial holders where all the slots are of the same dimensions or are elastic, so every vial can be stored anywhere.

When creating a module for an individual drug, we wanted to adapt the dimensions of the slot to the dimensions of the vial in such a way that it easily fits into the slot, but does not have significant room for movement. However, different manufacturers of the same drug sometimes use vials of different dimensions. Fortunately, this problem happens rarely, and can be avoided by ordering the drug from the same manufacturer. Nevertheless, even if a permanent change in the market occurs, all that is needed is to model and print just one new module with different slot dimensions.

Future improvements

During the development of our vial rack, we had some additional ideas for improving the basic model and the entire product.

Portability

Medical staff sometimes needs to use vials outside the practice, for example during home visits or emergencies. Usually, in these situations medical personnel use smaller portable vial holders in the form of pouches or cases. This requires an additional set of all or at least part of the vials available at all times for field work, which is not as common in family medicine as, for example, in EMS. This way of organisation represents a significant additional cost, not only because of the initial purchase, but also because of the higher probability of expiration of unused medication.

Our vial holders were made with the idea that they can be easily removed from the drawer, and that they also offer protection for the vials. For this reason, we are thinking about variations of the cover that could be used to close the individual module, so it can be placed in a medical bag and carried out of office with other equipment. The cover must be designed in such a way that it can be installed easily and quickly, provide protection against spillage and damage to the vials themselves, and be universal.

Smart medicine vial holders

We designed passive vial holders, without any advanced technology which would enable easier inventory maintenance and increase safety.

Sensors can be added to the modules inside the slots that could do multiple checks. One possible check is the presence of vials, which would allow automatic monitoring of the number of vials and transmission of a timely reminder about the need for restocking.

The second is to add an NFC tag to the vials, which would allow for a number of advanced features. With the NFC tag, each vial gets its own unique label, like a serial number. This means that every single vial can be tracked from the moment of receipt to the final moment of use or disposal. However, the main advantage would be achieved with an NFC reader in the vial slot itself. In this way, it would be possible to check whether there is a suitable vial in that slot (the correct medicine according to the label on the holder), but also in some way (with an LED light of the appropriate colour) to mark the vial with the closest expiry date and thus suggest to the staff to use it first. In this way, safety and economy would be further increased, i.e. optimal consumption of medicines.
Such a "smart" vial rack would be driven by electronic circuits and software in the form of mobile and/or web applications.

Online generator of 3D models

This project could be turned into an online service for generating 3D models of vial holders. Users would not have to work in the OpenSCAD application. On the website, users would define basic parameters such as module or drawer size and vial specifications according to their own needs. Web app would then generate an STL file ready for 3D printing. Interested?

Conclusion

For this project, we had a partner with a specific problem, which was screaming for a custom solution. We had some challenges along the way, but mainly we just had a lot of fun. Ultimately we are trilled that staff at Fiumed clinic are very happy with their new medicine storage solution.

If you came all the way down here, thanks! Please comment below the article with any question or suggestions for improvement. And yes, please let us know if you 3D printed your own medicine vial rack based on our script. That would be very cool.

Collaboration requests can be sent to info@giik.biz.