Quantcast
Channel: Arduino Forum - Latest topics
Viewing all articles
Browse latest Browse all 15622

Trying to improve sensor reading function

$
0
0

Hi everyone,

I've been working for some time on a project to eventually build a controller for my paludarium, using the Arduino Giga R1, connected to the arduino cloud.

Main functionality and interface almost finished and I've had it up and running for a few weeks now. I've added external EEPROM that keeps track of how many times it reboots with a simple counter + 1 (save to EEPROM) in the setup and the option to manually reset it. It's not bad but it's not great either so I'm trying to improve my existing code.

The main function of the controller is getting sensor data and using it to adjust conditions.
I've been running a fairly simple bit of code to read the sensors that does not account for problems with the sensors or readings. I don't know if this can actually cause a reboot but I wanted to improve it regardless to handle NAN readings and send me an alarm if things get dodgy.

Here is what I was using up until now:

void updateStatistics() {

  sht1.read();
  sht2.read();

  temp1 = dht1.readTemperature();
  hum1 = dht1.readHumidity();
  temp2 = dht2.readTemperature();
  hum2 = dht2.readHumidity();

  temp3 = sht1.getTemperature();
  hum3 = sht1.getHumidity();
  temp4 = sht2.getTemperature();
  hum4 = sht2.getHumidity();

  temp5 = bme1.getTemperature();
  hum5 = bme1.getHumidity();
  pres1 = (bme1.getPressure() / 100);
  temp6 = bme2.getTemperature();
  hum6 = bme2.getHumidity();
  pres2 = (bme2.getPressure() / 100);

  airTempAverage = (temp1 + temp2 + temp3 + temp4 + temp5 + temp6) / 6;
  humidityAverage = (hum1 + hum2 + hum3 + hum4 + hum5 + hum6) / 6;  
  pressureAverage = (pres1 + pres2) / 2;

  //read water temperature1
  Vo = analogRead(ThermistorPin);
  R2 = R1 * (1432.0 / (float)Vo - 1.0); //1432 used to be 1023, representing maximum binary value of 10 bit. For some reason the Giga R1 is different. I don't understand why.
  logR2 = log(R2);
  waterTemp_1 = (1.0 / (c1 + c2 * logR2 + c3 * logR2 * logR2 * logR2));
  waterTemp1 = waterTemp_1 - 273.15; // to Celsius
  //read water temperature2
  Vo2 = analogRead(Thermistor2Pin);
  R3 = R1 * (1432.0 / (float)Vo2 - 1.0);
  logR3 = log(R3);
  waterTemp_2 = (1.0 / (c1 + c2 * logR3 + c3 * logR3 * logR3 * logR3));
  waterTemp2 = waterTemp_2 - 273.15;
  //WaterTemp Average
  waterTempAverage = (waterTemp1 + waterTemp2) / 2;

}

This worked fine, but was always supposed to be improved

I've been thinking of the functionalities I wanted to add and wrote this bit of code:

void updateStatistics() {
  
  int totalReadings = 14;  
  float reading[totalReadings] = {temp1, temp2, temp3, temp4, temp5, temp6, hum1, hum2, hum3, hum4, hum5, hum6, pres1, pres2};
  float sensorValue[totalReadings] = {t1, t2, t3, t4, t5, t6, h1, h2, h3, h4, h5, h6, p1, p2};
  int sensor[totalReadings];

  sht1.read();
  sht2.read();

  t1 = dht1.readTemperature();
  h1 = dht1.readHumidity();
  t2 = dht2.readTemperature();
  h2 = dht2.readHumidity();

  t3 = sht1.getTemperature();
  h3 = sht1.getHumidity();
  t4 = sht2.getTemperature();
  h4 = sht2.getHumidity();

  t5 = bme1.getTemperature();
  h5 = bme1.getHumidity();
  p1 = bme1.getPressure() / 100;
  t6 = bme2.getTemperature();
  h6 = bme2.getHumidity();
  p2 = bme2.getPressure() / 100;

  for (i = 0; i < totalReadings; i++) {
    if(!isnan(sensorValue[i])) {
    reading[i] = sensorValue[i];
    sensor[i] = 0;
    } else {    
      sensor[i]++; 
    }
    
    if (sensor[i] == 60) { //if 60 consecutive readings fail the sensor may be broken: Trigger the alarm
      alarm(i);
    }
  }

  airTempAverage = (temp1 + temp2 + temp3 + temp4 + temp5 + temp6) / 6;

  humidityAverage = (hum1 + hum2 + hum3 + hum4 + hum5 + hum6) / 6;  

  pressureAverage = (pres1 + pres2) / 2;

  //if a reading differs too much from the average the sensor may be broken. Trigger the alarm
  for (i = 0; i < 6; i++) { //1-6 is temperature
    if ( (sensorValue[i] > airTempAverage + 5) || (sensorValue[i] < airTempAverage - 5)) {
      alarm(i);
    }
  }
  
  for (i = 7; i < 12; i++) {  //7-12 is humidity
    if ( (sensorValue[i] > humidityAverage + 10) || (sensorValue[i] < humidityAverage - 10)) {
      alarm(i);
    }
  }

  //read water temperature1
  Vo = analogRead(ThermistorPin);
  R2 = R1 * (1023.0 / (float)Vo - 1.0);
  logR2 = log(R2);
  waterTemp1 = (1.0 / (c1 + c2 * logR2 + c3 * logR2 * logR2 * logR2));
  waterTemp1 = waterTemp1 - 273.15;
  //read water temperature2
  Vo2 = analogRead(Thermistor2Pin);
  R3 = R1 * (1023.0 / (float)Vo2 - 1.0);
  logR3 = log(R3);
  waterTemp2 = (1.0 / (c1 + c2 * logR3 + c3 * logR3 * logR3 * logR3));
  waterTemp2 = waterTemp2 - 273.15;
  //WaterTemp Average
  waterTempAverage = (waterTemp1 + waterTemp2) / 2;

}

I think it should do what I want. I'm not sure yet what the alarm is supposed to do but at the very least it will print something in red on the TFT instead of white.

Now I'm not a programmer and I went to chatGPT to get a preliminary assessment. After some back and forth it suggested I use pointers.

I have a vague understanding of pointers and know there are risks involved. The final result of the code is this:

void updateStatistics() {
  // Define total number of readings and arrays to store readings and sensor status
  const int totalReadings = 14;  
  const int maxCount = 120;  
  float airDeviation = 5.0; //degress C
  float humidityDeviation = 10.0; //% RH
  float reading[totalReadings];
  float sensorValue[totalReadings] = {temp1, temp2, temp3, temp4, temp5, temp6, hum1, hum2, hum3, hum4, hum5, hum6, pres1, pres2};
  int sensor[totalReadings] = {maxCount}; 

  // Define pointers to sensor objects
  DHT *dht1_ptr = &dht1;
  DHT *dht2_ptr = &dht2;
  Adafruit_SHT31 *sht1_ptr = &sht1;
  Adafruit_SHT31 *sht2_ptr = &sht2;
  Adafruit_BME280 *bme1_ptr = &bme1;
  Adafruit_BME280 *bme2_ptr = &bme2;

  // Read sensor data
  reading[0] = readTemperature(dht1_ptr);
  reading[1] = readTemperature(dht2_ptr);
  reading[2] = sht1_ptr->getTemperature();
  reading[3] = sht2_ptr->getTemperature();
  reading[4] = bme1_ptr->getTemperature();
  reading[5] = bme2_ptr->getTemperature();
  reading[6] = readHumidity(dht1_ptr);
  reading[7] = readHumidity(dht2_ptr);
  reading[8] = sht1_ptr->getHumidity();
  reading[9] = sht2_ptr->getHumidity();
  reading[10] = bme1_ptr->getHumidity();
  reading[11] = bme2_ptr->getHumidity();
  reading[12] = bme1_ptr->readPressure() / 100;
  reading[13] = bme2_ptr->readPressure() / 100;

  // Check sensor readings and update sensor status
  for (int i = 0; i < totalReadings; i++) {
    if (!isnan(reading[i])) {
      sensorValue[i] = reading[i];
      sensor[i] = 0; //reset NAN counter
    } else {
      if (sensor [i] < maxCount) { //if NAN adjust the counter
        sensor[i]++;
      }
    }

    if (sensor[i] == maxCount) { //if 60 consecutive readings fail, trigger the alarm
      alarm(i);
    }
  }

  // Calculate averages
  float airTempAverage = (reading[0] + reading[1] + reading[2] + reading[3] + reading[4] + reading[5]) / 6;
  float humidityAverage = (reading[6] + reading[7] + reading[8] + reading[9] + reading[10] + reading[11]) / 6;
  float pressureAverage = (reading[12] + reading[13]) / 2;

  // Check for significant deviations in sensor readings
  for (int i = 0; i < 6; i++) { //1-6 is temperature
    if ((reading[i] > airTempAverage + airDeviation) || (reading[i] < airTempAverage - airDeviation)) {
      alarm(i);
    }
  }
  
  for (int i = 7; i < 12; i++) {  //7-12 is humidity
    if ((reading[i] > humidityAverage + humidityDeviation) || (reading[i] < humidityAverage - humidityDeviation)) {
      alarm(i);
    }
  }
  
  //read water temperature1
  Vo = analogRead(ThermistorPin);
  R2 = R1 * (1023.0 / (float)Vo - 1.0);
  logR2 = log(R2);
  waterTemp1 = (1.0 / (c1 + c2 * logR2 + c3 * logR2 * logR2 * logR2));
  waterTemp1 = waterTemp1 - 273.15;
  //read water temperature2
  Vo2 = analogRead(Thermistor2Pin);
  R3 = R1 * (1023.0 / (float)Vo2 - 1.0);
  logR3 = log(R3);
  waterTemp2 = (1.0 / (c1 + c2 * logR3 + c3 * logR3 * logR3 * logR3));
  waterTemp2 = waterTemp2 - 273.15;
  //WaterTemp Average
  waterTempAverage = (waterTemp1 + waterTemp2) / 2;

}

float readTemperature(DHT *dht) {
  float temperature = NAN;
  float temp = dht->readTemperature();
  if (!isnan(temp)) {
    temperature = temp;
  }
  return temperature;
}

float readHumidity(DHT *dht) {
  float humidity = NAN;
  float hum = dht->readHumidity();
  if (!isnan(hum)) {
    humidity = hum;
  }
  return humidity;
}

The temp1, temp 2 etc are used by other functions as well so they remained, the reading[] array whas shortened and some minor tweaks. All that I can comprehend, but the pointers are lightyears ahead of my understanding.

Does this look alright or is there some gibberish in there as well?

7 posts - 2 participants

Read full topic


Viewing all articles
Browse latest Browse all 15622

Latest Images

Trending Articles



Latest Images