Monday, August 4, 2014

Follow-up Test on the Gas Carbon Dioxide Sensor (Sainsmart MG 811)

The CO2 sensor arrived in a package together with the ozone sensor. The ozone sensor came physically damaged, but the CO2 sensor appeared unaffected in transit. Attempts to operate the CO2 sensor revealed that it might have been damages as it only outputs values from 0-2, instead of values 400++ ppm. Datasheet and articles indicate that the LED at the back of the sensor board should light up when it detects higher than normal carbon dioxide levels. After a night of tinkering, it turned out that the digital output of the device looks to be functioning as the analog output. After some research, a devised test with a strong CO2 producing chemical reaction from baking soda and vinegar put into a capped container is conducted on the sensor. This test is more robust than breathing into the apparatus. Results indicate that the carbon dioxide sensor worked! Here is the code with which the sensor functioned:

//////////////////////////////////////////////////////////////////////
/*Author:  Tiequan Shao: tiequan.shao@sandboxelectronics.com
         Peng Wei:     peng.wei@sandboxelectronics.com
       
Lisence: Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)

Note:    This piece of source code is supposed to be used as a demostration ONLY. More
         sophisticated calibration is required for industrial field application.
       
                                                    Sandbox Electronics    2012-05-31
************************************************************************************/

/************************Hardware Related Macros************************************/
#define         MG_PIN                       (0)     //define which analog input channel you are going to use
#define         BOOL_PIN                     (2)
#define         DC_GAIN                      (8.5)   //define the DC gain of amplifier


/***********************Software Related Macros************************************/
#define         READ_SAMPLE_INTERVAL         (50)    //define how many samples you are going to take in normal operation
#define         READ_SAMPLE_TIMES            (5)     //define the time interval(in milisecond) between each samples in
                                                     //normal operation

/**********************Application Related Macros**********************************/
//These two values differ from sensor to sensor. user should derermine this value.
#define         ZERO_POINT_VOLTAGE           (0.220) //define the output of the sensor in volts when the concentration of CO2 is 400PPM
#define         REACTION_VOLTGAE             (0.020) //define the voltage drop of the sensor when move the sensor from air into 1000ppm CO2

/*****************************Globals***********************************************/
float           CO2Curve[3]  =  {2.602,ZERO_POINT_VOLTAGE,(REACTION_VOLTGAE/(2.602-3))};
                                                     //two points are taken from the curve.
                                                     //with these two points, a line is formed which is
                                                     //"approximately equivalent" to the original curve.
                                                     //data format:{ x, y, slope}; point1: (lg400, 0.324), point2: (lg4000, 0.280)
                                                     //slope = ( reaction voltage ) / (log400 –log1000)


void setup()
{
    Serial.begin(9600);                              //UART setup, baudrate = 9600bps
    pinMode(BOOL_PIN, INPUT);                        //set pin to input
    digitalWrite(BOOL_PIN, HIGH);                    //turn on pullup resistors

   Serial.print("MG-811 Demostration\n");              
}

void loop()
{
    int percentage;
    float volts;
 
 
    volts = MGRead(MG_PIN);
    Serial.print( "SEN-00007:" );
    Serial.print(volts);
    Serial.print( "V           " );
 
    percentage = MGGetPercentage(volts,CO2Curve);
    Serial.print("CO2:");
    if (percentage == -1) {
        Serial.print( "<400" );
    } else {
        Serial.print(percentage);
    }
    Serial.print( "ppm" );
    Serial.print( "       Time point:" );
    Serial.print(millis());
    Serial.print("\n");
 
    if (digitalRead(BOOL_PIN) ){
        Serial.print( "=====BOOL is HIGH======" );
    } else {
        Serial.print( "=====BOOL is LOW======" );
    }
   
    Serial.print("\n");
 
    delay(200);
}


/*****************************  MGRead *********************************************
Input:   mg_pin - analog channel
Output:  output of SEN-000007
Remarks: This function reads the output of SEN-000007
************************************************************************************/
float MGRead(int mg_pin)
{
    int i;
    float v=0;

    for (i=0;i<READ_SAMPLE_TIMES;i++) {
        v += analogRead(mg_pin);
        delay(READ_SAMPLE_INTERVAL);
    }
    v = (v/READ_SAMPLE_TIMES) *5/1024 ;
    return v;
}

/*****************************  MQGetPercentage **********************************
Input:   volts   - SEN-000007 output measured in volts
         pcurve  - pointer to the curve of the target gas
Output:  ppm of the target gas
Remarks: By using the slope and a point of the line. The x(logarithmic value of ppm)
         of the line could be derived if y(MG-811 output) is provided. As it is a
         logarithmic coordinate, power of 10 is used to convert the result to non-logarithmic
         value.
************************************************************************************/
int  MGGetPercentage(float volts, float *pcurve)
{
   if ((volts/DC_GAIN )>=ZERO_POINT_VOLTAGE) {
      return -1;
   } else {
      return pow(10, ((volts/DC_GAIN)-pcurve[1])/pcurve[2]+pcurve[0]);
   }
}

///////////////////////////////////////////////////////////////////////////

Few things to remember about this sensor is that it has an on-board potentiometer that is adjusted using a plus-tipped Philips screwdriver. The technique used for this test is to turn the potentiometer clockwise at the edge of lighting up. Exposure to the CO2 source indicate that the sensor does detect CO2. Tinkering with the potentiometer to get the desired sensitivity is recommended because it is very reliant on a good calibration for its detection. Another important point is that the change in resistance in the sensor board happens through a chemical reaction happening on the MG811 CO2 sensor, which explains the delayed reaction from the sensor's output.

In official sensor tests, the sensors were subjected to extreme temperatures and pressure. On the former, the sensor was put in a less than 40 degrees Celsius environment. The ozone sensor gave out and the carbon dioxide mysteriously stopped functioning. In investigation of what might have went wrong, datasheets about the CO2 sensor indicate that it does not read CO2 levels below 400ppm. This officially disqualifies this sensor from the experiment because we were expecting significantly less CO2 at the 20-30 km altitude.

Here are some recommendations for future projects, high-altitude balloons and whatnot:

  • Spend more time on the documentation and previous project articles about this sensor as its code has a lot of information that could be vexing to anyone uninformed. 
  • Try to look for videos with experimentation regarding the sensor. This is where I got the CO2 source idea
  • Have better packaging for the delivery of the sensor. Transit damages is a big pain because transit usually takes weeks.
  • Check datasheets and check if it meets project's goal
Here are some links pertinent to this report:
Trello: https://trello.com/c/3DYC0UZo/15-sainsmart-mg811-gas-co2-carbon-dioxide-sensor
Sainsmart Site: http://www.sainsmart.com/sainsmart-mg811-gas-co2-carbon-dioxide-sensor-module-sensor-module.html
Spencerpages: http://www.spencerpages.com/wiki/index.php?title=MG811_Carbon_Dioxide_(CO2)_Sensor


No comments:

Post a Comment