Friday, May 2, 2014

Propane Gas Sensor Using the Arduino Uno

In this latest project I use the MQ6 propane gas sensor with the Arduino Uno to sense propane gas concentration in the air.

This sensor has a heater that requires about 150mA for 90s to take a reading. The Uno can't supply this current so I use a KA278R05 voltage regulator to provide it, with a 12v DC power supply providing the input power for the voltage regulator. The KA278R05 has an enable pin which I drive high using digital pin 8 of the Uno to enable the sensor for the 90 seconds it needs to be on in order to take a stable reading. I read the voltage level signal output of the MQ6 each second and the final stable value right at the 90s point after activating the sensor using analog input pin 0.

The schematic for the circuit I used:

The breadboard layout using the great tool from Fritzing:

The first set of results from clean air (no propane) graphed in excel. Here the measurement stabilized at around 256 after 90s:

The second set of results from air with a bit of propane graphed in excel. I put the sensor inside a grill with the lid closed and gave a small puff of propane, and without any flame. I recommend extreme caution if you try this. Just a tiny puff of propane, and in an outside area with good ventilation is how I did it. Have all the circuitry except the sensor outside the grill area. With this test the measurement stabilized at around 739 after 90s, which is almost 3 times higher than with clean air. Keeping in mind this was a very small puff of propane, this sensor is very sensitive:

Below is the sketch I used to drive the Uno for this test. I use a simple finite state machine to manage the state of the sensor.

#define MQ6_POWER_ON_DIGITAL_OUT_PIN 8
#define MQ6_LP_GAS_LEVEL_MEASURE_ANALOG_IN_PIN   0
#define MQ6_HEATER_TIME_MILLIS 90000
#define MQ6_SAMPLE_PERIOD_MILLIS 1000

int lpGas;

typedef enum {
  ST_MQ6_OFF,
  ST_MQ6_CYCLE_0_HIGH,
  ST_MQ6_DONE
} MQ6_STATE;

MQ6_STATE mq6State = ST_MQ6_OFF;

unsigned long mq6SwitchTimeMillis;
unsigned long mq6NextReadingTimeMillis;
unsigned long lpGasStartTimeMillis;
unsigned long startMillis;

//-----------------------------------------------------
void setup(){
  Serial.begin(19200);
  
  pinMode(MQ6_POWER_ON_DIGITAL_OUT_PIN, OUTPUT);
  
  startMillis = millis();
  
  // start 10s after power up
  lpGasStartTimeMillis = 10000; 

  // print headers for CSV output
  Serial.print("Seconds");
  Serial.print(",");
  Serial.println("LP Gas Level");
}

//-----------------------------------------------------
void loop(){
  readLPGas();
}

//-----------------------------------------------------
// uses a simple finite state machine to manage states of the MQ6 sensor
void readLPGas(){
  switch(mq6State){
    case ST_MQ6_OFF :
    {
      if(millis() > lpGasStartTimeMillis){
        digitalWrite(MQ6_POWER_ON_DIGITAL_OUT_PIN, HIGH);

        mq6State = ST_MQ6_CYCLE_0_HIGH;
        mq6SwitchTimeMillis = millis() + MQ6_HEATER_TIME_MILLIS;
      }
      break;
    }

    case ST_MQ6_CYCLE_0_HIGH :
    {
      if(millis() > mq6NextReadingTimeMillis) {
        lpGas = analogRead(MQ6_LP_GAS_LEVEL_MEASURE_ANALOG_IN_PIN);

        Serial.print((millis() - startMillis)/1000);
        Serial.print(",");
        Serial.println(lpGas);

        mq6NextReadingTimeMillis = millis() + MQ6_SAMPLE_PERIOD_MILLIS;
      }

      if(millis() > mq6SwitchTimeMillis){
        digitalWrite(MQ6_POWER_ON_DIGITAL_OUT_PIN, LOW);

        mq6State = ST_MQ6_DONE;
      }
      
      break;
    }

    case ST_MQ6_DONE :
    {
      break;
    }
  }
}

//-----------------------------------------------------

If you are interested in how this type of sensor can be integrated into a broader solution that includes notification of combustible gasses on a users Android phone see Receive Alerts of Combustible Gasses

You can find a PCB breakout for this sensor if you are ready to create something more polished.

Let me know if you build any cool enhancements to this. Have fun!