DIY weather station /w Enviro+ (MICS6814) - Converting Ohms to PPM

Hi there,

first off: this is not an openHAB-related topic but I wanted to post anyway because you guys always helped me =) (thanks for that)!

I ordered an Enviro+ sensor board ( to build a Raspberry-based weather station. Assembling was quite easy and I came up with a self-written .py that reads sensor data and sends it to an MQTT broker.

openHAB subscribes to that MQTT broker and integrating the topics into OH works like a charm. Furthermore I’m persisting data in InfluxDB and visualize it in Grafana.

On the Enviro+ board, there’s a MICS6814 sensor for measuring “reducing”, “oxidising” and NH3 gas(es). As the measurements are converted to Ohms I’d like to convert them into PPM to get a better understanding about air quality. Of course you could also monitor the Ohms and track air quality via them, but that’s not what I’d like to achieve.

So my question to all of you, who already did a similar conversion, is how I could tackle this. I’ve found a fact sheet @, but at least the “reducing” graph’s Y-axis only reaches to RS/R0 = 10.

Current readings are:

  • redu = 504 kOhm
  • oxid = 27 kOhm
  • NH3 = 369 kOhm

As always many thanks for your time, have a nice day!

What are the formulas?
Apply the formulas inside the python script BEFORE sending on MQTT and you will the “correct” values into openHAB

The key here is that you need to find you what are the mathematical formulae to convert the ohm value from the sensor into ppm

Hi Vincent,

unfortunately there are no formulas, just these diagrams with RS/R0 over PPM.

Please don’t get me wrong, I’m not assuming that anyone here is providing a working conversion for my specific case. I’m just looking if anyone has an approach on converting Ohms to PPM when it comes to eletrical sensors.

Many thanks for your reply and your tip with including that conversion into .py-script, I’m aware of that :). I’ll investigate further and if I find a solution I’ll post here!


According to this site, PPM is

a method of stating a component’s tolerance value by specifying how many parts per million units a component may vary from its nominal value.

Put another way, it’s a way to determine the tolerances of the electrical component. I’m definitely no expert, but I don’t think there is a single calculation that will work here. Every resistor and capacitor will have it’s own individual set of tolerances. One of the examples from that site might be informative:

Let’s say we a 1MΩ resistor.

A 1MΩ resistor is a resistor that has a color code of brown-black-green. It has a nominal value of 1,000,000Ω.

Now let’s say this resistor has a parts per million specification of 5000ppm. This means that for every 1,000,000 ohms of resistance that this resistor has, the resistance can vary as much as 5000 ohms. This means that this 1MΩ can have a resistance 5000 ohms below or above 1,000,000 ohms, which means its resistance can be as low as 995,000Ω or as high as 1,005,000Ω or somewhere in between.

Is that what you are after, or are you hoping to be able to convert the Ohms to a PPM of the gases you are sensing? If it’s the latter, you can’t get there from here.

In gas work, ppm is a measure of concentration. Just another way to express percentage or ratio.

I think OP needs his sensor maker to cough up the needed formulae ?

Hi there,

many thanks for the links. I’ve found a C++ library @ [1] where the author is starting conversion at line 349 and below.

Curious about lines like “c = pow(ratio1, -1.179)*4.385” I thought about exponential curves and stumbled upon a YT-video @ [2] where a guy is explaining how to read that charts and get equations in the format Y = a *x ^b out of it.

So I started again with the fact-sheet of my initial post and tried myself, being able to reconstruct almost the same values like the library in [1].

I’m testing right now and try to evaluate if the “generated” PPM could make sense in terms of common PPMs.

Thanks for your replies @rlkoshak and @rossko57!

That makes sense. Looking at the charts on the data sheet they are in a log10 scale. You can’t get a straight line on that sort of chart without there being exponential curves.

Comment only - that is a curious device. You seem to have to know what gases may be present before decoding what the output means. Reading XX might mean high AA% ammonia or BB% ethanol or CC% carbon monoxide or …

My 2 cents having spent most of my 40+ year career in R&D, I have had some experience with gas sensors. As far as I know there is no such thing as a universal sensor and each sensor needs to be calibrated for the gas of interest. This requires measuring and plotting resistance (ohms) as a function of gas concentration(ppm). A regression analysis is performed using the data collected, and unless you know with certainty otherwise, a straight line is assumed over the range of concentrations of interest, so ohms=a +m(conc) where ‘a’ is the y-axis intercept and ‘m’ is slope of the line. If the range of interest is broad and the sensor has non-linearity then a quadratic or power law fit can be used. The sensor mfg should provide this info ( at least generically if not specifically for that particular sensor) with sale of the sensor.


Hi @rossko57,
the MICS6814 has 3 different sensors, one for reducing gases, one for oxidising gases and one for NH3. Depending on what you’d like to “convert” (I’m writing this in " ", because I don’t think that this citizen science device will be able to replace professional sensors that are thoroughly calibrated) you’ve to apply your individually generated exponential curves.

For the moment I’m therefore “converting” CO and NO2.

Hi @John_Siemon,
as it’s my first touching point with that stuff (enviromental data on a citizen science base) I wanted to start a small project because I’m interested in such appliances (especially for Raspberry). I read an article about the Enviro+ sensor board in a Pi magazine and ordered it with the intention to…

  • learn sth about enviromental data
  • learn a bit of Python
  • make use of a MQTT broker
  • play around with my unused RPI

Thanks for clarifying how it’s properly done - for the moment I’m trying to calibrate NO and CO2 as there’s a professional station around that provides official calibrated and open data.

CO (my reading/conversion): 0.344ppm
NO2 (my reading/conversion): 0.005ppm

CO (official): 0.3mg/m³ eq. ~ 0.262ppm @ 28.01 g/mol
NO2 (official): 9µg/m³ eq. ~ 0.005 ppm @ 46.01 g/mol

So I’ll tweak a bit to get that CO right and then I guess I’m done.

Finally, something I’d like to add here - of course I don’t have intentions to take that collected data serious in any way. For me it’s a project that helps me learning new stuff with the idea to get a rough idea if air quality is improving or worsening.

Have a nice day and KR,

Those aren’t bad readings; I was wondering whether it was sensitive enough for any useful measurement of environmental atmosphere (as opposed to gross contaminants like a propane leak)

I think openHABs Number:Dimensionless type supports ppm units already. If the g/mol and g/m³ are common units, you could raise a request to have those added too for general benefit. My science is rusty, but those are properly “ratios” and so Dimensionless as well?

Hi guys,

after a few days of testing and tweaking I’m happy with the results. Also I don’t have any remarkable jitters (< 0,1%), so I can say that the sensor is providing stable readings (yes, at different temperatures and humidities).

Here are the main steps;

  • Read sensor-data with Python-library (these values are in Ohms for that specific sensor)
  • Based on diagrams in sensor’s fact sheet: build the exponential curve based on the gas you’d like to convert (in my case CO and NO2)
  • Put the Ohms in that equation (be careful if the diagrams are in Ohm or kOhm) to get PPM
  • Optional: Further conversion to mg/m³ [1]
  • Optional: Sending data to MQTT
  • Optional: openHAB subscribing to MQTT-topics
  • Optional: openHAB persisting data in InfluxDB
  • Optional: Grafana visualizing data from InfluxDB

In my case I was able to validate my readings via a nearby official and calibrated station.

[1] If you’re interested into further conversion like PPM to mg/m³ have a look into

Don’t hesitate to drop me a line here, I’ll elaborate further if it’s of interest.

@rossko57 - my items are numbers (float) with their unit defined specifically.

Hi, I’ve actually purchased the same hardware, with the same goal in mind, just haven’t had a chance to work it together yet. Feel like sharing your code & details of how it all works?


Hi! I have the same problem. Anyone can share the code to build the exponential curve based on the gas?


HI @Zylan, Hi @dta,

unfortunately I’m very busy at the moment, so I can’t go into details. What may help you for sure is Paul van Haastrecht’s Excel on GitHub -

If you take a look into “mics 6814.xls”, you’ll find the curves you’re looking for! These differ only slightly from mine. So @dta there’s no “code” to build the curves - you’ve to read them on your own from the fact-sheet.

@Zylan you can take a look into the shipped .py-files to get an idea of how to read sensor data.


Hi @csi_oh,

Thanks for your feedback and time. So, I don’t want the code to create the curves, only a code that converts Ohms to ppm … if possible.

Thanks again,


have you looked into this? Starting line 345ff.

Here’s some code that will do the conversion based on the datasheet graphs. They’re developed by undertaking a log-log linear regression. You will need to define R0 for each sensor, based on each sensor’s resistance in air. That allows you to undertake calibration. I haven’t included any temperature or humidity compensation at this stage.

Hope it helps.

red_r0 = 200000
ox_r0 = 20000
nh3_r0 = 750000

def read_gas_in_ppm():
gas_data = gas.read_all()
red_in_ppm = math.pow(10, -1.25 * math.log10(gas_data.reducing/red_r0) + 0.64)
ox_in_ppm = math.pow(10, math.log10(gas_data.oxidising/ox_r0) - 0.8129)
nh3_in_ppm = math.pow(10, -1.8 * math.log10(gas_data.nh3/nh3_r0) - 0.163)
return red_in_ppm, ox_in_ppm, nh3_in_ppm


Hi @Roscoe27,

The numbers here for the RED, OX and NH3 R0. Are they some rough estimates or ballpark figures? I’ve tried using this function and check the result on the sensor data sheet charts and it works out well.

So far I was just recording the kOhm output for each sensor and what always surprises me is how OX reading goes up whenever I open the window. The readouts would normally be around 22 kOhm, with opened window would go to 30-35 kOhm. I would really like to see how much ppm of NO2 are we talking about here.

You need to measure the resistances in “standard air” (i.e. with the normal levels of gas concentrations found in air) to obtain the three R0 resistance levels. They form the baselines against which RS is measured as each gas concentration varies from “standard air”. The algorithms are then applied to RS/R0 for each sensor. I don’t think you can specifically measure NO2, just the combination of oxidising gases as per the datasheet graphs.