Go Down

Topic: DS18b20 fails in small temperature range (Read 2222 times) previous topic - next topic

ElCaron

Jun 01, 2016, 08:24 pm Last Edit: Jun 01, 2016, 08:34 pm by ElCaron
Hi, I am using a DS18b20 (in the metal capsuled waterproof version) to monitor temperature. Strangely, it seems to fail in a small temperature range, reporting higher values. Above and below, everything is fine. Is my sensor just broken or does anybody have any idea?

The attached chart shows values collected with an ESP8266 and averaged over 5min. This is the code, based on the example sketch:
Code: [Select]

#include <OneWire.h>
#include <DallasTemperature.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266mDNS.h>
#include <PubSubClient.h>

#define min(a,b) ((a)<(b)?(a):(b))

const char *ssid = "SSID";
const char *password = "PSK";

const char *mqtt_server = "192.168.2.6";
const char *mqtt_user = "aquatemp";
const char *mqtt_pw = "PW";
const char *mqtt_state_topic = "home-le/firstfloor/diningroom/aquarium/temperature";
unsigned long mqttReconnectTime = millis();
unsigned long mqttReconnectInterval = 5000;

unsigned long reportTime = millis();
unsigned long reportInterval = 300000;

unsigned int valueCount = 0;
float valueSum = 0;

WiFiClient espClient;
PubSubClient mqttclient(espClient);

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS D6
const int ledPin = BUILTIN_LED;

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

// arrays to hold device address
DeviceAddress insideThermometer;

void setup(void)
{
  // start serial port
  Serial.begin(9600);
  digitalWrite ( ledPin, LOW );
  Serial.begin ( 115200 );
  WiFi.begin ( ssid, password );
  Serial.println ( "" );

  // Wait for connection
  while ( WiFi.status() != WL_CONNECTED ) {
    delay ( 500 );
    Serial.print ( "." );
  }

  Serial.println ( "" );
  Serial.print ( "Connected to " );
  Serial.println ( ssid );
  Serial.print ( "IP address: " );
  Serial.println ( WiFi.localIP() );

  if ( MDNS.begin ( "aquatemp" ) ) {
    Serial.println ( "MDNS responder started" );
  }

  mqttclient.setServer(mqtt_server, 1883);
  mqttclient.setCallback(mqtt_callback);
  digitalWrite ( ledPin, HIGH );

  Serial.println("Dallas Temperature IC Control Library Demo");

  // locate devices on the bus
  Serial.print("Locating devices...");
  sensors.begin();

  Serial.print("Found ");
  Serial.print(sensors.getDeviceCount(), DEC);
  Serial.println(" devices.");

  // report parasite power requirements
  Serial.print("Parasite power is: ");
  if (sensors.isParasitePowerMode()) Serial.println("ON");
  else Serial.println("OFF");

  // Method 1:
  // search for devices on the bus and assign based on an index.  ideally,
  // you would do this to initially discover addresses on the bus and then
  // use those addresses and manually assign them (see above) once you know
  // the devices on your bus (and assuming they don't change).
  if (!sensors.getAddress(insideThermometer, 0)) Serial.println("Unable to find address for Device 0");

  Serial.print("Device 0 Address: ");
  printAddress(insideThermometer);
  Serial.println();

  // set the resolution to 9 bit (Each Dallas/Maxim device is capable of several different resolutions)
  sensors.setResolution(insideThermometer, 12);

  Serial.print("Device 0 Resolution: ");
  Serial.print(sensors.getResolution(insideThermometer), DEC);
  Serial.println();
}

void mqtt_callback(char* topic, byte* payload, unsigned int length) {
}

// function to print the temperature for a device
void printTemperature(DeviceAddress deviceAddress)
{
  float tempC = sensors.getTempC(deviceAddress);
  Serial.print("Temp C: ");
  Serial.print(tempC);
  Serial.print(" Temp F: ");
  Serial.println(DallasTemperature::toFahrenheit(tempC)); // Converts tempC to Fahrenheit
}

void loop(void)
{
  // call sensors.requestTemperatures() to issue a global temperature
  // request to all devices on the bus
  delay(10);
  sensors.requestTemperatures(); // Send the command to get temperatures
  valueSum += sensors.getTempC(insideThermometer);
  valueCount++;

  if (!mqttclient.connected()) {
    mqtt_reconnect();
  }
  else {
    mqttclient.loop();
  }

  if (millis() - reportTime > reportInterval)
  {
    if (mqttclient.connected()) {
      char outputStr[5];
      float temp = valueSum / valueCount;
      reportTime = millis();
      sprintf(outputStr, "%d.%d", (int)temp, (int)(100 * (temp - (int)temp)));
      if (mqttclient.publish(mqtt_state_topic, outputStr, false)) {
        Serial.print("Published ");
        Serial.print(outputStr);
        Serial.print(" from ");
        Serial.print(valueCount);
        Serial.println(" measurements.");
      } else {
        Serial.println("Publishing failed.");
      }
    } else {
      Serial.println("MQTT not connected");
    }
    valueSum = 0;
    valueCount = 0;
  }
}

// function to print a device address
void printAddress(DeviceAddress deviceAddress)
{
  for (uint8_t i = 0; i < 8; i++)
  {
    if (deviceAddress[i] < 16) Serial.print("0");
    Serial.print(deviceAddress[i], HEX);
  }
}


void mqtt_reconnect() {
  // Loop until we're reconnected
  if (!mqttclient.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (mqttclient.connect("aquatemp", mqtt_user, mqtt_pw)) {
      Serial.println("connected");
    } else {
      Serial.print("failed, rc=");
      Serial.print(mqttclient.state());
      Serial.println(" try again in 5 seconds");
    }
  }
}

Koepel

#1
Jun 01, 2016, 11:16 pm Last Edit: Jun 01, 2016, 11:19 pm by Koepel
As far as I know, all the DS18B20 sensors are accurate. There are fake sensors, but they don't work.

In the graph, I see a repeating pattern that matches with the days. It could be sunlight, or the central heating.

The DS18B20 is sensitive for sunlight and other heat sources, for example a nearby voltage regulator. It is almost as if the DS18B20 collects the heat from around. I think the graph shows the actual temperature that the DS18B20 is measuring.

The straight line at "Thu 26 Fri 27" is obvious the averaging of the graph software. Probably no sensor data was received during that, and the graph software connects the samples.

I agree with Koepel. DS18B20 is very sensitive and accurate both, as far as we have genuine sensor with us.
Try evaluating first with the Maxim's 1-wireViewer software  and usb to ttl converter and check if it shows you right data logging. Then you can get connected with esp or arduinos.
I have demonstrated this in my video here..

https://youtu.be/fZX9FQuNBdc

i hope this might be helpful in troubleshooting your problem.
Good luck
Electromania
---------------

el_supremo

There are two things in your code that I find suspicious.
First the declaration of outputStr is for 5 characters which does not allow for the null on the end when using sprintf into that array.
Declare it to be 8 just to be sure. The problem is that when you overwrite outputStr[5] with a null, it is on the stack and very hard to predict what effect it will have. It is possible that it writes that null into part of the temp variable which is also on the stack. That will make a mess of your calculation of the average temperature.
Try that first.

If that doesn't fix it, try reading the temperature once just before using sprintf. At the moment you are reading the temperature and accumulating the values as fast as the loop() function will allow which amounts to around 400 readings per 5 minute reporting interval. This should work but take it out to see if it stops the variations. If you are measuring the temperature in an acquarium, it shouldn't vary much over 5 minutes anyway.
Near the beginning of loop() comment these statements:
Code: [Select]
 //sensors.requestTemperatures(); // Send the command to get temperatures
  //valueSum += sensors.getTempC(insideThermometer);
  //valueCount++;


and change this:
Code: [Select]
     char outputStr[5];
      float temp = valueSum / valueCount;


to this:
Code: [Select]
     char outputStr[8];
      float temp = sensors.getTempC(insideThermometer);


Pete

Don't send me technical questions via Private Message.

ElCaron

Thanks for the answers

@Koepel
I disagree. At first I thought the same, but looking closely, it does not match the day accurately. It shoots up as soon as the aquarium temperature reaches 26 degree. The temperature is solely governed by the lighting at the moment (look at it, it is beautiful, you can accurately see when it switches on on and when it switches of around noon).
This regularly happens in the evening, but also did on Sunday morning, which was particularly warm. On Saturday evening, there is just one spike, because the temperature never left the "broken" interval. On all the other days, it became normal again after the temperature exceeded 26.1 degree, which is one 12bit resolution step. So one particular value acts strange. I find this much too clear and regular to believe it is real.

@el_supremo
Thanks for looking through all the code. I will do the changes. With the output, you are of course right. Taking out the average will most certainly not work. I did that in the beginning and I can remember strange blocks of higher temperature. However, they looked more random, because at that point, the aquarium was warmer and more frequently around 26°C. I added the averaging to get a more smooth curve. During the transition between two digital values, I get ugly oscillation.

@Electromaniaworld
Thanks, I will try that after el_supremos suggestions (and perhaps replacing the sensor).

Koepel

I suggest to get a new DS18B20 from an other seller, and use a seperate Arduino, so you can see both temperatures. For example with the good old Arduino Uno board. The ESP8266 has still many problems with Arduino compatibility.
Did you use the newest libraries from the Library Manager ? If you have downloaded those libraries, did you use the newest versions ?
Could you add a check to test for a temperature below -100 ? When there is an error, a temperature of -127 is returned.
I rather see a very long log file with temperatures than a graph that could disguise a problem.

ElCaron

Currently not at home, but here are the charts after the changes suggested by el_supremo. No improvement.

I have ordered more sensors.

el_supremo

#7
Jun 03, 2016, 09:09 pm Last Edit: Jun 03, 2016, 09:12 pm by el_supremo
I think that the scale that you are using on the graph for the x (time) and y (temperature) axes is too compressed and makes it appear that there has been a very large temperature excursion over a very brief time period. Actually they are an occasional increase of about one degree over the course of an hour or two. E.g. in chart2, the first excursion is an increase of about half a degree which lasts for about an hour.
If you have a heater in the aquarium this is not unusual and would be particularly noticeable if the sensor is near the heater. [edit]I just re-read your msg#4 and you say there is no heater - perhaps the lighting has a large heating effect?[/edit]

Pete
Don't send me technical questions via Private Message.

Koepel

#8
Jun 04, 2016, 12:27 am Last Edit: Jun 04, 2016, 12:27 am by Koepel
Now I see what you mean. That seems like a change of the wrong bit somewhere along the line, as if a change of the last bits, also result into a change of a higher bit.

Can you get an Arduino Uno board and use the newest Arduino IDE 1.6.9 and use the libraries from the Library Manger (in the menu of the Arduino IDE).

We have not enough information to pinpoint the problem.

ElCaron

#9
Jun 04, 2016, 09:34 am Last Edit: Jun 04, 2016, 09:49 am by ElCaron
@el_supremo As I said, I think this is WAY to regular (always rises at the same temperature, always drops to the same temperature) to be real. There is no heating atm and the influence is visible in the slow changes over the day (look at the drop from a dark phase at noon). Also attached a week chart.

@koepel I have an original Arduino Ethernet (else just a lot of nano and pro micro clones) that I can test tomorrow, when i am back home. I am already using the libraries from lib manager.

wildbill

It might be worth capturing the telemetry you're sending out of the serial port and see what's happening around the time you see the spikes.

If you do that, I'd suggest you emit the outputStr to serial whether the publish fails or not.

el_supremo

I think that is too regular to be a faulty sensor. A sensor doesn't know what time it is and a faulty one wouldn't arbitrarily start going insane just before noon each day - not without some other process driving it. There has to be something that is heating the sensor. Is it in direct sunlight?
As wildbill says, it would be nice to see some raw data from the sensor. In particular, it would be useful to see some raw data from it when it is in a more controlled environment.

Pete
Don't send me technical questions via Private Message.

ElCaron

#12
Jun 05, 2016, 06:01 pm Last Edit: Jun 06, 2016, 09:45 am by ElCaron
Please look at the chart again. The errors are NOT tied to the time, as I pointed out multiple times, but to the temperature. The temperature, again, is loosely tied to the time because of the lighting. So it seems on very first glance that the errors occur always at the same time, but they don't. This becomes very clear during the morning lighting phases, where the temperature does not hit 26°C every day.
I'll go for a faulty sensor, until the new ones arrive and test the same.

EDIT: Quick update: Problem persists when resolution is reduced to 11bit


MarkT

I've never seen a genuine DS18B20 misbehave or fail (at one point I had a network of a dozen or so logging 24/7 for several years).  Did you buy your sensors from eBay?  These days those chips are highly likely to be counterfeit due to their premium price(*).  Reputable suppliers only for such things...

(*) They are individually laser trimmed if genuine - this is a large part of the price, making them targets for counterfeiting.
[ I DO NOT respond to personal messages, I WILL delete them unread, use the forum please ]

Go Up