Problem with variable being overwritten

I have a particle photon set up to read data from 2 DS18B20 temperature sensors. One is near the device, which I am calling the internal temperature sensor (intTemperature). One is connected to a 4 ft cable, which I am calling the external temperature sensor (extTemperature).

My intTemperature variable is being overwritten. I’ve narrowed the problem down to my addValue() function. The Serial.println() statements on lines 131 and 144 should give identical results, but they don’t. (Line numbers reference complete code. I’ve excerpted the relevant selection below).

I have some experience with microcontrollers (Arduino and BasicStamp), but am new to Particle Photon.

Let me know if you have any suggestions.

Thanks,
Dan

double intTemperature = 0;
double extTemperature = 0;
double extTempArray[11]; //array to hold external temperatures

void addValue(double newTemp){
  Serial.println("*** addValue function ***");
  Serial.println(intTemperature);
   // shift values in extTempArray
  for (int x = MED_ARRAY_LEN; x>=1; x--){
     extTempArray[x] = extTempArray[x-1];
  }
  extTempArray[0] = newTemp;
  Serial.println(intTemperature); // this should be identical to the same statement 6 lines earlier
}
Complete Code
/*
 * Project pp-weatherstation
 * Description: Log temperature data from DS18B20 sensor and post it to
 ThingSpeak and Wunderground
 * Author: Daniel Olson
 * Date: 3-26-2017
 * version control managed via GitHub
 */



// This #include statement was automatically added by the Particle IDE.
#include <OneWire.h>
#include <DS18B20.h>
#include <stdlib.h> // needed for qsort
#include "blynk.h"

const int      MAXRETRY          = 4; // max times to try to read temp sensor
const int      MED_ARRAY_LEN = 11;

DS18B20 intTempSensor(D3, true); //Sets Pin D3 for internal temperature sensor
DS18B20 extTempSensor(D4, true); //Sets Pin D4 for external temperature sensor

char szInfo[64]; // character array to hold temperature data as a String
char auth[] = "xxxxx"; // for Blynk app

//double celsius[2];
//double fahrenheit[2]; // temperature array
double intTemperature = 0;
double extTemperature = 0;
double medianExtTemp = 0;

double extTempArray[11]; //array to hold external temperatures

int iIdx = 0; // index of internal temperature in temperature array
int eIdx = 1; // index of external temperature in temperature array

unsigned int Publish_Rate = 30000;
unsigned int PublishTime;
int DS18B20nextSampleTime;
int DS18B20_SAMPLE_INTERVAL = 1000;
int dsAttempts = 0;

void setup() {
    Time.zone(-5);
    Particle.syncTime();

    Particle.variable("int_temp", intTemperature);
    Particle.variable("ext_temp", extTemperature);
    Serial.begin(9600);

    // initialize extTempArray
    for (int x = 0; x < MED_ARRAY_LEN; x++){
      extTempArray[x] = 0;
    }

    Blynk.begin(auth);
}

void loop() {
  //double medTemp;

  if (millis() > DS18B20nextSampleTime){
     Serial.println("$$$$$$$$$$$$$$$$ getTemp $$$$$$$$$$$$$$$$$$");
     extTemperature = getTemp(extTempSensor);
     Serial.println("ext temp=" + String(extTemperature));
     intTemperature = getTemp(intTempSensor);
     Serial.println("int temp=" + String(intTemperature));

     // send data to Blynk
     Blynk.run();
     Blynk.virtualWrite(V1, String(extTemperature));
     Blynk.virtualWrite(V2, String(intTemperature));
     Blynk.virtualWrite(V5, millis()/1000); // send uptime data to Blynk

     // calculate median temperatures
     addValue(extTemperature); // <-- THIS IS CAUSING THE PROBLEM
     medianExtTemp = getMedian();
     Serial.println("median temperature=" + String(medianExtTemp));
     DS18B20nextSampleTime = millis() + DS18B20_SAMPLE_INTERVAL;
     Serial.println("");
     Serial.println("end of nextSampleTime");
     Serial.println("ext temp=" + String(extTemperature));
     Serial.println("int temp=" + String(intTemperature));
    }

  if (millis() > PublishTime){
     Serial.println("****************** Publishing now ******************");
     publishData();
     PublishTime = millis() + Publish_Rate;
    }
    //delay(300);
}

// get median value of extTempArray
double getMedian(){
  double temporaryArray[MED_ARRAY_LEN];
  int middleValue = MED_ARRAY_LEN/2;
  //Serial.println("getMedian: middleValue=" + String(middleValue));
  // deep copy array
  for (int x=0; x<MED_ARRAY_LEN; x++){
    temporaryArray[x] = extTempArray[x];
  }

  qsort(temporaryArray, MED_ARRAY_LEN, sizeof(double), compare);

  /*
  Serial.println("getMedian: original array");
  for (int x=0; x<MED_ARRAY_LEN; x++){
    Serial.println(extTempArray[x]);
  }

  Serial.println("getMedian: sorted array");
  for (int x=0; x<MED_ARRAY_LEN; x++){
    Serial.println(temporaryArray[x]);
  }
  */
  return temporaryArray[middleValue];
}

// for qsort function
int compare (const void * a, const void * b) {
   double fa = *(const double*) a;
   double fb = *(const double*) b;
   return (fa > fb) - (fa < fb);
}

// add a new value to the extTempArray
void addValue(double newTemp){
  Serial.println("*** addValue function ***");
  Serial.println(intTemperature);
   // shift values in extTempArray
  for (int x = MED_ARRAY_LEN; x>=1; x--){
     extTempArray[x] = extTempArray[x-1];
  }
  extTempArray[0] = newTemp;

   /*
   //show what's in the array
   for (int x=0; x<MED_ARRAY_LEN; x++){
     Serial.println("addValue: " + String(x) + " val:" + String(extTempArray[x]));
   }
   */
  Serial.println(intTemperature);
}

void publishData(){
  //if(!ds18b20.crcCheck()){      //make sure the value is correct
    //return;
  //}
  //sprintf(szInfo, "%2.2f", extTemperature); // store temperature data as a formatted string
  //Particle.publish("temperature", szInfo, PRIVATE);

  // publish to Wunderground
  Particle.publish("temperature", String(medianExtTemp), PRIVATE);

  //publish raw data to ThingSpeak
  String data = String("{ \"tempInt\": \"" + String(intTemperature) + "\",  \"tempExt\": \"" +  String(extTemperature) + "\" }");
  Particle.publish("temp_both", data, PRIVATE);
}


// pass a DS18B20 object and get its temperature in deg F, as a double
double getTemp(DS18B20 &ds18b20){
  float _temp;
  double   celsius;
  double   fahrenheit;
  int   i = 0;

  do {
    _temp = ds18b20.getTemperature();
  } while (!ds18b20.crcCheck() && MAXRETRY > i++);

  if (i < MAXRETRY) {
    celsius = _temp;
    fahrenheit = ds18b20.convertToFahrenheit(_temp);
    //Serial.println("getTemp: " + String(fahrenheit));
    //Serial.println(fahrenheit);
  }
  else {
    celsius = fahrenheit = NAN;
    Serial.println("getTemp: Invalid reading");
  }

  return fahrenheit;
}

I think your problem is here. Your extTempArray has 11 members, so the index goes from 0 to 10. Since MED_ARRAY_LEN equals 11, you're writing into space that you shouldn't, one beyond the end of your array.

BTW, why are you shifting the values in extTempArray? It looks like you're creating a running average. If there's no reason that the values need to stay in order, then you can just fill the array from 0 to 10, then start over at 0, which will replace the oldest values. You only need an index variable that you increment every time you add a value to the array,

index = ( index + 1) % MED_ARRAY_LEN
2 Likes

That fixed it. Thanks!

I’m creating a running median. Shifting values in estTempArray was the first thing I thought of, but you’re right that I don’t need to keep the values in order, and I like your solution.