This is something I put together to allow my computer to control the pressure of the CPAP machine.
My plan was to make the computer adjust the pressure, in case it was the case that I simply needed a different pressure for different sleeping positions.
It's a pretty simple circuit. I just found the pressure sensor the machine uses to regulate the pressure, cut the trace between the sensor and the microcontroller inside the CPAP machine, and fed the sensor's output to an ADC attached to my own microcontroller, which then reads the voltage, calculates an adjustment, writes that to a DAC which outputs a voltage that then goes back into the machine to be read by its microcontroller as if it were the output of the pressure sensor.
Despite being a simple idea, it didn't work so well the first time I tried it some years ago. One reason is that the machine at some point reads the sensor and uses that as a baseline, and so not only do I have to be careful not to adjust the reading when the machine is turned off, but I have to be sure that the machine is never plugged in without the microcontroller running. For that reason, the circuit has an LED that blinks constantly, just to show that the microcontroller is actually running, and also has a little reset button in case it isn't, and so needs to be reset. To account for that baseline reading, I just programmed the microcontroller so that whenever the pressure is below 2 cm H2O, it outputs the sensors actual voltage rather than the modified signal.
So, with a design that's slightly improved, it now works much better. I've only seen it shut down with an error code once, and I seem to have fixed that simply by setting the machine to 10 instead of 8, which I think works better because it's closer to the middle of its operating range, and so when I mess with the signal, what the machine sees is less out of the ordinary and so it doesn't complain.
So, with working hardware, all I needed now was software.
I first wrote some code to detect breaths, which was surprisingly much easier than I anticipated, but probably because I didn't care so much about the exact boundary of inhalation/exhalation, but instead just wanted it to split them at some point during exhalation. I then had it score each breath by how much air was inhaled, or at least that was the intent. I ignored exhalation since it seems to be unobstructed anyway so that it didn't matter where within the exhalation waveform I split each breath, but instead I just had to measure how much of the voltage curve was above some baseline. The voltage from the CPAP machine's airflow sensor doesn't seem to be linear, and so it probably isn't all that accurate a representation of how much air was inhaled, but it comes up with a number which was all I wanted.
Then, for each breath, I had it toggle between a pressure 0.5 cm H2O higher or lower than the pressure it was currently set to. It would note the score for the two breaths, then adjust the pressure it was set to by 0.05 cm H2O. In this way, I figured that the difference between the high and low pressures of 1.0 cm H2O was enough to see any difference in the effectiveness of higher or lower pressure, and the low adjustment rate of 0.05 cm H2O per breath made sure that, while random variations in breathing might incorrectly nudge it in the wrong direction, as long as the majority of breaths reflected the actual effectiveness of the pressure, it would eventually end up in the correct place.
In actual practice, however, the pressure just goes up until it hits the upper limit.
At first I thought this might just be because higher pressure means more airflow, and thus, because of the "leak" holes in the mask, a higher pressure always results in more air flowing during inhalation. However, I figured that since higher pressure eventually makes things worse, it would reach a point where the degree to which it makes things worse would cancel this out. Since that didn't seem to be the case, I modified the code a bit, so that the higher pressure breaths had to improve on the score of lower pressure breaths by more than 10% in order to raise the pressure, but continued to lower the pressure if the lower-pressure breath's score was even the slightest bit better. However, even with this change in place, the pressure still continues to rise until it reaches the upper limit. It just takes a little longer. It doesn't seem to be possible to adjust the code so that the pressure doesn't always increase without modifying it to the point that the pressure never increases.
So, I don't know... Either my code sucks and just can't adjust the pressure for shit (entirely possible) or my previous discovery that 8.0 is the magic setting and that both 7.0 and 9.0 are worse is actually incorrect (also entirely possible).
Lacking any other clever ideas, I think tonight I'll just try having the machine alternate between 8.0 and 9.0 every minute, then look at the recording tomorrow and see whether or not 9.0 really does seem worse than 8.0. I did finally get my PDF generating script to work, after reinstalling Linux. FreeBSD was fun, but I just don't have the energy to deal with new things, and need to be able to use the Linux code I've already written.
A few days ago, my Zeo recorded nearly two hours of REM sleep, with only one tiny little break in it. I looked back through the years of data I had recorded, and it was the longest period I've seen, though there were a few others that were close (like 90 minutes). Usually they're just 30 to 45 minutes in length. Just one more thing to make me think that the CPAP is doing something to help, even if not doing everything it should.