1 wire temperature sensor getAddress

I am trying to use getAddress to verify that a temperature sensor is connected as a safety measure. When I function test this it works sometimes. Sometimes I get a serial print and MQTT message "Temp sensor disconnected" repeating in a loop. However sometimes when I disconnect the DS18B20 It just hangs on the last temperature message. When I plug in the DS18B20 the loop starts running and sending the temperature data again. I have tried repeating the process over and i get a mixture of these two results. I'm assuming that I made a simple mistake but I can't seem to figure it out. Here is my sketch:

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Streaming.h>
#include <PID_v1.h>

#define SLEEP_DELAY_IN_SECONDS  30
#define ONE_WIRE_BUS            D4      // DS18B20 pin
#define heaterPin               D1      // SSR output pin

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

const char* mqtt_server = "raspberrypi";
const char* mqtt_username = "<MQTT_BROKER_USERNAME>";
const char* mqtt_password = "<MQTT_BROKER_PASSWORD>";
const char* mqtt_topic_1 = "readTemp";
const char* mqtt_topic_2 = "setTemp";
const char* mqtt_topic_3 = "errorMssg";

WiFiClient espClient;
PubSubClient client(espClient);

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature DS18B20(&oneWire);
DeviceAddress tempSensor;

char temperatureString[6];
String varTemp = "0";
float fltVarTemp;

double Setpoint, Input, Output;
PID myPID(&Input, &Output, &Setpoint,500,1,20, DIRECT);


int WindowSize = 5000;
unsigned long windowStartTime;

void setup() {
  pinMode(heaterPin,OUTPUT);
  // setup serial port
  Serial.begin(115200);

  // setup WiFi
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);

  // setup OneWire bus
  DS18B20.begin();
    if (!DS18B20.getAddress(tempSensor, 0)) 
     {
        Serial.println("Temperature sensor disconnected");
        client.publish(mqtt_topic_3, "Temp sensor disconnected",1);
     }
     
  //PID setup
  Setpoint = 10;
  windowStartTime = millis();
  myPID.SetOutputLimits(0, WindowSize);
  myPID.SetMode(AUTOMATIC);
}

void setup_wifi() {
  delay(10);
  // Start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

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

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}
void callback(char* topic, byte* payload, unsigned int length) {

 payload[length]='\0';
 varTemp = String((char*)payload);
 Serial.println(varTemp);

 Serial << "Message arrived [" << mqtt_topic_2 << "] " << endl;

 for (int i=0;i<length;i++) {
  char receivedChar = (char)payload[i];
  Serial.print(receivedChar);
  }
  Serial.println();

}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    //if (client.connect("ESP8266Client", mqtt_username, mqtt_password)) {
    if (client.connect("ESP8266Client")) { 
      Serial.println("connected");
      client.subscribe(mqtt_topic_2);
    } else {
      Serial << "failed, rc=" << client.state() << " try again in 5 seconds" << endl;
      Serial.println("");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

float getTemperature() {
  //Serial << "Requesting DS18B20 temperature..." << endl;
  float temp;
  do {
    DS18B20.requestTemperatures();
    temp = DS18B20.getTempCByIndex(0);
    delay(100);
  } while (temp == 85.0 || temp == (-127.0));
  return temp;
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  if (!DS18B20.getAddress(tempSensor, 0)) {
    Serial.println("Temperature sensor disconnected");
    client.publish(mqtt_topic_3, "Temp sensor disconnected",1);
    digitalWrite(heaterPin,LOW);
    delay(1000); 
  } else {
    float displayTemp = getTemperature();
    //Convert from celcius to farenheight
    displayTemp = displayTemp * 1.8 + 32;
    // convert temperature to a string with two digits before the comma and 2 digits for precision
    dtostrf(displayTemp, 2, 2, temperatureString);
    // send temperature to the serial console
    Serial << "Sensor read temperature:" << temperatureString << " F." << endl;
    // send temperature to the MQTT topic
    client.publish(mqtt_topic_1, temperatureString);
    //Serial.println(displayTemp);
    //Serial << "Sensor read temperature:" << displayTemp << " F." << endl;
  
    fltVarTemp = atof (varTemp.c_str());

    Serial << "Target temperature:" << fltVarTemp << " F." << endl; 
    //Serial.println(fltVarTemp);
 
    Serial.println(); 

    Setpoint = fltVarTemp;
    Input = displayTemp;
    myPID.Compute();

    unsigned long now = millis();
    if(now - windowStartTime>WindowSize)
    { //time to shift the Relay Window
      windowStartTime += WindowSize;
    }
    if(Output > now - windowStartTime) digitalWrite(heaterPin,HIGH);
    else digitalWrite(heaterPin,LOW);
  
  } 
}

mwawrzyniec:
I am trying to use getAddress to verify that a temperature sensor is connected as a safety measure.

Would getting a return of 127 suffice instead?

The temperature sensor is measuring water temps that will range from 70f to 170f. Im not sure if that would interfere with what you are thinking. Essentially what I am trying to prevent is a "runaway" heating element that causes a fire.

A DS18B20 returns 127 C when it is disconnected. This means it tells you, rather than you having to ask it all the time. I imagine you can work out the fahrenheit equivalent.

When I disconnect it, it stops returning any values for me. It just sits there until I re connect the sensor. Then it starts reporting values again.

Probably your code but I can't comment because I have no idea of what you are doing. You might try using a basic temperature programme.

You might try :

if (!DS18B20.isConnected(address))
     {
        Serial.println("Temperature sensor disconnected");
        client.publish(mqtt_topic_3, "Temp sensor disconnected",1);
     }

Or you could try changing the do loop in the getTemperature function to this (which assumes that you only have one DS18B20 on the bus):

 while(DS18B20.getDeviceCount() == 0) {
    delay(1000);
  }
  DS18B20.requestTemperatures();
  temp = DS18B20.getTempCByIndex(0);

Pete

outsider:
You might try :

if (!DS18B20.isConnected(address))

{
        Serial.println("Temperature sensor disconnected");
        client.publish(mqtt_topic_3, "Temp sensor disconnected",1);
    }

I gave this a try and still intermittent results, sometimes it would display the error message and sometimes it wouldn't. As soon as I would plug in the sensor it would automatically start displaying the temperature again regardless of whether or not the error message was displayed.

el_supremo:
Or you could try changing the do loop in the getTemperature function to this (which assumes that you only have one DS18B20 on the bus):

 while(DS18B20.getDeviceCount() == 0) {

delay(1000);
 }
 DS18B20.requestTemperatures();
 temp = DS18B20.getTempCByIndex(0);




Pete

I changed the code and when I unplug the sensor it started displaying -127 so I added an if else statement in the main loop:

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  if (getTemperature() == -127) {
    Serial.println("Temperature sensor disconnected");
    client.publish(mqtt_topic_3, "Temp sensor disconnected",1);
    digitalWrite(heaterPin,LOW);
    delay(1000);
  
  } else {

Now the code runs as expected, as soon as I unplug the sensor it starts sending the error message and digital writes the GPIO pin low. Thank you!

I reset the micro-controller with the sensor disconnected and it gets stuck in the getTemperature() fuction. When I reconnect the sensor it never leaves the getTemperature() and just repeats the error message. Any ideas how to fix it? I tried changing the while statement to an if else statement and that just caused it to exit the function after the first failure. So I changed it back to the while statement. Here is the sketch I am working with now.

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Streaming.h>
#include <PID_v1.h>

#define SLEEP_DELAY_IN_SECONDS  30
#define ONE_WIRE_BUS            D4      // DS18B20 pin
#define heaterPin               D1      // SSR output pin

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

const char* mqtt_server = "raspberrypi";
const char* mqtt_username = "<MQTT_BROKER_USERNAME>";
const char* mqtt_password = "<MQTT_BROKER_PASSWORD>";
const char* mqtt_topic_1 = "readTemp";
const char* mqtt_topic_2 = "setTemp";
const char* mqtt_topic_3 = "errorMssg";

WiFiClient espClient;
PubSubClient client(espClient);

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature DS18B20(&oneWire);
DeviceAddress tempSensor;

char temperatureString[6];
String varTemp = "0";
float fltVarTemp;

double Setpoint, Input, Output;
PID myPID(&Input, &Output, &Setpoint,500,1,20, DIRECT);


int WindowSize = 5000;
unsigned long windowStartTime;

void setup() {
  pinMode(heaterPin,OUTPUT);
  // setup serial port
  Serial.begin(115200);

  // setup WiFi
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);

  // setup OneWire bus
  DS18B20.begin();
     
  //PID setup
  Setpoint = 10;
  windowStartTime = millis();
  myPID.SetOutputLimits(0, WindowSize);
  myPID.SetMode(AUTOMATIC);
}

void setup_wifi() {
  delay(10);
  // Start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

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

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}
void callback(char* topic, byte* payload, unsigned int length) {

 payload[length]='\0';
 varTemp = String((char*)payload);
 Serial.println(varTemp);

 Serial << "Message arrived [" << mqtt_topic_2 << "] " << endl;
 
 for (int i=0;i<length;i++) {
  char receivedChar = (char)payload[i];
  Serial.print(receivedChar);
  }
  Serial.println();

}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    //if (client.connect("ESP8266Client", mqtt_username, mqtt_password)) {
    if (client.connect("ESP8266Client")) { 
      Serial.println("connected");
      client.subscribe(mqtt_topic_2);
    } else {
      Serial << "failed, rc=" << client.state() << " try again in 5 seconds" << endl;
      Serial.println("");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

float getTemperature() {
  //Serial << "Requesting DS18B20 temperature..." << endl;
  float temp;
 while (DS18B20.getDeviceCount() == 0) {
    Serial.println("Temperature sensor disconnected");
    client.publish(mqtt_topic_3, "Temp sensor disconnected",1);    
    delay(1000);
  }
  DS18B20.requestTemperatures();
  temp = DS18B20.getTempCByIndex(0);
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  if (getTemperature() == -127) {
    Serial.println("Temperature sensor disconnected");
    client.publish(mqtt_topic_3, "Temp sensor disconnected",1);
    digitalWrite(heaterPin,LOW);
    delay(1000);
  
  } else {
    
    float displayTemp = getTemperature();
    //Convert from celcius to farenheight
    displayTemp = displayTemp * 1.8 + 32;
    // convert temperature to a string with two digits before the comma and 2 digits for precision
    dtostrf(displayTemp, 2, 2, temperatureString);
    // send temperature to the serial console
    Serial << "Sensor read temperature:" << temperatureString << " F." << endl;
    // send temperature to the MQTT topic
    client.publish(mqtt_topic_1, temperatureString);
    //convert set temp received from mqtt, from string to double
    fltVarTemp = atof (varTemp.c_str());

    Serial << "Target temperature:" << fltVarTemp << " F." << endl; 
 
    Serial.println(); 

    Setpoint = fltVarTemp;
    Input = displayTemp;
    myPID.Compute();

    unsigned long now = millis();
    if(now - windowStartTime>WindowSize)
    { //time to shift the Relay Window
      windowStartTime += WindowSize;
    }
    if(Output > now - windowStartTime) digitalWrite(heaterPin,HIGH);
    else digitalWrite(heaterPin,LOW);
  
  } 
}

Nick_Pyner
I'm sorry, I realized I never actually explained the purpose of the sketch. I am building a controller for a beer brewing setup. This will control the mash temperature and data log the brewing process for quality control by sending the temperature through an MQTT message to a raspberry pi running the mosquito MQTT broker. It also allows the mash temperature to be programmatically increased for the mash out step based on pre set times in a JavaScript page also running on the raspberry pi.

The end product doesn't matter.
What I menat was that I know nothing about
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Streaming.h>
#include <PID_v1.h> and therefore can't comment,

but I am familiar with
#include <OneWire.h>
#include <DallasTemperature.h>
hence my suggestion that you make up a programme that is confined to where the problem lies.

As it is, a common procedure is

{
  float tempC = sensors.getTempC(deviceAddress);
  if (tempC == -127.00) {
    Serial.print("Error getting temperature");
  } else {

as exemplified here, which is quite straight forward, hence my questioning the rest of your code.