0

I'm doing a school project in which I need to track different kinds of gases, the problem is I can't read more than one sensor at the same time, I'm using four sensors (mq5, mq7, mq8 and mq135) and the code I'm using was one that I merged using four different codes that I found on github (https://github.com/mdsiraj1992/Gassensors). When I'm only one sensor it works normally, but when I use the code I merged the values are totally off. So basically I'm doing something wrong, but I don't know what. Please help me, I have to deliver the code this week.

#include <Adafruit_Sensor.h>

#include <Adafruit_Sensor.h>

#include <DHT.h>
#include <DHT_U.h>

#include <DHT.h>
#include <DHT_U.h>

/***Hardware Related Macros***/

#define         MQ5PIN                       (2)
#define         RL_VALUE_MQ5                 (1)
#define         RO_CLEAN_AIR_FACTOR_MQ5      (6.455)

#define         MQ7PIN                       (3)
#define         RL_VALUE_MQ7                 (1)
#define         RO_CLEAN_AIR_FACTOR_MQ7      (26.09)

#define         MQ8PIN                       (1)
#define         RL_VALUE_MQ8                 (1)
#define         RO_CLEAN_AIR_FACTOR_MQ8      (1)

#define         MQ135PIN                     (5)
#define         RL_VALUE_MQ135               (1)
#define         RO_CLEAN_AIR_FACTOR_MQ135    (3.59)

/***Software Related Macros***/

#define         CALIBARAION_SAMPLE_TIMES     (50)
#define         CALIBRATION_SAMPLE_INTERVAL  (500)
#define         READ_SAMPLE_INTERVAL         (50)
#define         READ_SAMPLE_TIMES            (5)

/***Application Related Macros***/

#define         GAS_LPG                      (1)
#define         accuracy                     (0)
#define         GAS_CARBON_MONOXIDE          (3)
#define         GAS_HYDROGEN                 (0)
#define         GAS_METHANE                  (2)
#define         GAS_CARBON_DIOXIDE           (9)
#define         GAS_AMMONIUM                 (10)

/***Globals***/
float           Ro = 10;

void setup() {
  Serial.begin(9600);
  Serial.print("Calibrating...\n");

  Ro = MQCalibration(MQ5PIN);
  Serial.print("Calibration is done...\n");
  Serial.print("Ro5=");
  Serial.print(Ro);
  Serial.print("kohm");
  Serial.print("\n");

  Ro = MQCalibration(MQ7PIN);
  Serial.print("Calibration is done...\n");
  Serial.print("Ro7=");
  Serial.print(Ro);
  Serial.print("kohm");
  Serial.print("\n");

  Ro = MQCalibration(MQ8PIN);
  Serial.print("Calibration is done...\n");
  Serial.print("Ro8=");
  Serial.print(Ro);
  Serial.print("kohm");
  Serial.print("\n");

  Ro = MQCalibration(MQ135PIN);
  Serial.print("Calibration is done...\n");
  Serial.print("Ro135=");
  Serial.print(Ro);
  Serial.print("kohm");
  Serial.print("\n");
}

void loop() {

  Serial.print("METHANE:");
  Serial.print(MQGetGasPercentage(MQRead(MQ8PIN) / Ro, GAS_METHANE) );
  Serial.print( "ppm" );
  Serial.print("    ");
  Serial.print("HYDROGEN:");
  Serial.print(MQGetGasPercentage(MQRead(MQ8PIN) / Ro, GAS_HYDROGEN) );
  Serial.print( "ppm" );
  Serial.print("    ");
  Serial.print("GLP:");
  Serial.print(MQGetGasPercentage(MQRead(MQ5PIN) / Ro, GAS_LPG) );
  Serial.print( "ppm" );
  Serial.print("    ");
  Serial.print("CARBON_MONOXIDE:");
  Serial.print(MQGetGasPercentage(MQRead(MQ7PIN) / Ro, GAS_CARBON_MONOXIDE)
              );

  Serial.print( "ppm" );
  Serial.print("    ");
  Serial.print("CARBON_DIOXIDE:");
  Serial.print(MQGetGasPercentage(MQRead(MQ135PIN) / Ro, GAS_CARBON_DIOXIDE)
              );
  Serial.print( "ppm" );
  Serial.print("    ");
  Serial.print("AMMONIUM:");
  Serial.print(MQGetGasPercentage(MQRead(MQ135PIN) / Ro, GAS_AMMONIUM) );
  Serial.print( "ppm" );
  Serial.print("\n");
  delay(200);
}

/***MQResistanceCalculation*****************************************
  Input:   raw_adc - raw value read from adc, which represents the
  voltage
  Output:  the calculated sensor resistance
  Remarks: The sensor and the load resistor forms a voltage divider.
  Given the voltage
  across the load resistor and its resistance, the resistance of the
  sensor
  could be derived.

*******************************************************************/
float MQResistanceCalculation(int raw_adc)
{
  return ( ((float)RL_VALUE_MQ5 * (1023 - raw_adc) / raw_adc));
  return ( ((float)RL_VALUE_MQ7 * (1023 - raw_adc) / raw_adc));
  return ( ((float)RL_VALUE_MQ8 * (1023 - raw_adc) / raw_adc));
  return ( ((float)RL_VALUE_MQ135 * (1023 - raw_adc) / raw_adc));
}

/*** MQCalibration*******************************************************
  Input:   mq_pin - analog channel
  Output:  Ro of the sensor
  Remarks: This function assumes that the sensor is in clean air. It use
  MQResistanceCalculation to calculates the sensor resistance in clean
  air
  and then divides it with RO_CLEAN_AIR_FACTOR. RO_CLEAN_AIR_FACTOR is
  about
  10, which differs slightly between different sensors.
****************************************************************/
float MQCalibration(int mq_pin)
{
  int i;
  float RS_AIR_val = 0, r0;

  for (i = 0; i < CALIBARAION_SAMPLE_TIMES; i++) {
    RS_AIR_val += MQResistanceCalculation(analogRead(mq_pin));
    delay(CALIBRATION_SAMPLE_INTERVAL);
  }
  RS_AIR_val = RS_AIR_val / CALIBARAION_SAMPLE_TIMES;
  r0 = RS_AIR_val / RO_CLEAN_AIR_FACTOR_MQ5;

  return r0;



  for (i = 0; i < CALIBARAION_SAMPLE_TIMES; i++) {
    RS_AIR_val += MQResistanceCalculation(analogRead(mq_pin));
    delay(CALIBRATION_SAMPLE_INTERVAL);
  }
  RS_AIR_val = RS_AIR_val / CALIBARAION_SAMPLE_TIMES;
  r0 = RS_AIR_val / RO_CLEAN_AIR_FACTOR_MQ7;

  return r0;


  for (i = 0; i < CALIBARAION_SAMPLE_TIMES; i++) {
    RS_AIR_val += MQResistanceCalculation(analogRead(mq_pin));
    delay(CALIBRATION_SAMPLE_INTERVAL);
  }
  RS_AIR_val = RS_AIR_val / CALIBARAION_SAMPLE_TIMES;
  r0 = RS_AIR_val / RO_CLEAN_AIR_FACTOR_MQ8;

  return r0;

  for (i = 0; i < CALIBARAION_SAMPLE_TIMES; i++) {
    RS_AIR_val += MQResistanceCalculation(analogRead(mq_pin));
    delay(CALIBRATION_SAMPLE_INTERVAL);
  }
  RS_AIR_val = RS_AIR_val / CALIBARAION_SAMPLE_TIMES;
  r0 = RS_AIR_val / RO_CLEAN_AIR_FACTOR_MQ135;

  return r0;
}
/*****************  MQRead *********************************
  Input:   mq_pin - analog channel
  Output:  Rs of the sensor
  Remarks: This function use MQResistanceCalculation to caculate the
  sensor resistenc (Rs).
  The Rs changes as the sensor is in the different consentration of the
  target
  gas. The sample times and the time interval between samples could be
  configured
  by changing the definition of the macros.
********************************************************/
float MQRead(int mq_pin)
{
  int i;
  float rs = 0;

  for (i = 0; i < READ_SAMPLE_TIMES; i++) {
    rs += MQResistanceCalculation(analogRead(mq_pin));
    delay(READ_SAMPLE_INTERVAL);
  }

  rs = rs / READ_SAMPLE_TIMES;

  return rs;
}

/***********************  MQGetGasPercentage ****************************
  Input:   rs_ro_ratio - Rs divided by Ro
  gas_id      - target gas type
  Output:  ppm of the target gas
  Remarks: This function uses different equations representing curves of
  each gas to
  calculate the ppm (parts per million) of the target gas.
******************************************************************/
int MQGetGasPercentage(float rs_ro_ratio, int gas_id)
{
  if ( accuracy == 0 ) {

  }
  if ( gas_id == GAS_LPG ) {
    return (pow(10, ((-2.513 * (log10(rs_ro_ratio))) + 1.878)));
  }
  else if ( gas_id == GAS_CARBON_MONOXIDE ) {
    return (pow(10, ((-1.525 * (log10(rs_ro_ratio))) + 1.994)));
  }
  else if ( gas_id == GAS_HYDROGEN ) {
    return (pow(10, ((-2.568 * (log10(rs_ro_ratio))) + 0.360)));
  }
  else if ( gas_id == GAS_METHANE ) {
    return (pow(10, ((-16.16 * (log10(rs_ro_ratio))) + 1.093)));
  }
  else if ( gas_id == GAS_CARBON_DIOXIDE ) {
    return (pow(10, ((-2.890 * (log10(rs_ro_ratio))) + 2.055)));
  }
  else if ( gas_id == GAS_AMMONIUM ) {
    return (pow(10, ((-2.469 * (log10(rs_ro_ratio))) + 2.005)));

  }
  else if ( accuracy == 1 ) {
  }
  else if ( gas_id == GAS_LPG ) {
    return (pow(10, ((-2.513 * (log10(rs_ro_ratio))) + 1.878)));
  }
  else if ( gas_id == GAS_CARBON_MONOXIDE ) {
    return (pow(10, ((-1.525 * (log10(rs_ro_ratio))) + 1.994)));
  }
  else if ( gas_id == GAS_HYDROGEN ) {
    return (pow(10, ((-2.568 * (log10(rs_ro_ratio))) + 0.360)));
  }
  else if ( gas_id == GAS_METHANE ) {
    return (pow(10, (-281.3 * pow((log10(rs_ro_ratio)), 3) - 12.26 *
                     pow((log10(rs_ro_ratio)), 2) - 7.925 * (log10(rs_ro_ratio)) + 1.668)));
  }
  else if ( gas_id == GAS_CARBON_DIOXIDE ) {
    return (pow(10, ((-2.890 * (log10(rs_ro_ratio))) + 2.055)));
  }
  else if ( gas_id == GAS_AMMONIUM ) {
    return (pow(10, ((-2.469 * (log10(rs_ro_ratio))) + 2.005)));
  }
}
1
  • Using your merged code, but commenting out the calls to all but one sensor (at a time), will each of them run correctly?
    – JRobert
    Nov 28, 2018 at 14:18

1 Answer 1

1

First of all you only need to include once. Including anything more than once is pointless and could be bad, if the header doesn't have include guards (yours do, but still it just makes the code harder to read).

Let's take a look at the MQResistanceCalculation function, well... It's simply broken.

float MQResistanceCalculation(int raw_adc)
{
  return ( ((float)RL_VALUE_MQ5 * (1023 - raw_adc) / raw_adc));
  return ( ((float)RL_VALUE_MQ7 * (1023 - raw_adc) / raw_adc));
  return ( ((float)RL_VALUE_MQ8 * (1023 - raw_adc) / raw_adc));
  return ( ((float)RL_VALUE_MQ135 * (1023 - raw_adc) / raw_adc));
}

I'm not sure what you expect to happen, but as soon as you reach a return statement that block of code stops and the result is returned, so basically that function executes the first return and then stops. You probably want to pass a sensor type and then use a switch to make it return for either the MQ5, MQ7, MQ8 or MQ135, because right now it only returns the MQ5 value.

Then let's take a look at the MQCalibration function. So same thing as above applies, as long as you reach a return the function stops. Your MQCalibration function currently only does:

float MQCalibration(int mq_pin)
{
  int i;
  float RS_AIR_val = 0, r0;

  for (i = 0; i < CALIBARAION_SAMPLE_TIMES; i++) {
    RS_AIR_val += MQResistanceCalculation(analogRead(mq_pin));
    delay(CALIBRATION_SAMPLE_INTERVAL);
  }
  RS_AIR_val = RS_AIR_val / CALIBARAION_SAMPLE_TIMES;
  r0 = RS_AIR_val / RO_CLEAN_AIR_FACTOR_MQ5;

  return r0;
}

And then the MQGetGasPercentage function can be re-written with switch statements to be way easier to read and understand. Oh and also that accuracy == 0 check is also pointless it has nothing in it.

From reading this I see you've just copied code you don't understand and hoped it'll work, but as expected it didn't. And well copying code without atleast having an idea about what it does is stupid. So just read it, understand it and write it again, but by yourself. Your code has many pointless variable declarations and it just isn't well "written"(or copy-pasted should I say).

Also I've never worked with that sensor myself, so I was looking at the code aspect mostly, just so you know.

1
  • I understand now and I will try to make a new code by myself, I had to copy paste it because of my lack of knowledge in Arduino and I didn't have much time to research, thanks for the help, I'll make sure to do it right next time. Nov 29, 2018 at 15:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.