Commit 17f53c08 authored by user2684's avatar user2684
Browse files

Add support for MQ gas sensor #36

parent 15fc8d41
...@@ -154,6 +154,12 @@ void Sensor::before() { ...@@ -154,6 +154,12 @@ void Sensor::before() {
onBefore(); onBefore();
} }
// call the sensor-specific implementation of setup
void Sensor::setup() {
if (_pin == -1) return;
onSetup();
}
// call the sensor-specific implementation of loop // call the sensor-specific implementation of loop
void Sensor::loop(const MyMessage & message) { void Sensor::loop(const MyMessage & message) {
if (_pin == -1) return; if (_pin == -1) return;
...@@ -278,12 +284,16 @@ void SensorAnalogInput::setRangeMax(int value) { ...@@ -278,12 +284,16 @@ void SensorAnalogInput::setRangeMax(int value) {
_range_max = value; _range_max = value;
} }
// what do to during setup // what do to during before
void SensorAnalogInput::onBefore() { void SensorAnalogInput::onBefore() {
// prepare the pin for input // prepare the pin for input
pinMode(_pin, INPUT); pinMode(_pin, INPUT);
} }
// what do to during setup
void SensorAnalogInput::onSetup() {
}
// what do to during loop // what do to during loop
void SensorAnalogInput::onLoop() { void SensorAnalogInput::onLoop() {
// read the input // read the input
...@@ -375,12 +385,16 @@ void SensorThermistor::setOffset(float value) { ...@@ -375,12 +385,16 @@ void SensorThermistor::setOffset(float value) {
_offset = value; _offset = value;
} }
// what do to during setup // what do to during before
void SensorThermistor::onBefore() { void SensorThermistor::onBefore() {
// set the pin as input // set the pin as input
pinMode(_pin, INPUT); pinMode(_pin, INPUT);
} }
// what do to during setup
void SensorThermistor::onSetup() {
}
// what do to during loop // what do to during loop
void SensorThermistor::onLoop() { void SensorThermistor::onLoop() {
// read the voltage across the thermistor // read the voltage across the thermistor
...@@ -423,12 +437,16 @@ void SensorThermistor::onReceive(const MyMessage & message) { ...@@ -423,12 +437,16 @@ void SensorThermistor::onReceive(const MyMessage & message) {
SensorDigitalInput::SensorDigitalInput(int child_id, int pin): Sensor(child_id, pin) { SensorDigitalInput::SensorDigitalInput(int child_id, int pin): Sensor(child_id, pin) {
} }
// what do to during setup // what do to during before
void SensorDigitalInput::onBefore() { void SensorDigitalInput::onBefore() {
// set the pin for input // set the pin for input
pinMode(_pin, INPUT); pinMode(_pin, INPUT);
} }
// what do to during setup
void SensorDigitalInput::onSetup() {
}
// what do to during loop // what do to during loop
void SensorDigitalInput::onLoop() { void SensorDigitalInput::onLoop() {
// read the value // read the value
...@@ -459,6 +477,7 @@ void SensorDigitalInput::onReceive(const MyMessage & message) { ...@@ -459,6 +477,7 @@ void SensorDigitalInput::onReceive(const MyMessage & message) {
SensorDigitalOutput::SensorDigitalOutput(int child_id, int pin): Sensor(child_id, pin) { SensorDigitalOutput::SensorDigitalOutput(int child_id, int pin): Sensor(child_id, pin) {
} }
// what do to during before
void SensorDigitalOutput::onBefore() { void SensorDigitalOutput::onBefore() {
// set the pin as output and initialize it accordingly // set the pin as output and initialize it accordingly
pinMode(_pin, OUTPUT); pinMode(_pin, OUTPUT);
...@@ -467,6 +486,10 @@ void SensorDigitalOutput::onBefore() { ...@@ -467,6 +486,10 @@ void SensorDigitalOutput::onBefore() {
_value_int = _initial_value; _value_int = _initial_value;
} }
// what do to during setup
void SensorDigitalOutput::onSetup() {
}
// setter/getter // setter/getter
void SensorDigitalOutput::setInitialValue(int value) { void SensorDigitalOutput::setInitialValue(int value) {
_initial_value = value; _initial_value = value;
...@@ -560,12 +583,16 @@ SensorDHT::SensorDHT(int child_id, int pin, DHT* dht, int sensor_type, int dht_t ...@@ -560,12 +583,16 @@ SensorDHT::SensorDHT(int child_id, int pin, DHT* dht, int sensor_type, int dht_t
} }
} }
// what do to during setup // what do to during before
void SensorDHT::onBefore() { void SensorDHT::onBefore() {
// initialize the dht library // initialize the dht library
_dht->begin(); _dht->begin();
} }
// what do to during setup
void SensorDHT::onSetup() {
}
// what do to during loop // what do to during loop
void SensorDHT::onLoop() { void SensorDHT::onLoop() {
// temperature sensor // temperature sensor
...@@ -627,12 +654,16 @@ SensorSHT21::SensorSHT21(int child_id, int sensor_type): Sensor(child_id,A2) { ...@@ -627,12 +654,16 @@ SensorSHT21::SensorSHT21(int child_id, int sensor_type): Sensor(child_id,A2) {
} }
} }
// what do to during setup // what do to during before
void SensorSHT21::onBefore() { void SensorSHT21::onBefore() {
// initialize the library // initialize the library
Wire.begin(); Wire.begin();
} }
// what do to during setup
void SensorSHT21::onSetup() {
}
// what do to during loop // what do to during loop
void SensorSHT21::onLoop() { void SensorSHT21::onLoop() {
// temperature sensor // temperature sensor
...@@ -708,13 +739,17 @@ int SensorSwitch::getInitial() { ...@@ -708,13 +739,17 @@ int SensorSwitch::getInitial() {
return _initial; return _initial;
} }
// what do to during setup // what do to during before
void SensorSwitch::onBefore() { void SensorSwitch::onBefore() {
// initialize the value // initialize the value
if (_mode == RISING) _value_int = LOW; if (_mode == RISING) _value_int = LOW;
else if (_mode == FALLING) _value_int = HIGH; else if (_mode == FALLING) _value_int = HIGH;
} }
// what do to during setup
void SensorSwitch::onSetup() {
}
// what do to during loop // what do to during loop
void SensorSwitch::onLoop() { void SensorSwitch::onLoop() {
// wait to ensure the the input is not floating // wait to ensure the the input is not floating
...@@ -775,10 +810,14 @@ SensorDs18b20::SensorDs18b20(int child_id, int pin, DallasTemperature* sensors, ...@@ -775,10 +810,14 @@ SensorDs18b20::SensorDs18b20(int child_id, int pin, DallasTemperature* sensors,
_sensors = sensors; _sensors = sensors;
} }
// what do to during setup // what do to during before
void SensorDs18b20::onBefore() { void SensorDs18b20::onBefore() {
} }
// what do to during setup
void SensorDs18b20::onSetup() {
}
// what do to during loop // what do to during loop
void SensorDs18b20::onLoop() { void SensorDs18b20::onLoop() {
// request the temperature // request the temperature
...@@ -814,11 +853,15 @@ SensorBH1750::SensorBH1750(int child_id): Sensor(child_id,A4) { ...@@ -814,11 +853,15 @@ SensorBH1750::SensorBH1750(int child_id): Sensor(child_id,A4) {
_lightSensor = new BH1750(); _lightSensor = new BH1750();
} }
// what do to during setup // what do to during before
void SensorBH1750::onBefore() { void SensorBH1750::onBefore() {
_lightSensor->begin(); _lightSensor->begin();
} }
// what do to during setup
void SensorBH1750::onSetup() {
}
// what do to during loop // what do to during loop
void SensorBH1750::onLoop() { void SensorBH1750::onLoop() {
// request the light level // request the light level
...@@ -852,12 +895,16 @@ SensorMLX90614::SensorMLX90614(int child_id, Adafruit_MLX90614* mlx, int sensor_ ...@@ -852,12 +895,16 @@ SensorMLX90614::SensorMLX90614(int child_id, Adafruit_MLX90614* mlx, int sensor_
setValueType(TYPE_FLOAT); setValueType(TYPE_FLOAT);
} }
// what do to during setup // what do to during before
void SensorMLX90614::onBefore() { void SensorMLX90614::onBefore() {
// initialize the library // initialize the library
_mlx->begin(); _mlx->begin();
} }
// what do to during setup
void SensorMLX90614::onSetup() {
}
// what do to during loop // what do to during loop
void SensorMLX90614::onLoop() { void SensorMLX90614::onLoop() {
float temperature = _sensor_type == 0 ? _mlx->readAmbientTempC() : _mlx->readObjectTempC(); float temperature = _sensor_type == 0 ? _mlx->readAmbientTempC() : _mlx->readObjectTempC();
...@@ -907,9 +954,12 @@ SensorBME280::SensorBME280(int child_id, Adafruit_BME280* bme, int sensor_type): ...@@ -907,9 +954,12 @@ SensorBME280::SensorBME280(int child_id, Adafruit_BME280* bme, int sensor_type):
} }
} }
// what do to during setup // what do to during before
void SensorBME280::onBefore() { void SensorBME280::onBefore() {
// initialize the library }
// what do to during setup
void SensorBME280::onSetup() {
} }
// what do to during loop // what do to during loop
...@@ -965,6 +1015,152 @@ void SensorBME280::onReceive(const MyMessage & message) { ...@@ -965,6 +1015,152 @@ void SensorBME280::onReceive(const MyMessage & message) {
} }
#endif #endif
/*
* SensorMQ
*/
SensorMQ::SensorMQ(int child_id, int pin): Sensor(child_id,pin) {
setPresentation(S_AIR_QUALITY);
setType(V_LEVEL);
}
//setter/getter
void SensorMQ::setRlValue(float value) {
_rl_value = value;
}
void SensorMQ::setRoValue(float value) {
_ro = value;
}
void SensorMQ::setCleanAirFactor(float value) {
_ro_clean_air_factor = value;
}
void SensorMQ::setCalibrationSampleTimes(int value) {
_calibration_sample_times = value;
}
void SensorMQ::setCalibrationSampleInterval(int value){
_calibration_sample_interval = value;
}
void SensorMQ::setReadSampleTimes(int value) {
_read_sample_times = value;
}
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];
}
void SensorMQ::setCOCurve(float *value) {
_COCurve[0] = value[0];
_COCurve[2] = value[1];
_COCurve[2] = value[2];
}
void SensorMQ::setSmokeCurve(float *value) {
_SmokeCurve[0] = value[0];
_SmokeCurve[2] = value[1];
_SmokeCurve[2] = value[2];
}
// what do to during before
void SensorMQ::onBefore() {
// prepare the pin for input
pinMode(_pin, INPUT);
}
// what do to during setup
void SensorMQ::onSetup() {
_ro = _MQCalibration();
onLoop();
}
// what do to during loop
void SensorMQ::onLoop() {
if (_pin == -1) return;
// calculate rs/ro
float mq = _MQRead()/_ro;
// calculate the ppm
float lpg = _MQGetGasPercentage(mq,_gas_lpg);
float co = _MQGetGasPercentage(mq,_gas_co);
float smoke = _MQGetGasPercentage(mq,_gas_smoke);
// assign to the value the requested gas
uint16_t value;
if (_target_gas == _gas_lpg) value = lpg;
if (_target_gas == _gas_co) value = co;
if (_target_gas == _gas_smoke) value = smoke;
#if DEBUG == 1
Serial.print(F("MQ I="));
Serial.print(_child_id);
Serial.print(F(" V="));
Serial.print(value);
Serial.print(F(" LPG="));
Serial.print(lpg);
Serial.print(F(" CO="));
Serial.print(co);
Serial.print(F(" SMOKE="));
Serial.println(smoke);
#endif
// store the value
_value_int = (int16_t)ceil(value);
}
// what do to as the main task when receiving a message
void SensorMQ::onReceive(const MyMessage & message) {
onLoop();
}
// returns the calculated sensor resistance
float SensorMQ::_MQResistanceCalculation(int raw_adc) {
return ( ((float)_rl_value*(1023-raw_adc)/raw_adc));
}
// This function assumes that the sensor is in clean air
float SensorMQ::_MQCalibration() {
int i;
float val=0;
//take multiple samples
for (i=0; i< _calibration_sample_times; i++) {
val += _MQResistanceCalculation(analogRead(_pin));
delay(_calibration_sample_interval);
}
//calculate the average value
val = val/_calibration_sample_times;
//divided by RO_CLEAN_AIR_FACTOR yields the Ro
val = val/_ro_clean_air_factor;
//according to the chart in the datasheet
return val;
}
// This function use MQResistanceCalculation to caculate the sensor resistenc (Rs).
float SensorMQ::_MQRead() {
int i;
float rs=0;
for (i=0; i<_read_sample_times; i++) {
rs += _MQResistanceCalculation(analogRead(_pin));
delay(_read_sample_interval);
}
rs = rs/_read_sample_times;
return rs;
}
// This function passes different curves to the MQGetPercentage function which calculates the ppm (parts per million) of the target gas.
int SensorMQ::_MQGetGasPercentage(float rs_ro_ratio, int gas_id) {
if ( gas_id == _gas_lpg ) {
return _MQGetPercentage(rs_ro_ratio,_LPGCurve);
} else if ( gas_id == _gas_co) {
return _MQGetPercentage(rs_ro_ratio,_COCurve);
} else if ( gas_id == _gas_smoke) {
return _MQGetPercentage(rs_ro_ratio,_SmokeCurve);
}
return 0;
}
// returns ppm of the target gas
int SensorMQ::_MQGetPercentage(float rs_ro_ratio, float *pcurve) {
return (pow(10,( ((log10(rs_ro_ratio)-pcurve[1])/pcurve[2]) + pcurve[0])));
}
/******************************************* /*******************************************
NodeManager NodeManager
*/ */
...@@ -1059,6 +1255,7 @@ int NodeManager::registerSensor(int sensor_type, int pin, int child_id) { ...@@ -1059,6 +1255,7 @@ int NodeManager::registerSensor(int sensor_type, int pin, int child_id) {
else if (sensor_type == SENSOR_ANALOG_INPUT) return registerSensor(new SensorAnalogInput(child_id, pin)); else if (sensor_type == SENSOR_ANALOG_INPUT) return registerSensor(new SensorAnalogInput(child_id, pin));
else if (sensor_type == SENSOR_LDR) return registerSensor(new SensorLDR(child_id, pin)); else if (sensor_type == SENSOR_LDR) return registerSensor(new SensorLDR(child_id, pin));
else if (sensor_type == SENSOR_THERMISTOR) return registerSensor(new SensorThermistor(child_id, pin)); else if (sensor_type == SENSOR_THERMISTOR) return registerSensor(new SensorThermistor(child_id, pin));
else if (sensor_type == SENSOR_MQ) return registerSensor(new SensorMQ(child_id, pin));
#endif #endif
#if MODULE_DIGITAL_INPUT == 1 #if MODULE_DIGITAL_INPUT == 1
else if (sensor_type == SENSOR_DIGITAL_INPUT) return registerSensor(new SensorDigitalInput(child_id, pin)); else if (sensor_type == SENSOR_DIGITAL_INPUT) return registerSensor(new SensorDigitalInput(child_id, pin));
...@@ -1305,6 +1502,12 @@ void NodeManager::setup() { ...@@ -1305,6 +1502,12 @@ void NodeManager::setup() {
#if SERVICE_MESSAGES == 1 #if SERVICE_MESSAGES == 1
_send(_msg.set("STARTED")); _send(_msg.set("STARTED"));
#endif #endif
// run setup for all the registered sensors
for (int i = 0; i < 255; i++) {
if (_sensors[i] == 0) continue;
// call each sensor's setup()
_sensors[i]->setup();
}
} }
// run the main function for all the register sensors // run the main function for all the register sensors
......
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
#define EEPROM_SLEEP_UNIT 4 #define EEPROM_SLEEP_UNIT 4
// define NodeManager version // define NodeManager version
#define VERSION 1.3 #define VERSION 1.4
/************************************ /************************************
* Include user defined configuration settings * Include user defined configuration settings
...@@ -97,7 +97,7 @@ ...@@ -97,7 +97,7 @@
#define BATTERY_CHILD_ID 201 #define BATTERY_CHILD_ID 201
#endif #endif
// Enable this module to use one of the following sensors: SENSOR_ANALOG_INPUT, SENSOR_LDR, SENSOR_THERMISTOR // Enable this module to use one of the following sensors: SENSOR_ANALOG_INPUT, SENSOR_LDR, SENSOR_THERMISTOR, SENSOR_MQ
#ifndef MODULE_ANALOG_INPUT #ifndef MODULE_ANALOG_INPUT
#define MODULE_ANALOG_INPUT 0 #define MODULE_ANALOG_INPUT 0
#endif #endif
...@@ -147,6 +147,8 @@ ...@@ -147,6 +147,8 @@
#define SENSOR_LDR 2 #define SENSOR_LDR 2
// Thermistor sensor, return the temperature based on the attached thermistor // Thermistor sensor, return the temperature based on the attached thermistor
#define SENSOR_THERMISTOR 3 #define SENSOR_THERMISTOR 3
// MQ2 air quality sensor
#define SENSOR_MQ 19
#endif #endif
#if MODULE_DIGITAL_INPUT == 1 #if MODULE_DIGITAL_INPUT == 1
// Generic digital sensor, return a pin's digital value // Generic digital sensor, return a pin's digital value
...@@ -194,7 +196,7 @@ ...@@ -194,7 +196,7 @@
// MLX90614 sensor, contactless temperature sensor // MLX90614 sensor, contactless temperature sensor
#define SENSOR_BME280 18 #define SENSOR_BME280 18
#endif #endif
// last Id: 18 // last Id: 19
/*********************************** /***********************************
Libraries Libraries
*/ */
...@@ -301,10 +303,12 @@ class Sensor { ...@@ -301,10 +303,12 @@ class Sensor {
// define what to do at each stage of the sketch // define what to do at each stage of the sketch
virtual void before(); virtual void before();
virtual void presentation(); virtual void presentation();
virtual void setup();
virtual void loop(const MyMessage & message); virtual void loop(const MyMessage & message);
virtual void receive(const MyMessage & message); virtual void receive(const MyMessage & message);
// abstract functions, subclasses need to implement // abstract functions, subclasses need to implement
virtual void onBefore() = 0; virtual void onBefore() = 0;
virtual void onSetup() = 0;
virtual void onLoop() = 0; virtual void onLoop() = 0;
virtual void onReceive(const MyMessage & message) = 0; virtual void onReceive(const MyMessage & message) = 0;
protected: protected:
...@@ -353,6 +357,7 @@ class SensorAnalogInput: public Sensor { ...@@ -353,6 +357,7 @@ class SensorAnalogInput: public Sensor {
void setRangeMax(int value); void setRangeMax(int value);
// define what to do at each stage of the sketch // define what to do at each stage of the sketch
void onBefore(); void onBefore();
void onSetup();
void onLoop(); void onLoop();
void onReceive(const MyMessage & message); void onReceive(const MyMessage & message);
protected: protected:
...@@ -391,6 +396,7 @@ class SensorThermistor: public Sensor { ...@@ -391,6 +396,7 @@ class SensorThermistor: public Sensor {
void setOffset(float value); void setOffset(float value);
// define what to do at each stage of the sketch // define what to do at each stage of the sketch
void onBefore(); void onBefore();
void onSetup();
void onLoop(); void onLoop();
void onReceive(const MyMessage & message); void onReceive(const MyMessage & message);
protected: protected:
...@@ -409,6 +415,7 @@ class SensorDigitalInput: public Sensor { ...@@ -409,6 +415,7 @@ class SensorDigitalInput: public Sensor {
SensorDigitalInput(int child_id, int pin); SensorDigitalInput(int child_id, int pin);
// define what to do at each stage of the sketch // define what to do at each stage of the sketch
void onBefore(); void onBefore();
void onSetup();
void onLoop(); void onLoop();
void onReceive(const MyMessage & message); void onReceive(const MyMessage & message);
}; };
...@@ -425,6 +432,7 @@ class SensorDigitalOutput: public Sensor { ...@@ -425,6 +432,7 @@ class SensorDigitalOutput: public Sensor {
void setPulseWidth(int value); void setPulseWidth(int value);
// define what to do at each stage of the sketch // define what to do at each stage of the sketch
void onBefore(); void onBefore();
void onSetup();
void onLoop(); void onLoop();
void onReceive(const MyMessage & message); void onReceive(const MyMessage & message);
protected: protected:
...@@ -460,6 +468,7 @@ class SensorDHT: public Sensor { ...@@ -460,6 +468,7 @@ class SensorDHT: public Sensor {
SensorDHT(int child_id, int pin, DHT* dht, int sensor_type, int dht_type); SensorDHT(int child_id, int pin, DHT* dht, int sensor_type, int dht_type);
// define what to do at each stage of the sketch // define what to do at each stage of the sketch
void onBefore(); void onBefore();
void onSetup();
void onLoop(); void onLoop();
void onReceive(const MyMessage & message); void onReceive(const MyMessage & message);
protected: protected:
...@@ -479,6 +488,7 @@ class SensorSHT21: public Sensor { ...@@ -479,6 +488,7 @@ class SensorSHT21: public Sensor {
SensorSHT21(int child_id, int sensor_type); SensorSHT21(int child_id, int sensor_type);
// define what to do at each stage of the sketch // define what to do at each stage of the sketch
void onBefore(); void onBefore();
void onSetup();
void onLoop(); void onLoop();
void onReceive(const MyMessage & message); void onReceive(const MyMessage & message);
protected: protected:
...@@ -514,6 +524,7 @@ class SensorSwitch: public Sensor { ...@@ -514,6 +524,7 @@ class SensorSwitch: public Sensor {
int getInitial(); int getInitial();
// define what to do at each stage of the sketch // define what to do at each stage of the sketch
void onBefore(); void onBefore();
void onSetup();
void onLoop(); void onLoop();
void onReceive(const MyMessage & message); void onReceive(const MyMessage & message);