In recent weeks the fight against Covid-19 has seen both an exponential demand for key medical equipment and an array of restrictions imposed on global manufacturing and supply chains, resulting in a debilitating shortage of necessary healthcare provisions; inhibiting the capacity of health services to treat patients with potentially catastrophic consequences.
The scale of this urgent and fundamental need has provoked a global collaborative effort to design, validate, and manufacture ventilators, replacement parts, and personal protective equipment (PPE). These efforts are vast, ranging from household names such as Dyson and Airbus, commissioned with the redesign and production of ventilators for governments, to FabLabs, Universities, and individuals using their own design and rapid manufacturing capabilities to develop and share designs for open-source ventilators, replacement components, and PPE.
At the DMF Lab our expertise lies in optimising designs for new manufacturing technologies. So, in true form, we are demonstrating a method for low cost open-source ventilators and other key equipment to be easily and rapidly manufactured using a laser cutter and selection of standard components.
3D printing is a very capable and user-friendly technology, but it’s notoriously slow compared to modern manufacturing techniques. Redesigning to faster technologies vastly reduces manufacture time; switching to laser-cutting for our design reduces fabrication from 12hrs+ with a 3D printer to under 20 minutes, all from a single sheet of plastic!
This means increased production using only a single machine from 1 per day to more than 20.
We want to share our designs and our knowledge. Anyone is free to take our design, and we will share our knowledge with anyone looking to improve their own. If you have designs that are reliant on 3D printing, want to reduce manufacture time, or want to design for laser cutting and frugal manufacture, please get in touch!
All design details including CAD files and controller code are set out below, along with a video outlining the concept and process of assembly for rapidly manufactured laser cut designs.
Feel free to develop and share our designs, improve them further and join the global collaborative efforts to develop emergency devices and equipment.
If you would like to know more, share ideas, or get help with your designs, please contact hello@dmf-lab.co.uk.
The Methodology
Additive manufacturing (AM), widely known as 3D Printing is the process of building three-dimensional objects from a digital model by depositing material in a layer-by-layer fashion. The process allows parts previously impossible to manufacture, featuring internal geometry and complex surfaces to be fabricated with high accuracy by numerically controlled machines. However, as a tool for the production of manufactured goods the technologies widespread adoption has so far been limited by its time intensive layering process to high value applications such as aerospace.
By adopting a methodology of part creation through 2D profile assembly, components can be redesigned for industrial rapid manufacturing processes such as laser cutting, exponentially reducing manufacturing time to meet supply demands.
Our prototype ventilator is an example of the bag valve mask (BVM) design currently being researched for emergency use. The design can be laser cut from a single sheet of A3 paper sized material and assembled with standard M3 fasteners (standard nuts and bolts) in under 20 minutes.
This modular approach to prototyping further aids the process of development from concept to production line through its ability to rapidly implement design changes and substitute singular elements, iteratively optimising the performance of a prototype against a set of design requirements.
In conjunction with our proposed framework for the rapid manufacture of laser cut supplies we have also developed an open-source interface and circuit to enable plug-in Arduino control of different motor driven configurations.
The code allows motor parameters including, speed, travel and interval times for a stepping motor to be directly edited through a user interface to define and empirically test motor control settings. The code can be easily edited to add or remove parameters by copy and pasting blocks.
Whilst accessibility to laser cutters is predominantly confined to industry and academic institutions, we’re currently working on a set of tools to streamline the process of part generation for 2D profile assembly and cross-platform prototyping.
The first tool, automatically generates a male or female mounting profile for standard metric fasteners, given bolt length, size and material thickness. whilst the second, optimises a 2D profile for additive manufacture, allowing efficient cross-platform development of two-dimensional components.
Code;
//DMF-LAB University of Bristol - Prototpye Ventilator test interface
//Ricardo Real
#include<Wire.h>
#include<LiquidCrystal_I2C.h>
#include <AccelStepper.h>
//LCD Address
LiquidCrystal_I2C lcd(0x27, 16, 2);
//Stepper Motor Pins
#define dirPin 8
#define stepPin 9
#define motorInterfaceType 1
// Create a new instance of the AccelStepper class:
AccelStepper stepper = AccelStepper(motorInterfaceType, stepPin, dirPin);
//Encoder Pins
#define clk 2
#define dt 3
#define sw 4
//Logic
volatile boolean TurnDetected;
volatile boolean up;
boolean doonce = 0;
char screen = 0;
boolean changestate = 0;
//Encoder Logic
void isr0 () {
TurnDetected = true;
up = (digitalRead(clk) == digitalRead(dt));
}
//Interface Parameters (Motor Speeds, Acceleration, Distance)
//Edit or add additional parameters for your set-up
int motorspeed = 400; //stepspersec (1Rev = 200steps (step angle 1.8))
int strokeinterval = 1000; //millis //
int stepcount = 200; //how many steps the motor moves
void setup() {
//define pinMode Encoder
pinMode(sw, INPUT_PULLUP);
pinMode(clk, INPUT);
pinMode(dt, INPUT);
//interrupt service routine
attachInterrupt(0, isr0, RISING);
//Set maximum Motor speed (stepspersec)
stepper.setMaxSpeed(1000); //1000 stepspersec = 5 revolutions
//LCD Start routine
lcd.begin();
lcd.backlight();
lcd.setCursor(0,0);
delay(1000);
lcd.print("DMF-LAB UoB");
delay(3000);
lcd.setCursor(0,1);
lcd.print("Motion Controller");
delay(3000);
lcd.clear();
}
void loop() {
// Rotary encoder control of menu screen and value editing
if (TurnDetected) {
delay(200);
doonce = 0;
if (changestate == 0) {
if (up) {
screen++;
if (screen > 3) {
screen = 3;
}
}
else {
screen = screen -1;
if (screen < 0) {
screen = 0;
}
}
}
else {
if (up) {
switch (screen) {
case 0: motorspeed = motorspeed + 10; // value encoder changes default by
break;
case 1: strokeinterval = strokeinterval + 50;
break;
case 2: stepcount = stepcount + 10;
break;
}
}
else {
switch (screen) {
case 0: motorspeed = motorspeed - 10; // value encoder changes default by
break;
case 1: strokeinterval = strokeinterval - 50;
break;
case 2: stepcount = stepcount - 10;
break;
}
}
}
TurnDetected = false;
}
if (digitalRead(sw) == LOW) { //Low = encoder button pressed
delay(200);
changestate = !changestate; //Default state 0, button pushed = not 0
doonce = 0;
}
if (screen == 0 && doonce == 0) {
lcd.clear();
lcd.print("M-Speed");
lcd.setCursor(0, 1);
lcd.print(motorspeed);
lcd.setCursor(3, 1);
lcd.print(" Steps Sec");
if (changestate == 0) {
lcd.setCursor(11, 0);
lcd.print("EDIT?");
}
doonce = 1;
}
if (screen == 1 && doonce == 0) {
lcd.clear();
lcd.print("tDelay -/+");
lcd.setCursor(0, 1);
lcd.print(strokeinterval);
lcd.setCursor(4, 1);
lcd.print(" ms");
if (changestate == 0) {
lcd.setCursor(11, 0);
lcd.print("EDIT?");
}
doonce = 1;
}
if (screen == 2 && doonce == 0) {
lcd.clear();
lcd.print("Travel +/-");
lcd.setCursor(0, 1);
lcd.print(stepcount);
lcd.setCursor(3, 1);
lcd.print(" steps");
if (changestate == 0) {
lcd.setCursor(11, 0);
lcd.print("EDIT?");
}
doonce = 1;
}
if (screen == 3 && doonce == 0) {
lcd.clear();
if (changestate == 0) {
lcd.print("Run cycle?");
doonce = 1;
}
//-----------------------------------------------------
else {
lcd.print("Motor ON");
delay(strokeinterval);
lcd.setCursor(0,1);
lcd.print("<<---->>");
delay(50);
stepper.setCurrentPosition(0);
while(stepper.currentPosition() != -stepcount)
{
stepper.setSpeed(-motorspeed);
stepper.runSpeed();
}
delay(500);
stepper.setCurrentPosition(0);
while(stepper.currentPosition() != stepcount)
{
stepper.setSpeed(motorspeed);
stepper.runSpeed();
}
delay(strokeinterval);
}
}
}