March 23, 2020

2489 words 12 mins read



Complete control software for an emergency medical ventilator.

repo name ermtl/Open-Source-Ventilator
repo link
language C++
size (curr.) 55286 kB
stars (curr.) 21
created 2020-03-20
license GNU General Public License v3.0


Complete control software for an emergency medical ventilator.

This software is designed to control a Bag Valve Mask (BVM) AmbuBag medical Ventilator as part of the global effort to develop a fast, effective, easily replicable device using distributed digital manufacturing techniques including 3D printing, CNC or laser cutting. The project uses an Arduino Nano with Atmega328P. The software can be used with a wide range of mechanical designs.

Short video presentation / demo :

(I’m not a youtuber and English’s not my main language, you’ve been warned !)

NOTE: Requirements for a minimal emergency ventilator device have been issued by the UK government. This controller strives to follow these guidelines.

Thanks to uxvrob we now have a complete schematic diagram so that the controller can be tested.

Main components

  • The arduino Nano was chosen as a controller for it’s ability to perform the realtime tasks with relatively low latency (step generation & data acquisition) and it’s universal availability. More sophisticated controllers such as the Raspberry Pi usually have real time issues and unpredictable latency. Also, the Arduino ecosystem is very rich in well tested libraries.

  • The Bosch Sensortech BME280 / BMP280 sensor allows precise measurement of the air pressure delivered to the patient. It also allows measurement of the temperature and pressure (BME280 only). The software allows to use either of these. It’a a well known, mass produced, low cost sensor.

  • The TM1638 display / LED / keyboard This little board merges leds, a 8 digits 7 segments display and 8 buttons. It’s a very common Chinese board that possesses numerous advantages. It’s main drawback is the Old School look of it’s display, but does it really matter for this usage ? The main advantages are that the board is mechanically integrated making mechanical assembly very easy. Connection to the processor uses only 3 pins (Data, Clock, Strobe) The data is clocked and not timing sensitive. The whole board typically costs 1.50$ 2x16 character LCDs require a lot of pin connections or, when used with a “backpack”, they require a serial interface. Also, the LCD needs a temperature dependant analog adjustment to be well readable. The display is not very bright and can’t be read from a distance. That could be a problem when a person has to monitor several heavily infected patients. They also require a separate keyboard. OLED displays are not suited for this device as their active lifetime is limited. color LCDs would be another possibility, possibly with a touchscreen, but it would take longer to develop and require a more powerful processor without adding much to the main function of the device.

  • StepStick stepper driver The stepstick stepper motor drivers are widely available as they are used to drive 3D printer motors. When used with 24V and a low current/high torque NEMA23 motor, they can offer a very good torque. There are several types depending on the chip they use (A4988 / DRV8825 / Trinamic TMC2209 & TMC5160). The TMC5160 drives up to 4.4Amps and is even suitable for a NEMA24 or NEMA34 motor. All Trinamic drivers include advanced functions such as load measurement, stall prevention and detection, noiseless operation, etc … Since the software uses industry standard STEP/DIR interface, any external driver may be used to control a stepper, a servo-stepper or a 3 phases servo. A servo would probably be required for a leadscrew design, while a stepper would be more suited to a direct drive design.

To compile the software, you will need the following libraries (all from the library manager) :

#include <BME280I2C.h>      // Temperature / humidity / pressure
                            //  by Tyler Glenn -
#include <Wire.h>           // I2C protocol
#include <EEPROM.h>         // read / write to the processor's internal EEPROM
#include <TM1638plus.h>     // Keyboard / display / LED combo board
                            //  By Gavin Lyons -
#include <AccelStepper.h>   // Stepper / servo library with step pulse / dir interface
                            //  By Mike McCauley -
#include "TimerOne.h"       // Timer component
                            //  By Jesse Tane, Jérôme Despatis, Michael Polli, Dan Clemens, Paul Stroffregen

Software Functions

The software is contained in an Arduino “sketch” with many comments, nearly all parameters are in defined constants and can be easily changed. It is herein distributed under the GPL V3.0 licence. The software has the following functions:

  • Initialisation with display keyboard and sensor detection. The software have been designed to allow operation in degraded mode without BME/BMP280 sensor and even without keyboard / display (it will autostart with stored parameters) During the startup process, detailed debug information is provided through the serial/USB port. TBD : remote operation controlled by USB

  • User interface The software manages the display, keyboard navigation in the settings menu and an alarm beeper. The 8 leds above the keyboard are used as a bar-graph of the measured pressure and a breath cycle indicator. The 3rd LED represent neutral atmospheric pressure and blinks at the start of each breathing cycle. 1st and 2nd LEDs on the left indicate a low pressure, those on the right indicate a higher pressure. Display is scaled according to the preset pressure. The menu allows to change the following parameters:

  • Pulse rate The pulse rate in breathing cycles per second can be adjusted between 5 and 60 BPM.

  • Breathing volume The breathing volume in liter per cycle can be adjusted between 0.1l and 2l. The motor travel and acceleration are changed according to this parameter. There is a yet to be determined limit for high volume at high pulse rate depending on the mechanical design.

  • Breathing Pressure The breathing pressure in KPa can be adjusted between 3Kpa and 30Kpa. The pressure is used to limit the motor speed / travel to prevent exceeding the preset value. TBD : This feature is not fully implemented yet (but measurements are available and the stepper library allows to alter the motor parameters while it’s rotating).

  • Save settings This saves the 3 settings above and the running state, thus allowing for automatic start upon powerup.

The user interface management is done in a timed interrupt to be responsive and remain functionnal at all times, so that all parameters can be visualised and changed while the device is operating.

When changing the settings, the change will be gradual with each subsequent breath cycle to prevent sudden changes. The variation speed can be defined for all parameters.

  • data acquisition. Data is acquired from the BME/BMP280 sensor every 100ms. the acquisition includes filtering of the pressure


Required hardware


  • 0.10 Initial public version

  • 0.11 Add interactive terminal command line complete control (through USB link) A minimal device without screen or keyboard is possible with the same software.

  • 0.12 Add “Assist Control” mode with adaptive negative pressure trigger cycle. This mode was requested by a MD : "ER doc here chiming in, hopefully I can answers some questions or clarify minimal requirements.The basic mode you need is Assist Control. This mode provides a breath whenever the patient triggers a breath (by inhaling and creating negative pressure past a certain threshold) or whenever the patient is due for a breath (based on the set rate). The breath it provides are either a fixed volume (and the doc monitors the pressures delivered) or a fixed pressure (and the doc monitors the volume delivered). AC/volume is often called Volume Control, and AC/pressure is often called Pressure Control. While I do not have direct experience ventilating COVID patients yet, these 2 modes will cover 99% of ICU cases." This version also adds editing, permanent storage and USB setting of the new Patient Synchronization parameter and an audible alarm when pressure remains above 120% of preset pressure for 1 second or mode.

  • V0.13 Modular code - asymmetric breathing - Bug fix This version is a major reorganization of the code done to get a more modular software, ready for bringing in other sensors, a different user interface and ports to other controller architectures. Very long functions are broken down into smaller functionnal blocks that should be much easier to understand and modify, each global variable is commented. This version also implements most of the guidelines in the UK minimal emergency ventilator device specifications. Namely, all variable limits have been tweaked and the variable Inspiratory:Expiratory ratio is fully functionnal. A bug that allowed floating point variables retrieved from a garbage filled EEPROM to bypass the checks leading to malfunction have been corrected (NaN detection).

  • 0.14 This version include proper timing, speed and acceleration for the motor control. The pressure controlled and volume controlled modes are implemented.

  • 0.15 Minor version change. This version allows the replacement of the buggy Wire.h arduino library (can hang the controller) with a correct version known as jm_Wire ‘Wire.h’ is still the default library to prevent compiler errors. The processor’s hardware watchdog can now be enabled (off by default, use with care, you risk bricking your processor. Modularisation is getting better (work in progress)

  • 0.16 Double pressure sensor, breath phases modularization This version can use 2 absolute sensors (or still use just 1, configurable) to constantly monitor the ambiant air pressure. This is important for patients that are heliported and for patients placed in a negative pressure room, 2 situations where the ambiant pressure can change rapidly. The 2 sensors together will behave as a differential pressure sensor. Since pressure is a critical data, several safeguards and coping strategies have been added to make sure data from the sensor is acurate and there is a failsafe. Things such as randomly connecting/disconnecting sensors are non blocking and behave as expected. this feature requires the #define jm_Wire to be uncommented.Please see the link in the description for version 0.15 above

     Also, as requested, the various phases and functions managing the breathing cycle 
     itself have been modularized to allow third parties to implement more sophisticated
     control strategies.
     Finally, the processor's program memory is filing up quickly as the control becomes 
     more complex. There is still opportunities for important optimizations, but the base 
     version will have to give up some non essential functions to fit in a regular Arduino
     Nano (such as the verbose serial interface or the ability to manage both the native
     keyboard / display and the USB serial command line interface.
     This version barely fits with the USB commands on, so they've been deactivated.
     You can get them back by uncommenting the #define USBcontrol line.
     The following versions will both target the Nano and the Mega with Atmega2560 processor
     for 8 times the available program memory.
  • 0.17 2x16 LCD Display - Telemetry

      The ability to use an alphanumeric 2 lines * 16 characters LCD display had been
      requested, it will now be fully supported. Since this LCD uses lots of IO pins, 
      the retained version is connected to a PCF8574 "Backpack" board to make it I2C 
      compatible. The LCD+the backpack are sold online for around 2.50$.
      The TM1638 display is still supported as a minimal option.
      A good side effect is that the library is lean and so USB/serial terminal control
      is back by default.
      At this point, the keyboard and bargraph are still done with the TM1638, but a
      simple button keyboard will be supported very soon.
      Telemetry will send information in real time about the breathing cycle for further 
      data analysis and / or graphical display !
      This will be very very useful for people developing mechanical solutions, and 
      doing data analysis to develop motor position <=> volume mapping
      Data is sent in common CSV format, around 1 data point every 20 millisecond
      The "T" command, sent through the serial port toggles telemetry on or off.
      every data point includes :
      - Time since the breathing was activated.
      - Breathing cycle phase (more phases might be added in the future)
        0 : Start of new cycle
        1 : Inspiration
        2 : Start of expiration
        3 : Expiration
        4 : Patient breathing initiation search
        5 : Patient initiated a breathing cycle
       - Motor position (in step) Travelled distance depends on driver microstepping
                                  and driving mechanism.
       - relative pressure in cm H2O
      In addition to these data points, during phase 0 (start of cycle), the following 
       cycle data is sent:
       - Ambiant pressure (mBar)
       - Breathing volume per cycle in ml
       - Motor destination / target (steps)
       - Breathing length (in seconds)
       - Breathing in duration (in seconds)
       - breathing in top speed (in steps/second)
       - Motor acceleration during inspiration (in steps per second squared)
       - Breathing out duration (in seconds)
       - breathing out top speed (in steps/second)
       - Motor acceleration during expiration (in steps per second squared)
comments powered by Disqus