1+ /* 1.0.0 VERSION */
2+
3+ #include " ddmq4.h"
4+
5+ DDMQ4::DDMQ4 (int pin)
6+ {
7+ this ->_analogPin = pin;
8+ }
9+
10+ DDMQ4Val DDMQ4::getValue ()
11+ {
12+
13+ float sensor_volt; // Define variable for sensor voltage
14+ float RS_gas; // Define variable for sensor resistance
15+ float ratio; // Define variable for ratio
16+
17+ float sensorValue = analogRead (this ->_analogPin );
18+
19+ sensor_volt = sensorValue * (3.3 / 1023.0 ); // Convert analog values to voltage
20+ RS_gas = ((3.3 * 10.0 ) / sensor_volt) - 10.0 ; // Get value of RS in a gas
21+ ratio = RS_gas / this ->_R0 ; // Get ratio RS_gas/RS_air
22+
23+ double ppm_log = (log10 (ratio) - this ->_b ) / this ->_m ; // Get ppm value in linear scale according to the the ratio value
24+ double ppm = pow (10 , ppm_log); // Convert ppm value to log scale
25+ double percentage = ppm / 10000 ; // Convert to percentage
26+
27+ float realValue = 0.0 ;
28+
29+ if (sensorValue > this ->_valorecentrale )
30+ {
31+ realValue = this ->fscale (this ->_valorecentrale , 1023 , 1000 , 10000 , sensorValue, 10 );
32+ }
33+ else
34+ {
35+ realValue = this ->fscale (0 , this ->_valorecentrale , 200 , 1000 , sensorValue, 10 );
36+ }
37+
38+ DDMQ4Val ret;
39+ ret.realValue = realValue;
40+ ret.ppm = ppm;
41+ ret.sensorValue = sensorValue;
42+ ret.percentage = percentage;
43+ ret.success = true ;
44+
45+ return ret;
46+ }
47+
48+ float DDMQ4::fscale (float originalMin, float originalMax, float newBegin, float newEnd, float inputValue, float curve)
49+ {
50+
51+ float OriginalRange = 0 ;
52+ float NewRange = 0 ;
53+ float zeroRefCurVal = 0 ;
54+ float normalizedCurVal = 0 ;
55+ float rangedValue = 0 ;
56+ boolean invFlag = 0 ;
57+
58+ // condition curve parameter
59+ // limit range
60+
61+ if (curve > 10 )
62+ curve = 10 ;
63+ if (curve < -10 )
64+ curve = -10 ;
65+
66+ curve = (curve * -.1 ); // - invert and scale - this seems more intuitive - postive numbers give more weight to high end on output
67+ curve = pow (10 , curve); // convert linear scale into lograthimic exponent for other pow function
68+
69+ /*
70+ Serial.println(curve * 100, DEC); // multply by 100 to preserve resolution
71+ Serial.println();
72+ */
73+
74+ // Check for out of range inputValues
75+ if (inputValue < originalMin)
76+ {
77+ inputValue = originalMin;
78+ }
79+ if (inputValue > originalMax)
80+ {
81+ inputValue = originalMax;
82+ }
83+
84+ // Zero Refference the values
85+ OriginalRange = originalMax - originalMin;
86+
87+ if (newEnd > newBegin)
88+ {
89+ NewRange = newEnd - newBegin;
90+ }
91+ else
92+ {
93+ NewRange = newBegin - newEnd;
94+ invFlag = 1 ;
95+ }
96+
97+ zeroRefCurVal = inputValue - originalMin;
98+ normalizedCurVal = zeroRefCurVal / OriginalRange; // normalize to 0 - 1 float
99+
100+ /*
101+ Serial.print(OriginalRange, DEC);
102+ Serial.print(" ");
103+ Serial.print(NewRange, DEC);
104+ Serial.print(" ");
105+ Serial.println(zeroRefCurVal, DEC);
106+ Serial.println();
107+ */
108+
109+ // Check for originalMin > originalMax - the math for all other cases i.e. negative numbers seems to work out fine
110+ if (originalMin > originalMax)
111+ {
112+ return 0 ;
113+ }
114+
115+ if (invFlag == 0 )
116+ {
117+ rangedValue = (pow (normalizedCurVal, curve) * NewRange) + newBegin;
118+ }
119+ else // invert the ranges
120+ {
121+ rangedValue = newBegin - (pow (normalizedCurVal, curve) * NewRange);
122+ }
123+
124+ return rangedValue;
125+ }
0 commit comments