1 /* 2 * Author: Jon Trulson <jtrulson (at) ics.com> 3 * Copyright (c) 2015 Intel Corporation. 4 * 5 * Thanks to public domain code by Martin Liddament for some useful clues! 6 * http://www.veetech.org.uk/CO2_Monitor_Sketch_2_Operation.txt 7 * and sandbox electronics (http://sandboxelectronics.com/?p=147). 8 * 9 * Permission is hereby granted, free of charge, to any person obtaining 10 * a copy of this software and associated documentation files (the 11 * "Software"), to deal in the Software without restriction, including 12 * without limitation the rights to use, copy, modify, merge, publish, 13 * distribute, sublicense, and/or sell copies of the Software, and to 14 * permit persons to whom the Software is furnished to do so, subject to 15 * the following conditions: 16 * 17 * The above copyright notice and this permission notice shall be 18 * included in all copies or substantial portions of the Software. 19 * 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 24 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 25 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 26 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 */ 28 29 #include <iostream> 30 #include <math.h> 31 #include "mg811.h" 32 33 using namespace std; 34 using namespace upm; 35 36 // voltage gain of the DC amplifier 37 static const float dcGain = 8.5; 38 39 MG811::MG811(int pin, int dpin, float aref) : 40 m_aio(pin), m_gpio(dpin) 41 { 42 m_aRes = m_aio.getBit(); 43 m_aref = aref; 44 45 m_gpio.dir(mraa::DIR_IN); 46 47 // these are just placeholder values (coarsely measured during 48 // development), you should determine the appropriate values (in 49 // volts) for your environment at the specified concentrations. Use 50 // the getReferenceVoltage() method to get these values at 400ppm 51 // and 1000ppm respectively. Good luck. 52 setCalibration(0.5514, 0.370); 53 } 54 55 MG811::~MG811() 56 { 57 } 58 59 float MG811::volts() 60 { 61 int val = m_aio.read(); 62 63 return(float(val) * (m_aref / float(1 << m_aRes))); 64 } 65 66 void MG811::setCalibration(float ppm400, float ppm1000) 67 { 68 m_zeroPointValue = ppm400; 69 m_reactionValue = ppm1000; 70 } 71 72 float MG811::getReferenceVoltage() 73 { 74 return (volts() / dcGain); 75 } 76 77 float MG811::ppm() 78 { 79 static const float log400 = log10f(400); 80 static const float log1000 = log10f(1000); 81 82 float val = volts(); 83 84 if ((val / dcGain) >= m_zeroPointValue) 85 return 0.0; 86 else 87 return powf(10.0, ((val/dcGain)-m_zeroPointValue) / 88 (m_reactionValue / (log400-log1000))+log400); 89 } 90 91 bool MG811::thresholdReached() 92 { 93 return (m_gpio.read() ? true : false); 94 } 95