DS18B20 Reading temp issues

Hello,

I’m trying to code my first program and have had some success, learning the syntax is a doozie… However, the issue I currently have is trying to get a fan to turn on based upon the temperature of a DS18B20 sensor. If I load the DS18B20 example sketch it reads correctly; If I load my sketch next it reads correctly. But if I lose power the sensor reads 180.00. If I reload my sketch first it still reads 180.00 So again, I loaded the example sketch and it worked, then my sketch and it works again. But I have to repeat this process every time. I have double checked my wiring, have the 4.7k resistor between the data and 5v. I have also tried 2 other sensors as well and the problem persists. It is way to consistent for me to believe that it is a hardware issue. I basically copied the example DS18B20 sketch and pasted it into mine but maybe I missed something? Any help would be much appreciated.

#include "RTClib.h"
#include "Wire.h"
#include "LiquidCrystal_I2C.h"
#include <TimeAlarms.h>
#include <OneWire.h>
#include <DallasTemperature.h>

//Set the pins on the I2C chip used for LCD connections
//ADDR,EN,R/W,RS,D4,D5,D6,D7
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7); // 0x27 is the default I2C bus address

// Data wire is plugged into pin 2 on the Arduinoq
#define ONE_WIRE_BUS 13

// 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);

RTC_DS3231 RTC;

char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

const int redLedOne = 3;        //PWM pin
const int redLedTwo = 5;        //PWM pin
const int blueLed = 9;          //PWM pin
const int whiteLed = 11;        //PWM pin
int minTemp = 78;               //temp to turn fan off
int maxTemp = 82;               //temp to turn fan on
const int TIP120pin = 12;       //FAN PIN
boolean a = LOW, b = HIGH;


// the setup routine runs once when you press reset:
void setup() {
  lcd.begin (20, 4); //20x4 lcd module
  lcd.setBacklightPin(3, POSITIVE); // BL, BL_POL
  lcd.setBacklight(HIGH);
  Wire.begin();
  sensors.begin();
  Serial.begin(9600);
  delay(3000);

  if (! RTC.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  if (RTC.lostPower()) {
    Serial.println("RTC lost power, lets set the time!");
    // following line sets the RTC to the date & time this sketch was compiled
    RTC.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }


  pinMode(3, OUTPUT);   // declare pin 3 to be an output
  pinMode(5, OUTPUT);   // declare pin 5 to be an output
  pinMode(9, OUTPUT);   // declare pin 9 to be an output
  pinMode(11, OUTPUT);  // declare pin 11 to be an output
  pinMode(53, OUTPUT);  // TIP120 for fan control
}

void loop(void)
{
  // Get the current time
  DateTime now = RTC.now();
  lcd.setCursor(0, 0);
  lcd.print(now.day(), DEC);
  lcd.print('/');
  lcd.print(now.month(), DEC);
  lcd.print('/');
  lcd.print(now.year(), DEC);
  lcd.print(' ');
  lcd.print(now.hour(), DEC);
  lcd.print(':');
  lcd.print(now.minute(), DEC);
  lcd.print(':');
  lcd.print(now.second(), DEC);
  lcd.setCursor(0, 1);
  lcd.print(sensors.getTempFByIndex(0)); // Why "byIndex"?
  Serial.println(sensors.getTempFByIndex(0)); // Why "byIndex"?
 


  fanControl();
  if ((now.hour() * 100) >= 500 && (now.hour() * 100) + now.minute() <= 1600) {
    lightsOn();
  } else {
    lightsOff();
  }
}
void lightsOn() {
  digitalWrite(3, HIGH);
  digitalWrite(5, HIGH);
  digitalWrite(9, HIGH);
  digitalWrite(11, HIGH);
  lcd.setCursor(0, 2);
  lcd.print("Lights are on.");

}

void lightsOff() {
  digitalWrite(3, LOW);
  digitalWrite(5, LOW);
  digitalWrite(9, LOW);
  digitalWrite(11, LOW);
  lcd.setCursor(0, 2);
  lcd.print("Lights are off.");
}

void fanControl() {
  int temp = sensors.getTempFByIndex(0);
  if (temp >= maxTemp && a == LOW)
  {
    digitalWrite(TIP120pin, HIGH);
    a = HIGH;
    b = LOW;
  }
  else if (temp <= minTemp && b == LOW)
  {
    digitalWrite(TIP120pin, LOW);
    a = LOW;
    b = HIGH;
  }
}

Before you call getTempFByIndex you must first call the requestTemperatures function.

Pete

el_supremo:
Before you call getTempFByIndex you must first call the requestTemperatures function.

Pete

HA! Thank you that fixed the issue. I'm glad that it was something simple; yet disappointed I missed it. Thank you.

You're welcome :slight_smile:

Pete

Wait. One minor issue.

 lcd.print(sensors.getTempFByIndex(0)); // Why "byIndex"?
  Serial.println(sensors.getTempFByIndex(0)); // Why "byIndex"?

Technically there should be another call to requestTemperatures between these two statements but you're going to get the same temperature in return anyway.
However, it would be best to read the temperature once:

 int f_temp = sensors.getTempFByIndex(0);
  lcd.print(f_temp); // Why "byIndex"?
  Serial.println(f_temp); // Why "byIndex"?

Pete

Will change that as well. The only reason the Serial.println is in there was for troubleshooting. It will be deleted. Thanks for the advice.

You don’t appear to be timing the loop. I think this could lead to grief, sooner or later. Possibly when you stop sending serial prints.

If you don't tell it otherwise, the Dallas library will execute the appropriate delay between requestTemperatures and getTempFByIndex. i.e. its default behaviour is to block until the conversion is complete.

Pete

Thanx. I guess that's something yoiu get for using "by index"

No, it's something you get for using requestTemperatures (or requestTemperaturesByAddress) which you have to use anyway.

Pete

el_supremo:
If you don't tell it otherwise, the Dallas library will execute the appropriate delay between requestTemperatures and getTempFByIndex. i.e. its default behaviour is to block until the conversion is complete.

@OP
Before we acquire temperature data from DS18B20, we must command the sensor to start conversion. Your codes have not contained this command at all! The conversion time is about 1000 ms for 12-bit resolution. The end-of-conversion event could be met in one of the following two ways:
(a) Wait for 1000 ms after asserting the conversion command:

ds.reset();
ds.select(addr);
ds.write(0x44);     //conversion command
delay(1000);

(b) Wait for as much time as is required by the sensor. This is achieved by monitoring the bus status based on this principle: during the conversion period, the sensor pulls-down the bus-line. So, the execution of read() will reflect 0x00. This is known as read time slot. After conversion, the bus comes back to H-state; read time will reflect 0xFF.

ds.reset();
ds.select(addr);
ds.write(0x44);     //conversion command
do
{
   busStatus = ds.read();
}
while (busStatus != 0xFF);

I observe that Dallas equivalent library function for the above blocking codes is -- sensor.requestTemperatures() as mentioned in the above quoted text.

GolamMostafa:
I observe that Dallas equivalent library function for the above blocking codes is -- sensor.requestTemperatures() as mentioned in the above quoted text.

So your saying your above code is already within that function? Or do I need to implement this, I did not see any mention of it within the examples.

el_supremo:
Wait. One minor issue.

 lcd.print(sensors.getTempFByIndex(0)); // Why "byIndex"?

Serial.println(sensors.getTempFByIndex(0)); // Why "byIndex"?



Technically there should be another call to requestTemperatures between these two statements but you're going to get the same temperature in return anyway.
However, it would be best to read the temperature once:


int f_temp = sensors.getTempFByIndex(0);
  lcd.print(f_temp); // Why "byIndex"?
  Serial.println(f_temp); // Why "byIndex"?




Pete

I corrected that piece of code but now I'm wondering do I have to have separate requestTempertures for each loop? I have one request in void loop and another request in fanControl. Can I call it once and use the same value for both, or is it better that I call them individually.

Or do I need to implement this

No, your code uses the Dallas library and doesn't need that stuff at all.

Can I call it once and use the same value for both

That would be the best way. You call it first to display it on the LCD and then immediately afterwards, you call it again in the fanControl function. Might as well read the temperature once each time through the loop function, store it in a global variable and use that value for the LCD and fanControl.

Pete

joebob296:
So your saying your above code is already within that function? Or do I need to implement this, I did not see any mention of it within the examples.

Please, see the answer in Post#13 @el_supremo.

el_supremo:
That would be the best way. You call it first to display it on the LCD and then immediately afterwards, you call it again in the fanControl function. Might as well read the temperature once each time through the loop function, store it in a global variable and use that value for the LCD and fanControl.

Pete

So it should look like this?

int f_temp = 0; //global variable

void setup() {

}

void loop() {

sensors.requestTemperatures();
f_temp = sensors.getTempFByIndex(0);
}

Edit: Shouldn't I use float instead of int as I have a decimal ?

Yes, and you can then use f_temp in the fanControl function as well as in the loop function.

Pete