Could not control a relay to 'off' on a temperature log using ESP8266 + DS18B20

I tried to add relay that turns a fan ON when the sensor value reach the ‘max’ (87F) and OFF when reach the ‘min’ (85F) on the Temperature Logger code, but the code seems to latch to ‘ON’ since reach the ‘max’ value and never switch to ‘OFF’ even the value is lower than the ‘min’ :confused:

Could you please help me what I miss here? I appreciate your help!

Here is the code:

#include <ESP8266WiFi.h>
#include "HTTPSRedirect.h"
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <OneWire.h>

#define OLED_RESET 16
Adafruit_SSD1306 display(OLED_RESET);

OneWire  ds(0);

// WIFI thing
const char* ssid = "xxxxxxxxxxx";
const char* password = "yyyyyyyyyyy";

// The ID below comes from Google Sheets.
// Towards the bottom of this page, it will explain how this can be obtained
const char *GScriptId = "zzzzzzzzzzzzzzzzzzzzzzzzzz";

// Push data on this interval
const int dataPostDelay = 60000;  // 1 minutes = 1 * 60 * 1000

const char* host = "script.google.com";
const char* googleRedirHost = "script.googleusercontent.com";

const int httpsPort =  443;
HTTPSRedirect client(httpsPort);

// Prepare the url (without the varying data)
String url = String("/macros/s/") + GScriptId + "/exec?";

const char* fingerprint = "F0 5C 74 77 3F 6B 25 D7 3B 66 4D 43 2F 7E BC 5B E9 28 86 AD";

// We will take input from GPIO0 pin
byte data[15];

// Threshold range, get from the sensor
const int sensorMin = 85;    // Fahrenheit sensor minimum
const int sensorMax = 87;    // Fahrenheit sensor maximum

void setup() {
  Serial.begin(115200);
  pinMode(15, OUTPUT);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.print("Temp"); display.println(0xDEADBEEF, HEX);
  display.display();

  Serial.println("Connecting to wifi: ");
  Serial.println(ssid);
  Serial.flush();

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println(" IP address: ");
  Serial.println(WiFi.localIP());


  Serial.print(String("Connecting to "));
  Serial.println(host);

  bool flag = false;
  for (int i = 0; i < 5; i++) {
    int retval = client.connect(host, httpsPort);
    if (retval == 1) {
      flag = true;
      break;
    }
    else
      Serial.println("Connection failed. Retrying...");
  }

  // Connection Status, 1 = Connected, 0 is not.
  Serial.println("Connection Status: " + String(client.connected()));
  Serial.flush();

  if (!flag) {
    Serial.print("Could not connect to server: ");
    Serial.println(host);
    Serial.println("Exiting...");
    Serial.flush();
    return;
  }

  // Data will still be pushed even certification don't match.
  if (client.verify(fingerprint, host)) {
    Serial.println("Certificate match.");
  } else {
    Serial.println("Certificate mis-match");
  }
}

// This is the main method where data gets pushed to the Google sheet
void postData(String tag, float value0) {
  if (!client.connected()) {
    Serial.println("Connecting to client again...");
    client.connect(host, httpsPort);
  }
  String urlFinal = url + "tag=" + tag + "&value=" + String(value0);
  client.printRedir(urlFinal, host, googleRedirHost);
}

// Continue pushing data at a given interval
void loop() {

  // Read sensor value, in this case a DS18B20 probe
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  //  float celsius, fahrenheit;
  float fahrenheit0;

  if ( !ds.search(addr)) {
    Serial.println("No more addresses.");
    Serial.println();
    ds.reset_search();
    delay(250);
    return;
  }

  Serial.print("ROM =");
  for ( i = 0; i < 8; i++) {
    Serial.write(' ');
    Serial.print(addr[i], HEX);
  }

  if (OneWire::crc8(addr, 7) != addr[7]) {
    Serial.println("CRC is not valid!");
    return;
  }
  Serial.println();

  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);        // start conversion, with parasite power on at the end

  delay(1000);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.

  present = ds.reset();
  ds.select(addr);
  ds.write(0xBE);         // Read Scratchpad

  Serial.print("  Data = ");
  Serial.print(present, HEX);
  Serial.print(" ");
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }
  Serial.print(" CRC=");
  Serial.print(OneWire::crc8(data, 8), HEX);
  Serial.println();

  // Convert the data to actual temperature
  // because the result is a 16 bit signed integer, it should
  // be stored to an "int16_t" type, which is always 16 bits
  // even when compiled on a 32 bit processor.
  int16_t raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }

  fahrenheit0 = ((float)raw / 16.0) * 1.8 + 32.0;
  Serial.print("  Temperature = ");
  Serial.print(fahrenheit0);
  Serial.println(" F");

  display.clearDisplay();
  display.setTextSize(1);
  display.setCursor(0, 0);
  display.setTextColor(WHITE);
  display.print("Probe 0 = ");
  display.print(fahrenheit0);
  display.print(" F");
  display.display();
  display.clearDisplay();

  // Fan Relay Control from the Thermostat
  int sensorReading = fahrenheit0;
  // map the sensor range to a range of four options:
  int range = map(sensorReading, sensorMin, sensorMax, 0, 1);

  switch (range) {
    case 0:    // Thermostat HIGHER than Fahrenheit sensor maximum
      Serial.println("Fan ON");
      digitalWrite(15, HIGH);
      break;
    case 1:    // Thermostat LOWER than Fahrenheit sensor minimum
      Serial.println("Fan OFF");
      digitalWrite(15, LOW);
      break;
  }
  delay(10);

  // Post these information
  postData("Temperature", fahrenheit0);
  delay (dataPostDelay);

}

Could you please help me what I miss here?

What you are missing is a simple sketch that illustrates the problem. I see no relationship between turning a pin on when the temperature is above some value, and off when it is below some other value and fingerprints and/or clients.

  int sensorReading = fahrenheit0;

Seriously?

  int range = map(sensorReading, sensorMin, sensorMax, 0, 1);

map() does not return a range. It is strange, to say the least, to map the temperature to a range from 0 to 1.

What value do you get in range when the temperature is less than sensorMin? NOT 0. What value do you get when the temperature is above sensorMax? NOT 1.

Thanks for your reply!

Hope this help, so most of the code are working fine, which is getting temperature value and then push it to google spreadsheet.

Now what I am trying to do is adding a feature like a thermostat, switching a relay to 'on' when the temperature value is higher than 'max' and 'off' when the temperature value is lower than 'min'.

Here is the code for this thermostat feature:

  // Fan Relay Control from the Thermostat
  int sensorReading = fahrenheit0;
  // map the sensor range to a range of four options:
  int range = map(sensorReading, sensorMin, sensorMax, 0, 1);

  switch (range) {
    case 0:    // Thermostat HIGHER than Fahrenheit sensor maximum
      Serial.println("Fan ON");
      digitalWrite(15, HIGH);
      break;
    case 1:    // Thermostat LOWER than Fahrenheit sensor minimum
      Serial.println("Fan OFF");
      digitalWrite(15, LOW);
      break;
  }
  delay(10);

Prophet_Id:
Thanks for your reply!

Hope this help, so most of the code are working fine, which is getting temperature value and then push it to google spreadsheet.

Now what I am trying to do is adding a feature like a thermostat, switching a relay to ‘on’ when the temperature value is higher than ‘max’ and ‘off’ when the temperature value is lower than ‘min’.

I think the following will do what you want:-

   int sensorReading = farenheit0;  // You don't really need to do this. You could just use farenheit0
   
   if (sensorReading > sensorMax) {  // If the temperature is above 87F turn the fan on

       Serial.print("Fan ON");
       digitalWrite(15, HIGH);
   }
   
   if (sensorReading < sensorMin) {  // If the temperature is below 85F turn the fan off

       Serial.print("Fan OFF");
       digitalWrite(15, LOW);
   }
   
   delay(10);

Ian

IanCrowe:
I think the following will do what you want:-

   int sensorReading = farenheit0;  // You don't really need to do this. You could just use farenheit0

if (sensorReading > sensorMax) {  // If the temperature is above 87F turn the fan on

Serial.print(“Fan ON”);
      digitalWrite(15, HIGH);
  }
 
  if (sensorReading < sensorMin) {  // If the temperature is below 85F turn the fan off

Serial.print(“Fan OFF”);
      digitalWrite(15, LOW);
  }
 
  delay(10);




Ian

Awesome… this is very helpful! Thanks man!

Now what I am trying to do is adding a feature like a thermostat, switching a relay to 'on' when the temperature value is higher than 'max' and 'off' when the temperature value is lower than 'min'.

So, what, exactly, are you expecting the map() function to tell you? The measured temperature can be below the minimum value, at the minimum value, between the minimum and maximum values, at the maximum value, or above the maximum value. How do those 5 possibilities relate to the 0, 1 range that you are mapping to? Why are you ignoring the fact that map() can return values that are not in the to range, if the input is not in the from range (which in your case it appears that it often will not be)?

In other words, why are you calling map() at all?