Can this code be shortened using variables?

I just successfully set up an Arduino to monitor three NTC thermistors and to control a pump and a fan using a relay board. When writing the code (by borrowing from Adafruit NTC thermistor code), I was wondering if there is a better way, by using variables, to shorten it. Any ideas?

// SPDX-FileCopyrightText: 2011 Limor Fried/ladyada for Adafruit Industries
//
// SPDX-License-Identifier: MIT

// SPDX-FileCopyrightText: 2011 Limor Fried/ladyada for Adafruit Industries
//
// SPDX-License-Identifier: MIT

// Thermistor Example #3 from the Adafruit Learning System guide on Thermistors 
// https://learn.adafruit.com/thermistor/overview by Limor Fried, Adafruit Industries
// MIT License - please keep attribution and consider buying parts from Adafruit



#include <SPI.h>

// which analog pin to connect
#define oATemp A0 
#define supplyTemp A1
#define returnTemp A2  
#define fanControl 0 // Arduino pin connected to relay for fan
#define pumpControl 1 // Arduino pin connected to relayfor pump

// resistance at 25 degrees C
#define THERMISTORNOMINAL 10000      
// temp. for nominal resistance (almost always 25 C)
#define TEMPERATURENOMINAL 25   
// how many samples to take and average, more takes longer
// but is more 'smooth'
#define NUMSAMPLES 5
// The beta coefficient of the thermistor (usually 3000-4000)
#define BCOEFFICIENT 3950
// the value of the 'other' resistor
#define SERIESRESISTOR 10000    

int samples[NUMSAMPLES];

const int AIR_TEMP_THRESHOLD_UPPER = 74; // Start fan to circulate warm air around barrels, change to your desire value
const int AIR_TEMP_THRESHOLD_LOWER = 65; // Stop fan to prevent cooling barrels, change to your desire value

const int WATER_TEMP_THRESHOLD_UPPER = 50; // Start pump to heat greenhouse floor, change to your desire value
const int WATER_TEMP_THRESHOLD_LOWER = 40; // Stop pump to prevent cooling greenhouse floor, change to your desire value



void setup(void) {
  Serial.begin(9600);
  
  pinMode(oATemp, INPUT);
  pinMode(supplyTemp, INPUT);
  pinMode(returnTemp, INPUT);
  pinMode(fanControl, OUTPUT);
  pinMode(pumpControl, OUTPUT);
  
}

void loop(void) {
  uint8_t i;
  float average;

  // take N samples in a row, with a slight delay
  for (i=0; i< NUMSAMPLES; i++) {
   samples[i] = analogRead(oATemp);
   delay(10);
  }
  
  // average all the samples out
  average = 0;
  for (i=0; i< NUMSAMPLES; i++) {
     average += samples[i];
  }
  average /= NUMSAMPLES;

  
  // convert the value to resistance
  average = 1023 / average - 1;
  average = SERIESRESISTOR / average;

  
  float oATemp;
  oATemp = average / THERMISTORNOMINAL;     // (R/Ro)
  oATemp = log(oATemp);                  // ln(R/Ro)
  oATemp /= BCOEFFICIENT;                   // 1/B * ln(R/Ro)
  oATemp += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To)
  oATemp = 1.0 / oATemp;                 // Invert
  oATemp -= 273.15;                         // convert absolute temp to C
  oATemp = oATemp *1.8+32;
  
   {
    if (oATemp > AIR_TEMP_THRESHOLD_UPPER) {
      Serial.println("Fan relay is turned on");
      digitalWrite(fanControl, HIGH); // turn on
    } else if (oATemp < AIR_TEMP_THRESHOLD_LOWER) {
      Serial.println("Fan relay is turned off");
      digitalWrite(fanControl, LOW); // turn off
    }
  
  Serial.print("Outdoor Air Temperature "); 
  Serial.print(oATemp);
  Serial.println(" DegF");
  
  delay(1000);




uint8_t j;
  float average1;

  // take N samples in a row, with a slight delay
  for (j=0; j< NUMSAMPLES; j++) {
   samples[j] = analogRead(supplyTemp);
   delay(10);
  }
  
  // average all the samples out
  average = 0;
  for (j=0; j< NUMSAMPLES; j++) {
     average += samples[j];
  }
  average /= NUMSAMPLES;
 
  
  // convert the value to resistance
  average = 1023 / average - 1;
  average = SERIESRESISTOR / average;
  
  float supplyTemp;
  supplyTemp = average / THERMISTORNOMINAL;     // (R/Ro)
  supplyTemp = log(supplyTemp);                  // ln(R/Ro)
  supplyTemp /= BCOEFFICIENT;                   // 1/B * ln(R/Ro)
  supplyTemp += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To)
  supplyTemp = 1.0 / supplyTemp;                 // Invert
  supplyTemp -= 273.15;                         // convert absolute temp to C
  supplyTemp = supplyTemp *1.8+32;
  
  Serial.print("Supply Temperature "); 
  Serial.print(supplyTemp);
  Serial.println(" DegF");
  
  delay(1000);


uint8_t k;
  float average2;

  // take N samples in a row, with a slight delay
  for (k=0; k< NUMSAMPLES; k++) {
   samples[k] = analogRead(returnTemp);
   delay(10);
  }
  
  // average all the samples out
  average = 0;
  for (k=0; k< NUMSAMPLES; k++) {
     average += samples[k];
  }
  average /= NUMSAMPLES;
 
  
  // convert the value to resistance
  average = 1023 / average - 1;
  average = SERIESRESISTOR / average;
  
  float returnTemp;
  returnTemp = average / THERMISTORNOMINAL;     // (R/Ro)
  returnTemp = log(returnTemp);                  // ln(R/Ro)
  returnTemp /= BCOEFFICIENT;                   // 1/B * ln(R/Ro)
  returnTemp += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To)
  returnTemp = 1.0 / returnTemp;                 // Invert
  returnTemp -= 273.15;                         // convert absolute temp to C
  returnTemp = returnTemp *1.8+32;
  
   {
    if (returnTemp > WATER_TEMP_THRESHOLD_UPPER) {
      Serial.println("Pump relay is turned on");
      digitalWrite(pumpControl, HIGH); // turn on
    } else if (returnTemp < WATER_TEMP_THRESHOLD_LOWER) {
      Serial.println("Pump relay is turned off");
      digitalWrite(pumpControl, LOW); // turn off
    }
  
  
  
  Serial.print("Return Temperature "); 
  Serial.print(returnTemp);
  Serial.println(" DegF");
  
  delay(1000);

  

}
}
}

Yes

(It's nearly always possible. In this case, definitely!)

Can't for you just now, and I am looking through the tiny window, but it looks like you have two three (!) large blocks of code that are nearly identical.

You can try to write a function that is the essence of both. Pass as arguments to that function whatever makes these two blocks different, like they operate on a different sensor, or with different constants of one kind or another or whatever.

Functions + arrays = waaay less code.

Easier to perfect, modify or enhance, one stop shopping.

HTH

a7

  // take N samples in a row, with a slight delay
  for (i=0; i< NUMSAMPLES; i++) {
   samples[i] = analogRead(oATemp);
   delay(10);
  }
  
  // average all the samples out
  average = 0;
  for (i=0; i< NUMSAMPLES; i++) {
     average += samples[i];
  }
  average /= NUMSAMPLES

As far as I can tell, the array you have used here just isn't needed. The array gets filled with readings from an analog pin, but then the only thing that gets used for is to total up the values to calculate the average. That can be done without the array:

  // take N samples in a row, with a slight delay
  // and average all the samples out
  average = 0;
  for (i=0; i< NUMSAMPLES; i++) {
    average += analogRead(oATemp);
    delay(10);
  }
  average /= NUMSAMPLES;

A "crappy" code doing the job is a lot better then an "expert" code that nobody understand, nobody can maintain,or doesn't work.
Wait a few years and look at Your old codes...... You will learn things!

1 Like

That's the opposite of "expert code"! That's more "crappy code".

Ok, I agree that crappy code that works is better than crappy code that doesn't work.

But crappy code that nobody can understand or maintain is no better and no worse than any other crappy code :wink:

hmmmm, I'm picking up what you are throwing down, but...
I'm not really familiar with that coding requirement (for the NTC Thermistor). Not sure which variable to use. I have this part... just renamed the uint8_t (i,j,k)
I'm not sure what all of this code is doing, so, that's why I'm asking.

`uint8_t i;
float average;

// take N samples in a row, with a slight delay
for (i=0; i< NUMSAMPLES; i++) {
samples[i] = analogRead(oATemp);
delay(10);
}

// average all the samples out
average = 0;
for (i=0; i< NUMSAMPLES; i++) {
average += samples[i];
}
average /= NUMSAMPLES;

// convert the value to resistance
average = 1023 / average - 1;
average = SERIESRESISTOR / average;
``

I'm not sure, PaulRB. Why did Adafruit include it if it is not needed?

I think You get it, written for a newcommer....

I went to the original code on the Adafruit page. I don't see any reason.

Let's prove it!

Try this:

  // take N samples in a row, with a slight delay
  int averageB = 0;
  for (i=0; i< NUMSAMPLES; i++) {
    int r = analogRead(oATemp);
    samples[i] = r;
    averageB += r;
    delay(10);
  }
  
  // average all the samples out
  average = 0;
  for (i=0; i< NUMSAMPLES; i++) {
     average += samples[i];
  }
  average /= NUMSAMPLES;
  averageB /= NUMSAMPLES;

  if (average != averageB) Serial.println("They didn't match!");

@ragnardanneskjold perhaps an analogy.

You found some code to paint a car blue.

But you have a boat you want painted red, and a truck you want painted green.

So you take the code you found, copy and paste it, and go through it on your hands and knees replacing blue with red, and car with boat.

Presto, now you have twice the code, and you've solved 2/3 the problem.

You again take the code you found, copy and paste it, and go through it on your hands and knees replacing blue with green, and car with truck.

Now you have three times the code, and you are done.

It would have been better to change the code you found to paint <something> with <some colour>.

Now that same original code would be generalized, and you can call it with any object you want painted, along with what colour to paint it.

Leaving aside for the moment whether you needed to do it the way the code is written (I don't think so, but), this is the essence of the algorithm:

  for (ijk = 0; ijk < NUMSAMPLES; ijk++) {
   samples[ijk] = analogRead(aSensorPin);
   delay(10);
  }
  
  average = 0;
  for (ijk = 0; ijk < NUMSAMPLES; ijk++) {
     average += samples[ijk];
  }
  average /= NUMSAMPLES;
 
  average = 1023 / average - 1;
  average = SERIESRESISTOR / average;
  
  float output;
  output = average / THERMISTORNOMINAL; 
  output = log(output); 
  output /= BCOEFFICIENT;
  output += 1.0 / (TEMPERATURENOMINAL + 273.15); 
  output = 1.0 / output;
  output -= 273.15
  output = output *1.8 + 32;

which could form the body of a function called with one argument, a pin with a sensor hanging off it, which function can be made to return a floatating point result.

The italicized words should inform your googling or your work through your favorite learning source.

Try this

https://docs.arduino.cc/learn/programming/functions/

Any time you find yourself making new variables by appending a digit, it is time to consider using an array.

Any time you find yourself copy pasting code and changing things to alter the sources and destinations of the information that code uses, it is time to consider using a function.

A function would mean that when you tweak your algorithm, you have but one place to make changes, either to perfect, modify or enhance the process or calculations the code is meant to perform.

  float returnTemp = getConditionedTemperature(returnTempSensor);
 
  Serial.print("Return Temperature "); 
  Serial.print(returnTemp);
  Serial.println(" DegF");

If you went a bit further, you could pass into the function how to dress up the printing of the calculated value, but that would be too much. Better to have a function independent and usable everywhere, whether you just print the result or do the hysteresis thing or whatever.

You might also want to look into variable scope, try

HTH

a7

1 Like

Many thanks, alto777. You have been extremely helpful.
I just now had a chance to review your suggestions and they are spot on, however, I have a problem...
I am about to use this code on a Nano and put it on the Arduino IoT.
I don't know how much experience you've had with their IoT coding, but I have found that when I set up my device and use their IoT procedures ( creating a "Thing" and a "Dashboard"), their software sets up the variables automatically (sensors and other variables are named there and inserted into your sketch automatically based on the type and other parameters). So, for example, where you correctly suggested to use the variable "output" in place of oATemp, unless I can figure out how to correctly modify my coding to reflect that variable's 3 different possible values in this case, I don't know if this particular approach will work.
I will continue to noodle the solution. It is quite a challenge to a noob such as myself.
Thank you again.

Okay...
I read further. I just might figure this out!

I just re-wrote code, using variables. I'm not getting any readings from my sensors. I suspect it's in the area designated "float output". It seems there should be a reference to the 3 sensors there. Not sure. Your thoughts?

#include <SPI.h>

#define sensorPin1 A0
#define sensorPin2 A1
#define sensorPin3 A2  
#define fanControl 2 // Arduino pin connected to relay for fan
#define pumpControl 3 // Arduino pin connected to relayfor pump

#define getOutdoorTemp 
#define getSupplyTemp
#define getReturnTemp

// resistance at 25 degrees C
#define THERMISTORNOMINAL 10000      
// temp. for nominal resistance (almost always 25 C)
#define TEMPERATURENOMINAL 25   
// how many samples to take and average, more takes longer
// but is more 'smooth'
#define NUMSAMPLES 5
// The beta coefficient of the thermistor (usually 3000-4000)
#define BCOEFFICIENT 3950
// the value of the 'other' resistor
#define SERIESRESISTOR 10000    

int samples[NUMSAMPLES];

const int AIR_TEMP_THRESHOLD_UPPER = 74; // Start fan to circulate warm air around barrels, change to your desire value
const int AIR_TEMP_THRESHOLD_LOWER = 70; // Stop fan to prevent cooling barrels, change to your desire value

const int WATER_TEMP_THRESHOLD_UPPER = 50; // Start pump to heat greenhouse floor, change to your desire value
const int WATER_TEMP_THRESHOLD_LOWER = 40; // Stop pump to prevent cooling greenhouse floor, change to your desire value

void setup(void) {
  Serial.begin(9600);
  
  pinMode(sensorPin1, INPUT);
  pinMode(sensorPin2, INPUT);
  pinMode(sensorPin3, INPUT);
  pinMode(fanControl, OUTPUT);
  pinMode(pumpControl, OUTPUT);

  
  
}

void loop(void) {
  uint8_t i,j,k;
  float average;

  // take N samples in a row, with a slight delay
  for (i,j,k=0; i,j,k< NUMSAMPLES; i,j,k++) {
   samples[i,j,k] = analogRead(sensorPin1); analogRead(sensorPin2); analogRead(sensorPin3);
   delay(100);
  }
  
  // average all the samples out
  average = 0;
  for (i,j,k=0; i,j,k< NUMSAMPLES; i,j,k++) {
     average += samples[i,j,k];
  }
  average /= NUMSAMPLES;

  
  // convert the value to resistance
  average = 1023 / average - 1;
  average = SERIESRESISTOR / average;

  delay(100);

  
  float output;
  output = average / THERMISTORNOMINAL;     // (R/Ro)
  output = log(output);                  // ln(R/Ro)
  output /= BCOEFFICIENT;                   // 1/B * ln(R/Ro)
  output += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To)
  output = 1.0 / output;                 // Invert
  output -= 273.15;                         // convert absolute temp to C
  output = output *1.8+32;
  delay(100);

  float oATemp = getOutdoorTemp(sensorPin1);
  float supplyTemp = getSupplyTemp(sensorPin2);
  float returnTemp =  getReturnTemp(sensorPin3);

   {
    if (oATemp > AIR_TEMP_THRESHOLD_UPPER) {
      Serial.println("Fan relay is turned on");
      digitalWrite(fanControl, HIGH); // turn on
    } else if (oATemp < AIR_TEMP_THRESHOLD_LOWER) {
      Serial.println("Fan relay is turned off");
      digitalWrite(fanControl, LOW); // turn off
    }

    {
    if (returnTemp > WATER_TEMP_THRESHOLD_UPPER) {
      Serial.println("Pump relay is turned on");
      digitalWrite(pumpControl, HIGH); // turn on
    } else if (returnTemp < WATER_TEMP_THRESHOLD_LOWER) {
      Serial.println("Pump relay is turned off");
      digitalWrite(pumpControl, LOW); // turn off
    }
    }
   }
   
   Serial.print("Outdoor Air Temperature");
   Serial.print(oATemp);
   Serial.println(" Deg F");
   delay(1000);

   Serial.print("Supply Water Temperature");
   Serial.print(supplyTemp);
   Serial.println(" Deg F");
   delay(1000);

   Serial.print("Return Water Temperature");
   Serial.print(returnTemp);
   Serial.println(" Deg F");
   delay(1000);

}

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