CPAP Water Reservoir Monitor - Sleep Apnea

What happens when the humidifier for your CPAP runs dry in the night? It isn't pleasant. Let's fix this.

Similar projects worth following
Anyone with treated sleep apnea will tell you that the CPAP (Continuous Positive Airway Pressure) machine is life changing and actually allows for restful sleep. The regular CPAP machines aren't perfect though.

One of the most frequent complaints on CPAP machines (besides the uncomfortable mask) is what happens when the humidifier reservoir runs out of water. Due to seasonal changes in air humidity, the machine sometimes needs to use extra heat to maintain the set humidity level. As the reservoir becomes nearly empty, the air slowly heats up. Eventually when the user been blasted by enough hot dry air, they will wake up dried out and annoyed.

My solution to this common problem would be to monitor the water level, and have an alarm can go off to alert the user that more water needs to be added.


High level flow chart

Portable Network Graphics (PNG) - 82.11 kB - 08/06/2017 at 20:16


JPEG Image - 1.68 MB - 08/06/2017 at 19:19


JPEG Image - 1.64 MB - 08/06/2017 at 19:19


JPEG Image - 1.62 MB - 08/06/2017 at 19:18


  • 1 × Arduino Nano
  • 1 × 5kg Load Cell
  • 1 × HX711 Amplifier
  • 1 × 8 ohm speaker
  • 4 × push button switch

  • Solving the loose hose problem

    Scott Clandinin09/02/2017 at 03:32 0 comments

    As discussed before, the looseness of the hose on it's hanger has a varying effect of the weight measured, causing a lot of inaccuracy.

    The solution wasn't too difficult, I had bought a cable bracket that would tightly fit the hose to hold it in place on the wall.

    While this should work, it isn't perfect as in order to mount it screws are required. This would get annoying anytime I needed to move the apparatus or take it on a trip. A great solution that I will look into in the near future is to hold it in place with magnets.

    The hard drive magnets are obviously overkill and way too strong, but some less powerful magnets would be perfect.

  • Result of First Night Test

    Scott Clandinin08/29/2017 at 01:21 0 comments

    The alarm was triggered in the early morning, but as expected, did not trigger at the correct water amount. The effect of the tube shifting seems to have a pretty large effect, as it triggered with about 120mL of water remaining (when it should have been 60mL). The scale is pretty sensitive to such small changes, so I'll need to firmly secure the hose so that it does not affect the weight measured.

    Some kind of circular, adjustable clamp should do the trick.

  • First Accuracy Test

    Scott Clandinin08/27/2017 at 05:43 0 comments

    I have the device hooked up to the computer to read the serial monitor while slowly removing water to see the moment when the moving average sinks below the alarm weight.

    The reservoir holds exactly 400mL of water. I have the device set to alarm at only 15% water remaining, which would be 60mL (conveniently about 1/4 cup). By slowly removing water up until the alarm point is reached, it should alarm with 60mL of water remaining.

    This snapshot shows one a cycle in which the moving average falls below the alarm weight, and as intended this triggers the alarm.

    Success! The scaling and alarm calculation works, and the device alarms as intended. I'll be doing a test run tonight actually being hooked up to it. As seen below, I have a loose fitting bracket on the tub to relieve strain (and to keep it from drooping down by the radiator). 

    One issue that could arise is that during night movement, I could pull on the tube, changing the amount of strain, and therefore weight exerted by that strain. If the tube is pulled tight, it could reduce the measured weight. If the tube is made looser hanging, it could increase the measured weight.

    I will certainly need to improve this so that the tube is held tightly in position at the bracket, so that it has little-to-no effect on any measured weights. It will be interested to do a few tests and see how much this can affect the results.

  • Setting up for the first trial runs

    Scott Clandinin08/10/2017 at 04:12 0 comments

    With the code mostly complete, I can try actually running this at night and seeing how much water is remaining when the alarm goes off. The water usually doesn't run out during a 6-7 hour of sleep, so I'll need to fill it up half-way or so to ensure the water will run dry.

    The hanger is the main input for this device. While on the hanger, the device sits waiting for an input, but once removed from the hanger, the measurements begin. Calibration and alarm test can only be done with the mask on the hanger.

    The hanger is very hacked together. I will eventually find a better, more elegant way to implement this. The push button was chosen through Digikey's search system with priority on the amount of force required to depress the button. The mask is quite light, so the button needed to be very sensitive. 

    Unfortunately, the button was too short for the rounded edge of the hanger, so I had to improvise in the meanwhile. That is in fact paper super glue onto the button head to add some height.

    It's not pretty, but it works. Which is a good tagline for the first iteration of the design.

  • Testing the Scale

    Scott Clandinin08/08/2017 at 04:00 0 comments


    Five measurements are taken per weight measurement and averaged. No effort is made to put these resulting value in units of weight since I am working off percent remaining. These calibration values will be placed in EEPROM so calibration doesn't need to be done every time the device loses power.

    Moving Average

    As seen above, a new measurement value takes the place of the first value, and the oldest value is pushed out of the calculation. Every cycle the result is compared to the alarm weight to determine whether or not to sound the alarm.

  • High Level Flow Chart

    Scott Clandinin08/06/2017 at 20:34 0 comments

    Every measurement of weight is done by taking 5 measurements in 50ms increments, and taking the average of them. At any instance the weight is not exactly the same, so this helps dampen out outlier measurements.

    The alarm weight is calculated by: 

    ((full_weight - empty_weight) * alarm_percent) + empty_weight;

    This allows the device to monitor the weight as a function of percent remaining, rather than pre-defined weight.

    The weight to be compared to the alarm weight is the result of a 10 measurement moving average to get a stable value that will dampen out any outlying measurements. At any given time, this weight is the result of 50 separate measurements. When a new measurement is made, it adds it to the calculation, and pushes out the oldest measurement. 

    As long as the hanger is not in use, and the weight doesn't reach the alarm value, the device will keep making measurements. Weight calibrations can only be made while the mask is on the hanger. The user will be notified by a success or error sound based on whether or not calibration values properly set upon taking the mask off of the hanger. If the full weight is less than the empty weight in calibration, an error sound will play.

  • Hooking it all up

    Scott Clandinin08/06/2017 at 04:26 0 comments

    Now that the general enclosure/scale was complete, the next step is building the inputs/outputs into the design, and soldering it all up.

    The two buttons are for calibrating the empty and full water reservoir weights. I chose to semi-hide these to limit the chance of accidentally resetting calibration. The screw terminal is for connecting and disconnecting the mask hanger signal (the jumper was to simulate button press).

    The rails on the top were an afterthought to ensure that the CPAP machine would not move around and would be level.


    Power jack and switch.

    The board consists of an Arduino Nano and the load cell amplifier.

    Revised block diagram showing connections to microcontroller.

    Not the prettiest standoffs but it works.

    Hardware complete!

  • Building the Scale

    Scott Clandinin07/25/2017 at 04:21 0 comments

    There were some slight changes to the design from the original drawings. Mainly just bringing the speaker to the top rather than the side, and bringing the scale surface off-center to make the acknowledge button and speaker more prominent. As well as hiding the calibration buttons more as they won't need to be used as much.

    I did another test of the scale as shown above. More to come on the enclosure later. 

  • First Testing and Designing

    Scott Clandinin07/24/2017 at 05:01 0 comments

    I ordered a 5kg load sensor and HX711 amplifier board that came with it. This amplifier takes in the wheatstone bridge input and outputs the scaled value through a serial pin. I used the Q2HX711 Arduino library to do the work of interfacing with this amplifier.

    I won't be doing any scaling to proper weights with this as I am basing the calculations off of percentage of water remaining rather than comparing to any preset weight values. This way I won't need to worry about zeroing the scale or drifting results.

    Designing the Scale

    I will be making this out of wood as it needs to be fairly rigid to hold the weight of the CPAP machine. Below are rough sketches of what I am planning for the scale.

    The load bar is set up as shown above so that a moment of force will be exerted on one side of the bar to create strain which can be related to weight.

    There was some experimenting and trail and error before looking at the datasheet for the load sensor and realizing that the screw holes were for metric screws rather than imperial screws. It seems obvious now, but prior to this I had not considered imperial and metric screws incompatible. 

  • Processing the Data

    Scott Clandinin04/29/2017 at 16:29 0 comments

    The calibration for this will be pretty easy. Simply placing the empty humidifier reservoir on the base and hitting the calibrate button will measure the lowest weight of the design. This will be stored in non-volatile memory. The same will be done with the reservoir full.

    When the mask is off the hanger, data recording will begin. A measurement will be taken approximately every 30 seconds. Once the first 10 measurements have been taking. A moving average calculation will be make with every new measurement. If this moving average value represents only 10-20% of the water left, the alarm will trigger.

    Hitting the alarm acknowledge button will cause the device to wait 5 minutes and being taking measurements again. Hanging up the mask on the hanger will put the device back into inactive mode. Either way, 10 measurements will always be taken before moving average calculation begins.

    And here is a block diagram just for fun.

View all 11 project logs

Enjoy this project?



Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates