Simplify a system that depends on temperature, humidity and light

This is a project I’m doing to keep learning Arduino. In it a fan is activated when temperature or humidity gets a certain value and a LED goes on if light goes below a certain value. Temperature and humidity are measured using a DHT11 sensor and light, using a photoresistor GL55.

I’ve already finished my code and it’s working fine. I’m not a very experienced programmer and I’m sure there are easier ways to code this project. Can anybody show me other ways to code it?

#include "DHT.h"

#define THHU 10         // Temperature and humidity sensor on pin 10
#define LISE A2         // Light sensor
#define FAN 2           // Fan attached on pin 2
#define LED 6           // LED attached on pin 6

// Variables and constants used to store input data
const byte total_input_pins   = 2;
const byte total_input_values = 3;
const byte input_pin[]        = {THHU, LISE};
byte input_pin_number;
byte value_number;
float input_value[total_input_values];

// Maximum and minimum values used to trigger the fan and the LED {Humidity, Temperature, Light}
float min_input_value[total_input_values] = {0.0, 0.0, 50000.0};
float max_input_value[total_input_values] = {90.0, 29.0, 100000.0};

// Variables and constants used to manage the program output
const byte total_output_pins = 2;
const byte output_pin[]      = {FAN, LED};
byte output_pin_number;

// Variables used to diplay data through Serial Port
unsigned long checktime;
const int display_interval = 5000;

DHT dht(THHU, DHT11);

void setup() {
  dht.begin();
  Serial.begin(9600);
  for (input_pin_number = 0; input_pin_number < total_input_pins; input_pin_number++) {
    pinMode(input_pin[input_pin_number], INPUT);
  }
  for (output_pin_number = 0; output_pin_number < total_output_pins; output_pin_number++) {
    pinMode(output_pin[output_pin_number], OUTPUT);
    digitalWrite(output_pin[output_pin_number], LOW);
  }
}
void loop() {
  READ_SENSORS();
  PROGRAM_OUTPUT();
}

void READ_SENSORS() {
  for (value_number = 0; value_number < total_input_values; value_number++) {
    switch (value_number) {
      case 0:
        input_value[value_number] = dht.readHumidity();                               // Read humidity (%)
      break;
      case 1:
        input_value[value_number] = dht.readTemperature();                            // Read Temperature (ºC)
      break;
      case 2:
        input_value[value_number] = map(analogRead(LISE), 0, 1023, 0.0, 100000.0);    // Read Light Value (Lux)
      break;
    }
  }
}

void PROGRAM_OUTPUT() {
  for (output_pin_number = 0; output_pin_number < total_output_pins; output_pin_number++) {
    switch (output_pin_number) {
      case 0:
        if (input_value[0] < min_input_value[0] || input_value[0] > max_input_value[0]) {
          digitalWrite(output_pin[output_pin_number], HIGH);
        }
        else if (input_value[1] < min_input_value[1] || input_value[1] > max_input_value[1]) {
          digitalWrite(output_pin[output_pin_number], HIGH);
        }
        else {
          digitalWrite(output_pin[output_pin_number], LOW);
        }
      break;
      case 1:
        if (input_value[2] < min_input_value[2] || input_value[2] > max_input_value[2]) {
          digitalWrite(output_pin[output_pin_number], HIGH);
        }
        else {
          digitalWrite(output_pin[output_pin_number], LOW);
        }
      break;
    }
  }
  if (millis() >= checktime) {
    checktime = millis() + display_interval;
    Serial.print(F("Humidity: "));
    Serial.print(input_value[0]);
    Serial.print(F(" % Temperature: "));
    Serial.print(input_value[1]);
    Serial.print(F(" C Light: "));
    Serial.print(input_value[2]);
    Serial.println(F(" Lux"));
  }
}

Your use of switch/case is interesting but I don't think that it makes the program any simpler. You might just as well read temperature and humidity and light intensity each time through loop(). Having said that, as a learning exercise using switch/case is fine

On the subject of timing

 if (millis() >= checktime)
  {
    checktime = millis() + display_interval;

is liable to fail when millis() rolls over to zero. Use subtraction instead of addition, see Using millis() for timing. A beginners guide, Several things at the same time and look at the BlinkWithoutDelay example in the IDE. Using subtraction to determine whether it is time to act will prevent a problem with millis() rollover.

Well done for using appropriate data types and const for variables that will not change

Thank you very much for your answer and thank you for your advice with the millis() issue, I’ll check that out.

I’m using switch/case that way because I wanted to store all inputs in one array. My initial goal was to set an array for all the inputs, compare it to the max/min values and then do something like:

  for (output_pin_number = 0; output_pin_number < total_output_pins; output_pin_number++) {
    digitalWrite(output_pin[output_pin_number], pin_state[output_pin_number])
  }

Where pin_state[output_pin_number] is an array with HIGH/LOW values. I wasn’t able to achieve it, but left it anyway just in case inspiration comes to me.

I'm using switch/case that way because I wanted to store all inputs in one array.

You could, of course, have done

  input_value[0] = dht.readHumidity(); 
  input_value[1] = dht.readTemperature();
  input_value[2] = map(analogRead(LISE), 0, 1023, 0.0, 100000.0);
/code]

I meant that my initial goal was to make it as general as possible:

for (value_number = 0; value_number < total_input_values; value_number++) {
  for (input_pin_number = 0; input_pin_number < total_input_pins; input_pin_number++) {
    input_value[value_number] = analogRead(input_pin[input_pin_number]);
  }
}

Then I realized that Temperature and Humidity values were not read using analogRead() so I thought I could use switch that way.

Nevertheless, I find more elegant and intuitive your solution.

Thank you again for your attention

Here is a variation on your original method that gets round the different types of input

const byte inputPins[] = {A6, A1, A2};
int inputValues[3];

void setup()
{
  Serial.begin(115200);
  for (int p = 0; p < 3; p++)
  {
    pinMode(inputPins[p], INPUT);
  }
}

void loop()
{
  for (int p = 0; p < 3; p++)
  {
    p == 0 ? inputValues[p] = analogRead(inputPins[p]) : inputValues[p] = digitalRead(inputPins[p]);
    Serial.println(inputValues[p]);
  }
  delay(1000);
}

NOTES
(1) A1 and A2 are being used as digital inputs and have pullup resistors in place in the circuit.
(2) For the sake of speed of writing this I have hardcoded the number of pins in the arrays but you know how to do it properly
(3) The strange looking ? : syntax in the line that reads the inputs is known as the ternary operator and is the equivalent of if/else but written more tersely

Thank you very much for your help.

If I may, I'll ask one more thing: where can I find more resources to continue learning? I fell kind of stuck in an intermediate level and when I try to find more bibliography, I find it very easy or too difficult.

I promise to finish here this thread.

There are innumerable sites with C and C++ tutorials which Google will find for you. The Arduino examples in the IDE are good to learn the basics of the Arduino environment but where some people struggle is dealing with the logic of a program rather than with actually writing it.

Personally I learnt a lot (and still do) from reading the threads on this forum and I find it instructive to read an initial post in a thread and try to work out what might be wrong before reading replies

To improve my knowledge I have set myself challenges such as writing a library, even though it does exactly what several other libraries do. I then wrote a much more complicated library and kept adding functionality until I got fed up and I have never used it since !

I also wrote Using millis() for timing. A beginners guide which made me think more deeply about the subject and how to explain it to others.

The fact is that we all learn in different ways so there is no one path to take. I have the luxury of doing this because I want to. I am not a professional programmer and nobody else is providing me with a specification or badgering me to finish a project. Luxury !

Thank you, you help me a lot!