Introduction

Final project that I am thinking is small but consists of most of the process that we had learned in the process during this Fab Academy. Hence due to this COVID restrictions, I tried to finalize my project with Medicine Dispenser which I am Naming as Fab Med Dispenser with model Name FMD-VO signifying version 0.

The main purpose of the proposed system is to help patients, mainly seniors and elderly people, take their medications on time in an easy manner without the possibility of skipping pills and thus reducing the risk of accidental over/under dose treatment. Failing to take medications promptly can have serious consequences on patients including delay in recovery, occurrence of other illness and even death.

Problem statement

People with busy schedule, elderly people and people who forget often needs Fab Med Dispenser because they often forget or tend to do so due to either age of their schedule or priority which when forgetten will or might effect your health or the effectiveness of your medication.

Target Uses

  1. Elderly people
  2. People who are absent minded
  3. In general, all who use medication.

Designed for following aspects
1. Reliability
2. Compactness
3. User friendly
4. Assembly
5. Modularity

Device specifications
1. Size: 83mm (L) X 50mm (W) X 107mm (H) (H: 241mm with cartridge)
2. Power: 5V 
3. Medicine per cartridge: 15 (Can be expanded as per requirement)
4. Tablet type: circular (13mm dia X 4.5 mm thick)

In the Box (Master): 
1. Dispenser
2. Magnetic Tray
3. 5V adapter
4. Cartridge with lid
5. Hopper with lid 

In the Box (Secondary)
1. Dispenser
2. Connector


Process during fabrication


Process Used:
1. 2D Design
2. 3D Design
4. Electronics Design
5. Embedded programming

Machines Used
1. Laser Cutter
2. 3D printer
3. PCB milling machine
4. Vinyl Cutting

I used miro board for planning the project. It is very easy way to plan the process and for managing it. It can also be used for collaboration. I used KanBan template for my project planning

fablab_planning_project

We can also export the whole planning to excel file as well.

Planning

Main planning for the working mechanism
1. Will be using servo motor for powering the whole mechanism. 
2. Scotch yoke mechanism will be used to dispense the Tablets
3. Wifi Enabled microcontroller will be used.
4. Signal will be given when medicine is dispensed via hall sensor.


CAD design (2D and 3D)


First thing to do was limiting myself with design constraints as we cannot design for everything at once. So i selected the tablet size for the design. As paracetamol tablet was cheapest to test so everything that is designed hereafter are for the tablets of size (13mm dia X 4,5 mm  thick).

Selection of mechanism for dispensing:
Then for the selection of the mechanism, I referred to different models among which most has used the horizontal orientation of the tablet. But, I was not happy with it. The reason is that. If the minimum cross-section is not used while sorting then there might be a possiblity of two meds getting stuck in the outlet

Mechanism_1

Hence I decided to go with the smallest cross-section that the tablet has and designed accordingly. Now for linear reciprocating motion for the ejection of the tablet, there were options like directly using servo arm to push the medicine. Or rotary motion which moves the tablet in rotation ad ejects when there is an outlet in the rotation path. However dew to space and design concept, I decided to use the Scotch yoke mechanism which converts the rotary motion of the servo to the linear motion. And this was just perfect for me

Scotch_yoke


As we were in lockdown for 2 months During that time I focused on the 3D design and animation from where i can get some insights if there might be some problem. Following are the initial sketch of the models

Design_sketch2
3D skecth
mobile_stand
Components Allocation Sketch
Mechanism
Mechanism sketch

Selection of Mechanism:
I reviewed different mechanisms which uses 

Then the 3D design was done so that animation can be done and simulated to know about the feasilibility. Following are the screenshots of the first iteration of the model

3D model
CAD model
render_prototype1
Rendered Model

Then after the CAD Designing and modeling was done, I exported the STL file to blender to use physics and see how it performs when animated, I used only gravity for the medicity. Main casing as the domain and added reciprocating motion to the slider which gave the following result.

blender

While I was designing the body, I was also parallely designing the cartridge, I am thinking about using the transparent acrylic sheet and lasercut it and then assemble to make a cuboidal hollow part. The reason for making it transparent was that the tablets could be seen from out and when it is empty, can be refilled again. And using laser cutter, if is faster for fabrication as well as the length of the cartridge can be increased as per our requirement as well.

So after the Lab was open, Time to protoype the mechanism first. So, as I wanted to have as much tablets in the cartridge, I had to find the spot up to which it can be kept in zig-zag position. So i wanted to test the width of the cartridge first with the just the dispensing part.

Then I made the dxf file from from the 3D CAD design and following the process, laser cut was done in 3mm acrylic sheet. First time since it was just a test, red acrylic was cut.

cartridge
3D model for cartridge
laser_prototype
2D files for Laser cut
laser_cut_prototype
After laser cut

Following this, 3D printing just for the specific sliding mechanism was done to test the smoothness of the slides and also the cartridge. 

buffer_3d
Slider+cartridge case
3D_slicing
Slicing the prototype
mask_holder
3D printed slider + case

Following this, testing was done for from where there were some times when the tablets were stuck. Then a space was made from the laser cutter itself and then placing the prototype from where I found the problem and aslo the actual width that should be used for the cartridge. 

Opening
with_spacer
sorting

problem during testing

Then after placing spacers the dimension for the cartridge was found to me 18mmX 5mm (Inside dimension). FInally the slider and mechanism was working fine that you can see on the following. Then a transparent acrylic was cut for the final as well.

final_cartridge
mechanism_working_fine

Then after the mechanism was done, the issue that i had was how to hold the medicine during loading to the product. So i was thinking so complex but simplicity is the key and simpler the design better it is. so I came up with simple idea to add autolocking part which can just be inserted in the laser cut acrylic while assembly. The design is shown in the following figures. Here the add on should lock on six different locations in one full rotation however we don't need that much

cartridge_lock
Stopper
loading

Parallely, Main casing design was done where the tested mechanism was included and other things like motor placement was considered on the first prototype of the casing. The purpose of this was to install all mechanical and moving part in casing from which i can move to electronics. Here first, the testing was done with motor orientation longitudionally.

PROT_2_FRONT
PROT_2_BACK

Parallelly, as it was hard to put tablets one at a time, I designed a hopper with a lid. This will be given to the consumer with the master unit. This will only be used when the user loads the medicine. Same hopper can be used for multiple modules.
For designing the lid, A U type cantilever snap joint was taken as reference. the 3D hopper and Lid can be seen below

hopper
Hopper_up
Hoppper_section

After everything was design, it was exported to stl file and the slicing was done with higher layer thickness as this was a prototype. Then all the parts were printed.

3DP_1_prototype

Parts were taken out and assembled, and servo motor was also installed and for the lever from the motor, I 3D printed part which goes to the motor and also stick into the slider of the dispenser.

Casing 1
Main casing
lid
Lid for hopper
Hopper
Hopper

Here I found out that the motor also can be rotated 90 or placed laterally, hence making the space more compact and product small as well as provide rigidity to the motor while operation. Hence, I reflected it in the final one. Then I tested the dispenser by giving power to the motor and yes it was working, It took time to tune the servo for the best overlap for intake and exit holes but finally, mechanical testing was a success.

with Hopper
Cartridge with hopper
all assembled
All mechanical components assembled
Mech_test

Electronics Design


After the mechanical design had been 90% completed, I moved to electronics design. In electronics design, I had planned using ESP-32, a buzzer, a servo motor obviously for powering the mechanism, a hall sensor as an input and i2c for the communication to make it modular. And for the secondary, I planned to use same devices but in place of ESP32, I will be using Attiny 412 as a secondary module.

First thing to do is study and know abut ESP32 and the pins which i will use for different IO devices and communication. Following is the pin diagram for ESP32

ESP32-pinout

Then, I started with eagle, and started the schematics straight where hall sensor component, buzzer, servo unit with leds and ESP32.

buzzer_unit
position_sketch
5V to 3v3
ESP_sche

Here slide was inserted because in flashing ESP32 we have to keep on pressing while the program is uploading so it is good to have SPDT switch and a push button on the boot or reset button. Also since ESP32 works on 3.3, a voltage regulator is added. For servo and hall sensors, pads are made so that THT type male pin header can be inserted here and the servo and hall sensor can be connected from back. (Update: I forgot to add pullup resistor on the board for I2C while fabrication so added it on the secondary, but it is always good to have it in master so updated the board putting 5K resistors as a pull up resistor for SDA and SCL)

Similarly for buzzer as well, two hole were made for the rivets so that it can be soldered from back. Then the ERC was clicked which gave couple or warning and errors, I was panicking at that point but, every thing was OK and could be approved. 

ERC_final

Then after all the schematics is OK I then switched to the board. Then set up the design rules of 16 mil and then was arranged. Luckily, Saheen made a library for ESP32 processor which can be milled by 16 mill bit. I was also doing an i2c connection here, so added 4.99K resistor and 4 pins for communication to the secondary boards. After lots of auto route rearrangement, manual route I finally came up though the route and placed two places to clamp the board.

ESP32Final_DRC
DRC_ESP

Following are the traces and the trim line for the master board

Trim_ESP32
Trace_ESP32

Similarly, Schematics for the hall sensor module was done. Here 5V to 3.3V logic level converter was used since the supply voltage for the hall sensor was 4.5V to 5.5V. 

ERC_hall_master
Hall_master_sche

Then after all the schematics is OK I then switched to the board. Then set up the design rules of 16 mil and then was arranged.

Hall_master_module
DRC_hall_master

Following are the traces and the trim line for the master board

Trace_hall_master
Holes_hall_master
Trim_hall_master

Here holes and trim is separated because, when it is sent together, it cuts the trim line and cuts the hole, during which the board moved. Hence, like other manufacturing process as well, trim has to done at last.

Similar to this secondary bards have been done for output week which you can goto from this link. Meanwhile, I have imported the schematics, board traces and trims for your reference.

Main secondary board:

schematics_network
board_network
trace_network
Trim+hole_network

Hall Sensor module with indicator LED for secondary product,

Sec_hall_board
Sec_hall_schem
Trace_sec_hall
drill_sec_hall
trim_sec_hall

Following are the list of components that I will be using for the boards

Master-Main board

  1. ESP-32 X 1
  2. 10K ohm resistor   X 2
  3. 4.99K ohm resistor   X 2
  4. 1K ohm resistor X 1
  5. 10uF Capacitor   X 1
  6. 1uF Capacitor X 1
  7. 0.1uF Capacitor X 1
  8. MOSFET N-Channel
  9. 5 to 3.3 Voltage regulator   X 1
  10. 2x2 header pin   X 1
  11. FTDI header pin X 1
  12. 1x3 THT header pin X 1
  13. 1x4 THT header pin X 1
  14. SPDT switch X 1
  15. Tactile switch X 1
  16. Buzzer X 1
  17. Connection Jack 2.1mm X 1
  18. Servo Motor X 1

Master-Hall module

  1. Hall effect sensor X 1
  2. MOSFET N-Channel X 1
  3. 10K ohm Resistor X 2
  4. 1K ohm Resistor X 1
  5. 1uF Capacitor X 1
  6. Blue Led THT X 1
  7. 1x4 THT header pin X 1

Secondary- main board:

  1. ATtiny 412 X 1
  2. 10K ohm resistor X 1
  3. 1K ohm resistor X 1
  4. 4.99K ohm resistor X 1
  5. 1uF Capacitor X 1
  6. MOSFET N-Channel X 1
  7. 2x2 header pin X 2
  8. 1x3 THT header pin X 2
  9. Buzzer X 1
  10. Servo Motor X 1

Secondary - Hall module

  1. Hall effect sensor X 1
  2. 1K ohm Resistor X 1
  3. Blue Led THT X 1
  4. 1x3 THT header pin X 1

After the Design and export for electronics design was done, parallely, 3D modeification is done where boss and other shapes are added to secure the location of the board, from PCB milling process, it is shown in fabrication process below.

Since the mechanical design was already tested, I wanted to confirm the electronics part first so I did milling first. The png file for the traces, holes and trim line after exported it cut on the copper board with the help of Models via mods platform. You can know the details of the process is electronics production from the link here

Mods_final
final_mill
Stuffing-soldering

After all the parts are milled, components as listed above were collected from the inventory and stuffed into each board and the master and secondary boards with hall module looks line below.

Master_pair
Master Board+hall module
Secondary_pair
Secondary Board + hall module

Here you can see jumper wires on the the Main master board which will be explained in the programming and debugging section.


Programming, Debugging and testing


It started with understanding ESP32 first. Here, first the datasheet of ESP32 was studied earlier while deciding [igs. Noe since all parts are there, I started with Node MCU first which I had used during testing the mechanism. So step by step I used program each component.

First connecting to WiFi.

#include <WiFi.h>

const char* ssid = "iPhone"; //WiFi Name
const char* password = "NMF123!!!"; // WiFi Password

void setup()
{
Serial.printf("Connecting to %s ", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" CONNECTED");
}

void loop()
{
delay(500);
}

Now getting time from the NTP server. Here i have tried to convert everything to seconds so that i can compare only actual seconds to the seconds set by the user to dispense the tables.

#include <WiFi.h>
#include <SPI.h>
#include <NTPClient.h>
#include <WiFiUdp.h>

const char* ssid = "iPhone"; //WiFi Name
const char* password = "NMF123!!!"; // WiFi Password

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "1.asia.pool.ntp.org", 19800);

void setup()
{
Serial.printf("Connecting to %s ", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" CONNECTED");
}

void loop()
{
timeClient.update();
int h = timeClient.getHours();
int m = timeClient.getMinutes();
int s = timeClient.getSeconds();
int actsec = h * 3600 + m * 60 + s;
Serial.print(h);
Serial.print(":");
Serial.println(m);
Serial.println(actsec);
delay(500);
}

Now time to connect output device. First i took servo as this was the first thing needed to test the mechanism. Here the servo pin is connected to pin 14 on the board. I kept the servo in a function as it will be easy moving on the project.

#include <WiFi.h>
#include <SPI.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <Servo_ESP32.h>

#define servoPin 14 //printed G14 on the board
Servo_ESP32 servo1;


int angle = 0;
int angleMin = 0;
int angleMax = 180;
int angleStep = 1;

int med_qty = 0;

const char* ssid = "iPhone"; //WiFi Name
const char* password = "NMF123!!!"; // WiFi Password

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "1.asia.pool.ntp.org", 19800);

void setup()
{
Serial.begin(115200);
servo1.attach(servoPin);
//connect to WiFi
Serial.printf("Connecting to %s ", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" CONNECTED");
}

void loop()
{
timeClient.update();
int h = timeClient.getHours();
int m = timeClient.getMinutes();
int s = timeClient.getSeconds();
int actsec = h * 3600 + m * 60 + s;
Serial.print(h);
Serial.print(":");
Serial.println(m);
Serial.println(actsec);
dispense(10);
delay(500);
}

void dispense(int med_qty) {
for (int i = 1 ; i <= med_qty; i++) {
for (int angle = angleMin; angle <= angleMax; angle += angleStep) {
servo1.write(angle);
Serial.println(angle);
delay(20);
}
delay(100);

for (int angle = angleMax; angle >= angleMin; angle -= angleStep) {
servo1.write(angle);
Serial.println(angle);
delay(20);
}
delay(100);
}

Now the servo was tested and tuned to the required angle for smooth operation where the minimum angle came out to be 100 and maximum 170. Then time to test hall sensor and buzzer. For the hall sensor, I have to know the range or characterstics of the hall sensor, Hence first it was tested, but the value I had received was so unreliable. Sometimes it was jumping up and sometimes down even where there was no magnet. I tried just hall sensor only but was working fine. I was using analog read as i wanted to set alarm according to distance of magnet. Using hall sensor only I found the spot for me, i.e if the value is less than or equal to 3500 set the alarm or set it off. However, When i tried to combine it with other part of code, it does not work. 

#define hall 12

void setup()
{
pinMode(hall, INPUT);
}

void loop()
{
Serial.println(analogRead(hall));
delay(500);

I spend whole day just for finding out what is wrong. I tried digital read. I tried deleting and adding each part of program and finally found out that the pin that is connecting to hall sensor does not work when ESP32 is connected to WiFi. May be it is the problem with the inbuilt library but according to the forum and answers of people, ADC2 does not work for hall sensor when it is connected to WiFi. Only pins GPIO 34, 35, 36, and 39 can be used for analog reading. Here is the link to the forum. Then I disconnected the connection from the pin 12 and used jumper wire to connect that trace to pin. and uploaded all the code with Wifi anf finally it was working fine. Then for buzzer, I wanted to just have a strobe kind meaning just on off in a delay as it is an alarm to have tablets. Here buzzer is connected to Pin 27 and hall in Pin 35 (via jumper wire).

#include <WiFi.h>
#include <SPI.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <Servo_ESP32.h>

#define servoPin 14 //printed G14 on the board
#define buzzer 27
#define hall 35
Servo_ESP32 servo1;


int angle = 100;
int angleMin = 100;
int angleMax = 170;
int angleStep = 1;

int med_qty = 0;

const char* ssid = "iPhone"; //WiFi Name
const char* password = "NMF123!!!"; // WiFi Password

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "1.asia.pool.ntp.org", 19800);


void setup()
{
Serial.begin(115200);
servo1.attach(servoPin);
pinMode(buzzer, OUTPUT);
pinMode(hall, INPUT);
//connect to WiFi
Serial.printf("Connecting to %s ", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" CONNECTED");
}

void loop()
{
timeClient.update();
int h = timeClient.getHours();
int m = timeClient.getMinutes();
int s = timeClient.getSeconds();
int actsec = h * 3600 + m * 60 + s;
Serial.print(h);
Serial.print(":");
Serial.println(m);
dispense(med_qty);
while (analogRead(hall) <= 3500) {
buzz();
}
delay(500);
}

void dispense(int med_qty) {
for (int i = 1 ; i <= med_qty; i++) {
for (int angle = angleMin; angle <= angleMax; angle += angleStep) {
servo1.write(angle);
Serial.println(angle);
delay(20);
}
delay(100);

for (int angle = angleMax; angle >= angleMin; angle -= angleStep) {
servo1.write(angle);
Serial.println(angle);
delay(20);
}
delay(100);
}
}

void buzz() {
digitalWrite(buzzer, 1);
delay(100);
digitalWrite(buzzer, 0);
delay(100);


User Interface


In first cycle, I am using Blynk application for setting time, quantity and model number for the secondary as well.. As this application is easy to use and have been used in other IOT devices, I decide to use it for the first phase and during the futher development of the product, dedicated application can be made from platforms like AppInventor, Thunkable, etc. There is a simiilar platform that is offered by arduino as well which you can try from this link.

Blynk

About Blynk

Blynk IoT platform offers a full suite of software allowing to prototype, deploy, and remotely manage connected electronic devices at any scale: from small IoT projects to millions of commercial connected products. With Blynk, you can connect hardware to the cloud and use pre-made app modules to build iOS, Android, and web applications ready for the end-users. In short, Blynk is an “Internet of Things” (IoT) platform that allows you to build your own apps to control certain devices over the internet.

Steps for using Blynk
It is very easy to use Blynk. First you have to download the application from app store if you are an iPhone user of google play if you are using android. I am using iPhone so will be giving example on that one. After you download the application see the step below how I created the application

New_Project
Main Page. Click on the new project
Setting
Now add name of you project and select the device. For me it was ESP32 Dev board
Authentication
As soon as you create the project, authentication token will be sent which you will use in coding
Authentication
You will see the blank page which where you can now add different widgets. Just press on the screen anywhere 
Authentication
You will now see the given list of widgets from which you can select the required one. For me it was Time Input
Authentication
Here the widget select is the one which send data to the device. The data is sent to the device via virtual pin. You can set virtual pin and will be used while coding.

After arranging different widgets here and there you will get to the layout suitable for you. For me the layout shown below was the required one.

FAB_GUI

Linking Programming and GUI pins 


First the main program is opened and install the blynk library which you can download from this link. Then ass the library on your Arduino IDE. you can also get different example using this link where you can select between your boards as well as programs from this link. Now after everything is set on the mobile, get your authentication code and note the virtual pin that you have selected. Then the code from the previous step was edited to test blynk.

#include <WiFi.h>
#include <SPI.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <Servo_ESP32.h>
#include <BlynkSimpleEsp32.h>
#include "time.h"

#define servoPin 14 //printed G14 on the board
#define buzzer 27
#define hall 35
Servo_ESP32 servo1;


int angle = 100;
int angleMin = 100;
int angleMax = 170;
int angleStep = 1;

int med_qty = 0;
int buttonState = 0;
int setsec1 = 0;
int setsec2 = 0;
int setsec3 = 0;

char auth[] = "CXPXe4FBMq3APKm3-9C0hI5wrK1lKW5x";

const char* ssid = "iPhone"; //WiFi Name
const char* password = "NMF123!!!"; // WiFi Password

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "1.asia.pool.ntp.org", 19800);



void setup()
{
Serial.begin(115200);
Blynk.begin(auth, ssid, password);
servo1.attach(servoPin);
pinMode(buzzer, OUTPUT);
pinMode(hall, INPUT);
//connect to WiFi
Serial.printf("Connecting to %s ", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" CONNECTED");

}

void loop()
{
timeClient.update();
int h = timeClient.getHours();
int m = timeClient.getMinutes();
int s = timeClient.getSeconds();
int actsec = h * 3600 + m * 60 + s;
Serial.print(h);
Serial.print(":");
Serial.println(m);
Blynk.run();
if (actsec == setsec1 || actsec == setsec2 || actsec == setsec3 || buttonState == 1) {
dispense(med_qty);
while (analogRead(hall) <= 3500) {
buzz();
}
}
delay(500);
}

void dispense(int med_qty) {
for (int i = 1 ; i <= med_qty; i++) {
for (int angle = angleMin; angle <= angleMax; angle += angleStep) {
servo1.write(angle);
Serial.println(angle);
delay(20);
}
delay(100);

for (int angle = angleMax; angle >= angleMin; angle -= angleStep) {
servo1.write(angle);
Serial.println(angle);
delay(20);
}
delay(100);
}
}

void buzz() {
digitalWrite(buzzer, 1);
delay(100);
digitalWrite(buzzer, 0);
delay(100);
}

BLYNK_WRITE(V0)
{
med_qty = param.asInt(); // assigning incoming value from pin V1 to a variable
}

BLYNK_WRITE(V1) {
TimeInputParam t(param);

if (t.hasStartTime())
{
Serial.println(String("Start: ") +
t.getStartHour() + ":" +
t.getStartMinute() + ":" +
t.getStartSecond());
setsec1 = (t.getStartHour() * 3600) + (t.getStartMinute() * 60) + t.getStartSecond();
}
}

BLYNK_WRITE(V2) {
TimeInputParam t(param);

if (t.hasStartTime())
{
Serial.println(String("Start: ") +
t.getStartHour() + ":" +
t.getStartMinute() + ":" +
t.getStartSecond());
setsec2 = (t.getStartHour() * 3600) + (t.getStartMinute() * 60) + t.getStartSecond();
}
}

BLYNK_WRITE(V3) {
TimeInputParam t(param);

if (t.hasStartTime())
{
Serial.println(String("Start: ") +
t.getStartHour() + ":" +
t.getStartMinute() + ":" +
t.getStartSecond());
setsec3 = (t.getStartHour() * 3600) + (t.getStartMinute() * 60) + t.getStartSecond();
}
}

BLYNK_WRITE(V4)
{
buttonState = param.asInt(); // assigning incoming value from pin V1 to a variable
}

Here you can see the virtual pins being used under BLYNK_WRITE(V0) and similarly for other pins and the program was working for all the pins as set on the application.

Then I added the i2c connection where address "8" was given to the secondary boards and then the code was added and here from the GUI i programmed that the address should also be inserted by the user according to the module they buy. Hence following is the final code that I made for the main board or master board.

#include <WiFi.h>
#include <SPI.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <Servo_ESP32.h>
#include <BlynkSimpleEsp32.h>
#include <Wire.h>
#include "time.h"

#define servoPin 14 //printed G14 on the board
#define buzzer 27
#define hall 35
Servo_ESP32 servo1;


int angle = 100;
int angleMin = 100;
int angleMax = 170;
int angleStep = 1;

int med_qty = 0;
int buttonState = 0;
int setsec1 = 0;
int setsec2 = 0;
int setsec3 = 0;

int med_qty_sl1 = 0;
int buttonState_sl1 = 0;
int model1 = 0;
int setsec4 = 0;
int setsec5 = 0;
int setsec6 = 0;

int med_qty_sl2 = 0;
int buttonState_sl2 = 0;
int model2 = 0;
int setsec7 = 0;
int setsec8 = 0;
int setsec9 = 0;

char auth[] = "CXPXe4FBMq3APKm3-9C0hI5wrK1lKW5x";


const char* ssid = "iPhone"; //WiFi Name
const char* password = "NMF123!!!"; // WiFi Password

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "1.asia.pool.ntp.org", 19800);


void setup()
{
Serial.begin(115200);
Blynk.begin(auth, ssid, password);
servo1.attach(servoPin);
pinMode(buzzer, OUTPUT);
pinMode(hall, INPUT);
//connect to WiFi
Serial.printf("Connecting to %s ", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" CONNECTED");
Wire.begin();

}

void loop()
{
timeClient.update();
int h = timeClient.getHours();
int m = timeClient.getMinutes();
int s = timeClient.getSeconds();
int actsec = h * 3600 + m * 60 + s;
Serial.print(h);
Serial.print(":");
Serial.println(m);
Blynk.run();
Serial.println(setsec1);
if (actsec == setsec4 || actsec == setsec5 || actsec == setsec6 || buttonState_sl1 == 1) {
Wire.beginTransmission(model1);
Wire.write(med_qty_sl1);
Wire.endTransmission();
}

if (actsec == setsec7 || actsec == setsec8 || actsec == setsec9 || buttonState_sl2 == 1) {
Wire.beginTransmission(model2);
Wire.write(med_qty_sl2);
Wire.endTransmission();
}

if (actsec == setsec1 || actsec == setsec2 || actsec == setsec3 || buttonState == 1) {
dispense(med_qty);
while (analogRead(hall) <= 3500) {
buzz();
}
}
delay(500);


}

void dispense(int med_qty) {
for (int i = 1 ; i <= med_qty; i++) {
for (int angle = angleMin; angle <= angleMax; angle += angleStep) {
servo1.write(angle);
Serial.println(angle);
delay(20);
}
delay(100);

for (int angle = angleMax; angle >= angleMin; angle -= angleStep) {
servo1.write(angle);
Serial.println(angle);
delay(20);
}
delay(100);
}
}

void buzz() {
digitalWrite(buzzer, 1);
delay(100);
digitalWrite(buzzer, 0);
delay(100);
}

BLYNK_WRITE(V0)
{
med_qty = param.asInt(); // assigning incoming value from pin V1 to a variable
}

BLYNK_WRITE(V1) {
TimeInputParam t(param);

if (t.hasStartTime())
{
Serial.println(String("Start: ") +
t.getStartHour() + ":" +
t.getStartMinute() + ":" +
t.getStartSecond());
setsec1 = (t.getStartHour() * 3600) + (t.getStartMinute() * 60) + t.getStartSecond();
}
}

BLYNK_WRITE(V2) {
TimeInputParam t(param);

if (t.hasStartTime())
{
Serial.println(String("Start: ") +
t.getStartHour() + ":" +
t.getStartMinute() + ":" +
t.getStartSecond());
setsec2 = (t.getStartHour() * 3600) + (t.getStartMinute() * 60) + t.getStartSecond();
}
}

BLYNK_WRITE(V3) {
TimeInputParam t(param);

if (t.hasStartTime())
{
Serial.println(String("Start: ") +
t.getStartHour() + ":" +
t.getStartMinute() + ":" +
t.getStartSecond());
setsec3 = (t.getStartHour() * 3600) + (t.getStartMinute() * 60) + t.getStartSecond();
}
}

BLYNK_WRITE(V4)
{
buttonState = param.asInt(); // assigning incoming value from pin V1 to a variable
}

BLYNK_WRITE(V5)
{
model1 = param.asInt(); // assigning incoming value from pin V1 to a variable
}

BLYNK_WRITE(V6)
{
med_qty_sl1 = param.asInt(); // assigning incoming value from pin V1 to a variable
}

BLYNK_WRITE(V7) {
TimeInputParam t(param);

if (t.hasStartTime())
{
Serial.println(String("Start: ") +
t.getStartHour() + ":" +
t.getStartMinute() + ":" +
t.getStartSecond());
setsec4 = (t.getStartHour() * 3600) + (t.getStartMinute() * 60) + t.getStartSecond();
}
}

BLYNK_WRITE(V8) {
TimeInputParam t(param);

if (t.hasStartTime())
{
Serial.println(String("Start: ") +
t.getStartHour() + ":" +
t.getStartMinute() + ":" +
t.getStartSecond());
setsec5 = (t.getStartHour() * 3600) + (t.getStartMinute() * 60) + t.getStartSecond();
}
}

BLYNK_WRITE(V9) {
TimeInputParam t(param);

if (t.hasStartTime())
{
Serial.println(String("Start: ") +
t.getStartHour() + ":" +
t.getStartMinute() + ":" +
t.getStartSecond());
setsec6 = (t.getStartHour() * 3600) + (t.getStartMinute() * 60) + t.getStartSecond();
}
}

BLYNK_WRITE(V10)
{
buttonState_sl1 = param.asInt(); // assigning incoming value from pin V1 to a variable
}

BLYNK_WRITE(V11)
{
model2 = param.asInt(); // assigning incoming value from pin V1 to a variable
}

BLYNK_WRITE(V12)
{
med_qty_sl2 = param.asInt(); // assigning incoming value from pin V1 to a variable
}

BLYNK_WRITE(V13) {
TimeInputParam t(param);

if (t.hasStartTime())
{
Serial.println(String("Start: ") +
t.getStartHour() + ":" +
t.getStartMinute() + ":" +
t.getStartSecond());
setsec7 = (t.getStartHour() * 3600) + (t.getStartMinute() * 60) + t.getStartSecond();
}
}

BLYNK_WRITE(V14) {
TimeInputParam t(param);

if (t.hasStartTime())
{
Serial.println(String("Start: ") +
t.getStartHour() + ":" +
t.getStartMinute() + ":" +
t.getStartSecond());
setsec8 = (t.getStartHour() * 3600) + (t.getStartMinute() * 60) + t.getStartSecond();
}
}

BLYNK_WRITE(V15) {
TimeInputParam t(param);

if (t.hasStartTime())
{
Serial.println(String("Start: ") +
t.getStartHour() + ":" +
t.getStartMinute() + ":" +
t.getStartSecond());
setsec9 = (t.getStartHour() * 3600) + (t.getStartMinute() * 60) + t.getStartSecond();
}
}

BLYNK_WRITE(V16)
{
buttonState_sl2 = param.asInt(); // assigning incoming value from pin V1 to a variable
}

Secondary Coding

For coding secondary the same code will be used for all the secondary board hence produced but the address should be changed according to the sticker that will be pasted on the model which will be cut by vinyl cutter.

Following is the code that will be used.

#include <Wire.h>
#include <Servo.h>
#define buzz 4
#define hall 1
Servo myservo;

volatile bool flag = 0;
volatile int val = 0;
int angle = 0;

void setup() {
Wire.begin(8); // please use the address mentioned in the product
Wire.onReceive(receiveEvent);
pinMode(buzz, OUTPUT);
myservo.attach(0);

}

void loop() {
if (flag) {
for (int i = 1; i <= val; i++) {
for (angle = 128; angle <= 180; angle += 1) {
myservo.write(angle);
delay(20);
}
delay(100);
for ( angle = 180; angle >= 128; angle -= 1) {
myservo.write(angle);
delay(20);
}
delay(100);
}
while (analogRead(hall) <= 300) {
digitalWrite(buzz, 1);
delay(100);
digitalWrite(buzz, 0);
delay(100);
}
flag = 0;
}
}

void receiveEvent(int howMany) {
val = Wire.read();
flag = 1;
}

After everything is pushed, and can see the product operating as per expected. The connection and test is shown in the figure below.. Now time to add everything together.


Putting everthing all together


After electronics was designed before fabrication I had to add a way to clamp the board to the casing. As during the electronics design, two hole were made in the feasible area for makin
g the boss, Here I have to get the 3D data of the board which will be easier for making corresponding fitting part in the casing. 

Then, I opened fusion 360 where i went to electronics design and then imported the *.brd file. after the board file is open there might be different errors that you might see due to mismatch of the libraries. However when you click on the 3D PCB in the top left area of the window, you can get a 3D model of your PCB which then can be used to make casing. This is a very handy for making synchronized design and makes it more efficient and easy as well.

Elex_design_fusion
Open fusion and open the New Electronics Design
Import_brd
Press open in file and select the board you have made
to_3DPCB
Press on view 3D PCB on the left top area of the window.
3DPCB
You will then see the 3D of your PCB designed in Eagle
3DPCB_export
To use it on other CAD right click on the part, hit export
to_3DPCB
Now you can select format, and export (I used step)
master_PCB_import
3D PCB imported in master
secondary_PCB_import
3D PCB imported in secondary

After adding the components, to 3D, boss was added in both master and secondary. the a locking tray is added at the base for the main board. However, for the hall sensor module at bottom, I made a slide type insertion design on the casing. and same for the secondary. Then also added slots for magnets so that it can be used for magnetic tray and for connecting modules

boss_master
2 boss for master board
boss_secondary
2 boss for secondary board
boss_secondary
slide lock for master/secondary board
Master_hall_slide
Slide type slot for hall sensor for master module
Secondary_hall_slide
Slide type slot for hall sensor for secondary module
magnetic_slot
slot for magnets

While doing so, i also had to add cover for the whole casing. SO for that I wanted to reduce as much screws as possible so i tried making a slide type lock in the bottom and then 4 screws, two at bottom and two at the top with some snap fit latch in th middle

slide_type_fit
Slide type assembly and lower screws
Top_screws
Top screws
snap_latch
Snap fit latches 4 places
CAD FInal
Final CAD model
rendered
Rendered in Keyshot

Fabrication and assembly


After everything was designed, time for fabrication, the main cartridge is already mage during the design while testing. following are the design files and how it look

hands-free_handles_poster
3D cardtridle
final_laser_cartridge
final cartrige design
laser-cartridge
after fabrication and assembly

Hopper, hopper lid, cover, casing and the back cover of casing was left for printing in prusa and ultimaker

printing hopper
casing_cover
magnetic_tray
servo_hall
magnetic_tray
servo_add
servo_hall_2
packed
packed
packed
i2C_top
i2C_front

Adding magnetic tray and making connector


Now for magnetic tray, I wanted to test live hinge from the beginning, So I was trying to incorporate it in my product. Then i Thought of using the transparent laser cut top with magnetic bottom for the tray. Then i tried designing the live hinge, failed couple of time and then finally came up with the design which can just flex and form as per my requirement. the hardest part for me was to find out actual final dimension it would be after bending. But through multiple trials and errors, I was able to cut and assemble in 2mm transparent acrylic.

Laser_cut_live_hinge
Laser cut for magnetic tray
Magnet_insert_3DP
Magnet insert while 3D printing
final_tray
Tray final

I also made a connector pins that would go between master and secondary for connecting it by i2c communication.

Connection_pin

Finally the design


master_front
Master front
master_back
Master back
secondary_front
Secondary front
Secondary_back
Secondary back
Assembled_front
Assembled front
Assembled_back
Assembled back
final_final

Develop a website with Mobirise