Having problem with shifting an array

Hello,

I have an array called sensorFeedback[] that I use for storing the old and new DHT22 temperature feedback. I use this array to compare these values and if the difference between two values big, I shift the array to left and add new feedback to compare with the previous value. Temperature is returned back after the difference between these values is minimal.

Let me show you my problem with the following example:
In this example sensor's first two feedbacks are 29 and 30.

Serial.println(sensorFeedback[0]); // prints out 29
Serial.println(sensorFeedback[1]); // prints out 30

// array shifting
sensorFeedback[0] = sensorFeedback[1];
sensorFeedback[1] = dht.readTemperature();

Serial.println(sensorFeedback[0]); // prints out something like 1.95 which should have been 30. Wrong output.
Serial.println(sensorFeedback[1]); // new sensor feedback such as 30.1

After shifting the array, sensorFeedback[0] doesn't store 30. I'm having difficulty understanding this. I would be really glad if you could help me.

Thank you,
Ozan

I'm having difficulty understanding this.

So am I. But, I'm willing to bet that the fine folks at http://snippets-r-us.com will be able to help you with your snippets.

You're right Paul. I should have been more clear while asking my question.

Here is my whole code with comments.

#define BLYNK_PRINT Serial

// Libraries
#include <DHT.h>
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

// WIFI Configurations
char auth[] = "";
char ssid[] = "";
char pass[] = "";

#define DHTPIN 2 // DHT22 Data Pin
#define DHTTYPE DHT22 // Sensor Type

DHT dht(DHTPIN, DHTTYPE); // Define sensor configuration
BlynkTimer timer;

// Global variables
float t, h, hi, sensorFeedback[4];
int sensorFeedbackCounter = 0; // Sensor Feedback counter
int nanCounter = 0;
bool isDifferenceBig = false;

// Use of Blynk_Delay() is preffered over delay()
void Blynk_Delay(int milli)
{
  int end_time = millis() + milli;
  while (millis() < end_time)
  {
    if (Blynk.connected())
    {
      Blynk.run();
    }
    yield();
  }
}

float* getConsistentFeedbacks()
{
  if (isDifferenceBig == false)
  {
    for (int i = 0; i < 2; i++) {
      Blynk_Delay(2000);
      sensorFeedback[i]   = dht.readTemperature();
      sensorFeedback[i+2] = dht.readHumidity();
      Blynk_Delay(2000);
      Serial.println("+");
      sensorFeedbackCounter++;

      // Check for any nan values. If found, repeat getConsistentFeedbacks()
      if (isnan(sensorFeedback[i]) || isnan(sensorFeedback[i+2]))
      {
        getConsistentFeedbacks();
      }
    }
  }
  else {
    // If isDifferenceBig = true, shift the array to add new feedbacks
    // to sensorFeedback[1] and sensorFeedback[3]
    sensorFeedback[0] = sensorFeedback[1];
    sensorFeedback[2] = sensorFeedback[3];
    sensorFeedback[1] = dht.readTemperature();
    sensorFeedback[3] = dht.readHumidity();
    sensorFeedbackCounter++;

    // Check for any nan values. If found, repeat getConsistentFeedbacks()
    if (isnan(sensorFeedback[1]) || isnan(sensorFeedback[3]))
    {
      nanCounter++;
      getConsistentFeedbacks();
    }
  }

  // Print out readings
  Serial.println(sensorFeedback[0]);
  Serial.println(sensorFeedback[1]);
  Serial.println(sensorFeedback[2]);
  Serial.println(sensorFeedback[3]);
  Serial.println(sensorFeedbackCounter);
  Serial.println(nanCounter);
  Serial.println("---");

  // Check for temperature and humidity reading differences
  // Repeat the whole function until conditions are met
  if ((abs(sensorFeedback[1] - sensorFeedback[0]) > 0.1) || (abs(sensorFeedback[3] - sensorFeedback[2]) > 0.3))
  {
    isDifferenceBig = true;
    getConsistentFeedbacks();
  }
  else
  {
    Serial.println("Sending update!");
    Serial.println(sensorFeedbackCounter);
    // Variables such as sensorFeedbackCounter or nanCounter are not set to zero
    // because deepSleep() resets the memory and whole program starts over
    return sensorFeedback;
  }
}

void setup()
{
  Blynk_Delay(10);
  Serial.begin(9600); // Start serial connection
  Blynk.begin(auth, ssid, pass); // Connect to WIFI
  dht.begin(); // Start DHT22 sensor

  float* readings = getConsistentFeedbacks();

  t = readings[1]; // Temperature
  h = readings[3]; // Humidity

  hi = dht.computeHeatIndex(t, h, false); // HeatIndex function

  // Send acquired variables to Blynk server
  Blynk.virtualWrite(V5, h);
  Blynk.virtualWrite(V6, t);
  Blynk.virtualWrite(V7, hi);
  Blynk.virtualWrite(V8, sensorFeedbackCounter);
  Blynk.virtualWrite(V9, nanCounter);

  ESP.deepSleep(5 * 60 * 1000000L, WAKE_RF_DEFAULT); // Sleep NodeMCU for 5 mins.
}

void loop()
{
  Blynk.run();
  timer.run();
}

In my original question, I mentioned that sensorFeedback array has 2 elements but in fact it has 4. First two for temperature and last two for humidity.

After the array shift, sensorFeedback[0] and sensorFeedback[3] give false values. Please help me figure out the problem here.

Thanks,
Ozan

I'm gonna go out on a limb and say that the recursive calls to 'getConsistentFeedbacks()' aren't a good idea.

And I am going to suggest that you NEVER shift an array like this

sensorFeedback[0] = sensorFeedback[1];

Instead you have variables that index into the array and you update the variables. For example

prevIndex = 0;
currentIndex = 1;
Serial.print("Current "); Serial.println(sensorFeedback[currentIndex]);
Serial.print("Previous "); Serial.println(sensorFeedback[prevIndex]);

then when you want to store a new value and keep the most recent value

prevIndex ++;
if (prevIndex > maxIndex) {
  prevIndex = 0;
}
currentIndex ++;
if (currentIndex > maxIndex) {
  currentIndex = 0;
}

sensorFeedback[currnetIndex] = newValue;

...R

Google, circular buffer. Have a look at Hardware serial to see an example of an implementation.

Well I handled the issue thanks to you.

Now my code looks like this:

#define BLYNK_PRINT Serial

// Libraries
#include <DHT.h>
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

// WIFI Configurations
char auth[] = "";
char ssid[] = "";
char pass[] = "";

#define DHTPIN 2 // AMD2302 Data Pin
#define DHTTYPE DHT22 // Sensor Type

DHT dht(DHTPIN, DHTTYPE); // Define sensor configuration
BlynkTimer timer;

// Global variables
double t, h, hi, sensorFeedback[4];
int sensorFeedbackCounter = 0; // Sensor Feedback counter
bool isDifferenceBig = false;
double sampleDuration, sampleStartTime = 0;

// Use of Blynk_Delay() is preffered over delay()
void Blynk_Delay(int milli)
{
 int end_time = millis() + milli;
 while (millis() < end_time)
 {
   if (Blynk.connected())
   {
     Blynk.run();
   }
   yield();
 }
}

double* getConsistentFeedbacks()
{
 if (isDifferenceBig == false)
 {
   for (int i = 0; i < 2; i++)
   {
     do {
       if (sensorFeedbackCounter == 0) Blynk_Delay(2000);
       sensorFeedback[i] = dht.readTemperature();
       sensorFeedback[i+2] = dht.readHumidity();
       Blynk_Delay(2000);
       Serial.println("+");
       sensorFeedbackCounter++;
     } while(isnan(sensorFeedback[i]) || isnan(sensorFeedback[i+2]));
   }
 }
 else {
   double newTemperatureValue, newHumidityValue;
   double oldTemperatureValue, oldHumidityValue;

   // If isDifferenceBig = true, shift the array to add new feedbacks
   // to sensorFeedback[1] and sensorFeedback[3]
   do {
     Blynk_Delay(2000);
     oldTemperatureValue = sensorFeedback[1];
     sensorFeedback[0] = oldTemperatureValue;
     oldHumidityValue = sensorFeedback[3];
     sensorFeedback[2] = oldHumidityValue;
     newTemperatureValue = dht.readTemperature();
     sensorFeedback[1] = newTemperatureValue;
     newHumidityValue = dht.readHumidity();
     sensorFeedback[3] = newHumidityValue;

     sensorFeedbackCounter++;
   } while(isnan(sensorFeedback[1]) || isnan(sensorFeedback[3]));
 }

 // Print out readings
 Serial.println(sensorFeedback[0]);
 Serial.println(sensorFeedback[1]);
 Serial.println(sensorFeedback[2]);
 Serial.println(sensorFeedback[3]);
 Serial.println(sensorFeedbackCounter);
 Serial.println("---");

 // Check for temperature and humidity reading differences
 // Repeat the whole function until conditions are met
 if ((abs(sensorFeedback[1] - sensorFeedback[0]) > 0.20) || (abs(sensorFeedback[3] - sensorFeedback[2]) > 0.30))
 {
   isDifferenceBig = true; // should be true!!!
   getConsistentFeedbacks();
 }
 else
 {
   Serial.println("Sending update!");
   Serial.println(sensorFeedbackCounter);
   // Variables such as sensorFeedbackCounter or nanCounter are not set to zero
   // because deepSleep() resets the memory and whole program starts over
   return sensorFeedback;
 }
}

void setup()
{
 sampleStartTime = millis();
 Blynk_Delay(10);
 Serial.begin(9600); // Start serial connection
 Blynk.begin(auth, ssid, pass); // Connect to WIFI
 dht.begin(); // Start DHT22 sensor

 double* readings = getConsistentFeedbacks();

 t = readings[1]; // Temperature
 h = readings[3]; // Humidity

 hi = dht.computeHeatIndex(t, h, false); // HeatIndex function

 // Send acquired variables to Blynk server
 Blynk.virtualWrite(V5, h);
 Blynk.virtualWrite(V6, t);
 Blynk.virtualWrite(V7, hi);
 Blynk.virtualWrite(V8, sensorFeedbackCounter);
 sampleDuration = (millis() - sampleStartTime) / 1E3;
 Blynk.virtualWrite(V9, sampleDuration);

 Serial.println(sampleDuration);

 ESP.deepSleep(5 * 60 * 1000000L, WAKE_RF_DEFAULT); // Sleep NodeMCU for 5 mins.
}

void loop()
{
 Blynk.run();
 timer.run();
}

First of all, I replaced most of the recursive functions with do - while loops. There is still one remaining and I need to think about how to get rid of it.

Also, I changed how to shift an array. Similar to what Robin described in his example, I used variables to hold and pass the values to array elements. I didn't use max limiter but this works just like how I want it.

Thank you very much for your guidance.

Ozan

I am certain that the code in your snippet would work perfectly. This means that there is other code that you did not post in your snippet that is messing up what happens.

To continue: to shift an array we do not iterate through the elements - we use memcpy(dest, src, n).

memcpy copies n bytes of memory from src to dest. To shift an array, you need to copy from element 1 to element zero (or the other way around) a number of bytes equal to the size of the array minus the size of one element.

But this won't work for you, because your array conains both temerature and humitity all mixed in together in weird slots. To adress this, use a struct or a class.

struct SensorData {
  float temperature;
  float humidity;
};

const int sensorSamples = 2;

SensorData sensorData[sensorSamples];

/// etc ///
  memcpy(sensorData+0, sensorData+1, sizeof(sensorData) - sizeof(sensorData[0]));
  sensorData[sensorSamples-1].temperature = newTemperature;
  sensorData[sensorSamples-1].humidity = newHumidity;

This gives everything meaningful names, and it's easy to change how many samples you want to keep.

The other fix is to use a circular buffer, which is very slightly more complicated.

struct SensorData {
  float temperature;
  float humidity;
};

const int sensorSamples = 2;

int latestSensorRead = sensorSamples-1;

SensorData sensorData[sensorSamples];

/// etc ///
  latestSensorRead++;
  if(latestSensorRead >= sensorSamples) latestSensorRead = 0;
  sensorData[latestSensorRead].temperature = newTemperature;
  sensorData[latestSensorRead].humidity = newHumidity;

Again, this will adapt to any number of samples. To keep a running average, hold a sum of the temperature and humidity. When you take a new sample, subtract the old value and add the new one:

struct SensorData {
  float temperature;
  float humidity;
};

const int sensorSamples = 2;

int latestSensorRead = sensorSamples-1;

SensorData sensorData[sensorSamples];
SensorData runningAverage;

/// etc ///
  latestSensorRead++;
  if(latestSensorRead >= sensorSamples) latestSensorRead = 0;

  runningAverage.temperature -= sensorData[latestSensorRead].temperature / sensorSamples;
  runningAverage.humidity -= sensorData[latestSensorRead].humidity / sensorSamples;

  sensorData[latestSensorRead].temperature = newTemperature;
  sensorData[latestSensorRead].humidity = newHumidity;

  runningAverage.temperature += sensorData[latestSensorRead].temperature / sensorSamples;
  runningAverage.humidity += sensorData[latestSensorRead].humidity / sensorSamples;

Note, however, that this will accumulate errors over time. Every now and then you will want to recacluate the average from scratch.