hi there
i have DS18B20 displaying the temp in one of my project but every now and then it display 0.00, -127 or 85 degrees for a short period of time, i think the reason is because the cable run is about 100m. but it is wired in screened cable and earthed at one end.
so is there something i can do software wise? maybe like looking at the new temp and comparing against the old one or something what do you lot think and how would i go about doing it?
Errors do occur and your software should remove them. If only specific wrong values show up, simply check for those and discard them. Otherwise, a check for "reasonable differences" from one reading to the next, or from one reading to a running average, should work.
o ok i see, what would be a good way of including that into my code?
here is my code at mo:
int encoderPin1 = 2;
int encoderPin2 = 3;
volatile int lastEncoded = 0;
volatile float encoderValue = 30;
long lastencoderValue = 0;
int lastMSB = 0;
int lastLSB = 0;
int led = 13;
/*-----( Import needed libraries )-----*/
#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
/*-----( Declare Constants )-----*/
#define ONE_WIRE_BUS 7 /*-(Connect to Pin 7 )-*/
/*-----( Declare objects )-----*/
/* Set up a oneWire instance to communicate with any OneWire device*/
OneWire ourWire(ONE_WIRE_BUS);
/* Tell Dallas Temperature Library to use oneWire Library */
DallasTemperature sensors(&ourWire);
#define _Digole_Serial_UART_ //To tell compiler compile the special communication only,
//all available are:_Digole_Serial_UART_, _Digole_Serial_I2C_ and _Digole_Serial_SPI_
#include <DigoleSerial.h>
//--------UART setup, if you don't use UART, use // to comment following line
#if defined(_Digole_Serial_UART_)
DigoleSerialDisp mydisp(&Serial, 9600); //UART:Arduino UNO: Pin 1(TX)on arduino to RX on module
#endif
#define LCDCol 16
#define LCDRow 2
const unsigned char fonts[] = {
6, 10, 18, 51, 120, 123};
void setup()
{
pinMode(led, OUTPUT);
pinMode(encoderPin1, INPUT);
pinMode(encoderPin2, INPUT);
digitalWrite(encoderPin1, HIGH); //turn pullup resistor on
digitalWrite(encoderPin2, HIGH); //turn pullup resistor on
attachInterrupt(0, updateEncoder, CHANGE);
attachInterrupt(1, updateEncoder, CHANGE);
mydisp.begin();
mydisp.clearScreen(); //CLear screen
mydisp.drawStr(5, 0, "Hello");
delay(1000);
mydisp.clearScreen(); //CLear screen
mydisp.drawStr(0, 0, "Temp:");
mydisp.drawStr(0, 1, "Set :");
/*-( Start up the DallasTemperature library )-*/
sensors.begin();
}
void loop()
{
sensors.requestTemperatures();
mydisp.setPrintPos(5, 0);
mydisp.print(sensors.getTempCByIndex(0));
mydisp.setPrintPos(5, 1);
mydisp.print(encoderValue); // display a char array
if (encoderValue < sensors.getTempCByIndex(0)) {
digitalWrite(led, HIGH);
}
else {
digitalWrite(led, LOW);
}
}
void updateEncoder(){
int MSB = digitalRead(encoderPin1); //MSB = most significant bit
int LSB = digitalRead(encoderPin2); //LSB = least significant bit
int encoded = (MSB << 2) |LSB; //converting the 2 pin value to single number
int sum = (lastEncoded << 2) | encoded; //adding it to the previous encoded value
if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue = encoderValue + 0.1;
if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue = encoderValue - 0.1;
lastEncoded = encoded; //store this value for next time
}
It's pretty hard to tell what's going on, and seems to be somewhat more than getting the temperature, but I'm surprised you are getting anything at all with it.
Of the three results:
I can't explain the 0.00. I have had it twice in recent months after running perfectly for about a year. I have not looked into it yet and it may be due to weather conditions. I just fixed it with the reset button.
-127 indicates a bad connection or, in your case, perhaps an inadequate one. Such long runs are problematic but there has been plenty of discussion about it on the forum. Since it works sometimes, you might find that changing the pullup resistor to 2.2k is all that is needed.
The 85 indicates the sensor hasn't had time to do its job. Since you defaulting to 12 bit resolution, the sensor needs about 750ms to stay in play, and you seem to be giving it nothing, hence my surprise. You can probably fix this by adding a quick'n'dirty.
delay(1000);
in the loop, thereby giving readings approx once per second, which I bet is as frequent as you really need.
Your problems may be caused by using parasitic power, which always seems to be more trouble than it is worth. I recognise your code can work, but you might be better off with that in the Hacktronics tutorial.
-127 indicates a bad connection or, in your case, perhaps an inadequate one. Such long runs are problematic but there has been plenty of discussion about it on the forum. Since it works sometimes, you might find that changing the pullup resistor to 2.2k is all that is needed.
i have a 1k at the arduino end and at the sensor end i have 1k as well, the only way i could get it to work
The 85 indicates the sensor hasn't had time to do its job. Since you defaulting to 12 bit resolution, the sensor needs about 750ms to stay in play, and you seem to be giving it nothing, hence my surprise. You can probably fix this by adding a quick'n'dirty.
i see yes i will at a delay there
Your problems may be caused by using parasitic power, which always seems to be more trouble than it is worth. I recognise your code can work, but you might be better off with that in the Hacktronics tutorial.
i'm not using parasitic power as could not get it to work at all over the length
another quick question i have is how can i get it just to display max of one decimal place?
Joes:
i have a 1k at the arduino end and at the sensor end i have 1k as well, the only way i could get it to work
1+1 = 2.2 but you should be able to have a single resistor at the Arduino end. That will cover all sensors.
i'm not using parasitic power as could not get it to work at all over the length
No surprise there and hence my comment
another quick question i have is how can i get it just to display max of one decimal place?
I don't really know but I guess you have assemble a string of the int and a rounded frac, using the dtostrf command. i don't think setting the resolution of the sensor is the answer.
another quick question i have is how can i get it just to display max of one decimal place?
// Fetch temperature for device index
float DallasTemperature::getTempCByIndex(uint8_t deviceIndex)
{
DeviceAddress deviceAddress;
getAddress(deviceAddress, deviceIndex);
return getTempC((uint8_t*)deviceAddress);
}
getTempCByIndex() is returning a float, and your display looks like it knows how to print it as a number without conversion to a character string. If it is inheriting from the general print class, then you can try
Joes:
hi there
i have DS18B20 displaying the temp in one of my project but every now and then it display 0.00, -127 or 85 degrees for a short period of time, ...
If you look at the source, it returns DEVICE_DISCONNECTED if it couldn't read the device, so getting -127 isn't too surprising.
// Fetch temperature for device index
float DallasTemperature::getTempCByIndex(uint8_t deviceIndex)
{
DeviceAddress deviceAddress;
getAddress(deviceAddress, deviceIndex);
return getTempC((uint8_t*)deviceAddress);
}
what am i looking at here, confused on what I'm looking at could you explain?
mydisp.print(sensors.getTempCByIndex(0),1);
this seems to work fine apart from if you disconnect the sensor you get -127 and when reconnected you get the temp back but if the sensor is reading 25.5 it will display 25.5.0 how can i over come that?
If you look at the source, it returns DEVICE_DISCONNECTED if it couldn't read the device, so getting -127 isn't too surprising.
I do not understand why mydisp.print(sensors.getTempCByIndex(0),1) is giving you xx.x.x
I do not have your display hardware or use the library, but a google review would lead me to believe that the xxx.print(float,1) should give you one decimal place.
You could try print a transfer variable like this
float value = sensors.getTempCByIndex(0);
mydisp.print (value,1);
If that doesn't work, I think you should try Nick Pynor's suggestion of converting the float to a character string with dtostrf and printing the string. The format for dtostrf is dtostrf(floatvar, StringLengthIncDecimalPoint, numVarsAfterDecimal, charbuf);
where
floatvar float variable
StringLengthIncDecimalPoint This is the length of the string that will be created
numVarsAfterDecimal The number of digits after the decimal point to print
charbuf the array to store the results
display one decimal place, like 25.5 or does it display 25.5.0?
In all likelihood it is the simple error of not clearing the display before redisplaying. For example if you display -127.0 and then 25.5 without clearing you will get that effect, eg.
-127.0
25.5
^^ <--- left over from last time
Simply displaying a couple of trailing spaces would fix it.
Nick_Pyner:
The 85 indicates the sensor hasn't had time to do its job. Since you defaulting to 12 bit resolution, the sensor needs about 750ms to stay in play, and you seem to be giving it nothing, hence my surprise. You can probably fix this by adding a quick'n'dirty.
delay(1000);
The requestTemperatures() function already adds a delay which varies depending on the selected resolution, there shouldn't be a need to add an extra delay.
I find the 85 appears when I first get a temp from the sensor. Maybe it is losing connection/power temporarily.
Where did you get the library exactly? One version I have, at least, gets the CRC check from the device and then ignores it. Without checking the CRC you have no way of knowing if the data is good. There is a difference between not finding the device at all, and finding it and getting corrupt data.
ChrisHigs:
The requestTemperatures() function already adds a delay which varies depending on the selected resolution, there shouldn't be a need to add an extra delay.
I find the 85 appears when I first get a temp from the sensor. Maybe it is losing connection/power temporarily.
I submit this is nonsense. The function is code, and the code doesn't add the delay, the delay is in the sensor and is caused by the conversion time required - the more converting, the more time.
The 85 you see is the power-on reset value. It is not telling you something is wrong, quite the opposite - plus the fact that you are too eager. The reason why you see it when you "first get a temperature" is that you are asking for a temperature before the sensor has had enough time to give you one. This is common enough in simple programmes and not really a problem. You sometimes see a delay(1000); thrown into the Setup to avoid this, and called settle-down time. In a more comprehensive programme, there will be more stuff like initialising SD, naming files, setting up Ethernet etc., thus more code between power-up and requestTemperature(), hence more time taken, and the 85s go away.
I imagine you would would be a bit unlucky if you ever saw an 85 and were calling for 9 or 10 bit resolution, but OP wasn't calling anything and hence getting 12 bit by default.
This is from DallasTemperature.cpp. When request temperature() is called it calls blockTilConversionComplete() which ask millisToWaitForConversion how long to wait. 12 bit returns 750. Then delays that long. Maybe it doesn’t delay long enough on the first call of it.
int delms = millisToWaitForConversion(bitResolution);
if (deviceAddress != NULL && checkForConversion && !parasite)
{
unsigned long timend = millis() + delms;
while(!isConversionAvailable(deviceAddress) && (millis() < timend));
}
else
{
delay(delms);
}