DIY_VENTILATOR
Designed and built a negative pressure ventilator , using materials like windshield wiper motor, PVC pipes and some scrap wood. This acts as a respirator that can support patients with COPD, Pneumonia and other respiratory diseases before they could reach the extreme condition of intubation. This is a breathing support that reduces the effort of lungs, oxygenates blood and increases heart efficiency by 25%. The highlight of this product is that it can be easily built by anyone and can help save lives of people who die from curable diseases, without the need of a respiratory therapist. A nurse or any family member of the patient will be able to do it.
Basically this is a negative pressure ventilator built from locally sourced scrap materials.
Downloads
MATERIALS REQUIRED
-
Windshield wiper motor -Mitsuba 12v - 02
-
PVC pipe - 110*1000mm
-
End cap - 110mm
-
½ inch drive hex Socket
-
Bearings - 608
-
Wood
-
Arduino Mega or UNO
-
Photodetectors -2
-
Relays
-
Resistors
-
IC driver - ULN2003APG
-
Fuse : 5 amps
-
Badminton strings
-
Tyre inner tube
-
Fevikwik
-
connecting wires
-
Switches
-
Philips head screws 4mm
-
Bolts and nuts 8mm , 6mm
-
20Ltr water can
-
Water hose
Making Layouts for the Frame
Take a print out of the given PDF in poster mode.Lay it out and stick it on the wooden board. Drill holes at specified points and cut on the given borders(using a jigsaw or a handsaw) to get the basic components of the ventilator body.
Optional: If you have access to a 2D router use the below DXF file to directly get the parts made on a router.
Directions to Assemble :
- Assembling supports (motor side and end cap side):
-
To make motor side supports, stick the big T and the small T, with 2 spacer blocks in between as shown below. Make 2 of these.
-
To make the end cap side supports, stick the L shaped parts with 3 spacer blocks in between as shown below.
- Screw the smaller circle part to the bigger part using M4x19 screws.
-
Screw the smaller circle part to the bigger part using M4x19 screws.
-
Insert a M8 bolt from the bigger circle side(bolt head on bigger circle side) and lock its position using a washer and nut
-
Hold the setup straight and firm. Add layers of sawdust and fevikwik over the bolt head to secure its position.
-
Sand the fevikwik sawdust wall to get a smooth surface .
-
Make 2 of these parts
- Remove the nuts from the other side of the bolt , add spacers and bearing. Position a nut at the tail of the bolt and weld it.( using fevikwik to hold this bolt in position helps too)
-
Attach these 2 parts , with the smooth surface being in contact with each other.
- Socket attachment to motor :
-
Motors usually come with an attachment like this. Cut it on this line. The right block of it will go on the motor shaft.
-
Cut a generic hex socket 15mm away from its hex end
-
Weld these parts together
-
Attach this part to the shaft of the motor using a 6mm nut.
- Piston making
-
Cut a PVC pipe of length-__mm
-
Remove a segment of width —-mm from above cylinder
-
Cut out 8 rings from PVC , each of width— and cut segment width ___
-
Position the longer PVC pipe inside another uncut PVC pipe. And stack the rings on it
- Remove the alternate rings and stick the other rings on the cut PVC pipe to make slots for other rings. Use a PVC solvent to stick the rings.
-
Wait for it to dry. Remove the piston setup from the PVC pipe and cut away the extra length of pipe.
- Limit switch
- Make a bridge from the wood cut pieces as shown in the image.
-
Attach the photodiodes on top of the bridge and secure it with screws.
- Cuirass
- Cut the top half portion of a 20 ltr water bottle.(approx 20cm from the top of the bottleneck)
-
Mark a curve to suit your chest and abdomen around the bottle
-
Cut it out from the bottle
-
You can use a hose from the kitchen sink or from a washing machine to connect the cuirass to the ventilator outlet.
- Endcap
- Mark 2 circles on the outside of the end cap .
-
Cut out the circles.
-
Cut rubber sheets in the shape of number 8 to cover the outlets.
- To attach a PVC pipe at the bottom hole, use the circular rubber cutouts. Place them on the circular hole on both sides of the endcap. Push the pvc pipe from the inside to outside and secure its position using feviquick.
-
Stick 8 shaped rubber cutouts from inside for the bottom hole and from outside for the top hole.
FINAL ASSEMBLY
- Lay flat the base.
- Screw in and fix the motor supports and the end pipe supports.
- Assemble the tension arm
- Connect the detector channel with the limit switches between these 2 supports.
- Screw in and secure the supports for the PVC pipe.
- Assemble the piston inside PVC and attach the end cap.
- Position the pvc pipe with the end cap.
- Attach the motors.
Electronics
Refer the schematic to understand the circuit.
Arduino Code
a setup
void setup() { // Serial.begin(115200); Serial.begin(115200); Serial.println("In setup"); //HD /* cli();//stop interrupts //set timer1 interrupt at 1Hz TCCR1A = 0;// set entire TCCR1A register to 0 TCCR1B = 0;// same for TCCR1B TCNT1 = 0;//initialize counter value to 0 // set compare match register for 1hz increments OCR1A = 15624;// = (16*10^6) / (1*1024) - 1 (must be <65536) // turn on CTC mode TCCR1B |= (1 << WGM12); // Set CS10 and CS12 bits for 1024 prescaler TCCR1B |= (1 << CS12) | (1 << CS10); // enable timer compare interrupt TIMSK1 |= (1 << OCIE1A); // sei();//allow interrupts */ // initialize the digital pin as an output. pinMode(13, OUTPUT); // digitalWrite(led, HIGH); //pinMode(vacuum_limit_switch, INPUT); //pinMode(return_limit_switch, INPUT); pinMode(motor_direction, OUTPUT); pinMode(enable_motor, OUTPUT); digitalWrite(enable_motor, MTR_STOP); pinMode(light_enable, OUTPUT); digitalWrite(light_enable, HIGH); pinMode(Vacuum_Limit_Sensor, INPUT_PULLUP); pinMode(Return_Limit_Sensor, INPUT_PULLUP); pinMode(Over_Run_Interrupt, INPUT); // attachInterrupt(digitalPinToInterrupt(Over_Run_Interrupt), piston_over_run_interrupt, LOW); // attachInterrupt(0, piston_over_run_interrupt, LOW); // playground(); // initialize_piston_position(); }
b loop
void loop() { Serial.println("In loop"); int val = 0; float inhale_time = 2000; float exhale_time = 3000; // playground(); // voltage(); do { if(Serial.available()){ //id data available val = Serial.read(); Serial.print("val = "); Serial.println( val); switch (val) { case 'r': //Run break; case 's': //Stop break; case 'l': //Toggle the lights LightToggle(); break; case 'd': //Read the contents of the EEPROM DataFromEEPROM(); break; case 'i': //Jog Up in Vacuum / exhale Direction Serial.println("I jog"); vacuum_jog(); if (serial_enabled) Serial.println("executed"); break; case 'e': //Jog Down in Return / Exhale Direction digitalWrite(13, HIGH); delay(1500); digitalWrite(13, LOW); // Serial.println("E jog"); delay(500); return_jog(); break; case 'R': //Run break; case 'S': //Stop break; case 'L': //Toggle the lights LightToggle(); break; case 'D': //Read the contents of the EEPROM DataFromEEPROM(); break; case 'I': //Jog Up in Vacuum / exhale Direction Serial.println("I jog"); vacuum_jog(); if (serial_enabled) Serial.println("executed"); break; case 'E': //Jog Down in Return / Exhale Direction Serial.println("E jog"); return_jog(); break; default: // if nothing else matches, do the default // default is optional if(val >= 110 && val <= 122) { // Calculate the Inhale time. exhale_time = val; if (serial_enabled) Serial.println("aaaaa"); if (serial_enabled) Serial.println(exhale_time); exhale_time -= 110; if (serial_enabled) Serial.println(exhale_time); exhale_time = exhale_time / 2 ; if (serial_enabled) Serial.println(exhale_time); exhale_time = exhale_time * 1000 ; //Change to milliseconds. if (serial_enabled) Serial.println(exhale_time); if (serial_enabled) Serial.println("bbbbb"); // digitalWrite(13, HIGH); //turn on delay(exhale_time); // digitalWrite(13, LOW); //turn on } else if (val >= 100 && val <= 106) { // Calculate the Exhale time. inhale_time = val; if (serial_enabled) Serial.println("yyyyy"); if (serial_enabled) Serial.println(inhale_time); inhale_time -= 100; if (serial_enabled) Serial.println(inhale_time); inhale_time = inhale_time / 2 ; if (serial_enabled) Serial.println(inhale_time); inhale_time = inhale_time * 1000 ; //Change to milliseconds. if (serial_enabled) Serial.println(inhale_time); if (serial_enabled) Serial.println("xxxxx"); // digitalWrite(13, HIGH); //turn on delay(inhale_time); // digitalWrite(13, LOW); //turn on } break; } } } while (val != 'R' && val != 'r'); // Serial.println("After the while"); val = 'R'; int run_time; // get_serial_data(); // Serial.println("At the do"); Serial.println("A"); do { move_to_vac_start_position(exhale_time); Serial.print("val1 = "); Serial.println(val); if(Serial.available()){ //Check for "S" Stop signal. val = Serial.read(); if (val == 'S'){ digitalWrite(13, HIGH); //turn on break; } val = 'R'; } Serial.print("val2 = "); Serial.println(val); create_vacuum_new(inhale_time); Serial.print("val3 = "); Serial.println(val); } while (val == 'R'); } void voltage(){ unsigned int Vin= analogRead(A2); float V_relle = ((Vin*(Tmax/1024))/coeff_pont); if (serial_enabled) Serial.print("V_relle"); if (serial_enabled) Serial.print(" : "); if (serial_enabled) Serial.println(V_relle); }
dm_create_vacuum_new.ino
void create_vacuum_new(int inhale_time){ int period = 200; unsigned long time_now = 0; bool vacuum_limit_switch_value = read_vacuum_limit_sensor(); // Serial.println("2.0"); //HD digitalWrite(motor_direction, MOTOR_DIRECTION_TO_CREATE_A_VACUUM); //HD // Serial.println("2.1"); //HD last_time = millis(); int start_time = millis(); TCNT1 = 0 ; //Reset Timer/Counter to zero start_interrupt_timer(); // Serial.println("2.2"); //HD digitalWrite(enable_motor, MTR_RUN); // Serial.println("2.3"); //HD last_time = millis(); int VacuumTravelDetector = 0; //Read the Vacuum_Limit_Sensor // Serial.println("2.4"); //HD do { VacuumTravelDetector = digitalRead(Vacuum_Limit_Sensor); } while(!VacuumTravelDetector); // Serial.println("2.5"); //HD digitalWrite(motor_direction, !MOTOR_DIRECTION_TO_CREATE_A_VACUUM); time_now = millis(); while(millis() < time_now + period){ } // Serial.println("2.6"); //HD digitalWrite(enable_motor, MTR_STOP); // Serial.println("2.7"); //HD temporarily_disable_ISR = true; last_time = millis(); int end_time = millis(); int remain_inhale_time = inhale_time - (end_time - start_time); if (remain_inhale_time > 0) delay(remain_inhale_time); // Serial.println("2.8"); //HD }
e_move_to_vac_start_position.ino
void move_to_vac_start_position(int exhale_time){
Serial.println("Move to vac."); int period = 100; unsigned long time_now = 0; // Serial.println("1.0"); //HD digitalWrite(motor_direction, !MOTOR_DIRECTION_TO_CREATE_A_VACUUM); // Serial.println("1.1"); //HD last_time = millis(); int start_time = millis(); TCNT1 = 0 ; //Reset Timer/Counter to zero start_interrupt_timer(); // Serial.println("1.2"); //HD digitalWrite(enable_motor, MTR_RUN); // Serial.println("1.3"); //HD last_time = millis(); int ReturnTravelDetector = 0; //digitalRead(Return_Limit_Sensor); int i = 0; // Serial.println("1.4"); //HD do { ReturnTravelDetector = digitalRead(Return_Limit_Sensor); } while(!ReturnTravelDetector); // Serial.println("1.5"); //HD digitalWrite(motor_direction, MOTOR_DIRECTION_TO_CREATE_A_VACUUM); last_time = millis(); time_now = millis(); // Serial.println("1.5"); //HD while(millis() < time_now + period){ } // Serial.println("1.6"); //HD digitalWrite(enable_motor, MTR_STOP); // Serial.println("1.7"); //HD temporarily_disable_ISR = true; last_time = millis(); int end_time = millis(); int remain_exhale_time = exhale_time - (end_time - start_time); if (remain_exhale_time > 0) delay(remain_exhale_time); // Serial.println("1.8"); //HD }
f_read_return_limit_sensor.ino
bool read_return_limit_sensor() {
bool switch_value; // Read in the ADC and convert it to a voltage: int proximityADC = analogRead(Return_Limit_Sensor); float proximityV = (float)proximityADC * 5.0 / 1023.0; if (serial_enabled) Serial.print("Ret "); if (serial_enabled) Serial.println(proximityV); //if (serial_enabled) Serial.println("#A");
if(proximityV > 3.5) { //Originally set at 1.0. Changed to 3.5 switch_value = false; } else { switch_value = true;
} //if (serial_enabled) Serial.println("#B"); // if (serial_enabled) Serial.println((String)"Voltage of return sensor = "+ proximityV);
return(switch_value); }
g_read_vacuum_limit_sensor.ino
bool read_vacuum_limit_sensor() {
bool switch_value; // Read in the ADC and convert it to a voltage: int proximityADC = analogRead(Vacuum_Limit_Sensor); float proximityV = (float)proximityADC * 5.0 / 1023.0; if (serial_enabled) Serial.print("Vac "); if (serial_enabled) Serial.println(proximityV); //if (serial_enabled) Serial.println("#A");
if(proximityV > 3.5) { //Originally set at 1.0. Changed to 3.5 switch_value = false; } else { switch_value = true;
} //if (serial_enabled) Serial.println("#B"); // if (serial_enabled) Serial.println((String)"Voltage of vacuum sensor = "+ proximityV); return(switch_value); }
h_back_pulse_the_motors.ino
void back_pulse_the_motors(int msec, bool reverse_motor_direction) {
//if (serial_enabled) Serial.println("In back pulse."); // if (serial_enabled) Serial.println(msec); // if (serial_enabled) Serial.println(reverse_motor_direction);
int period = msec; unsigned long time_now = 0; digitalWrite(motor_direction, reverse_motor_direction); while(millis() < time_now + period){ if(digitalRead(Over_Run_Interrupt) == 0) { //A zero voltage level inidicates that a limit switch has been tripped. The motor will be turned off and the program will be halted. digitalWrite(enable_motor, LOW); halt(); } }
}
i_get_serial_data.ino
void get_serial_data() {
if(Serial.available()){ //id data available int val = Serial.read(); switch (val) { case 'I': // digitalWrite(13, HIGH); //turn on vacuum_jog(); break; case 'E': // digitalWrite(13, LOW); //turn off return_jog(); break; default: // if nothing else matches, do the default // default is optional break; } } }
void LightToggle(){ light_state = !light_state; digitalWrite(light_enable, light_state); //Toggle the LED strip light. // digitalWrite(13, light_state); //turn on LED } /* void DataFromEEPROM(){ int R_address= E_address +1; for (E_address = 0; E_address < 10; E_address++ ) { // EEPROM.write(E_address, E_address+10); byte value = EEPROM.read(E_address); byte val2= EEPROM.read(R_address); if (serial_enabled) Serial.print(E_address); if (serial_enabled) Serial.print(": "); if (serial_enabled) Serial.println(value); if (serial_enabled) Serial.print(val2); } clear_EEPROM(); } */ void DataFromEEPROM(){ for (E_address = 0; E_address < 60; ) { // EEPROM.write(E_address, E_address+10); if (serial_enabled) Serial.print(E_address); for (int i = 0; i < 10; i++) { value = EEPROM.read(E_address+i); if (serial_enabled) Serial.print(": "); if (serial_enabled) Serial.print(value); } E_address += 10; if (serial_enabled) Serial.println(" "); } clear_EEPROM(); }
void vacuum_jog(){ digitalWrite(13, HIGH); //turn on digitalWrite(motor_direction, MOTOR_DIRECTION_TO_CREATE_A_VACUUM); digitalWrite(enable_motor, MTR_RUN); int period = 50; unsigned long time_now = millis(); while(millis() < time_now + period){ /* if(digitalRead(Over_Run_Interrupt) == 0) { //A zero voltage level inidicates that a limit switch has been tripped. The motor will be turned off and the program will be halted. digitalWrite(enable_motor, MTR_STOP); halt(); }*/ } digitalWrite(enable_motor, MTR_STOP); digitalWrite(13, LOW); //turn on } void return_jog(){ digitalWrite(13, HIGH); //turn on digitalWrite(motor_direction, !MOTOR_DIRECTION_TO_CREATE_A_VACUUM); digitalWrite(enable_motor, MTR_RUN); int period = 50; unsigned long time_now = millis(); while(millis() < time_now + period){ /* if(digitalRead(Over_Run_Interrupt) == 0) { //A zero voltage level inidicates that a limit switch has been tripped. The motor will be turned off and the program will be halted. digitalWrite(enable_motor, MTR_STOP); halt(); }*/ } digitalWrite(enable_motor, MTR_STOP); digitalWrite(13, LOW); //turn on }
void clear_EEPROM(){ for (E_address = 0; E_address < 256; E_address++) { EEPROM.write(E_address, 0); } } /* void E_write(byte code_position){ //if (serial_enabled) Serial.print("First into E_write and the Eaddress is: "); // if (serial_enabled) Serial.println(E_address); int R_address= E_address +1; EEPROM.write(E_address+=1, code_position); EEPROM.write(R_address+=1, 255); if (E_address > 50) {E_address = 0;} //EEPROM.write(E_address, 255); //if (serial_enabled) Serial.print("We just wrote the position to EProm. Now the address is: "); //if (serial_enabled) Serial.println(E_address); //if (serial_enabled) Serial.print("We are now going to write 255 marker at Eaddress of: "); //if (serial_enabled) Serial.println(E_address); // EEPROM.write(E_address, 255); //if (serial_enabled) Serial.print("We wrote the marker of 255 to address: "); // if (serial_enabled) Serial.println(E_address); // if (serial_enabled) Serial.println("We will now exit. Next time in, we should have the same address as above."); // if (E_address > 50) {E_address = 0;} // if (serial_enabled) Serial.println(E_address); //EEPROM.write(E_address, 255); //if (serial_enabled) Serial.println(E_address);
} */ void E_write(byte code_position){ EEPROM.write(E_address, code_position); E_address = E_address + 1; if (E_address > 49) {E_address = 0;} EEPROM.write(E_address, 255); if (E_address > 49) {E_address = 0;} } /* ISR(TIMER1_COMPA_vect){ //change the 0 to 1 for timer1 and 2 for timer2 digitalWrite(enable_motor, MTR_STOP); do { digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(13, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second } while(1); //interrupt commands here } */
z_start_interrupt_timer.ino
void start_interrupt_timer(){
TCCR1A = 0; TCCR1B = 5; // bitSet(TCCR1B, CS10 | CS12); // 256 prescaler // See https://forum.arduino.cc/index.php?topic=118105.0... for explanation of two lines below. TIFR1 = OCF1A; // HD clear timer1 compare interrupt TIFR1 = OCF1B; // HD bitSet(TIMSK1, TOIE1); // timer overflow interrupt pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, 1); temporarily_disable_ISR = false; } ISR(TIMER1_OVF_vect) { E_write(31);
if (temporarily_disable_ISR == false) { digitalWrite(enable_motor, MTR_STOP); signal_interrupt_timed_out(); } else { digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); } }
void signal_interrupt_timed_out() { E_write(32); temporarily_disable_ISR = true; do { digitalWrite(13, HIGH); //turn on // E_write(33); for (unsigned int i = 0; i <= 65530; i++) { digitalRead(12); } digitalWrite(13, LOW); //turn on for (unsigned int i = 0; i <= 65530; i++) { digitalRead(12); } } while(1); }
DESIGNING OF COVER
You can choose to create covers of your choice for the ventilator.
Heres the one that i made that has controlling monitor stand on top.