Sampling Rate Changed Once Integrated into Different Code

Hi! :slight_smile:

I have created a code to run my analog sound sensor (DFRobot DFR0034) from my Arduino. The sensor is bringing in samples at a rapid rate. The data is half zeros (i assume this is not intended and it is probably noise) and I have based my calibration off of the max values recorded. So, my code for the sensor individually accounts for this and chooses the max value from the last 40 responses and uses that as the value from the sensor. Here is the code for this:

void setup() {
  // Initialize serial and wait for port to open:
  Serial.begin(9600);
  // This delay gives the chance to wait for a Serial Monitor without blocking if none is found
  delay(1500); 

  // Defined in thingProperties.h
  initProperties();

  // Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);
  
  /*
     The following function allows you to obtain more information
     related to the state of network and IoT Cloud connection and errors
     the higher number the more granular information you’ll get.
     The default is 0 (only errors).
     Maximum is 4
  */
  setDebugMessageLevel(2);
  ArduinoCloud.printDebugInfo();
}

void loop() {
  ArduinoCloud.update();
  
  static int count = 0;
  static float maxSoundValue = 0;
  
  float rawsensorvalue = analogRead(A1);
  
  if (rawsensorvalue > maxSoundValue) {
    maxSoundValue = rawsensorvalue;
  }

  count++;

  if (count == 40) {
    float soundsensorvalue = maxSoundValue;
    float y;
    
    if (soundsensorvalue < 10) {
      y = 0.826 * soundsensorvalue + 55.8;
    } else {
      y = 0.17 * soundsensorvalue + 65;
    }

    soundsensor = y;
    Serial.println(soundsensor);
    
    // Reset for next 40 data points
    count = 0;
    maxSoundValue = 0;
  }
}

Here is the code for the entire system. It is a monitoring system for a warehouse. I just want the sound sensor to be able to operate the way it does on its own code, when it is integrated into the new code. For the life of me, I can not figure out why it doesn't work. Thanks for you help.

/* 
  Sketch generated by the Arduino IoT Cloud Thing "Untitled 2"
  https://create.arduino.cc/cloud/things/3451d766-df36-4ad9-8d01-5f06978edb88 

  Arduino IoT Cloud Variables description

  The following variables are automatically generated and updated when changes are made to the Thing

  float cel;
  float humidity;
  float oxygenData;
  float percentage_co2;
  float sensor_volt_co;
  float temperature_far;
  int soundsensor;

  Variables which are marked as READ/WRITE in the Cloud Thing will also have functions
  which are called when their values are changed from the Dashboard.
  These functions are generated with the Thing and added at the end of this sketch.
*/

#include "thingProperties.h"


// Temp and Humid needed info
#include <DHT.h>
#define DHTPIN 8   
#define DHTTYPE DHT22   
DHT dht(DHTPIN, DHTTYPE);

// CO2 sensor needed info
#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_VOLTAGE             (0.020) //define the voltage drop of 
/*****************************Globals***********************************************/
float           CO2Curve[3]  =  {2.602,ZERO_POINT_VOLTAGE,(REACTION_VOLTAGE/(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) 

// Oxygen sensor needed info
#include <DFRobot_OxygenSensor.h>
#define Oxygen_IICAddress ADDRESS_3
#define COLLECT_NUMBER  10             
//collect number,the collection range is 1-100.
DFRobot_OxygenSensor oxygen;

void setup() {
  // Initialize serial and wait for port to open:
  Serial.begin(9600);
  // This delay gives the chance to wait for a Serial Monitor without blocking if none is found
  delay(1500); 

  // Defined in thingProperties.h
  initProperties();

  // Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);
  
  
  setDebugMessageLevel(2);
  ArduinoCloud.printDebugInfo();

  // Sound add-ons
  // CO sensor add-ons:
  pinMode(sensor_volt_co, INPUT);

  // Temp and Humid sensor add-ons:
  dht.begin();

  // CO2 sensor add-ons:
  pinMode(BOOL_PIN, INPUT);                        //set pin to input
  digitalWrite(BOOL_PIN, HIGH);                    //turn on pullup resistors

  // Oxygen sensor add-ons:
  
  while(!oxygen.begin(Oxygen_IICAddress)){
    Serial.println("I2c device number error !");
    delay(1000);
  }
  Serial.println("I2c connect success !");
// Defined in thingProperties.h



  
  
}

void loop() {
  ArduinoCloud.update();
  // Your code here 
   //Sound Sensor Code:
  static int count = 0;
  static float maxSoundValue = 0;
  
  float rawsensorvalue = analogRead(A1);
  if (rawsensorvalue > maxSoundValue) {
    maxSoundValue = rawsensorvalue;
  }

  count++;

  if (count == 40) {
    float soundsensorvalue = maxSoundValue;
    float y;
    
    if (soundsensorvalue < 10) {
      y = 0.826 * soundsensorvalue + 55.8;
    } else {
      y = 0.17 * soundsensorvalue + 65;
    }

    soundsensor = y;
    Serial.print("sound level: ");
    Serial.println(soundsensor);
    
    // Reset for next 40 data points
    count = 0;
    maxSoundValue = 0;
  }
  
  // CO sensor Code:
  float rS_gas; // Get value of RS in a GAS
  float ratio; // Get ratio RS_GAS/RS_air
  int sensorValue = analogRead(A3);
  sensor_volt_co=(float)sensorValue/1024*5.0;
  rS_gas = (5.0-sensor_volt_co)/sensor_volt_co; // omit *RL
  float r0 = 3.01;
  ratio = rS_gas/r0; // ratio = RS/R0
  Serial.print("sensor_volt = ");
  Serial.println(sensor_volt_co);
  delay(1000);

  // Temp and Humid Sensor code:
  humidity = dht.readHumidity();// Read humidity
  temperature_far = dht.readTemperature(true);  // Read temperature in Fahrenheit
  cel = dht.readTemperature();
  Serial.print("Humid ");
  Serial.print(humidity);
  Serial.println("Temp ");
  Serial.print(temperature_far);

  //Oxygen Sensor Code
  oxygenData = oxygen.getOxygenData(COLLECT_NUMBER);
  Serial.print(" oxygen concentration is ");
  Serial.print(oxygenData);
  Serial.println(" %vol");
  delay(1000);

  // CO2 sensor code
   float volts;
 
    volts = MGRead(MG_PIN);
    Serial.print( "SEN-00007:" );
    Serial.println(volts); 
    Serial.println( "V           " );
 
    percentage_co2 = MGGetPercentage(volts,CO2Curve);
    Serial.print("CO2:");
    if (percentage_co2 == -1) {
        Serial.print( "<400" );
      percentage_co2 = 400;
    } else {
        Serial.print(percentage_co2);
    }
 
    Serial.print( "ppm" );  
    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]);
   }

 
}



/*
  Since Soundsensor is READ_WRITE variable, onSoundsensorChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onSoundsensorChange()  {
  // Add your code here to act upon Soundsensor change
}

/*
  Since SensorVolt is READ_WRITE variable, onSensorVoltChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onSensorVoltChange()  {
  // Add your code here to act upon SensorVolt change
}

/*
  Since Humidity is READ_WRITE variable, onHumidityChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onHumidityChange()  {
  // Add your code here to act upon Humidity change
}

/*
  Since TemperatureFar is READ_WRITE variable, onTemperatureFarChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onTemperatureFarChange()  {
  // Add your code here to act upon TemperatureFar change
}

/*
  Since Percentage is READ_WRITE variable, onPercentageChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onPercentageChange()  {
  // Add your code here to act upon Percentage change
}

/*
  Since OxygenData is READ_WRITE variable, onOxygenDataChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onOxygenDataChange()  {
  // Add your code here to act upon OxygenData change
}

/*
  Since SensorVoltCo is READ_WRITE variable, onSensorVoltCoChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onSensorVoltCoChange()  {
  // Add your code here to act upon SensorVoltCo change
}

/*
  Since PercentageCo2 is READ_WRITE variable, onPercentageCo2Change() is
  executed every time a new value is received from IoT Cloud.
*/
void onPercentageCo2Change()  {
  // Add your code here to act upon PercentageCo2 change
}

/*
  Since Cel is READ_WRITE variable, onCelChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onCelChange()  {
  // Add your code here to act upon Cel change
}

At the beach, so maybe this isn't your problem

delay(1000);

nor this

delay(1000);

nor this

delay(200);

Also and BTW, you could avoid using floating point until it is necessary. Usually not a problem, but some of us are old enough to remember when using floating point was just an unaffordable luxury. There is a body of knowledge for doing without entirely.

a7

That helped some, now the rest of the sensors, including the sound sensor, are displaying their data once every .5 seconds or so... Is there any way to change the sampling frequency of just the sound sensor and not the others? How would I go about doing that? Sorry to interrupt your beach time!

NP. It's a nice change of pace, even if a tablet is an inferior device for this.

It is relatively easy to have multiple things being handled, each at a chosen frequency.

The key is to not have any single thing that needs attention hog up the resources.

In this context delay() is not your friend. It literally means the progress through your code halts for what can be looked at as an eternity.

The essential pattern is on display in the IDE example Blink Without Delay. This article goes with it

https://docs.arduino.cc/built-in-examples/digital/BlinkWithoutDelay/

This video has been pointed out recently as perhaps a gentler kinder intro, which you may want to watch before or after looking at Blink Without Delay

Then see if this makes sense.

void loop() {

  static unsigned long lastTime;

  if (millis() - lastTime > 777) {

// stuff here gets executed every 777 milliseconds (0.777 seconds)

    lastTime = millis();
  }

// flow passes through here 1000s of times a second
// copying the if statement and providing a separate timer (lastTime in the above if statement
// and any different constant to 777
// would let some other stuff execute at a different rate here :

}

For your sensor, an entirely beautiful approach would be to collect one sample every time the loop executes and it is N milliseconds since the last sample. When the 40th sample is taken, or however many, act on the maximum and reset.

Or just leave the sensor thing in throttled by the timing mechanism.Yoi could just do the 40 samples all at one go, but this verges on hogging the resource which is processing time, so make sure you other responsibilities are nor neglected.

As long as the timed code sections behave and the total processing they need doesn't add up to more than is available, the general technique works well.

You will see it expressed a bit differently here and there, but it all amount to watching the clock and acting when the clock has advanced past the time to do something again.

a7

1 Like