Water temp dropping while sensors are being called

Hello all

I have a problem i need your collective mind to help me fix.
Arduino uno driven off usb with Ds18B20 connected to pin 2 powered from 5vpin on uno and ground to uno with a 4.7k resistor between 5v and signal.
the realy is connected to 5v and ground on uno and signal to pin 5.
The program looks at the current water temperature if its lower than the target temp (heatPadTemp) the relay will turn on a heat pad when the temp goes higher it turns off etc.

I want to call the sensors.requestTemperatures(); every 2 seconds as its quite labour intensive on the uno the problem i have is when sensors.requestTemperatures(); is called the temperture at sensors.getTempCByIndex(0) displays -127C causing the relay to change state. Is there a way i can save the temperature without useing EEprom so while the requesttemp is being called it does not affect the relay state?

1x DS18B20 water temp sensor
1x 4.7K resistor
1x Uno
1x logic driven Relay

#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 2
#define TEMPERATURE_PRECISION 9
const int RelayPin = 5;
long currentsensorTime;
long previoussensorTime = 0;
int HeatPadTempSwing = 0;
float heatPadTemp = 20.00;
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

void setup(void)
{
  Serial.begin(9600);
  sensors.begin();
  pinMode(RelayPin, OUTPUT);
  digitalWrite(RelayPin, HIGH);
  sensors.setResolution(0, TEMPERATURE_PRECISION);
  sensors.requestTemperatures();
}

void loop(void)
{
  currentsensorTime = millis();
  Serial.print("Temp 1 C=");
  Serial.println (sensors.getTempCByIndex(0));

  if (currentsensorTime - previoussensorTime > 2000)          // Request Temperatures every 2 seconds
  {
    previoussensorTime = currentsensorTime;
    sensors.requestTemperatures();
    Serial.println("Requesting Water Temp");
  }

  if (sensors.getTempCByIndex(0) < heatPadTemp && HeatPadTempSwing == 0) {     // heat mat on     
    digitalWrite(RelayPin, LOW);
    Serial.println("Heat Mat ON");
  }
  else if (sensors.getTempCByIndex(0) > heatPadTemp) {    // heat mat off
    digitalWrite(RelayPin, HIGH);
    Serial.print("Temp 1 C=");
    Serial.println ("Heat Mat OFF");
    HeatPadTempSwing = 1;
  }
  if (sensors.getTempCByIndex(0) < heatPadTemp - 1.00 && HeatPadTempSwing == 1) {
    HeatPadTempSwing = 0;
  }
}

Is there a way i can save the temperature without useing EEprom so while the requesttemp is being called it does not affect the relay state?

Put the temperature in a separate variable to that updated by the calls to sensors, then when the function call is complete copy the received value to the main temperature variable and use that to make on/off decisions rather than using the value returned by the call to sensors

Thank you UKHeliBob

something like this

void loop(void)
{
  currentsensorTime = millis();
  currentTime = millis();
  Serial.print("Temp 1 C=");
  Serial.println (sensors.getTempCByIndex(0));

  if (currentsensorTime - previoussensorTime > 2000)          // Request Temperatures every 2 seconds
  {
    previoussensorTime = currentsensorTime;
    sensors.requestTemperatures();
    Serial.println("Requesting Water Temp");
  }
 if (currentTime - previouseTime > 1000)          // Request Temperatures every 1 seconds
  {
   previouseTime = currentTime;
   Sensor1 = sensors.getTempCByIndex(0);
  }
  
  if (Sensor1 < heatPadTemp && HeatPadTempSwing == 0) {     // heat mat on     
    digitalWrite(RelayPin, LOW);
    Serial.println("Heat Mat ON");
  }
  else if (Sensor1 > heatPadTemp) {    // heat mat off
    digitalWrite(RelayPin, HIGH);
    Serial.print("Temp 1 C=");
    Serial.println ("Heat Mat OFF");
    HeatPadTempSwing = 1;
  }
  if (Sensor1 < heatPadTemp - 1.00 && HeatPadTempSwing == 1) {
    HeatPadTempSwing = 0;
  }
}

Does it do what you want ?

The trick is to use a variable to hold the value returned by the function rather than directly using the value in the comparison. Doing it this way also allows you the opportunity to print the value without another call to the function by which time it may have changed anyway

I understand thank you! I will have a play and see what i come up with thank you for your time UKHeliBob

Hi,
What you need to do is read ALL your sensors at the start of the loop, and store those values as variables.
THEN use the variables throughout the rest of your code.

So basically you take a snapshot of your system inputs, THEN act on the results.

Tom... :slight_smile:

The vital item that is actually intelligible,

-127

is telling you that there is no connection to the sensor, the most likely reason being bad wiring, inadequate power, or quite likely both.

What you apparently want to do is entirely reasonable, not at all labour intensive, and you are right to want to avoid using the EEPROM for this.

Thanks for the reply Tom i will have a play!

Nick_Pyner:
The vital item that is actually intelligible,is telling you that there is no connection to the sensor, the most likely reason being bad wiring, inadequate power, or quite likely both.

What you apparently want to do is entirely reasonable, not at all labour intensive, and you are right to want to avoid using the EEPROM for this.

It would seem that every 2 seconds or so -125 will be displayed then immediately display the correct temperature obviously at this point changing the relay state!
However you may be right the wire i am using is very thin and runs along side some heavy mains and a few pumps i will upgrade and rerun the cable as its possibly interference.

Hi,
How much wire have you got from sensor to controller?

Yes, keep sensor wires way from AC cables, especially those that will have switching transients on them.

A two core shielded cable my be advisable, audio type would be okay.

Tom... :slight_smile:

TomGeorge:
Hi,
How much wire have you got from sensor to controller?

Yes, keep sensor wires way from AC cables, especially those that will have switching transients on them.

A two core shielded cable my be advisable, audio type would be okay.

Tom… :slight_smile:

Quite a bit ive now don it in a 2 core screen 0.50 mic cable!

Thank you everyone for your help!.
After alot of playing about i connected the water sensor directly to another uno on the bench and the result was the same as it happens its the sensorits output is erratic!

20.00
20.00
20.00
-127.00
20.00
20.00
-127.00
etc

I have now ordered some more expensive (buy cheap buy twice) sensor. But in the mean time my solution was this it works well and the system is now stable!

#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 2
#define TEMPERATURE_PRECISION 9
const int RelayPin = 5;
long currentsensorTime;
long previoussensorTime = 0;
int HeatPadTempSwing = 0;
float heatPadTemp = 20.00;
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
float Sensor1 =0;
float Sensor1TrueRead = 0;
long currentTime;
long previouseTime =0;


void setup(void)
{
  Serial.begin(9600);
  sensors.begin();
  pinMode(RelayPin, OUTPUT);
  digitalWrite(RelayPin, HIGH);
  sensors.setResolution(0, TEMPERATURE_PRECISION);
  sensors.requestTemperatures();
}


void loop(void)
{
  currentsensorTime = millis();
  currentTime = millis();
  Serial.print("Temp 1 C=");
  Serial.println (sensors.getTempCByIndex(0));

  if (currentsensorTime - previoussensorTime > 2000)          // Request Temperatures every 2 seconds
  {
    previoussensorTime = currentsensorTime;
    sensors.requestTemperatures();
    Serial.println("Requesting Water Temp");
  }
 if (currentTime - previouseTime > 1000)          // Request Temperatures every 1 seconds
  {
   previouseTime = currentTime;
   Sensor1 = sensors.getTempCByIndex(0);
  }
  if(Sensor1 == -127){}
    else{
      Sensor1TrueRead = Sensor1;
    }
    
  if (Sensor1TrueRead < heatPadTemp && HeatPadTempSwing == 0) {     // heat mat on     
    digitalWrite(RelayPin, LOW);
    Serial.println("Heat Mat ON");
  }
  else if (Sensor1TrueRead > heatPadTemp) {    // heat mat off
    digitalWrite(RelayPin, HIGH);
    Serial.print("Temp 1 C=");
    Serial.println ("Heat Mat OFF");
    HeatPadTempSwing = 1;
  }
  if (Sensor1TrueRead < heatPadTemp - 1.00 && HeatPadTempSwing == 1) {
    HeatPadTempSwing = 0;
  }

I don't know how long you anticipate the program running without a reset, but unless you change all of the timing variables to unsigned long it will fail after about 24.5 days of continuous running

UKHeliBob:
I don't know how long you anticipate the program running without a reset, but unless you change all of the timing variables to unsigned long it will fail after about 24.5 days of continuous running

Thank you UKHeliBob just changed them now thank you! also thank you to everyone for there input very much appreciated :slight_smile: :slight_smile:

UKHeliBob:
I don’t know how long you anticipate the program running without a reset, but unless you change all of the timing variables to unsigned long it will fail after about 24.5 days of continuous running

Why is that? And how did you tell this from the code?

Why is that? And how did you tell this from the code?

millis() returns the number of milliseconds since the Arduino was last powered up or reset. The value returned is in a 32 bit unsigned long variable the maximum value of which is 2^32 - 1, ie 4,294,967,295

After that number of milliseconds has passed the value rolls over to zero and the count starts again. If you work it out you will find that 4,294,967,295 milleseconds is just over 49 days so, in calculations like this

 if (currentTime - previouseTime > 1000)          // Request Temperatures every 1 seconds

what will happen because currentTime may actually be smaller than previouseTime so how can the test ever work ? Well, as long as none of the elements of the calculation are not negative it will still work (see below ***).

However, if any of the elements are negative then the comparison will not work. Note that you have declared the timing variables such as currentTime as longs rather than unsigned longs so they will go negative after about 24.5 days and cause the comparison to fail.

For this reason it is important to declare timing variables as unsigned longs rather than longs.

*** Why does calculation of a period by subtraction work even when the variable rolls over to zero ?
To make it easier to understand let's use a byte variable instead of unsigned long as the numbers are easier to get your head round.

Example: If your old time was at 250 and now you're at 5 , you calculate (5 - 250) and interpret the result as an unsigned byte, the result is 11.

I hope that this helps

Tcw82:
Why is that? And how did you tell this from the code?

long currentsensorTime;
long previoussensorTime = 0;

Long variables are extended size variables for number storage, and store 32 bits (4 bytes), from -2,147,483,648 to 2,147,483,647.

Unsigned long variables are extended size variables for number storage, and store 32 bits (4 bytes). Unlike standard longs unsigned longs won’t store negative numbers, making their range from 0 to 4,294,967,295 (2^32 - 1).

long = time positive only so max value is;
2,147,483,648 ms = ‭2,147,483s = ‭35,791 mins = ‭596 hours = ‭24days.
Then the variable roles over to negative numbers.

unsigned long = time positive only max value is;
2 x 2,147,483,648 = 4,294,967,295 >> 2 x 24 = 48days.

Tom... :slight_smile: