From ea9596ecaf1a6e467b9f7a4b7c9bd1ac979bf423 Mon Sep 17 00:00:00 2001
From: Reinhold Kainhofer <reinhold@kainhofer.com>
Date: Sun, 2 Jul 2017 17:32:41 +0200
Subject: [PATCH] Optimize MQ sensors (share default curve coefficients) (#162)

* Fix compilation and other issues

-) Enums (in particular the sensor types) start with 0, so we have to allow a sensor type of 0
-) Add missing SensorMQ::setTargetGas method
-) Make gas type identifiers for MQ sensors const static to preserve 6 bytes of memory per MQ instance

* Fix wrong array index (typo)

* Optimize the MQ sensors by using one static array for the default curve coefficients. This adds three extra pointers, but saves 48 bytes for each additional MQ sensor after the first
---
 NodeManager.cpp | 25 +++++++++++++++----------
 NodeManager.h   | 15 +++++++++------
 2 files changed, 24 insertions(+), 16 deletions(-)

diff --git a/NodeManager.cpp b/NodeManager.cpp
index 7336b57..06ead41 100644
--- a/NodeManager.cpp
+++ b/NodeManager.cpp
@@ -2174,12 +2174,23 @@ void SensorMCP9808::onProcess(Request & request) {
  * SensorMQ
  */
 #if MODULE_MQ == 1
+
+static float SensorMQ::_default_LPGCurve[3] = {2.3,0.21,-0.47};
+static float SensorMQ::_default_COCurve[3] = {2.3,0.72,-0.34};
+static float SensorMQ::_default_SmokeCurve[3] = {2.3,0.53,-0.44};
+
 SensorMQ::SensorMQ(NodeManager* node_manager, int child_id, int pin): Sensor(node_manager,child_id,pin) {
   setPresentation(S_AIR_QUALITY);
   setType(V_LEVEL);
+  _LPGCurve = SensorMQ::_default_LPGCurve;
+  _COCurve = SensorMQ::_default_COCurve;
+  _SmokeCurve = SensorMQ::_default_SmokeCurve;
 }
 
 //setter/getter
+void SensorMQ::setTargetGas(int value) {
+  _target_gas = value;
+}
 void SensorMQ::setRlValue(float value) {
   _rl_value = value;
 }
@@ -2202,19 +2213,13 @@ void SensorMQ::setReadSampleInterval(int value) {
   _read_sample_interval = value;
 }
 void SensorMQ::setLPGCurve(float *value) {
-  _LPGCurve[0] = value[0];
-  _LPGCurve[2] = value[1];
-  _LPGCurve[2] = value[2];
+  _LPGCurve = value;
 }
 void SensorMQ::setCOCurve(float *value) {
-  _COCurve[0] = value[0];
-  _COCurve[2] = value[1];
-  _COCurve[2] = value[2];
+  _COCurve = value;
 }
 void SensorMQ::setSmokeCurve(float *value) {
-  _SmokeCurve[0] = value[0];
-  _SmokeCurve[2] = value[1];
-  _SmokeCurve[2] = value[2];
+  _SmokeCurve = value;
 }
 
 // what to do during before
@@ -2570,7 +2575,7 @@ int NodeManager::registerSensor(int sensor_type, int pin, int child_id) {
   // get a child_id if not provided by the user
   if (child_id < 0) child_id = _getAvailableChildId();
   // based on the given sensor type instantiate the appropriate class
-  if (sensor_type == 0) return -1;
+  if (sensor_type < 0) return -1;
   #if MODULE_ANALOG_INPUT == 1
     else if (sensor_type == SENSOR_ANALOG_INPUT) return registerSensor(new SensorAnalogInput(this,child_id, pin));
     else if (sensor_type == SENSOR_LDR) return registerSensor(new SensorLDR(this,child_id, pin));
diff --git a/NodeManager.h b/NodeManager.h
index 5123a11..7e752f6 100644
--- a/NodeManager.h
+++ b/NodeManager.h
@@ -1116,17 +1116,20 @@ class SensorMQ: public Sensor {
     int _read_sample_interval = 50;
     int _read_sample_times = 5;
     float _ro = 10000.0;
-    float _LPGCurve[3] = {2.3,0.21,-0.47};
-    float _COCurve[3] = {2.3,0.72,-0.34};
-    float _SmokeCurve[3] = {2.3,0.53,-0.44};
+    static float _default_LPGCurve[3];
+    static float _default_COCurve[3];
+    static float _default_SmokeCurve[3];
+    float *_LPGCurve;
+    float *_COCurve;
+    float *_SmokeCurve;
     float _MQResistanceCalculation(int raw_adc);
     float _MQCalibration();
     float _MQRead();
     int _MQGetGasPercentage(float rs_ro_ratio, int gas_id);
     int  _MQGetPercentage(float rs_ro_ratio, float *pcurve);
-    int _gas_lpg = 0;
-    int _gas_co = 1;
-    int _gas_smoke = 2;
+    const static int _gas_lpg = 0;
+    const static int _gas_co = 1;
+    const static int _gas_smoke = 2;
     int _target_gas = _gas_co;
 };
 #endif
-- 
GitLab