Ketosense – An Arduino based ketosis detector

Ketosense – An Arduino based ketosis detector

In this post I will go through the hardware and software of the instrument I have made. If you are curious to why I have made it, I would recommend that you start reading the other posts I have done about this project and work your way forward. Just click on Ketosis detector under categories.


The instrument´s purpose is to detect the amount of acetone gas that is present in a persons breath.

By measuring the amount of breath acetone gas present in a persons breath, it should be possible to determine wether or not a person is in a state called ketosis. Ketosis is, very simplified, when the body runs on fat rather then carbohydrates. If you eat a ketogenic diet, your ketone levels will be elevated. Currently, the only way to monitor your ketone levels are either to take a blood based test or a urine based test, with test strips that changes color depending on the amount of ketons that are present. Both methods work fine but the blood method is very expensive, about 2$ per test, and the urine method is not very precise. Being the curious type of person, and getting inspired by a podcast where Steve Gibson was talking about building an instrument like this, I decided to give it a shot myself.

On a very high level, the instrument consists of an electrochemical gas sensor that is sensitive to various types of gases, a combined hygrometer/thermometer and an Arduino Uno board. The electrochemical gas sensor and hygrometer/thermometer has been placed in a plastic case that serves as a ”gas chamber” that you blow into to collect the gas sample. If there is gas present in the air, the resistance of the sensor will decrease. The decrease of resistance is dependent on three factors; gas concentration, humidity and temperature. If these values are known, it is possible to calculate the gas concentration in PPM (parts per million) using the data sheet provided by the manufacturer.

Does it work?

I don’t normally eat a ketogen diet, but in the name of science and curiosity I gave it a shot. Over the last two weeks I have and taken measurements with the Ketosense and compared them to the results from urine test strips. During the first 10 days, I ate a strict ketogen diet consuming less then 50 grams of carbohydrates a day. I took a reading each morning before breakfast, and one right before going to bed. However, the urine test strips does not have a very granular scale, so it is difficult to say what the exact concentration is  when you go above 1,5 mmol/l. The steps of the Keto-Diastix are 0, 0.5, 1.5, 4, 8 and above 16.

The measurements taken with the Ketosense actually correlates a lot better then I expected to the reference measurements from the Keto-Diastix. This means that the hypothesis that it is possible to calculate ketone levels based on the amount of acetone present in a persons exhalation, seems to be sound. One realization I had was that you have to eat very large amounts of fat to really get the ketones going, it was not until I started to eat a few spoons of 100% coconut fat a day that I reached higher levels of ketones, (witch can be seen around measurement 17 in the graph).


Main Unit


Total price for the components is about 30$.

TGS822 – Electro chemical gas sensor

This sensor works like a resistor, the higher the gas concentration is, the lower the resistance gets. It has 6 pins, the two middle pins are the power to the internal heater and the other are the resistor connections. There are two pairs of resistors connectors called ”A” and ”B”, but they are essentially the same so I just soldered them together. It is very important that the power provided to the internal heater is exactly 5 Volts, or else you risk damaging the sensor. I used an LM7805L voltage regulator to provide the power for both the TGS822 and the DHT11 sensor.

This sensor is far from ideal to be applied in an application as this, it is slow to start, sensitive to humidity and temperature, sensitive to many other gasses other than acetone, and almost impossible to calibrate without special equipment. A wisdom I can pass on, is that one of the gasses the TGS822 is sensitive to is ethanol so don’t try to demo or measure your breath acetone during a dinner where there is wine served. The sensor is so sensitive that it goes bananas if you just have a glass of whine next to it.

The TGS822 is connected to the Arduino on analog pin 0 in parallel with a 10k resistor to create a voltage divider circuit.

DHT11 – digital temperature and humidity sensor.

I added the DHT11 sensor because the characteristics of the gas sensor changes depending on temperature and humidity. Since a persons breath is both humid and warm, it was necessary to factor that in when trying to determine the gas concentration. At first I had placed both the gas sensor and the temperature and humidity sensor close to each other. This turned out to be a mistake since the heater in the gas sensor heated the air around it, thus drying out the air and elevating the temperature. To avoid this, I moved the temperature and humidity sensor to sit as far away from the gas sensor as possible.

The DHT11 is not very fast, especially when it comes to humidity. It can take about 2-3 minutes before the humidity reaches it’s max value. This presents a bit of a problem when it comes to scaling the reading from the gas sensor, depending of humidity from the DHT11. The gas sensor reaches it’s max value just seconds after you finished blowing into it. So if you read the DHT11 at the same time as the gas sensor reaches it’s max value, the humidity value will be to low because the DHT11 is slow.

After blowing into the instrument a couple of times I noticed that the temperature and humidity of a persons breath was stabile at around 60% humidity and 28-29ºC. After realizing this I hardcoded the temperature and humidity to those values to get the scaling right without having to wait for the DHT11.

The DHT11 sensor is connected to digital input pin 10.

16 x 2 Character LCD Display Module

The display is wired as such:

RS: Pin 2
EN: Pin 3
D4: Pin 4
D5: Pin 5
D6: Pin 6
D7: Pin 7

I used the LCD crystal library by David A. Mellis, Limor Fried,  and Tom Igoe to control it.


There are three switches on the Ketosense. One to trigger a reset cycle of the gas sensor, one to reset read max value and one to toggle between the result being displayed as PPM or mmol/l.

resetMaxSwitchPin = 13;
resetSensorSwitchPin = 12;
toggleModeSwitchPin = 11;

Mouthpiece case

When choosing a case to use as a mouthpiece, make sure it is easy to open to be able to ventilate all gas in between readings.

Breadboard view of the whole circuit



This is my first time doing anything with an Arduino so I learned as I went along, the code is not very pretty and I am sure that there are many better ways to get it done, but this way works good enough for me. The code is available at my Github, it is perhaps not super clean but I will try to explain the concepts in words here to perhaps make it a bit more understandable.

Initiation and reset sequence

As I mentioned in the hardware section, the TGS822 sensor is quite slow. When you power on the Ketosense it can take up to 10 minutes before the sensors resistance is stabile, so to determine if the sensor is stabile, readings are taken continuously every second and compared. If the reading changes less then 5 steps over 20 seconds, the sensor is determined to be stabile otherwise the sequence restart.

After a person has blown into the Ketosense it takes a few minutes for the sensor to reset, so the same method as described above is used to determine if the sensor is able to do another reading. This is triggered by pushing one of the buttons.

On the left you can see the Ketosense while it is in startup mode waiting for the sensor to become stabile. On the top row H = current humidity, T = current temperature and i = what step in the 20 second cycle the algorithm that determines if the sensor should be considered stabile is at. On the bottom row the Max and Min value detected on when reading the voltage from the sensor, if the sensor is to be considered stabile and ready to use to take a measure the difference between these two values has to be less then 5. After the sensor has been considered stabile the user is prompted to start the measurement by blowing into the mouthpeice.

Making sense of the readings from the TGS822

The only info I had about the TGS822 was what was written in the datasheet. I wrote a post a little while back called ”Calibrating a Figaro TGS822 sensor, by drawing…” so take a look at that if you want to know more about my thoughts on how to use the info in the data-sheet.

Since I feed 5V to the sensor and it is connected in a voltage divider circuit with a 10k resistor the voltage going into the A0 port of the Arduino is between 0-5 volts. The Arduino then divide it into 1023 parts so the value I actually read from the sensor is a voltage where every step is a change of 5/1023 = 0,0048V.

To get the resistance of the corresponding to the voltage read use this formula:


To find the relation between resistance and gas concentration I did some regression analysis using libre office. I found out that a reasonable approximation to the ppm vs voltage can be achieved with the functions:

if resistance is between 50kΩ & 3600Ω
logPPM = (log10(tempResistance/R0)*-1.5512)+2.5911
PPM = pow(10, logPPM)

if resistance is below 3600Ω
logPPM = (log10(sensorResistanec/R0)*-0.9768)+2.4906
PPM = pow(10, logPPM)

How I went about calculating my sensors R0 is described in the post called ”Calibrating a Figaro TGS822 sensor, by drawing…” I noticed that in the graph for gas vs resistance in the datasheet, it stated that in Air the resistance is ≈ R0 * 19, so I simply divided the startup resistance of the sensor  after it had stabilized with 19 and went with that.

calculated value vs datasheet graph


I applied the same reasoning for temperature and humidity graph and there the function is:

scalingFactor = (((Temperature * -0.02573)+1.898)+((Humidity*-0.011)+0.3966))

The last thing to do is to convert from PPM to mmol/l since that is the most common unit when talking about ketone levels. Im not entirely sure that I got it right but it seems to give reasonable results.

float ppmInmmol = (((float) PPM / 1000) / 58.08);
ppmInmmol = ppmInmmol * 1000;

58.08 is the molar weight of acetone.

Fine tuning the scaling function

After doing the 14 day journey into ketosis I had enough data so tune my original scaling functions to fit the reference of the Keto-Diastix.

logPPM = (log10(sensorResistance/R0)*-2,6)+2.7
PPM = pow(10, logPPM)

I also updated the R0 from 3000 to 4500.


Collecting the measurement

After the Ketosense has started and is stabile, the display prompts to the user to blow into the mouthpiece to start. Actually the measuring has already started, even before that point, however the screen is only updated once the sensor is reading changes and thus indicating that someone is blowing into the mouthpiece. The samples are taken three at a time with 5ms between them and compared to each other. For a measurement to be considered valid, all three samples has to have the same value. This is to minimize the risk for an unexpected voltage rise that would give a false indication as a max value. If a sample is considered valid it is then scaled based on humidity and temperature. As I wrote in the hardware part, the humidity is hardcoded to 60 and the temperature to 28 due to the DHT11 sensor being much slower then the gas sensor, thus causing the scaling to be wrong if both sensors are being read at the same time.


Every time the collected value is valid, (3 samples after each other that are the same), the screen is updated. The current reading is displayed on the bottom row as ”Now:” If the current value is greater then the last one, the ”Max:” is also updated. Typical behavior is that during the first 30 seconds after someone has blown into the Ketosense mouthpiece the max value keeps increasing, therefor the gas collection chamber is crucial to give the gas sensor time to react. It is possible to tell when the actual max value has been reached since the ”now value” is decreasing and is lower than ”max value”.

To reset the instrument to make it ready to use for another measurement, remove the cover of the mouthpiece to ventilate the current sample and then push the reset button to trigger the same sequence as during startup to detect when the sensor has been reset. The reset button is actually the little nut (button) in the middle beneath the dispalay, (the microswitch was not tall enough to reach out of the case, so I extended it by gluing a nut on top of the switch). The nut on the left is to switch between displaying the result as PPM or mmol/l and the one to the right to reset the current max value.


I would not go as far as to claim that my instrument works, It is tricky to decide if it does since I don’t have a reliable way to get a reference other then the keto-diastix, (and those are not exact enough). But I will go so far as to say it looks promising.


If I had access to an instrument reading blood ketone levels, it would be possible to further improve the scaling functions relative to that. Take one measurement of blood ketone levels, and then blow into the Ketosense and write down the raw voltage from the TGS822 rather than the scaled value. Do this for a couple of different values and do some regression analysis on the results and I would have a function that was entirely adapted to my sensor and to displaying ketone levels. However I am not prepared to spend money on a blood ketone level measuring device, but perhaps someone else will after having being inspired by this post.

Another application for this device is actually a breath alcohol detector, since the sensor is actually sensitive to ethanol as well as acetone.

Sources and additional information

I found three different data sheets for the sensor while searching:

100 svar till “Ketosense – An Arduino based ketosis detector”

  1. Awsome, thank you for sharing Jen! As a Type 1 diabetic who uses urine strips to measure my Ketone levels, this is extremely exciting!

    One suggestion for scaling/calibration: Ketone meters can be purchased that will give you a numerical blood-ketone reading, usually as a secondary fuction of a blood-glucose monitor. For example:
    Thanks again Jan! I can’t wait to try building this 🙂


  2. hi, thank you for your interesting site. I´m building an alcohol detector. I use the tgs 822 too. But the analog input on the arduino shows me always only values between 0 and 1023. its going from 0 to 1023 and back and that all the time. can you imagine what i did wrong here?


    • Have you connected the input to one of the Analogue ports A0-A5? Im not sure if you can do an analogue read of one of the digital ports but it sounds like what you are getting is either 0 or 1 (1023).


  3. thank you very much for your answer.
    yes its connected to A5. it shows not only 0 and 1023. its going up like 0,84,144,278,527,798,953,1023, and then a few seconds only 1023 and then its going back to 0 and shows a few seconds only the 0. then its going up to 1023…………..


  4. so now i have connected the grounds to the board. had not seen this mistake. it shows me now values between 306 and 310 🙂
    but the sensor doesnt show other values when i hold alcohol in the near of it….. really difficult


      • i don`t really know it. i`m using two old mobile phone wires for the sensor power. one has 5 volt and the other 14,4. maybe i connected the grounds wrong together. now i have to find out how to calculate from the values the ethanol ppm without an temperature sensor like you did it


      • You don’t rely need the temperature sensor, after a lot of measuring I discovered that accurate readings can be achieved by assuming that temperature is 28C and humidity 65% in the scaling function.


      • thank you very much for this information. tomorrow i will try to calculate this. at the moment i`m testing out how the sensor reacts to my alcohol values. after 1 beer it shows me something about 700, i think thats too much (i made a break between drinking and testing). maybe my resistors are not right


      • thank you. now i got it, my project is working. for creating the formula i aksed a friend because logarithmics are not my world 😀


  5. Hi, thank you for this great project. I am keto dieting and it will be very useful for me. Is it possible to use another part instead of using tgs 822? Thank you.


    • There are some other sensors that are sensitive to acetone, I have talked about a bunch of them in this post. The TGS822 and the MQ-3 from HANWEI ELETRONICS have similar properties when it comes to what kind of gas it can detect. However the MQ-3 has a completely different sensitivity curve if you look at the data sheet. So if you go with the MQ-3 sensor you need to do some tweaking of the scaling parameters in the code to get it to show the correct aceton concentration values.


  6. Hey, very interesting… Very nice to have a real impact on what is a shift in the understanding of how to be optimum individuals, with what we have. So. The importance of this you didn’t quite touch on… The ketones in urine decrease as your kidneys begin to process, convert and ultimately utilize this superior energy source; which must be fueled properly and maintained properly as you pointed out. Acetone is the ONLY way to test the advanced stages (beyond two weeks) of normal ketogenic metabolism.
    Check out ”the art and science of low carbohydrate living” phinney & somebody else. Must like salt and knowledge and immortality.


  7. Hello, in behalf of my group of graduating electronics engineering students from the Philippines conducting a study on non-invasive blood glucose level detection, I would like to ask if your product is available in the market?

    Thank you and we are hoping for your immediate response.


    • Hi, No I don’t sell any Ketosenses. There is product called the Ketonix that has the same sensor but only shows ketone levels based with different colored LEDs rather then with a number like the Ketosense does.


  8. Hi, thanks this will help a lot. I currently use a ketonix and blood tests to measure and they correlate well, but would like to build my own version showing ppm. Just waiting for the 822 to arrive.
    I may be missing something, but how do you isolate out the results for the Acetone given that the 822 can read other gases. For example 30% of the population have methane in their breath, and I imagine a lot have ethanol.


    • Hi Wayne, I don’t isolate from the other gasses. The way the sensor is built it will react to all the gasses it is built detect. A way to compensate would be to add additional sensors that are not sensitive to acetone but to ethanol as an example. Then you subtract the ethanol result from the acetone or at least warn the user that ethanol was detected and that the measured value could be wrong.


      • Thanks for the quick reply, I didn’t see it before adding the following. Yes, I will just have to get sensors that focus on each specific gas I want to measure. I also want to build a SIBO detector to detect hydrogen, methane and hydrogen sulphide in the breath. These gases are caused by bacteria in the small intestine (SIBO)


    • As well as measuring ketones, I also wanted to measure Hydrogen, Methane, and Hydrogen Sulphide on the breath. I’ve ordered a lot of different sensors, but if they don’t distinguish between the gases then I guess it is going to be a difficult task to get the individual gas levels. If you know someone with Fibromyalgia you could try your ketosense on them as they typically breath out lots of hydrogen from the bacteria causing the problem.


      • You can always make assumptions of what gasses are involved by comparing different sensor values and what gasses they are sensitive to. However complexity will increase the more sensors you add. Please let med know how it goes for you.


      • I’ll let you know how it goes, and how well your algorithms compare to the Ketonix and bloods. Thanks for your help


  9. Hello i’m looking how to use an equation in order to compensate the MQ3 temperature dependance according the data sheet graph. is see you done something like that. can you advise me please to write the wright arduino code?
    My MQ3 sensor will be calibarte using a known alcohol concentration.

    Thank you.


  10. Hi! I’m from the Philippines. Me and my thesis group are interested with your device. May we know if you are selling this? We badly need one to complete our thesis study. We are more than willing to pay you. Thank you very much!


  11. Do you think this sensor would be able to detect ketones/acetone in urine if the urine is drained into a container and allowed to stand? My cat has recently developed diabetes and while the test strips are negative for ketones I know that they can evaporate and if you think giving a cat a pill is hard, try obtaining a fresh urine sample. Not Happening. I picked up a new litter box called the Smart Cat Box that uses a non-absorbent litter, which allows the urine to pass through to a chamber that slopes toward a small hole, where it drains into a container. If I were to secure the gas sensor to the top of the chamber where it will stay dry, I’m wondering if I’ll be able to get a good reading? Or, even if I do, do you think I’d get constant false positives from the breakdown of urea into ammonia?



  12. HI, This might seem as a very silly question, but I am just a beginner..Besides the three micro switches what is the component (labeled 104) on the breadboard at position 52G ?


  13. Thanks for the clarification. Because pins 1 and 3 are internally connected, I will use one of them. Similarly, because 4 and 6 are internally connected, I will any one of these two pins. It looks like I do not have to connect these two pairs of pins externally.


    • That is correct! I read somewhere when I was researching those sensors that someone had said they saw more consistant results with both pins connected but in theory it should be redundant.


      • Sorry, but I have run into another problem. Now that the circuit is ready, I am uploading the program but nothing gets displayed on the LCD. I have checked the connections as per your circuit diagram and everything seems to be OK. The display lights up but does not show any text.


  14. Hi, what do you call the component that is connected to the voltage regulator and GND and VIN pins of the arduino. The one with lightning symbol. Did you use that to power the arduino? Thanks


  15. Hi, I may be missing something here, but I cannot see how the pin 11 on the Arduino is connected to the circuit. It seems to be left floating on an unconnected line between the toggle switch terminals. Also, given that an Arduino has the ability to deliver 5 volts, why wouldn’t we just connect it to the USB port of a computer and simply get the power supply for the sensor from the Arduino itself?


    • You are absolutely right about pin 11. It should be connected to the button one line to the right. The heater in the gas sensor consumes quite a lot of power, if you power it directly from the 5V pin you risk damaging the Arduino.


      • What is meant by R0? I can not understand the R0 part. Can you please the significance of R0.


  16. Hi I am confusing about the connection between the TGS822 to the Arduino. Because the gas sensor did not have any label. can you show me the connection please. Would you email me?


  17. Hi Jens, I am currently doing this project for my class. I would like to know the connection of the TGS 822 Figaro sensor, would you mind to help me?


  18. I am reading your project. Very interested, but I can’t understand how to you derive the equation, ”scalingFactor = (((Temperature * -0.02573)+1.898)+((Humidity*-0.011)+0.3966))”. Could you let me know your knowhow?


  19. And the other question is the currentHumidity and currentTemperature are fixed number in your source. However, as this case, scalingFactor is always constant. is it correct?


  20. One more question, I am confused that you used same term ”scalingFactor” in this post and ”Calibrating a Figaro TGS822 sensor, by drawing…”, but it looks totally different factor for calculation ppm. is this correct? Could you explain the difference both of these two?


  21. And I am curious as well that how the ”logPPM = (log10(sensorResistance/R0) * -2.6) + 2.7” can be derived? Could you let me know more detailed explanation?


  22. Hi Jens, I’m trying to reproduce your project (which is great, by the way!). I’ve connected up the TGS822 as shown, except that I’m using a 12k resistor for RL (the shop was out of 10k…). For some reason my analog pin is not reading 1023 when the circuit is connected. It drops down to about 943, which translates to about 4.6V. Do you know why this could be? It seems that a small bit of current is being lost somewhere…


  23. Hey Jenslab. Im recreating your project. I set up everything but im a little confused. Is the TGs822 connected to the DHT 1! like it shows on schematic? its giving me this error message” Check DHT sensor, Time out Error”


  24. I tried skipping the DHT sensor like you said. I unplugged it and it still gave me the same error message ” Check DHT sensor, Time out Error.” The MAX,MIN and i values are changing but the T and H values remain at 0. what do you think could be the issue?


    • It looks like the orange cable is connected between the DHT and gas sensor? If that is the case it’s wrong. Both sensor should be connected to 5V and Ground. To make it easy to test connect each sensor separatly. Dht sensor to 5v on Vdd pin, GND to GND. And s pin to an input on the Arduino. The gas sensor need to have the heater in the sensor connected to 5V and GND. Then you also need a wire from 5V to one side of the gas sensor and another wire from the sensor to an input om the Arduino. So 3 cables to dht sensor. 4 cables to gas sensor. I also want to highlight that the dht sensor turned out to be unnessecary and you can just set the temperature to a fixed constant in the code.


  25. I changed up some wires and now it says ‘DHT ok” and its giving me normal readings for like one minute and then the screen slowly fades out. Do you think its not getting enough power?


  26. also I’m not using a voltage regulator. I’m getting power straight from the usb cable to the arduino. Do you think its why it is fading and not getting enough power?


  27. Okay.This is a video of what i got so far. It prompts us to blow but when we do nothing changes. The readings remain static and don’t change for some reason. what do you think might cause this?


  28. Hey Jenslab. I connected the pins as you showed me in the schematic. Used another arduino with 5v as a separate power source for the sensor and the normal arduino as it was. It gave me some values but when i blow it doesn’t increase nor decrease so i don’t know if its accurate. Also i tried using a 9v battery to power sensor and got the same values. Then i tried switching the two 5V pins on the sensor and exchanging the power source between the arduino and the battery and got different values. The thing is out of all the three attempts none really gave me an accurate reading when i blew into the sensor so i really don’t know if its reading my breath or not. I have attached some pictures and videos so you can have a better picture.


Lämna ett svar till Avbryt svar

Fyll i dina uppgifter nedan eller klicka på en ikon för att logga in:

Du kommenterar med ditt Logga ut /  Ändra )


Du kommenterar med ditt Twitter-konto. Logga ut /  Ändra )


Du kommenterar med ditt Facebook-konto. Logga ut /  Ändra )

Ansluter till %s

%d bloggare gillar detta: