diff --git a/examples/c++/CMakeLists.txt b/examples/c++/CMakeLists.txt index 692682cd..71350e70 100644 --- a/examples/c++/CMakeLists.txt +++ b/examples/c++/CMakeLists.txt @@ -134,6 +134,7 @@ add_executable (ak8975-example ak8975.cxx) add_executable (lsm9ds0-example lsm9ds0.cxx) add_executable (eboled-example eboled.cxx) add_executable (hyld9767-example hyld9767.cxx) +add_executable (mg811-example mg811.cxx) include_directories (${PROJECT_SOURCE_DIR}/src/hmc5883l) include_directories (${PROJECT_SOURCE_DIR}/src/grove) @@ -241,6 +242,7 @@ include_directories (${PROJECT_SOURCE_DIR}/src/hp20x) include_directories (${PROJECT_SOURCE_DIR}/src/pn532) include_directories (${PROJECT_SOURCE_DIR}/src/lsm9ds0) include_directories (${PROJECT_SOURCE_DIR}/src/hyld9767) +include_directories (${PROJECT_SOURCE_DIR}/src/mg811) target_link_libraries (hmc5883l-example hmc5883l ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries (groveled-example grove ${CMAKE_THREAD_LIBS_INIT}) @@ -376,3 +378,4 @@ target_link_libraries (ak8975-example mpu9150 ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries (lsm9ds0-example lsm9ds0 ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries (eboled-example i2clcd ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries (hyld9767-example hyld9767 ${CMAKE_THREAD_LIBS_INIT}) +target_link_libraries (mg811-example mg811 ${CMAKE_THREAD_LIBS_INIT}) diff --git a/examples/c++/mg811.cxx b/examples/c++/mg811.cxx new file mode 100644 index 00000000..b17423cf --- /dev/null +++ b/examples/c++/mg811.cxx @@ -0,0 +1,68 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2015 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include "mg811.h" + +using namespace std; + +bool shouldRun = true; + +#define MG811_AREF 5.0 + +void sig_handler(int signo) +{ + if (signo == SIGINT) + shouldRun = false; +} + +int main() +{ + signal(SIGINT, sig_handler); + +//! [Interesting] + + // Instantiate an MG811 on analog pin A0, and digital pin D2 with an + // analog reference voltage of MG811_AREF (5.0) + upm::MG811 *sensor = new upm::MG811(0, 2, MG811_AREF); + + // Every tenth of a second, sample the sensor and output it's + // detected CO2 concentration in parts per million (ppm) + + while (shouldRun) + { + cout << "CO2 concentration in PPM: " << sensor->ppm() << endl; + + usleep(100000); + } + +//! [Interesting] + + cout << "Exiting" << endl; + + delete sensor; + return 0; +} diff --git a/examples/javascript/mg811.js b/examples/javascript/mg811.js new file mode 100644 index 00000000..21e63a8e --- /dev/null +++ b/examples/javascript/mg811.js @@ -0,0 +1,53 @@ +/*jslint node:true, vars:true, bitwise:true, unparam:true */ +/*jshint unused:true */ + +/* + * Author: Jon Trulson + * Copyright (c) 2015 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +var sensorObj = require('jsupm_mg811'); + +// Instantiate an MG811 on analog pin A0, and digital pin D2 with an +// analog reference voltage of MG811_AREF (5.0) + +var sensor = new sensorObj.MG811(0, 2, 5.0); + +// Every tenth of a second, sample the sensor and output it's +// detected CO2 concentration in parts per million (ppm) + +setInterval(function() +{ + console.log("CO2 concentration in PPM: " + sensor.ppm()); +}, 100); + +// exit on ^C +process.on('SIGINT', function() +{ + sensor = null; + sensorObj.cleanUp(); + sensorObj = null; + console.log("Exiting."); + process.exit(0); +}); + diff --git a/examples/python/mg811.py b/examples/python/mg811.py new file mode 100644 index 00000000..78a75d80 --- /dev/null +++ b/examples/python/mg811.py @@ -0,0 +1,51 @@ +#!/usr/bin/python +# Author: Jon Trulson +# Copyright (c) 2015 Intel Corporation. +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +import time, sys, signal, atexit +import pyupm_mg811 as sensorObj + +# Instantiate an MG811 on analog pin A0, and digital pin D2 with an +# analog reference voltage of MG811_AREF (5.0) + +sensor = sensorObj.MG811(0, 2, 5.0) + +## Exit handlers ## +# This function stops python from printing a stacktrace when you hit control-C +def SIGINTHandler(signum, frame): + raise SystemExit + +# This function lets you run code on exit +def exitHandler(): + print "Exiting" + sys.exit(0) + +# Register exit handlers +atexit.register(exitHandler) +signal.signal(signal.SIGINT, SIGINTHandler) + +# Every tenth of a second, sample the sensor and output it's +# detected CO2 concentration in parts per million (ppm) + +while (1): + print "CO2 concentration in PPM: ", sensor.ppm() + time.sleep(.1) diff --git a/src/mg811/CMakeLists.txt b/src/mg811/CMakeLists.txt new file mode 100644 index 00000000..66b70dab --- /dev/null +++ b/src/mg811/CMakeLists.txt @@ -0,0 +1,5 @@ +set (libname "mg811") +set (libdescription "upm DFRobot CO2 sensor") +set (module_src ${libname}.cxx) +set (module_h ${libname}.h) +upm_module_init() diff --git a/src/mg811/javaupm_mg811.i b/src/mg811/javaupm_mg811.i new file mode 100644 index 00000000..e405761c --- /dev/null +++ b/src/mg811/javaupm_mg811.i @@ -0,0 +1,8 @@ +%module javaupm_mg811 +%include "../upm.i" + +%{ + #include "mg811.h" +%} + +%include "mg811.h" diff --git a/src/mg811/jsupm_mg811.i b/src/mg811/jsupm_mg811.i new file mode 100644 index 00000000..0a4a4bb9 --- /dev/null +++ b/src/mg811/jsupm_mg811.i @@ -0,0 +1,8 @@ +%module jsupm_mg811 +%include "../upm.i" + +%{ + #include "mg811.h" +%} + +%include "mg811.h" diff --git a/src/mg811/mg811.cxx b/src/mg811/mg811.cxx new file mode 100644 index 00000000..622dd854 --- /dev/null +++ b/src/mg811/mg811.cxx @@ -0,0 +1,94 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2015 Intel Corporation. + * + * Thanks to public domain code by Martin Liddament for some useful clues! + * http://www.veetech.org.uk/CO2_Monitor_Sketch_2_Operation.txt + * and sandbox electronics (http://sandboxelectronics.com/?p=147). + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include "mg811.h" + +using namespace std; +using namespace upm; + +// voltage gain of the DC amplifier +static const float dcGain = 8.5; + +MG811::MG811(int pin, int dpin, float aref) : + m_aio(pin), m_gpio(dpin) +{ + m_aRes = m_aio.getBit(); + m_aref = aref; + + m_gpio.dir(mraa::DIR_IN); + + // these are just placeholder values (coarsely measured during + // development), you should determine the appropriate values (in + // volts) for your environment at the specified concentrations. Use + // the getReferenceVoltage() method to get these values at 400ppm + // and 1000ppm respectively. Good luck. + setCalibration(0.5514, 0.370); +} + +MG811::~MG811() +{ +} + +float MG811::volts() +{ + int val = m_aio.read(); + + return(float(val) * (m_aref / float(1 << m_aRes))); +} + +void MG811::setCalibration(float ppm400, float ppm1000) +{ + m_zeroPointValue = ppm400; + m_reactionValue = ppm1000; +} + +float MG811::getReferenceVoltage() +{ + return (volts() / dcGain); +} + +float MG811::ppm() +{ + static const float log400 = log10f(400); + static const float log1000 = log10f(1000); + + float val = volts(); + + if ((val / dcGain) >= m_zeroPointValue) + return 0.0; + else + return powf(10.0, ((val/dcGain)-m_zeroPointValue) / + (m_reactionValue / (log400-log1000))+log400); +} + +bool MG811::thresholdReached() +{ + return (m_gpio.read() ? true : false); +} diff --git a/src/mg811/mg811.h b/src/mg811/mg811.h new file mode 100644 index 00000000..21aaf822 --- /dev/null +++ b/src/mg811/mg811.h @@ -0,0 +1,146 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2015 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#pragma once + +#include +#include +#include +#include + +namespace upm { + /** + * @brief DFRobot CO2 Sensor + * @defgroup mg811 libupm-mg811 + * @ingroup dfrobot analog gas + */ + + /** + * @library mg811 + * @sensor mg811 + * @comname DFRobot CO2 Sensor + * @altname MG811 + * @type gas + * @man dfrobot + * @web http://www.dfrobot.com/index.php?route=product/product&product_id=1023 + * @con analog + * + * @brief API for the DFRobot CO2 Sensor + * + * This sensor returns an an analog voltage that falls as the + * concentration of CO2 increases. It contains a heater that must + * be allowed to 'warm' up the sensor before measurements are stable + * (hours to days is the recommendation). It requires that the MCU + * be powered from an external power supply (not USB) at 5v, since + * the heater will consume significant current. + * + * The sensor should be allowed to 'heat' up for some time before + * beginning use, typically a couple of hours minimum. It also + * needs fairly precise calibration at 400ppm and 1000ppm to return + * meaningful results. + * + * The sensor also incorporates a potentiometer that can be adjusted + * to specific threshold. Once that threshold is reached, an LED + * on the sensor will light, and the digital pin will be driven + * high. + * + * @snippet mg811.cxx Interesting + */ + + class MG811 { + public: + + /** + * MG811 constructor + * + * @param pin Analog pin to use + * @param dpin Digital pin that indicates threshold + * @param aref Analog reference voltage; default is 5.0 V + */ + MG811(int pin, int dpin, float aref=5.0); + + /** + * MG811 destructor + */ + ~MG811(); + + /** + * Return a cumputed reference voltage to be used in calibration. + * @return Computed reference voltage + */ + float getReferenceVoltage(); + + /** + * Set calibration parameters. You should measure the reference + * voltage you get when at CO2 concentrations of 400ppm (ambient) + * and 1000ppm using the getReferenceVoltage() method. Then + * specify those voltages here for more accurate results. + * + * @param ppm400 The measured reference voltage at 400 ppm + * @param ppm40000 The measured reference voltage at 1000 ppm + */ + void setCalibration(float ppm400, float ppm1000); + + /** + * Returns the voltage detected on the analog pin + * + * @return The detected voltage + */ + float volts(); + + /** + * Returns the computed CO2 concentration in ppm (Parts Per + * Million). This method will return 0.0 if the reference voltage + * is greater than the ppm400 value. Essentially, ppm values + * below 400 will be reported as 0. + * + * @return The computed CO2 concentration in ppm + */ + float ppm(); + + /** + * Read the digital pin and return true if the set threshold has + * been reached or exceeded. This threshold is set by adjusting + * the potentiometer on the sensor. + * + * @return true if the threshold has been reached, false otherwise + */ + bool thresholdReached(); + + protected: + mraa::Aio m_aio; + mraa::Gpio m_gpio; + + // calibration values + float m_zeroPointValue; + float m_reactionValue; + + // ADC resolution + int m_aRes; + + private: + float m_aref; + }; +} + + diff --git a/src/mg811/pyupm_mg811.i b/src/mg811/pyupm_mg811.i new file mode 100644 index 00000000..d69f043a --- /dev/null +++ b/src/mg811/pyupm_mg811.i @@ -0,0 +1,9 @@ +%module pyupm_mg811 +%include "../upm.i" + +%feature("autodoc", "3"); + +%include "mg811.h" +%{ + #include "mg811.h" +%}