1) New sensor types to be supported!: MG811, SP3S-AQ2, TGS2600, TGS2610, TGS2611 TGS2620, TGS2612, TGS2442, TGS2201, TGS4161, TGS8100, TGS813, TGS822, TGS2602, TGS6812
"The first and only Arduino library where Geiger Counter and MQ Sensors combine with Data Science"

1) ppm = a*ratio^b (a: valuea b: valueb) 2) ppm = 10^[(log10(ratio)-b)/m] (m: logm b: logb)
If R^2 equals 1 :
a*ratio^b = 10^[(log10(ratio)-b)/m]
logm = valueb, logb = log10(valuea)
1] [(1,10), (2,4), (3,3)]
loge(b) = ln(b)
(ln(1),ln(10)) for ≈ (0,2.3026)
(ln(2),ln(4)) ≈ (0.6931,1.3863) and
(ln(3),ln(3)) ≈ (1.0986,1.0986)
b = ∑ i=1 n (x i − x ˉ ) 2 ∑ i=1 n (xi − xˉ)(yi−yˉ)
ln(x):(0,0.6931,1.0986)ln(y):(2.3026,1.3863,1.0986)ln(y)ˉ=(2.3026+1.3863+1.0986)/3≈1.5958
ln(x)ˉ=(0+0.6931+1.0986)/3≈0.5972
b = (0−0.5972)(2.3026−1.5958)+(0.6931−0.5972)(1.3863−1.5958)+(1.0986−0.5972)(1.0986−1.5958)/(0−0.5972)^2+(0.6931−0.5972)^2+(1.0986−0.5972)^2 ≈ -1.2
ln(a) = − ln ˉ (y) - b ln ˉ (x) ≈ 1.5958−(−1.2)⋅0.5972≈2.31244
a=e^2.31244 ≈ 9.947
b ≈ -1.2
a ≈ 9.947
2] y = mx+ n
n = b
log10(y) = m*log10(x) + b
-b = m*log10(x) - log10(y)
last b = log10(y) - m*log10(x)
m = (y - y0) / (x - x0)
m = (log10(y) - log10(y0)) / (log10(x) - log10(x0))
if y= a*x^b:
last m = log10(y/y0) / log10(x/x0)
m = slope of the line
b = intersection point
m = log10(y/y0) / log10(x/x0)
b = log10(y) - m*log10(x)
if r_squared >= 0.9995:
print("R-squared value for {gas name} is above 0.9995, plotting against first and last values.")
x0, y0 = x[0], y[0]
xn, yn = x[-1], y[-1]
b = np.log10(yn/y0) / np.log10(xn/x0)
a = 10**(np.log10(yn) - b * np.log10(xn))
b2 = np.log10(yn) - b * np.log10(xn)
b2_rounded = round(b2, 4)
a_rounded = round(a, 4)
b_rounded = round(b, 4)
The first formula is determined according to all points (OldCurve.py, OldCurve), while the second formula is determined according to the first and last point. Therefore, in order to collect them all in the same formula and to increase the accuracy rate, we used the method in the second formula and took the logarithm (if R^2 = 1 (%100) always: logm = valueb, logb = log10(valuea)) for slopes greater than 99.95% and collected them all in the first formula, thus we increased the accuracy rate without having to use 2 different formulas (Regression.py, NewCurve).
Therefore, we need to make a transition according to the formula: In data graphs, the x-axis is given as ppm and the y-axis is given as ratio.
ratio = a*ppm^b --> ppm = (ratio / a)^1/b
V = I x R -> VRL = [VC / (RS + RL)] x RL -> VRL = (VC x RL) / (RS + RL)
RS: -> VRL x (RS + RL) = VC x RL -> (VRL x RS) + (VRL x RL) = VC x RL -> (VRL x RS) = (VC x RL) - (VRL x RL)
RS = [(VC x RL) - (VRL x RL)] / VRL -> RS = [(VC x RL) / VRL] – RL
Rs = (voltage * Rload) / (voltage/2^n-1)) - (Rload)
SensorValue / 2^(AdcBitResulation1-1) -> SensorCalibrationValue / 2^(AdcBitResulation2-1)
Rs = 2^(AdcBitResulation1-1) * [Rload / SensorValue - Rload] -> calibrationRs = 2^(AdcBitResulation2-1) * [Rload / SensorCalibrationValue – Rload]
Ro = calibrationRs / Air ||| ratio = Rs / Ro -> ratio = Rs / (calibrationRs / Air) -> ratio = Rs x Air / calibrationRs
Ratio = (2^(AdcBitResulation1-1) * [Rload1 / SensorValue – Rload1]) * RsRoMQAir / (2^(AdcBitResulation2-1) * [Rload2 / SensorCalibrationValue – Rload2]) [Rs / Ro]
If Sensor Calibration and Sensor Measurement are Under the Same Conditions:
Rload1 = Rload2 && 2^(AdcBitResulation1-1) = 2^(AdcBitResulation2-1)
SensorRange = [0 - 2^(AdcBitResulation-1)]
if MinSensorValue == 0 && MaxSensorValue == 1: SensorRange [0 - 1]
if SensorRange [0 - 1]: 0 <= (SensorValue) <= 1 && 0 <= SensorCalibrationValue <= 1
Ratio = (MaxSensorValue * [Rload / SensorValue – Rload]) * RsRoMQAir / (MaxSensorValue * [Rload / SensorCalibrationValue – Rload]) [Rs / Ro]
Ratio = [Rload / SensorValue – Rload] * RsRoMQAir / [Rload / SensorCalibrationValue – Rload] [Rs / Ro]
Ratio = f(R) * RsRoMQAir
f(R) = [R / S - R] / [R / C - R] -> [(R - RS) / S] / [(R - RC) / C] -> [(R - RS) / S] * [C / (R - RC)]
f(R) = [(R - RS) / S] * [C / (R - RC)] = [C * (R - RS) / S (R - RC)]
g(x) = (R - Rx1) / (R - Rx2) -> g(x) = (1 - x1) / (1 - x2)
f(R) = [(R - RS) / S] * [C / (R - RC)] = [C * (1 - S) / S (1 - C)]
Ratio = [SensorCalibrationValue * (1 - SensorValue)] * RsRoMQAir / [SensorValue * (1 - SensorCalibrationValue)] [Rs / Ro]
(1) if ratio = Rs / Ro: Ratio = Ratio
(2) if ratio = Rs / Rs: RsRoMQAir = 1 --> Ratio = Ratio
(3) if ratio = Ro / Rs: a = 1 / a^(1 / b) & b = 1 / b --> Ratio = Ratio
(3) if ratio is inverted: ratio --> 1 / ratio
(ratio / a)^(1/b) --> (1 / (a * ratio))^(1/b) --> (1 / a)^(1/b) * (1 / ratio)^(1/b) --> [(1 / a)^(1/b)] * [1 / ratio^(1/b)]
(ratio / a′)^(1/b′) --> ratio^(1/b′) / a′^(1/b′)
if both sides are equal: (1 / a)^(1/b) * 1 / ratio^(1/b) = ratio^(1/b′) / a′^(1/b′) -> 1 / a′ = (1 / a)^(1/b) & b′ = 1 / b
STATUS 1: MQ-2, MQ-3, MQ-4, MQ-5, MQ-6, MQ-7, MQ-8, MQ-9, MQ-135, MQ-136, MQ-137 [Almost All & Standart]
STATUS 2: MQ303A, MQ303B, MQ307A, MQ309A [A & B models]
STATUS 3: MQ-131_LOW, MQ131 [MQ131 models]
ppm = (ratio / CorrectionCoefficient / a)^(1/b) ppm = ([1 / CorrectionCoefficient / Air × SensorRLCalRL × (CalValue × (SensorValue – 1)) / (SensorValue × (CalValue – 1))]/a)^(1/b)
ppm=([1/interpolate(RH,33,85,a_RH33,a_RH85)((temp+15)/5)^interpolate(RH,33,85,b_RH33,b_RH85)×Air×SensorRLCalRL×(CalValue×(SensorValue–1))/(SensorValue×(CalValue–1))]/a)^(1/b)
interpolate(RH, 33, 85, a_RH33, a_RH85) --> (RH-33)×(a_RH85-a_RH33)+a_RH33
interpolate(RH, 33, 85, b_RH33, b_RH85) --> (RH-33)×(b_RH85-b_RH33)+b_RH33

This repository presents a multivariable exponential regression model to estimate Average CPM (counts per minute) based on Time, Radiation dose rate (Usv/hr), Standard Deviation of CPM (sdCPM), and Total CPM Count.
The predicted average CPM is defined by the following equation:

Where:

-
Input features:
Time
Usv/hr
(radiation dose rate)sdCPM
(standard deviation of CPM)CPM Count
(total count)
-
Apply natural logarithm (
ln
) to all features except time to linearize exponential behavior. -
Fit a linear regression model to:

- Final prediction is obtained by exponentiating the output.