Code not checking for updated sensor values after connecting to firebase?

I am using a project with an MQ138 sensor and want to push the real time sensor reads to firebase. Currently, the wifi/firebase part and sensor part work fine separately. The code connects to wifi and will update a temporary variable (just an int that gets 1 added to it every time the loop runs) and put that on firebase. On a separate arduino file, the code is also able to read the sensor, do math with it, and consistently update. However, when I put the two together and try to print the sensor output, the value does not change at all (both the raw analogRead AND the raw value after being put through some math)--even when it does change on the separate code I ran without any firebase/wifi involved.

Why is this? Could there be some sort of cache that saves the old sensor value? Something with the way the code loops?

My code is below (currently, the sensor output is only getting printed in serial, and the integer "n" is consistently getting updated and pushed on firebase, but even the serial output of the sensor won't change):

#include <Firebase.h>
#include <FirebaseArduino.h>
#include <FirebaseCloudMessaging.h>
#include <FirebaseError.h>
#include <FirebaseHttpClient.h>
#include <FirebaseObject.h>
#include <dummy.h>

#include <ESP8266WiFi.h>
#include <FirebaseArduino.h>
#include <SPI.h>
#include <Wire.h>
#include <DHT.h>
#include <Adafruit_BMP085.h>

//passwords have been removed, but are in the actual code
#define FIREBASE_HOST ""
#define FIREBASE_AUTH ""

#define WIFI_SSID ""
#define WIFI_PASSWORD ""

//Hardware Macros for sensor
#define MQ138 (5) //Analog 5 input
#define RL_VALUE (10000) //Load resistance in ohms
//Software macros
#define         CALIBRATION_SAMPLE_TIMES     (40)    //define how many samples you are going to take in the calibration phase
#define         CALIBRATION_SAMPLE_INTERVAL  (500)   //define the time interal(in milisecond) between each samples in the
//cablibration phase
#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 interal(in milisecond) between each samples in 

//Globals for math with the sensor
float AcetoneCurve[2] = {3.720, -2.222}; //A, B
float R0 = 10000; //Initialized to 10k ohms
unsigned long SLEEP_TIME = 600; // Sleep time between reads (in seconds)
int val = 0;          // variable to store the value coming from the sensor
float calcVoltage = 0;
float dustDensity = 0;
boolean metric = true;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.print("help");
  WiFi.disconnect();
  Serial.setDebugOutput(true);
  /*IPAddress ip(192,168,3,34);
  IPAddress gateway(192,168,3,1);
  IPAddress subnet(255,255,255,0);*/
  WiFi.setAutoReconnect(true);

  //connect to Wifi
  WiFi.mode(WIFI_STA);
  WiFi.hostname("ESP-host");
  //WiFi.config(ip, gateway, subnet);
  WiFi.enableInsecureWEP(true);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("connecting");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    Serial.print("Wifi status: ");
    Serial.println(WiFi.status());
    delay(500);
  }
  Serial.println();
  Serial.print("connected: ");
  Serial.println(WiFi.localIP());
  Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);

  //define pin
  pinMode(MQ138, INPUT);
}

int n = 0;

void loop() {
  // put your main code here, to run repeatedly:
  //MQ138 code
  int raw = analogRead(MQ138);
  static float Ro = MQCalibration(MQ138, 25, RL_VALUE, AcetoneCurve);    //Assuming 25ppm of acetone in clean air?
  float Rs = MQRead(MQ138, RL_VALUE);
  float ratio = Rs / Ro;
  int ppm = MQGetPercentage(ratio, Ro, AcetoneCurve);

 //This prints the same output every time, even when it shouldn't
  Serial.println(raw);
  Serial.print("PPM: ");
  Serial.println(ppm);

//Firebase code
  // set value
  Firebase.setFloat("PPM", n);
  //error catching
  if (Firebase.failed()) {
    Serial.print("setting /number failed:");
    Serial.println(Firebase.error());
    return;
  }
  delay(1000);
  // appending a new value to /logs, CHANGE INT
  String name = Firebase.pushInt("logs", n++);
  //handle error
  if (Firebase.failed()) {
    Serial.print("pushing /logs failed: ");
    Serial.println(Firebase.error());
    return;
  }
  Serial.print("pushed: /logs/");
  Serial.println(name);
  delay(1000);

  if (Firebase.failed()) {
    return;
  }

}

//Functions - for calculating the PPM from a raw sensor reading, can be ignored
/****************** 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, float rl_value)
{
  return  (long)((long)(1024 * 1000 * (long)rl_value) / raw_adc - (long)rl_value);
  ;
}

/***************************** MQCalibration (R0) ****************************************
  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.        .
************************************************************************************/
float MQCalibration(int mq_pin, double ppm, double rl_value, float *pcurve )
{
  int i;
  float val = 0;

  for (i = 0; i < CALIBRATION_SAMPLE_TIMES; i++) {      //take multiple samples
    val += MQResistanceCalculation(analogRead(mq_pin), rl_value);
    delay(CALIBRATION_SAMPLE_INTERVAL);
  }
  val = val / CALIBRATION_SAMPLE_TIMES;                 //calculate the average value
  //Ro = Rs * sqrt(a/ppm, b) = Rs * exp( ln(a/ppm) / b )

  return  (long)val * exp((log(pcurve[0] / ppm) / pcurve[1]));

}

/*****************************  MQRead (Rs) *********************************************
  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, float rl_value)
{
  int i;
  float rs = 0;

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

  rs = rs / READ_SAMPLE_TIMES;

  return rs;
}

/*****************************  MQGetPercentage **********************************
  Input:   rs_ro_ratio - Rs divided by Ro
         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(rs_ro_ratio) is provided. As it is a
         logarithmic coordinate, power of 10 is used to convert the result to non-logarithmic
         value.
************************************************************************************/
int  MQGetPercentage(float rs_ro_ratio, float ro, float *pcurve)
{
  return (double)(pcurve[0] * pow(((double)rs_ro_ratio), pcurve[1]));
}

Any help would be much appreciated!

where is the sensor value in the posted code?

//MQ138 code
  int raw = analogRead(MQ138);
  static float Ro = MQCalibration(MQ138, 25, RL_VALUE, AcetoneCurve);    //Assuming 25ppm of acetone in clean air?
  float Rs = MQRead(MQ138, RL_VALUE);
  float ratio = Rs / Ro;
  int ppm = MQGetPercentage(ratio, Ro, AcetoneCurve);

 //PRINT SENSOR OUTPUT HERE
//This prints the same output every time, even when it shouldn't
  Serial.println(raw);
  Serial.print("PPM: ");
  Serial.println(ppm);

This is the section of the code responsible for dealing with the sensor, I'm currently having it print (in serial) the raw read and value after being calculated

Can you post the code which successfully reads the sensor.

I'm not sure about this

#define MQ138 (5) //Analog 5 input
int raw = analogRead(MQ138);

Does this syntax with the double parenthesis work properly?
`analogRead((5));

What happens if you make this change

#define MQ138 A5 //Analog 5 input

hm I never noticed that, here is the code that successfully reads the sensor, which also has it as #define MQ138(5)


//Source: https://github.com/empierre/arduino-mysensors-contribs/blob/master/AirQuality-Multiple_Gas_Sensor1_4.ino

// Libraries
#include <SPI.h>  
#include <Wire.h> 
#include <DHT.h>  
#include <Adafruit_BMP085.h>

//Hardware Macros
#define MQ138 (5) //Analog 5 input
#define RL_VALUE (10000) //Load resistance in ohms
//Software macros
#define         CALIBRATION_SAMPLE_TIMES     (40)    //define how many samples you are going to take in the calibration phase
#define         CALIBRATION_SAMPLE_INTERVAL  (500)   //define the time interal(in milisecond) between each samples in the
                                                     //cablibration phase
#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 interal(in milisecond) between each samples in 

//Globals
float AcetoneCurve[2] = {3.720, -2.222}; //A, B
float R0 = 10000; //Initialized to 10k ohms
unsigned long SLEEP_TIME = 600; // Sleep time between reads (in seconds)
int val = 0;          // variable to store the value coming from the sensor
//idfk what this is
float calcVoltage = 0;
float dustDensity = 0;
boolean metric = true; 


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(MQ138, INPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  int raw = analogRead(MQ138);
  static float Ro = MQCalibration(MQ138, 25, RL_VALUE, AcetoneCurve);    //Assuming 25ppm of acetone in clean air?
  //https://www.health.ny.gov/environmental/indoors/air/contaminants/acetone.htm#:~:text=Levels%20of%20acetone%20are%20typically,common%20ingredient%20in%20many%20products.
  float Rs = MQRead(MQ138, RL_VALUE);
  float ratio = Rs / Ro;
  int ppm = MQGetPercentage(ratio, Ro, AcetoneCurve);
  Serial.println(raw);
  Serial.print("PPM: ");
  Serial.println(ppm);
}

//Functions
/****************** 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,float rl_value)
{
  return  (long)((long)(1024*1000*(long)rl_value)/raw_adc-(long)rl_value);
;
}

/***************************** MQCalibration (R0) ****************************************
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.        .
************************************************************************************/ 
float MQCalibration(int mq_pin, double ppm, double rl_value,float *pcurve )
{
  int i;
  float val=0;

  for (i=0;i<CALIBRATION_SAMPLE_TIMES;i++) {            //take multiple samples
    val += MQResistanceCalculation(analogRead(mq_pin),rl_value);
    delay(CALIBRATION_SAMPLE_INTERVAL);
  }
  val = val/CALIBRATION_SAMPLE_TIMES;                   //calculate the average value
  //Ro = Rs * sqrt(a/ppm, b) = Rs * exp( ln(a/ppm) / b )

  return  (long)val*exp((log(pcurve[0]/ppm)/pcurve[1]));

}

/*****************************  MQRead (Rs) *********************************************
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,float rl_value)
{
  int i;
  float rs=0;
 
  for (i=0;i<READ_SAMPLE_TIMES;i++) {
    rs += MQResistanceCalculation(analogRead(mq_pin),rl_value);
    delay(READ_SAMPLE_INTERVAL);
  }
 
  rs = rs/READ_SAMPLE_TIMES;
 
  return rs;  
}

/*****************************  MQGetPercentage **********************************
Input:   rs_ro_ratio - Rs divided by Ro
         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(rs_ro_ratio) is provided. As it is a 
         logarithmic coordinate, power of 10 is used to convert the result to non-logarithmic 
         value.
************************************************************************************/ 
int  MQGetPercentage(float rs_ro_ratio, float ro, float *pcurve)
{
  return (double)(pcurve[0] * pow(((double)rs_ro_ratio), pcurve[1]));
}

What processor unit is running these sketches?

Is the processor running the wifi sketch the same as what ran the stand alone MQ138 sketch?

I am confused by what looks like an ESP8266 running the wifi and the use of analogRead on a pin 5.

hm now that you bring that up it does seem like an issue--the firebase sketch is run with the ESP8266 selected as a board but the standalone MQ138 sketch is run with Arduino Uno as a board. Does that mean I can't do AnalogRead on the ESP8266?

You can, but there is only a single pin for input. I think it is addressed as A0. The input may be limited to 1v. and you may need a voltage divider.

Do some research on your specific module. Check the pin out and the voltage limit for the module you are using.

Probably should have clarified earlier, but my circuit is set up so that I have an Arduino Uno connected to a ESP8266 and MQ138 sensor. Within the Arduino software however, my board is selected as ESP8266--would the sensor reading work this way or do I have to connect my sensor to the ESP8266 because that is what's selected in the software?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.