Help with aditional code

Hi, I have included my sketch of a home thermometer using an Arduino Nano, a servo is used as a temperature indicator, from 10 > 26 deg C. .Also three led's show room temperature trends, either rising, falling, or steady state.

A 2 minute delay is introduced between each reading in the void loop, for sampling room temperature.

My programming skills are limited, however I've managed to put together a sketch that works. Would appreciate a member taking a look over it for me please, and if improvements to the code are needed, please advise.

The three led's temperature trend, share the same monitoring period of 30 seconds within the current room temperature loop, however could the previous temperature historic period be extended to say 20 minutes? Allowing a better overall indication as to how the room temperature has been progressing over the past time, ie warming, cooling or holding steady.

I would appreciate some help with the code please, and to how to include it in my sketch.

// date  24/05/2024
//Home_temp_leds_DHT22_v2_IDE
// conventional delay
//This version uses a DHT22 Sensor
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>
#include <Servo.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define DHTPIN 2
#define DHTTYPE DHT22
DHT_Unified dht(DHTPIN, DHTTYPE);
// =========================================
int SENSOR_PIN = 2;
int SERVO_PIN = 9;
int sensorValue;          // variable to store temp. sensor value
int previousTemperature;  // last temperature shown prior to current temparature reading
int currentTemperature = 0;
const int ledH = (10);  // warmng red led and wire
const int ledL = (11);  // cooling orange wire
const int ledN = (12);  //steady green led and wire
//const float TEMPERATURE_THRESHOLD = 26;
Servo servo;
OneWire oneWire(SENSOR_PIN);
DallasTemperature sensor(&oneWire);
float temperature;
float Temperature;
float servopos;
// ==========================================================================
void setup() {
  Serial.begin(9600);
  pinMode(ledH, OUTPUT);
  pinMode(ledL, OUTPUT);
  pinMode(ledN, OUTPUT);

  servo.attach(SERVO_PIN);  // attaches the servo on pin 9 to the servo object
  servo.write(0);
  currentTemperature = (SENSOR_PIN);  //(temperature);   //(SENSOR_PIN);
  sensor.begin();
  dht.begin();
  Serial.println(F("DHTxx Unified Sensor Example"));
  sensor_t sensor;
  dht.temperature().getSensor(&sensor);
}
//==============================================================================
void loop() {
  delay(4000);
 // delay(2 * 60 * 1000UL);  //set delay time = 2 min
  sensors_event_t event;
  dht.temperature().getEvent(&event);
  if (isnan(event.temperature)) {
    Serial.println(F("Error reading temperature!"));
  } else {
    Serial.print(F("Temperature: "));
    Serial.print(event.temperature);
    Serial.println(F("°C"));
  }
  previousTemperature = currentTemperature;
  currentTemperature = (event.temperature);            //(DHT22 SENSOR_PIN);
 
  if (currentTemperature > previousTemperature)  // warming
  {
    Serial.println(F(" Warming"));
    digitalWrite(ledH, HIGH);
    digitalWrite(ledL, LOW);
    digitalWrite(ledN, LOW);
    delay(50);
  } else if (currentTemperature < previousTemperature)  // cooling
  {
    Serial.println(F("Cooling"));
    digitalWrite(ledL, HIGH);
    digitalWrite(ledH, LOW);
    digitalWrite(ledN, LOW);
    delay(50);
  } else if (currentTemperature == previousTemperature)  // steady
  {
    Serial.println(F(" Steady"));
    digitalWrite(ledN, HIGH);
    digitalWrite(ledH, LOW);
    digitalWrite(ledL, LOW);
  }
  { servopos = map(currentTemperature, 10, 26, 180, 0);  // set temperature range and servo angles
  if (servopos < 0) servopos = 0;
  if (servopos > 180) servopos = 180;
  servo.write(servopos);  // write servo position indcating temperature
  //delay(50);
}
    delay(2 * 60 * 1000UL);  //set delay time = 2 min
  }


I moved your topic to an appropriate forum category @Jevray.

In the future, please take some time to pick the forum category that best suits the subject of your topic. There is an "About the _____ category" topic at the top of each category that explains its purpose.

This is an important part of responsible forum usage, as explained in the "How to get the best out of this forum" guide. The guide contains a lot of other useful information. Please read it.

Thanks in advance for your cooperation.

Hi, sorry for my error, appreciate, regards Jevray

1 Like

Do not use delay() in your programs.

Learn to use millis() for timed events. Here is an example.

+1.

Here's a perfect place to figure out how to do several things at once, each with its own timing so

you could move the servos whenever the temperature changed

you could have short term and longer term LEDs for trends

and so forth.

This can be placed in the loop() function to control a periodic process, the rest of the loop will sti execute very rapidly, you could repeat the pattern for something meant to happen once an hour or whatever

  static unsigned long lastTime;
  if (millis() - lastTime >= 10000) {

// code here only gets executed every 10000 milliseconds (10 seconds)

    lastTime =millis();   // update the timing variable
  }

It is an important concept to master. It usually starts with a suggestion to come to a thorough understanding of "blink without delay". There's an example in the IDE and this article

https://docs.arduino.cc/built-in-examples/digital/BlinkWithoutDelay/

HTH

a7

Thanks for your prompt response, I am aware of using Millis, but not certain how I would go about fitting it into my sketch, however, I will go through the lesson. Jevray

Thanks for your prompt reply, I must go through, 'using millis' and see how I can use it. Jevray

I'm not in the lab so I can't test this, but it should be close. Upload and watch the serial monitor output, set the serial monitor to 115200 to match baud rates.

void setup() {
  Serial.begin(115200);
  Serial.println("every so often world!");
  Serial.println("");
}

void loop() {

  static unsigned long lastTime1;
  if (millis() - lastTime1 >= 10000) {

// code here only gets executed every 10000 milliseconds (10 seconds)

    Serial.println("every ten seconds ");

    lastTime1 =millis();   // update the timing variable
  }


  static unsigned long lastTime2;
  if (millis() - lastTime2 >= 7000) {

// code here only gets executed every 7000 milliseconds (7 seconds)

    Serial.println("                                       every seven seconds ");

    lastTime2 =millis();   // update the timing variable
  }

}

[/quote]

The two sections are independent and each one fires off at a different time since.

a7

I have 2 observations to make.
The first is simple and is the repetition of the definition of the temperature variable.

The second is about the 18B20 sensor.
It is included, defined, started, but not used.

Simulated @ "Sensor_DHT_DS18B20 - Wokwi ESP32, STM32, Arduino Simulator

Thank you kindly for your comments, the sketch was originally for the 1820 sensor, but I had issues with odd temperature variations in the readings, so I used the DHT22 instead. Should have deleted the library for it. I’ve used temperature and Temperature elsewhere in the sketch, thanks for spotting it, l will correct it. Jevray

Here is a simulation (click the white arrow in the green circle) that shows the use multiple events... that you can add to if you want to experiment. Imagine your sketch started with two timed events, but grew to many more events. I encourage the use of this simulator to practice coding to help with your real-world project.

A variation on this is to put each task inside its own function and then all your time variables can be local. I find this a bit more contained and a nice repeatable template, but YMMV.

void setup() {
  Serial.begin(115200);
  Serial.println("every so often world!");
  Serial.println("");
}

void loop() {

  CheckFirstEvent();
  CheckSecondEvent();

}

void CheckFirstEvent() {
  static unsigned long lastTime;
  const unsigned long interval = 10000UL;

  if (millis() - lastTime >= interval) {
    lastTime = millis();  // update the timing variable

    // code here only gets executed every 10000 milliseconds (10 seconds)

    Serial.println("every ten seconds ");
  }
}

void CheckSecondEvent() {
  static unsigned long lastTime;
  const unsigned long interval = 7000UL;

  if (millis() - lastTime >= interval) {
    lastTime = millis();  // update the timing variable

    // code here only gets executed every 7000 milliseconds (7 seconds)

    Serial.println("                                       every seven seconds ");
  }
}

That’s ideal, I can experiment with that. I have a spare nano that I can use. Thanks for your reply👍

Another good idea, easy to see how each block of code performs, and easy to edit. Many thanks for your response and posting your example code. Jevray

Thanks to all of you for your help, much appreciated, I have plenty of ideas and examples to go by.
I have the home thermometer in place and working nicely. I’m going to put together another test bed to experiment with following all your comments. Kind regards Jevray

also

both more like real code, but all the examples offered exploit the idiomatic timing pattern

  if the time has come
    do whatever it's time for and
    remember when you did it     

I don't like copy/paste/editing code to make two or more of something there is already one of. In my example I did, only to illustrate how two totally independent periodically executed code step live together in one loop(), whilst avoiding use of functions and arrays for the moment.

Both functions and arrays are essential language features for writing good code and for making it easier to get things working.

A further step to both improvements would be the use of some C++, or even just those features of C++ which have been put into what is now C. That's another level of power, and the same sense of it will be easier to make if the clumsy literal code is fully understood.

a7

Many thanks, food for thought. I have got a better idea know, as to the way forward. From the information I have gained and the examples shown, my next move is to put those examples into practice for myself.
Thanks to all here for offering their time and experience.
Regards Jevray.

This is my final sketch for the room thermometer I requested help with, using millis. All’s working fine, but just a strange anomaly which occurs occasionally. The temperature will suddenly jump a couple of degrees, led shows “WARMING” next loop through shows a temperature drop, led shows “COOLING”, this may repeat a couple of times before the actual temperature becomes stable and led “STEADY” indicates the actual temperature. This only seems to happen around 19degC. My thoughts were possibly sensor playing up, so I swapped the18b20 for a DHT22 but no difference. Not a big issue, but annoying.. any ideas? Finally, any thoughts for improvements?

// date  30/05/2024
// millis delay
//This version uses a DHT22 Sensor
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>
#include <Servo.h>
#define DHTPIN 2
#define DHTTYPE DHT22
DHT_Unified dht(DHTPIN, DHTTYPE);
// =========================================
int SENSOR_PIN = 2;
int SERVO_PIN = 9;
int sensorValue;          // variable to store temp. sensor value
int previousTemperature;  // last temperature shown prior to current temparature reading
int currentTemperature = 0;
const int ledH = (10);  // warmng red led and wire
const int ledL = (11);  // cooling orange wire
const int ledN = (12);  //steady green led and wire

Servo servo;
float temperature;
float Temperature;
float servopos;
// ==========================================================================
void setup() {
  Serial.begin(9600);
  pinMode(ledH, OUTPUT);
  pinMode(ledL, OUTPUT);
  pinMode(ledN, OUTPUT);

  servo.attach(SERVO_PIN);  // attaches the servo on pin 9 to the servo object
  servo.write(0);
  currentTemperature = (SENSOR_PIN);  //(temperature);   //(SENSOR_PIN);
  dht.begin();
  Serial.println(F("DHTxx Unified Sensor Example"));
  sensor_t sensor;
  dht.temperature().getSensor(&sensor);
}
//==============================================================================
void loop() {
  static unsigned long lastTime1;
  if (millis() - lastTime1 >= 30000ul) {  // set servo active positioning time = 30 SECONDS
  sensors_event_t event;
  dht.temperature().getEvent(&event);
  if (isnan(event.temperature)) {
    Serial.println(F("Error reading temperature!"));
  } else {
    Serial.print(F("Temperature: "));
    Serial.print(event.temperature);
    Serial.println(F("°C"));
  }
  previousTemperature = currentTemperature;
  currentTemperature = (event.temperature);
  { servopos = map(currentTemperature, 10, 26, 180, 0);  // set temperature range and servo angles
    if (servopos < 0) servopos = 0;
    if (servopos > 180) servopos = 180;
    servo.write(servopos);  // write servo position indcating temperature
  } lastTime1 = millis();  // update the timing variable}
  // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     static unsigned long lastTime2;
    if (millis() - lastTime2 >=5000ul) // set past temperature period (5000) seconds
    
  if (currentTemperature > previousTemperature)  // warming
  { Serial.println(F(" Warming"));
    digitalWrite(ledH, HIGH);
    digitalWrite(ledL, LOW);
    digitalWrite(ledN, LOW);
    
  } else if (currentTemperature < previousTemperature)  // cooling
  { Serial.println(F("Cooling"));
    digitalWrite(ledL, HIGH);
    digitalWrite(ledH, LOW);
    digitalWrite(ledN, LOW);
   
  } else if (currentTemperature == previousTemperature)  // steady
  {
    Serial.println(F(" Steady"));
    digitalWrite(ledN, HIGH);
    digitalWrite(ledH, LOW);
    digitalWrite(ledL, LOW);
    lastTime2 = millis();  // update the timing variable
  }
 }
}

You can always apply some hysteresis or averaging to smooth things out a bit.

I for the code itself, Ctrl-T in the IDE will auto-format it and tidy it up a bit. This if() statement

Does not have any curly braces so only the next statement is associated with that if(). Lucky for you, the next statement is another if() statement so the entire block works as expected. In the future, if you put some other statement between those two statements, it would break. Probably good to get into the habit of always using curly braces, and using them in a consistent manner

Hi, thanks for your comments, I do get confused with IF statements, please take a look at my sketch that I have corrected, I seem to have more curly brackets at the end of my loop.
I also want to take a look at using hysteresis or averaging as you mentioned.
Jevray.

// date  06/06/2024
// millis delay
//This version uses a DHT22 Sensor
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>
#include <Servo.h>
#define DHTPIN 2
#define DHTTYPE DHT22
DHT_Unified dht(DHTPIN, DHTTYPE);
// =========================================
int SENSOR_PIN = 2;
int SERVO_PIN = 9;
int sensorValue;          // variable to store temp. sensor value
int previousTemperature;  // last temperature shown prior to current temparature reading
int currentTemperature = 0;
const int ledH = (10);  // warmng red led and wire
const int ledL = (11);  // cooling orange wire
const int ledN = (12);  //steady green led and wire

Servo servo;
float temperature;
float Temperature;
float servopos;
// ==========================================================================
void setup() {
  Serial.begin(9600);
  pinMode(ledH, OUTPUT);
  pinMode(ledL, OUTPUT);
  pinMode(ledN, OUTPUT);

  servo.attach(SERVO_PIN);  // attaches the servo on pin 9 to the servo object
  servo.write(0);
  currentTemperature = (SENSOR_PIN);  //(temperature);   //(SENSOR_PIN);
  dht.begin();
  Serial.println(F("DHTxx Unified Sensor Example"));
  sensor_t sensor;
  dht.temperature().getSensor(&sensor);
}
//==============================================================================
void loop() {
  static unsigned long lastTime1;
  if (millis() - lastTime1 >= (30000ul)) {  // set servo active positioning time = 30 SECONDS
    sensors_event_t event;
    dht.temperature().getEvent(&event);
    if (isnan(event.temperature)) {
      Serial.println(F("Error reading temperature!"));
    } else {
      Serial.print(F("Temperature: "));
      Serial.print(event.temperature);
      Serial.println(F("°C"));
    }
    previousTemperature = currentTemperature;
    currentTemperature = (event.temperature);
    {
      servopos = map(currentTemperature, 10, 26, 180, 0);  // set temperature range and servo angles
      if (servopos < 0) servopos = 0;
      if (servopos > 180) servopos = 180;
      servo.write(servopos);  // write servo position indcating temperature
    }
    lastTime1 = millis();  // update the timing variable}
                           // +++++++++++++++++++++++++++++++++++++++++
    static unsigned long lastTime2;
    //{
      if (millis() - lastTime2 >= (5000ul))  // set past temperature period (5000) seconds
    {
        if (currentTemperature > previousTemperature)  // warming
        {
          Serial.println(F(" Warming"));
          digitalWrite(ledH, HIGH);
          digitalWrite(ledL, LOW);
          digitalWrite(ledN, LOW);

        } else if (currentTemperature < previousTemperature)  // cooling
        {
          Serial.println(F("Cooling"));
          digitalWrite(ledL, HIGH);
          digitalWrite(ledH, LOW);
          digitalWrite(ledN, LOW);

        } else if (currentTemperature == previousTemperature)  // steady
        {
          Serial.println(F(" Steady"));
          digitalWrite(ledN, HIGH);
          digitalWrite(ledH, LOW);
          digitalWrite(ledL, LOW);
          lastTime2 = millis();  // update the timing variable
       }    
     }
    }
  }